Commit e7fd6fd2 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

Implemented a lot of Netbios().

parent e94dad18
......@@ -4,13 +4,17 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = netapi32.dll
IMPORTS = iphlpapi advapi32 kernel32
IMPORTS = iphlpapi ws2_32 advapi32 kernel32
C_SRCS = \
access.c \
apibuf.c \
browsr.c \
nbcmdqueue.c \
nbnamecache.c \
nbt.c \
netapi32.c \
netbios.c \
wksta.c
SUBDIRS = tests
......
/* Copyright (c) 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/debug.h"
#include "nbcmdqueue.h"
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
struct NBCmdQueue
{
HANDLE heap;
CRITICAL_SECTION cs;
PNCB head;
};
#define CANCEL_EVENT_PTR(ncb) (PHANDLE)((ncb)->ncb_reserved)
#define NEXT_PTR(ncb) (PNCB *)((ncb)->ncb_reserved + sizeof(HANDLE))
/* The reserved area of an ncb will be used for the following data:
* - a cancelled flag (BOOL, 4 bytes??)
* - a handle to an event that's set by a cancelled command on completion
* (HANDLE, 4 bytes)
* These members are used in the following way
* - on cancel, set the event member of the reserved field (with create event)
* - NBCmdComplete will delete the ncb from the queue of there's no event;
* otherwise it will set the event and not delete the ncb
* - cancel must lock the queue before finding the ncb in it, and can unlock it
* once it's set the event (and the cancelled flag)
* - NBCmdComplete must lock the queue before attempting to remove the ncb or
* check the event
* - NBCmdQueueCancelAll will lock the queue, and cancel all ncb's in the queue.
* It'll then unlock the queue, and wait on the event in the head of the queue
* until there's no more ncb's in the queue.
* Space optimization: use the handle as a boolean. NULL == 0 => not cancelled.
* Non-NULL == valid handle => cancelled. This allows storing a next pointer
* in the ncb's reserved field as well, avoiding a memory alloc for a new
* command (cool).
*/
struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap)
{
struct NBCmdQueue *queue;
if (heap == NULL)
heap = GetProcessHeap();
queue = (struct NBCmdQueue *)HeapAlloc(heap, 0, sizeof(struct NBCmdQueue));
if (queue)
{
queue->heap = heap;
InitializeCriticalSection(&queue->cs);
queue->head = NULL;
}
return queue;
}
UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb)
{
UCHAR ret;
TRACE(": queue %p, ncb %p\n", queue, ncb);
if (!queue)
return NRC_BADDR;
if (!ncb)
return NRC_INVADDRESS;
*CANCEL_EVENT_PTR(ncb) = NULL;
EnterCriticalSection(&queue->cs);
*NEXT_PTR(ncb) = queue->head;
queue->head = ncb;
ret = NRC_GOODRET;
LeaveCriticalSection(&queue->cs);
TRACE("returning 0x%02x\n", ret);
return ret;
}
static PNCB *NBCmdQueueFindNBC(struct NBCmdQueue *queue, PNCB ncb)
{
PNCB *ret;
if (!queue || !ncb)
ret = NULL;
else
{
ret = &queue->head;
while (ret && *ret != ncb)
ret = NEXT_PTR(*ret);
}
return ret;
}
UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb)
{
UCHAR ret;
PNCB *spot;
TRACE(": queue %p, ncb %p\n", queue, ncb);
if (!queue)
return NRC_BADDR;
if (!ncb)
return NRC_INVADDRESS;
EnterCriticalSection(&queue->cs);
spot = NBCmdQueueFindNBC(queue, ncb);
if (spot)
{
*CANCEL_EVENT_PTR(*spot) = CreateEventW(NULL, FALSE, FALSE, NULL);
WaitForSingleObject(*CANCEL_EVENT_PTR(*spot), INFINITE);
CloseHandle(*CANCEL_EVENT_PTR(*spot));
*spot = *NEXT_PTR(*spot);
if (ncb->ncb_retcode == NRC_CMDCAN)
ret = NRC_CMDCAN;
else
ret = NRC_CANOCCR;
}
else
ret = NRC_INVADDRESS;
LeaveCriticalSection(&queue->cs);
TRACE("returning 0x%02x\n", ret);
return ret;
}
UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode)
{
UCHAR ret;
PNCB *spot;
TRACE(": queue %p, ncb %p\n", queue, ncb);
if (!queue)
return NRC_BADDR;
if (!ncb)
return NRC_INVADDRESS;
EnterCriticalSection(&queue->cs);
spot = NBCmdQueueFindNBC(queue, ncb);
if (spot)
{
if (*CANCEL_EVENT_PTR(*spot))
SetEvent(*CANCEL_EVENT_PTR(*spot));
else
*spot = *NEXT_PTR(*spot);
ret = NRC_GOODRET;
}
else
ret = NRC_INVADDRESS;
LeaveCriticalSection(&queue->cs);
TRACE("returning 0x%02x\n", ret);
return ret;
}
UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue)
{
UCHAR ret;
TRACE(": queue %p\n", queue);
if (!queue)
return NRC_BADDR;
EnterCriticalSection(&queue->cs);
while (queue->head)
{
TRACE(": waiting for ncb %p (command 0x%02x)\n", queue->head,
queue->head->ncb_command);
NBCmdQueueCancel(queue, queue->head);
}
LeaveCriticalSection(&queue->cs);
ret = NRC_GOODRET;
TRACE("returning 0x%02x\n", ret);
return ret;
}
void NBCmdQueueDestroy(struct NBCmdQueue *queue)
{
TRACE(": queue %p\n", queue);
if (queue)
{
NBCmdQueueCancelAll(queue);
DeleteCriticalSection(&queue->cs);
HeapFree(queue->heap, 0, queue);
}
}
/* Copyright (c) 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __NBCMDQUEUE_H__
#define __NBCMDQUEUE_H__
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "nb30.h"
/* This file defines a queue of pending NetBIOS commands. The queue operations
* are thread safe, with the exception of NBCmdQueueDestroy: ensure no other
* threads are manipulating the queue when calling NBCmdQueueDestroy.
*/
struct NBCmdQueue;
/* Allocates a new command queue from heap. */
struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap);
/* Adds ncb to queue. Assumes queue is not NULL, and ncb is not already in the
* queue. If ncb is already in the queue, returns NRC_TOOMANY.
*/
UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb);
/* Cancels the given ncb. Blocks until the command completes. Implicitly
* removes ncb from the queue. Assumes queue and ncb are not NULL, and that
* ncb has been added to queue previously.
* Returns NRC_CMDCAN on a successful cancellation, NRC_CMDOCCR if the command
* completed before it could be cancelled, and various other return values for
* different failures.
*/
UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb);
/* Sets the return code of the given ncb, and implicitly removes the command
* from the queue. Assumes queue and ncb are not NULL, and that ncb has been
* added to queue previously.
* Returns NRC_GOODRET on success.
*/
UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode);
/* Cancels all pending commands in the queue (useful for a RESET or a shutdown).
* Returns when all commands have been completed.
*/
UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue);
/* Frees all memory associated with the queue. Blocks until all commands
* pending in the queue have been completed.
*/
void NBCmdQueueDestroy(struct NBCmdQueue *queue);
#endif /* __NBCMDQUEUE_H__ */
/* Copyright (c) 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This implementation uses a linked list, because I don't have a decent
* hash table implementation handy. This is somewhat inefficient, but it's
* rather more efficient than not having a name cache at all.
*/
#include "wine/debug.h"
#include "nbnamecache.h"
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
typedef struct _NBNameCacheNode
{
DWORD expireTime;
NBNameCacheEntry *entry;
struct _NBNameCacheNode *next;
} NBNameCacheNode;
struct NBNameCache
{
HANDLE heap;
CRITICAL_SECTION cs;
DWORD entryExpireTimeMS;
NBNameCacheNode *head;
};
/* Unlinks the node pointed to by *prev, and frees any associated memory.
* If that node's next pointed to another node, *prev now points to it.
* Assumes the caller owns cache's lock.
*/
static void NBNameCacheUnlinkNode(struct NBNameCache *cache,
NBNameCacheNode **prev)
{
if (cache && prev && *prev)
{
NBNameCacheNode *next = (*prev)->next;
if ((*prev)->entry)
HeapFree(cache->heap, 0, (*prev)->entry);
HeapFree(cache->heap, 0, *prev);
*prev = next;
}
}
/* Walks the list beginning with cache->head looking for the node with name
* name. If the node is found, returns a pointer to the next pointer of the
* node _prior_ to the found node (or head if head points to it). Thus, if the
* node's all you want, dereference the return value twice. If you want to
* modify the list, modify the referent of the return value.
* While it's at it, deletes nodes whose time has expired (except the node
* you're looking for, of course).
* Returns NULL if the node isn't found.
* Assumes the caller owns cache's lock.
*/
static NBNameCacheNode **NBNameCacheWalk(struct NBNameCache *cache,
const char name[NCBNAMSZ])
{
NBNameCacheNode **ret = NULL;
if (cache && cache->head)
{
NBNameCacheNode **ptr;
ptr = &cache->head;
while (ptr && *ptr && (*ptr)->entry)
{
if (!memcmp((*ptr)->entry->name, name, NCBNAMSZ - 1))
ret = ptr;
else
{
if (GetTickCount() > (*ptr)->expireTime)
NBNameCacheUnlinkNode(cache, ptr);
}
if (*ptr)
ptr = &(*ptr)->next;
}
}
return ret;
}
struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS)
{
struct NBNameCache *cache;
if (!heap)
heap = GetProcessHeap();
cache = (struct NBNameCache *)HeapAlloc(heap, 0,
sizeof(struct NBNameCache));
if (cache)
{
cache->heap = heap;
InitializeCriticalSection(&cache->cs);
cache->entryExpireTimeMS = entryExpireTimeMS;
cache->head = NULL;
}
return cache;
}
BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry)
{
BOOL ret;
if (cache && entry)
{
NBNameCacheNode **node;
EnterCriticalSection(&cache->cs);
node = NBNameCacheWalk(cache, entry->name);
if (node)
{
(*node)->expireTime = GetTickCount() +
cache->entryExpireTimeMS;
HeapFree(cache->heap, 0, (*node)->entry);
(*node)->entry = entry;
ret = TRUE;
}
else
{
NBNameCacheNode *newNode = (NBNameCacheNode *)HeapAlloc(
cache->heap, 0, sizeof(NBNameCacheNode));
if (newNode)
{
newNode->expireTime = GetTickCount() +
cache->entryExpireTimeMS;
newNode->entry = entry;
newNode->next = cache->head;
cache->head = newNode;
ret = TRUE;
}
else
ret = FALSE;
}
LeaveCriticalSection(&cache->cs);
}
else
ret = FALSE;
return ret;
}
const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache,
const UCHAR name[NCBNAMSZ])
{
const NBNameCacheEntry *ret;
UCHAR printName[NCBNAMSZ];
memcpy(printName, name, NCBNAMSZ - 1);
printName[NCBNAMSZ - 1] = '\0';
if (cache)
{
NBNameCacheNode **node;
EnterCriticalSection(&cache->cs);
node = NBNameCacheWalk(cache, name);
if (node)
ret = (*node)->entry;
else
ret = NULL;
LeaveCriticalSection(&cache->cs);
}
else
ret = NULL;
return ret;
}
BOOL NBNameCacheUpdateNBName(struct NBNameCache *cache,
const UCHAR name[NCBNAMSZ], const UCHAR nbname[NCBNAMSZ])
{
BOOL ret;
if (cache)
{
NBNameCacheNode **node;
EnterCriticalSection(&cache->cs);
node = NBNameCacheWalk(cache, name);
if (node && *node && (*node)->entry)
{
memcpy((*node)->entry->nbname, nbname, NCBNAMSZ);
ret = TRUE;
}
else
ret = FALSE;
LeaveCriticalSection(&cache->cs);
}
else
ret = FALSE;
return ret;
}
void NBNameCacheDestroy(struct NBNameCache *cache)
{
if (cache)
{
DeleteCriticalSection(&cache->cs);
while (cache->head)
NBNameCacheUnlinkNode(cache, &cache->head);
HeapFree(cache->heap, 0, cache);
}
}
/* Copyright (c) 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_NBNAMECACHE_H
#define __WINE_NBNAMECACHE_H
#include "winbase.h"
#include "nb30.h"
struct NBNameCache;
/* Represents an entry in the name cache. If the NetBIOS name is known, it's
* in nbname. Otherwise, nbname begins with '*'. numAddresses defines the
* number of addresses in addresses.
* Notice that it allows multiple addresses per name, but doesn't explicitly
* allow group names. That's because all names so far are unique; if a use for
* group names comes up, adding a flag here is simple enough.
* Also, only the first NCBNAMSZ - 1 bytes are considered significant. This is
* because a name may have been resolved using DNS, and the suffix byte is
* always truncated for DNS lookups.
*/
typedef struct _NBNameCacheEntry
{
UCHAR name[NCBNAMSZ];
UCHAR nbname[NCBNAMSZ];
DWORD numAddresses;
DWORD addresses[1];
} NBNameCacheEntry;
/* Functions that create, manipulate, and destroy a name cache. Thread-safe,
* with the exception of NBNameCacheDestroy--ensure that no other threads are
* manipulating the cache before destoying it.
*/
/* Allocates a new name cache from heap, and sets the expire time on new
* entries to entryExpireTimeMS after a cache entry is added.
*/
struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS);
/* Adds an entry to the cache. The entry is assumed to have been allocated
* from the same heap as the name cache; the name cache will own the entry
* from now on. The entry's expire time is initialized at this time to
* entryExpireTimeMS + the current time in MS. If an existing entry with the
* same name was in the cache, the entry is replaced. Returns TRUE on success
* or FALSE on failure.
*/
BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry);
/* Finds the entry with name name in the cache and returns a pointer to it, or
* NULL if it isn't found.
*/
const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache,
const UCHAR name[NCBNAMSZ]);
/* If the entry with name name is in the cache, updates its nbname member to
* nbname. The entry's expire time is implicitly updated to entryExpireTimeMS
* + the current time in MS, since getting the NetBIOS name meant validating
* the name and address anyway.
* Returns TRUE on success or FALSE on failure.
*/
BOOL NBNameCacheUpdateNBName(struct NBNameCache *cache,
const UCHAR name[NCBNAMSZ], const UCHAR nbname[NCBNAMSZ]);
void NBNameCacheDestroy(struct NBNameCache *cache);
#endif /* ndef __WINE_NBNAMECACHE_H */
/*
* Copyright 2001 Mike McCormack
/* Copyright 2001 Mike McCormack
* Copyright 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -18,185 +18,36 @@
#include "config.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
#include "winerror.h"
#include "nb30.h"
#include "lm.h"
#include "iphlpapi.h"
#include "netbios.h"
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
HMODULE NETAPI32_hModule = 0;
static UCHAR NETBIOS_Enum(PNCB ncb)
{
int i;
LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
DWORD apiReturn, size = 0;
PMIB_IFTABLE table;
UCHAR ret;
TRACE("NCBENUM\n");
apiReturn = GetIfTable(NULL, &size, FALSE);
if (apiReturn != NO_ERROR)
{
table = (PMIB_IFTABLE)malloc(size);
if (table)
{
apiReturn = GetIfTable(table, &size, FALSE);
if (apiReturn == NO_ERROR)
{
lanas->length = 0;
for (i = 0; i < table->dwNumEntries && lanas->length < MAX_LANA;
i++)
{
if (table->table[i].dwType != MIB_IF_TYPE_LOOPBACK)
{
lanas->lana[lanas->length] = table->table[i].dwIndex;
lanas->length++;
}
}
ret = NRC_GOODRET;
}
else
ret = NRC_SYSTEM;
free(table);
}
else
ret = NRC_NORESOURCES;
}
else
ret = NRC_SYSTEM;
return ret;
}
static UCHAR NETBIOS_Astat(PNCB ncb)
{
PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
MIB_IFROW row;
TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
memset(astat, 0, sizeof astat);
row.dwIndex = ncb->ncb_lana_num;
if (GetIfEntry(&row) != NO_ERROR)
return NRC_INVADDRESS;
/* doubt anyone cares, but why not.. */
if (row.dwType == MIB_IF_TYPE_TOKENRING)
astat->adapter_type = 0xff;
else
astat->adapter_type = 0xfe; /* for Ethernet */
return NRC_GOODRET;
}
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hinstDLL);
NETAPI32_hModule = hinstDLL;
break;
case DLL_PROCESS_DETACH:
break;
NetBIOSInit();
NetBTInit();
break;
}
case DLL_PROCESS_DETACH:
{
NetBIOSShutdown();
break;
}
}
return TRUE;
}
UCHAR WINAPI Netbios(PNCB pncb)
{
UCHAR ret = NRC_ILLCMD;
TRACE("ncb = %p\n",pncb);
if(!pncb)
return NRC_INVADDRESS;
switch(pncb->ncb_command&0x7f)
{
case NCBRESET:
FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
if(pncb->ncb_lana_num < MAX_LANA )
{
MIB_IFROW row;
row.dwIndex = pncb->ncb_lana_num;
if (GetIfEntry(&row) != NO_ERROR)
ret = NRC_GOODRET;
else
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
}
else
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
break;
case NCBADDNAME:
FIXME("NCBADDNAME\n");
break;
case NCBADDGRNAME:
FIXME("NCBADDGRNAME\n");
break;
case NCBDELNAME:
FIXME("NCBDELNAME\n");
break;
case NCBSEND:
FIXME("NCBSEND\n");
break;
case NCBRECV:
FIXME("NCBRECV\n");
break;
case NCBHANGUP:
FIXME("NCBHANGUP\n");
break;
case NCBCANCEL:
FIXME("NCBCANCEL\n");
break;
case NCBLISTEN:
FIXME("NCBLISTEN\n");
break;
case NCBASTAT:
ret = NETBIOS_Astat(pncb);
break;
case NCBENUM:
ret = NETBIOS_Enum(pncb);
break;
default:
FIXME("(%p): command code %02x\n", pncb, pncb->ncb_command);
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
}
pncb->ncb_retcode = ret;
return ret;
}
NET_API_STATUS WINAPI NetServerEnum(
LPCWSTR servername,
DWORD level,
......
/* Copyright (c) 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_NETBIOS_H__
#define __WINE_NETBIOS_H__
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "lm.h"
#include "nb30.h"
/* This file describes the interface WINE's NetBIOS implementation uses to
* interact with a transport implementation (where a transport might be
* NetBIOS-over-TCP/IP (aka NetBT, NBT), NetBIOS-over-IPX, etc.)
*/
/**
* Public functions
*/
void NetBIOSInit(void);
void NetBIOSShutdown(void);
struct _NetBIOSTransport;
/* A transport should register itself during its init function (see below) with
* a unique id (the transport_id of ACTION_HEADER, for example) and an
* implementation. Returns TRUE on success, and FALSE on failure.
*/
BOOL NetBIOSRegisterTransport(ULONG id, struct _NetBIOSTransport *transport);
/* Registers an adapter with the given transport and ifIndex with NetBIOS.
* ifIndex is an interface index usable by the IpHlpApi. ifIndex is not
* required to be unique, but is required so that NetWkstaTransportEnum can use
* GetIfEntry to get the name and hardware address of the adapter.
* Returns TRUE on success, FALSE on failure.
* FIXME: need functions for retrieving the name and hardware index, rather
* than assuming a correlation with IpHlpApi.
*/
BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *adapter);
/* During enumeration, all adapters from your transport are disabled
* internally. If an adapter is still valid, reenable it with this function.
* Adapters you don't enable will have their transport's NetBIOSCleanupAdapter
* function (see below) called on them, and will be removed from the table.
* (This is to deal with lack of plug-and-play--sorry.)
*/
void NetBIOSEnableAdapter(UCHAR lana);
/* Gets a quick count of the number of NetBIOS adapters. Not guaranteed not
* to change from one call to the next, depending on what's been enumerated
* lately. See also NetBIOSEnumAdapters.
*/
UCHAR NetBIOSNumAdapters(void);
typedef struct _NetBIOSAdapterImpl {
UCHAR lana;
DWORD ifIndex;
void *data;
} NetBIOSAdapterImpl;
typedef BOOL (*NetBIOSEnumAdaptersCallback)(UCHAR totalLANAs, UCHAR lanaIndex,
ULONG transport, const NetBIOSAdapterImpl *data, void *closure);
/* Enumerates all NetBIOS adapters for the transport transport, or for all
* transports if transport is ALL_TRANSPORTS. Your callback will be called
* once for every enumerated adapter, with a count of how many adapters have
* been enumerated, a 0-based index relative to that count, the adapter's
* transport, and its ifIndex.
* Your callback should return FALSE if it no longer wishes to be called.
*/
void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb,
void *closure);
/* Hangs up the session identified in the NCB; the NCB need not be a NCBHANGUP.
* Will result in the transport's hangup function being called, so release any
* locks you own before calling to avoid deadlock.
* This function is intended for use by a transport, if the session is closed
* by some error in the transport layer.
*/
void NetBIOSHangupSession(PNCB ncb);
/**
* Functions a transport implementation must implement
*/
/* This function is called to ask a transport implementation to enumerate any
* LANAs into the NetBIOS adapter table by:
* - calling NetBIOSRegisterAdapter for any new adapters
* - calling NetBIOSEnableAdapter for any existing adapters
* NetBIOSEnumAdapters (see) may be of use to determine which adapters already
* exist.
* A transport can assume no other thread is modifying the NetBIOS adapter
* table during the lifetime of its NetBIOSEnum function (and, therefore, that
* this function won't be called reentrantly).
*/
typedef UCHAR (*NetBIOSEnum)(void);
/* A cleanup function for a transport. This is the last function called on a
* transport.
*/
typedef void (*NetBIOSCleanup)(void);
/* Adapter functions */
/* Functions with direct mappings to the Netbios interface. These functions
* are expected to be synchronous, although the first four bytes of the
* reserved member of the ncb are a cancel flag. A long-running function
* should check whether this is not FALSE from time to time (see the
* NCB_CANCELLED macro), and return NRC_CMDCAN if it's been cancelled. (The
* remainder of the NCB's reserved field is, well, reserved.)
*/
/* Used to see whether the pointer to an NCB has been cancelled. The NetBIOS
* interface designates certain functions as non-cancellable functions, but I
* use this flag for all NCBs. Support it if you can.
* FIXME: this isn't enough, need to support an EVENT or some such, because
* some calls (recv) will block indefinitely, so a reset, shutdown, etc. will
* never occur.
*/
#define NCB_CANCELLED(pncb) *(PBOOL)((pncb)->ncb_reserved)
typedef UCHAR (*NetBIOSAstat)(void *adapter, PNCB ncb);
typedef UCHAR (*NetBIOSFindName)(void *adapter, PNCB ncb);
/* Functions to support the session service */
/* Implement to support the NCBCALL command. If you need data stored for the
* session, return it in *session. You can clean it up in your NetBIOSHangup
* function (see).
*/
typedef UCHAR (*NetBIOSCall)(void *adapter, PNCB ncb, void **session);
typedef UCHAR (*NetBIOSSend)(void *adapter, void *session, PNCB ncb);
typedef UCHAR (*NetBIOSRecv)(void *adapter, void *session, PNCB ncb);
typedef UCHAR (*NetBIOSHangup)(void *adapter, void *session);
/* The last function called on an adapter; it is not called reentrantly, and
* no new calls will be made on the adapter once this has been entered. Clean
* up any resources allocated for the adapter here.
*/
typedef void (*NetBIOSCleanupAdapter)(void *adapter);
typedef struct _NetBIOSTransport
{
NetBIOSEnum enumerate;
NetBIOSAstat astat;
NetBIOSFindName findName;
NetBIOSCall call;
NetBIOSSend send;
NetBIOSRecv recv;
NetBIOSHangup hangup;
NetBIOSCleanupAdapter cleanupAdapter;
NetBIOSCleanup cleanup;
} NetBIOSTransport;
/* Transport-specific functions. When adding a transport, add a call to its
* init function in netapi32's DllMain. The transport can do any global
* initialization it needs here. It should call NetBIOSRegisterTransport to
* register itself with NetBIOS.
*/
/* NetBIOS-over-TCP/IP (NetBT) functions */
/* Not defined by MS, so make my own private define: */
#define TRANSPORT_NBT "MNBT"
void NetBTInit(void);
#endif /* ndef __WINE_NETBIOS_H__ */
......@@ -25,9 +25,6 @@
extern "C" {
#endif
/* NetBIOS */
UCHAR WINAPI Netbios(PNCB pncb);
typedef struct _WKSTA_TRANSPORT_INFO_0 {
DWORD wkti0_quality_of_service;
DWORD wkti0_number_of_vcs;
......
......@@ -26,18 +26,34 @@ extern "C" {
#define NCBNAMSZ 16
#define MAX_LANA 0xfe
#define NCBRESET 0x32
#define NCBADDNAME 0x30
#define NCBADDGRNAME 0x36
#define NCBDELNAME 0x31
#define NCBCALL 0x10
#define NCBLISTEN 0x11
#define NCBHANGUP 0x12
#define NCBSEND 0x14
#define NCBRECV 0x15
#define NCBHANGUP 0x12
#define NCBCANCEL 0x35
#define NCBLISTEN 0x11
#define NCBCALL 0x10
#define NCBRECVANY 0x16
#define NCBCHAINSEND 0x17
#define NCBDGSEND 0x20
#define NCBDGRECV 0x21
#define NCBDGSENDBC 0x22
#define NCBDGRECVBC 0x23
#define NCBADDNAME 0x30
#define NCBDELNAME 0x31
#define NCBRESET 0x32
#define NCBASTAT 0x33
#define NCBSSTAT 0x34
#define NCBCANCEL 0x35
#define NCBADDGRNAME 0x36
#define NCBENUM 0x37
#define NCBUNLINK 0x70
#define NCBSENDNA 0x71
#define NCBCHAINSENDNA 0x72
#define NCBLANSTALERT 0x73
#define NCBACTION 0x77
#define NCBFINDNAME 0x78
#define NCBTRACE 0x79
#define ASYNCH 0x80
typedef struct _NCB
{
......@@ -51,7 +67,7 @@ typedef struct _NCB
UCHAR ncb_name[NCBNAMSZ];
UCHAR ncb_rto;
UCHAR ncb_sto;
VOID (*ncb_post)(struct _NCB *);
VOID (CALLBACK *ncb_post)(struct _NCB *);
UCHAR ncb_lana_num;
UCHAR ncb_cmd_cplt;
UCHAR ncb_reserved[10];
......@@ -89,22 +105,111 @@ typedef struct _ADAPTER_STATUS
WORD name_count;
} ADAPTER_STATUS, *PADAPTER_STATUS;
typedef struct _NAME_BUFFER
{
UCHAR name[NCBNAMSZ];
UCHAR name_num;
UCHAR name_flags;
} NAME_BUFFER, *PNAME_BUFFER;
#define NAME_FLAGS_MASK 0x87
#define GROUP_NAME 0x80
#define UNIQUE_NAME 0x00
#define REGISTERING 0x00
#define REGISTERED 0x04
#define DEREGISTERED 0x05
#define DUPLICATE 0x06
#define DUPLICATE_DEREG 0x07
typedef struct _LANA_ENUM
{
UCHAR length;
UCHAR lana[MAX_LANA+1];
} LANA_ENUM, *PLANA_ENUM;
#define NRC_GOODRET 0x00
#define NRC_BUFLEN 0x01
#define NRC_ILLCMD 0x03
#define NRC_CMDTMO 0x05
#define NRC_INCOMP 0x06
typedef struct _FIND_NAME_HEADER
{
WORD node_count;
UCHAR reserved;
UCHAR unique_group;
} FIND_NAME_HEADER, *PFIND_NAME_HEADER;
typedef struct _FIND_NAME_BUFFER
{
UCHAR length;
UCHAR access_control;
UCHAR frame_control;
UCHAR destination_addr[6];
UCHAR source_addr[6];
UCHAR routing_info[6];
} FIND_NAME_BUFFER, *PFIND_NAME_BUFFER;
typedef struct _SESSION_HEADER {
UCHAR sess_name;
UCHAR num_sess;
UCHAR rcv_dg_outstanding;
UCHAR rcv_any_outstanding;
} SESSION_HEADER, *PSESSION_HEADER;
typedef struct _SESSION_BUFFER {
UCHAR lsn;
UCHAR state;
UCHAR local_name[NCBNAMSZ];
UCHAR remote_name[NCBNAMSZ];
UCHAR rcvs_outstanding;
UCHAR sends_outstanding;
} SESSION_BUFFER, *PSESSION_BUFFER;
#define LISTEN_OUTSTANDING 0x01
#define CALL_PENDING 0x02
#define SESSION_ESTABLISHED 0x03
#define HANGUP_PENDING 0x04
#define HANGUP_COMPLETE 0x05
#define SESSION_ABORTED 0x06
#define ALL_TRANSPORTS "M\0\0\0"
#define NRC_GOODRET 0x00
#define NRC_BUFLEN 0x01
#define NRC_ILLCMD 0x03
#define NRC_CMDTMO 0x05
#define NRC_INCOMP 0x06
#define NRC_BADDR 0x07
#define NRC_SNUMOUT 0x08
#define NRC_NORES 0x09
#define NRC_SCLOSED 0x0a
#define NRC_CMDCAN 0x0b
#define NRC_DUPNAME 0x0d
#define NRC_NAMTFUL 0x0e
#define NRC_ACTSES 0x0f
#define NRC_LOCTFUL 0x11
#define NRC_REMTFUL 0x12
#define NRC_ILLNN 0x13
#define NRC_NOCALL 0x14
#define NRC_NOWILD 0x15
#define NRC_INUSE 0x16
#define NRC_NAMERR 0x17
#define NRC_SABORT 0x18
#define NRC_NAMCONF 0x19
#define NRC_IFBUSY 0x21
#define NRC_TOOMANY 0x22
#define NRC_BRIDGE 0x23
#define NRC_CANOCCR 0x24
#define NRC_CANCEL 0x26
#define NRC_DUPENV 0x30
#define NRC_ENVNOTDEF 0x34
#define NRC_OSRESNOTAV 0x35
#define NRC_MAXAPPS 0x36
#define NRC_NOSAPS 0x37
#define NRC_NORESOURCES 0x38
#define NRC_INVADDRESS 0x39
#define NRC_PENDING 0xff
#define NRC_OPENERROR 0x3f
#define NRC_SYSTEM 0x40
#define NRC_INVADDRESS 0x39
#define NRC_INVDDID 0x3b
#define NRC_LOCKFAIL 0x3c
#define NRC_OPENERROR 0x3f
#define NRC_SYSTEM 0x40
#define NRC_PENDING 0xff
UCHAR WINAPI Netbios(PNCB pncb);
#ifdef __cplusplus
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment