<directory name="mswsock">
<xi:include href="mswsock/mswsock.xml" />
</directory>
-<directory name="netapi32">
- <xi:include href="netapi32/netapi32.xml" />
-</directory>
<directory name="netcfgx">
<xi:include href="netcfgx/netcfgx.xml" />
</directory>
+++ /dev/null
-EXTRADEFS = -D_SVRAPI_
-TOPSRCDIR = @top_srcdir@
-TOPOBJDIR = ../..
-SRCDIR = @srcdir@
-VPATH = @srcdir@
-MODULE = netapi32.dll
-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
-
-@MAKE_DLL_RULES@
-
-### Dependencies:
+++ /dev/null
-/*
- * Copyright 2002 Andriy Palamarchuk
- *
- * netapi32 access functions
- *
- * 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 <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "winerror.h"
-#include "lmcons.h"
-#include "lmaccess.h"
-#include "lmapibuf.h"
-#include "lmerr.h"
-#include "netapi32_misc.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-
-const WCHAR sAdminUserName[] = {'A','d','m','i','n','i','s','t','r','a','t',
- 'o','r',0};
-const WCHAR sGuestUserName[] = {'G','u','e','s','t',0};
-
-/************************************************************
- * NETAPI_ValidateServername
- *
- * Validates server name
- */
-NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
-{
- if (ServerName)
- {
- if (ServerName[0] == 0)
- return ERROR_BAD_NETPATH;
- else if (
- ((ServerName[0] == '\\') &&
- (ServerName[1] != '\\'))
- ||
- ((ServerName[0] == '\\') &&
- (ServerName[1] == '\\') &&
- (ServerName[2] == 0))
- )
- return ERROR_INVALID_NAME;
- }
- return NERR_Success;
-}
-
-/************************************************************
- * NETAPI_IsKnownUser
- *
- * Checks whether the user name indicates current user.
- */
-BOOL NETAPI_IsKnownUser(LPCWSTR UserName)
-{
- DWORD dwSize = UNLEN + 1;
- BOOL Result;
- LPWSTR buf;
-
- if (!lstrcmpW(UserName, sAdminUserName) ||
- !lstrcmpW(UserName, sGuestUserName))
- return TRUE;
- NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf);
- Result = GetUserNameW(buf, &dwSize);
-
- Result = Result && !lstrcmpW(UserName, buf);
- NetApiBufferFree(buf);
-
- return Result;
-}
-
-#define NETAPI_ForceKnownUser(UserName, FailureCode) \
- if (!NETAPI_IsKnownUser(UserName)) \
- { \
- FIXME("Can't find information for user %s\n", \
- debugstr_w(UserName)); \
- return FailureCode; \
- }
-
-/************************************************************
- * NetUserGetInfo (NETAPI32.@)
- */
-NET_API_STATUS WINAPI
-NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
- LPBYTE* bufptr)
-{
- NET_API_STATUS status;
- TRACE("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username),
- level, bufptr);
- status = NETAPI_ValidateServername(servername);
- if (status != NERR_Success)
- return status;
- NETAPI_ForceLocalComputer(servername, NERR_InvalidComputer);
- NETAPI_ForceKnownUser(username, NERR_UserNotFound);
-
- switch (level)
- {
- case 0:
- {
- PUSER_INFO_0 ui;
- int name_sz;
-
- name_sz = lstrlenW(username) + 1;
-
- /* set up buffer */
- NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
- (LPVOID *) bufptr);
-
- ui = (PUSER_INFO_0) *bufptr;
- ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
-
- /* get data */
- lstrcpyW(ui->usri0_name, username);
- break;
- }
-
- case 10:
- {
- PUSER_INFO_10 ui;
- PUSER_INFO_0 ui0;
- NET_API_STATUS status;
- /* sizes of the field buffers in WCHARS */
- int name_sz, comment_sz, usr_comment_sz, full_name_sz;
-
- comment_sz = 1;
- usr_comment_sz = 1;
- full_name_sz = 1;
-
- /* get data */
- status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
- if (status != NERR_Success)
- {
- NetApiBufferFree(ui0);
- return status;
- }
- name_sz = lstrlenW(ui0->usri0_name) + 1;
-
- /* set up buffer */
- NetApiBufferAllocate(sizeof(USER_INFO_10) +
- (name_sz + comment_sz + usr_comment_sz +
- full_name_sz) * sizeof(WCHAR),
- (LPVOID *) bufptr);
- ui = (PUSER_INFO_10) *bufptr;
- ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
- ui->usri10_comment = (LPWSTR) (
- ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
- ui->usri10_usr_comment = (LPWSTR) (
- ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
- ui->usri10_full_name = (LPWSTR) (
- ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
-
- /* set data */
- lstrcpyW(ui->usri10_name, ui0->usri0_name);
- NetApiBufferFree(ui0);
- ui->usri10_comment[0] = 0;
- ui->usri10_usr_comment[0] = 0;
- ui->usri10_full_name[0] = 0;
- break;
- }
-
- case 1:
- {
- static const WCHAR homedirW[] = {'H','O','M','E',0};
- PUSER_INFO_1 ui;
- PUSER_INFO_0 ui0;
- NET_API_STATUS status;
- /* sizes of the field buffers in WCHARS */
- int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
-
- password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
- comment_sz = 1;
- script_path_sz = 1;
-
- /* get data */
- status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
- if (status != NERR_Success)
- {
- NetApiBufferFree(ui0);
- return status;
- }
- name_sz = lstrlenW(ui0->usri0_name) + 1;
- home_dir_sz = GetEnvironmentVariableW(homedirW, NULL,0);
- /* set up buffer */
- NetApiBufferAllocate(sizeof(USER_INFO_1) +
- (name_sz + password_sz + home_dir_sz +
- comment_sz + script_path_sz) * sizeof(WCHAR),
- (LPVOID *) bufptr);
-
- ui = (PUSER_INFO_1) *bufptr;
- ui->usri1_name = (LPWSTR) (ui + 1);
- ui->usri1_password = ui->usri1_name + name_sz;
- ui->usri1_home_dir = ui->usri1_password + password_sz;
- ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
- ui->usri1_script_path = ui->usri1_comment + comment_sz;
- /* set data */
- lstrcpyW(ui->usri1_name, ui0->usri0_name);
- NetApiBufferFree(ui0);
- ui->usri1_password[0] = 0;
- ui->usri1_password_age = 0;
- ui->usri1_priv = 0;
- GetEnvironmentVariableW(homedirW, ui->usri1_home_dir,home_dir_sz);
- ui->usri1_comment[0] = 0;
- ui->usri1_flags = 0;
- ui->usri1_script_path[0] = 0;
- break;
- }
- case 2:
- case 3:
- case 4:
- case 11:
- case 20:
- case 23:
- case 1003:
- case 1005:
- case 1006:
- case 1007:
- case 1008:
- case 1009:
- case 1010:
- case 1011:
- case 1012:
- case 1013:
- case 1014:
- case 1017:
- case 1018:
- case 1020:
- case 1023:
- case 1024:
- case 1025:
- case 1051:
- case 1052:
- case 1053:
- {
- FIXME("Level %ld is not implemented\n", level);
- break;
- }
- default:
- ERR("Invalid level %ld is specified\n", level);
- return ERROR_INVALID_LEVEL;
- }
- return NERR_Success;
-}
-
-
-
-/************************************************************
- * NetUserEnum (NETAPI32.@)
- */
-NET_API_STATUS WINAPI
-NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
- DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
- LPDWORD resume_handle)
-{
- FIXME("stub!\n");
- return ERROR_ACCESS_DENIED;
-}
-
-/************************************************************
- * ACCESS_QueryAdminDisplayInformation
- *
- * Creates a buffer with information for the Admin User
- */
-void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
-{
- const WCHAR sAdminUserName[] = {
- 'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
-
- /* sizes of the field buffers in WCHARS */
- int name_sz, comment_sz, full_name_sz;
- PNET_DISPLAY_USER usr;
-
- /* set up buffer */
- name_sz = lstrlenW(sAdminUserName);
- comment_sz = 1;
- full_name_sz = 1;
-
- *pdwSize = sizeof(NET_DISPLAY_USER);
- *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
- NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
-
- usr = *buf;
- usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
- usr->usri1_comment = (LPWSTR) (
- ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
- usr->usri1_full_name = (LPWSTR) (
- ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
-
- /* set data */
- lstrcpyW(usr->usri1_name, sAdminUserName);
- usr->usri1_comment[0] = 0;
- usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
- usr->usri1_full_name[0] = 0;
- usr->usri1_user_id = 500;
- usr->usri1_next_index = 0;
-}
-
-/************************************************************
- * ACCESS_QueryGuestDisplayInformation
- *
- * Creates a buffer with information for the Guest User
- */
-void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
-{
- const WCHAR sGuestUserName[] = {
- 'G','u','e','s','t',0 };
-
- /* sizes of the field buffers in WCHARS */
- int name_sz, comment_sz, full_name_sz;
- PNET_DISPLAY_USER usr;
-
- /* set up buffer */
- name_sz = lstrlenW(sGuestUserName);
- comment_sz = 1;
- full_name_sz = 1;
-
- *pdwSize = sizeof(NET_DISPLAY_USER);
- *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
- NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
-
- usr = *buf;
- usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
- usr->usri1_comment = (LPWSTR) (
- ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
- usr->usri1_full_name = (LPWSTR) (
- ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
-
- /* set data */
- lstrcpyW(usr->usri1_name, sGuestUserName);
- usr->usri1_comment[0] = 0;
- usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
- UF_DONT_EXPIRE_PASSWD;
- usr->usri1_full_name[0] = 0;
- usr->usri1_user_id = 500;
- usr->usri1_next_index = 0;
-}
-
-/************************************************************
- * NetQueryDisplayInformation (NETAPI32.@)
- * Copies NET_DISPLAY_USER record.
- */
-void ACCESS_CopyDisplayUser(PNET_DISPLAY_USER dest, LPWSTR *dest_buf,
- PNET_DISPLAY_USER src)
-{
- LPWSTR str = *dest_buf;
-
- src->usri1_name = str;
- lstrcpyW(src->usri1_name, dest->usri1_name);
- str = (LPWSTR) (
- ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
-
- src->usri1_comment = str;
- lstrcpyW(src->usri1_comment, dest->usri1_comment);
- str = (LPWSTR) (
- ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
-
- src->usri1_flags = dest->usri1_flags;
-
- src->usri1_full_name = str;
- lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
- str = (LPWSTR) (
- ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
-
- src->usri1_user_id = dest->usri1_user_id;
- src->usri1_next_index = dest->usri1_next_index;
- *dest_buf = str;
-}
-
-/************************************************************
- * NetQueryDisplayInformation (NETAPI32.@)
- *
- * The buffer structure:
- * - array of fixed size record of the level type
- * - strings, referenced by the record of the level type
- */
-NET_API_STATUS WINAPI
-NetQueryDisplayInformation(
- LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
- DWORD PreferredMaximumLength, PDWORD ReturnedEntryCount,
- PVOID *SortedBuffer)
-{
- TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName),
- Level, Index, EntriesRequested, PreferredMaximumLength,
- ReturnedEntryCount, SortedBuffer);
- NETAPI_ForceLocalComputer(ServerName, ERROR_ACCESS_DENIED);
- switch (Level)
- {
- case 1:
- {
- /* current record */
- PNET_DISPLAY_USER inf;
- /* current available strings buffer */
- LPWSTR str;
- PNET_DISPLAY_USER admin, guest;
- DWORD admin_size, guest_size;
- LPWSTR name = NULL;
- DWORD dwSize;
-
- /* sizes of the field buffers in WCHARS */
- int name_sz, comment_sz, full_name_sz;
-
- /* number of the records, returned in SortedBuffer
- 3 - for current user, Administrator and Guest users
- */
- int records = 3;
-
- FIXME("Level %ld partially implemented\n", Level);
- *ReturnedEntryCount = records;
- comment_sz = 1;
- full_name_sz = 1;
-
- /* get data */
- dwSize = UNLEN + 1;
- NetApiBufferAllocate(dwSize, (LPVOID *) &name);
- if (!GetUserNameW(name, &dwSize))
- {
- NetApiBufferFree(name);
- return ERROR_ACCESS_DENIED;
- }
- name_sz = dwSize;
- ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
- ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
-
- /* set up buffer */
- dwSize = sizeof(NET_DISPLAY_USER) * records;
- dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
-
- NetApiBufferAllocate(dwSize +
- admin_size - sizeof(NET_DISPLAY_USER) +
- guest_size - sizeof(NET_DISPLAY_USER),
- (LPVOID *) SortedBuffer);
- inf = (PNET_DISPLAY_USER) *SortedBuffer;
- str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
- inf->usri1_name = str;
- str = (LPWSTR) (
- ((PBYTE) str) + name_sz * sizeof(WCHAR));
- inf->usri1_comment = str;
- str = (LPWSTR) (
- ((PBYTE) str) + comment_sz * sizeof(WCHAR));
- inf->usri1_full_name = str;
- str = (LPWSTR) (
- ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
-
- /* set data */
- lstrcpyW(inf->usri1_name, name);
- NetApiBufferFree(name);
- inf->usri1_comment[0] = 0;
- inf->usri1_flags =
- UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
- inf->usri1_full_name[0] = 0;
- inf->usri1_user_id = 0;
- inf->usri1_next_index = 0;
-
- inf++;
- ACCESS_CopyDisplayUser(admin, &str, inf);
- NetApiBufferFree(admin);
-
- inf++;
- ACCESS_CopyDisplayUser(guest, &str, inf);
- NetApiBufferFree(guest);
- break;
- }
-
- case 2:
- case 3:
- {
- FIXME("Level %ld is not implemented\n", Level);
- break;
- }
-
- default:
- ERR("Invalid level %ld is specified\n", Level);
- return ERROR_INVALID_LEVEL;
- }
- return NERR_Success;
-}
-
-/************************************************************
- * NetGetDCName (NETAPI32.@)
- *
- * Return the name of the primary domain controller (PDC)
- */
-
-NET_API_STATUS WINAPI
-NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
-{
- FIXME("stub!\n");
- return NERR_DCNotFound; /* say we can't find a domain controller */
-}
-
-
-/************************************************************
- * NetUserModalsGet (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetUserModalsGet(LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
-{
- FIXME("%s %ld %p\n", debugstr_w( szServer ), level, pbuffer );
- return NERR_InternalError;
-}
-
-NET_API_STATUS WINAPI NetLocalGroupAdd( LPCWSTR servername, DWORD level,
- LPBYTE buf, LPDWORD parm_err)
-{
- FIXME("%s %ld %p %p\n", debugstr_w( servername ), level, buf, parm_err);
- return NERR_Success;
-}
-
-NET_API_STATUS WINAPI NetLocalGroupSetMembers( LPCWSTR servername,
- LPCWSTR groupname, DWORD level, LPBYTE buf, DWORD totalentries)
-{
- FIXME("%s %s %ld %p %ld\n", debugstr_w(servername), debugstr_w(groupname),
- level, buf, totalentries);
- return NERR_Success;
-}
+++ /dev/null
-/*
- * Copyright 2002 Andriy Palamarchuk
- *
- * Net API buffer calls
- *
- * 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 <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "lmcons.h"
-#include "lmapibuf.h"
-#include "lmerr.h"
-#include "winerror.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-
-extern inline DWORD WINAPI GetLastError(void);
-extern inline DWORD WINAPI GetLastError(void)
-{
- DWORD ret;
- __asm__ __volatile__( ".byte 0x64\n\tmovl 0x34,%0" : "=r" (ret) );
- return ret;
-}
-
-/************************************************************
- * NetApiBufferAllocate (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
-{
- TRACE("(%ld, %p)\n", ByteCount, Buffer);
- *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
- if (*Buffer)
- return NERR_Success;
- else
- return GetLastError();
-}
-
-/************************************************************
- * NetApiBufferFree (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
-{
- TRACE("(%p)\n", Buffer);
- HeapFree(GetProcessHeap(), 0, Buffer);
- return NERR_Success;
-}
-
-/************************************************************
- * NetApiBufferReallocate (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
- LPVOID* NewBuffer)
-{
- TRACE("(%p, %ld, %p)\n", OldBuffer, NewByteCount, NewBuffer);
- if (NewByteCount)
- {
- *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
- return *NewBuffer ? NERR_Success : GetLastError();
- }
- else
- {
- if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
- *NewBuffer = 0;
- return NERR_Success;
- }
-}
-
-/************************************************************
- * NetApiBufferSize (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
-{
- DWORD dw;
-
- TRACE("(%p, %p)\n", Buffer, ByteCount);
- if (Buffer == NULL)
- return ERROR_INVALID_PARAMETER;
- dw = HeapSize(GetProcessHeap(), 0, Buffer);
- TRACE("size: %ld\n", dw);
- if (dw != 0xFFFFFFFF)
- *ByteCount = dw;
- else
- *ByteCount = 0;
-
- return NERR_Success;
-}
+++ /dev/null
-/*
- * Copyright 2002 Andriy Palamarchuk
- *
- * netapi32 browser functions
- *
- * 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 <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "winerror.h"
-#include "lmcons.h"
-#include "lmbrowsr.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-
-/************************************************************
- * I_BrowserSetNetlogonState (NETAPI32.@)
- */
-NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
- LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
- DWORD Role)
-{
- return ERROR_NOT_SUPPORTED;
-}
-
-/************************************************************
- * I_BrowserQueryEmulatedDomains (NETAPI32.@)
- */
-NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(LPWSTR ServerName,PBYTE* blah,PDWORD EntriesRead)
-//NET_API_STATUS I_BrowserQueryEmulatedDomains(
-// LPWSTR ServerName, PBYTE *EmulatedDomains
-// PDWORD EntriesRead)
-{
- return ERROR_NOT_SUPPORTED;
-}
-
-/************************************************************
- * NetShareEnum (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetShareEnum( LPWSTR servername, DWORD level, LPBYTE* bufptr,
- DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
-{
- FIXME("%s %ld %p %ld %p %p %p\n", debugstr_w(servername), level, bufptr,
- prefmaxlen, entriesread, totalentries, resume_handle);
- return ERROR_NOT_SUPPORTED;
-}
+++ /dev/null
-/* 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_reserve)
-#define NEXT_PTR(ncb) (PNCB *)((ncb)->ncb_reserve + 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);
- }
-}
+++ /dev/null
-/* 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__ */
+++ /dev/null
-/* 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 "config.h"
-#include "wine/port.h"
-#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);
- }
-}
+++ /dev/null
-/* 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 <stdarg.h>
-
-#include "windef.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 */
+++ /dev/null
-/* 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
- *
- * I am heavily indebted to Chris Hertel's excellent Implementing CIFS,
- * http://ubiqx.org/cifs/ , for whatever understanding I have of NBT.
- * I also stole from Mike McCormack's smb.c and netapi32.c, although little of
- * that code remains.
- * Lack of understanding and bugs are my fault.
- *
- * FIXME:
- * - Of the NetBIOS session functions, only client functions are supported, and
- * it's likely they'll be the only functions supported. NBT requires session
- * servers to listen on TCP/139. This requires root privilege, and Samba is
- * likely to be listening here already. This further restricts NetBIOS
- * applications, both explicit users and implicit ones: CreateNamedPipe
- * won't actually create a listening pipe, for example, so applications can't
- * act as RPC servers using a named pipe protocol binding, DCOM won't be able
- * to support callbacks or servers over the named pipe protocol, etc.
- *
- * - Datagram support is omitted for the same reason. To send a NetBIOS
- * datagram, you must include the NetBIOS name by which your application is
- * known. This requires you to have registered the name previously, and be
- * able to act as a NetBIOS datagram server (listening on UDP/138).
- *
- * - Name registration functions are omitted for the same reason--registering a
- * name requires you to be able to defend it, and this means listening on
- * UDP/137.
- * Win98 requires you either use your computer's NetBIOS name (with the NULL
- * suffix byte) as the calling name when creating a session, or to register
- * a new name before creating one: it disallows '*' as the calling name.
- * Win2K initially starts with an empty name table, and doesn't allow you to
- * use the machine's NetBIOS name (with the NULL suffix byte) as the calling
- * name. Although it allows sessions to be created with '*' as the calling
- * name, doing so results in timeouts for all receives, because the
- * application never gets them.
- * So, a well-behaved Netbios application will typically want to register a
- * name. I should probably support a do-nothing name list that allows
- * NCBADDNAME to add to it, but doesn't actually register the name, or does
- * attempt to register it without being able to defend it.
- *
- * - Name lookups may not behave quite as you'd expect/like if you have
- * multiple LANAs. If a name is resolvable through DNS, or if you're using
- * WINS, it'll resolve on _any_ LANA. So, a Call will succeed on any LANA as
- * well.
- * I'm not sure how Windows behaves in this case. I could try to force
- * lookups to the correct adapter by using one of the GetPreferred*
- * functions, but with the possibility of multiple adapters in the same
- * same subnet, there's no guarantee that what IpHlpApi thinks is the
- * preferred adapter will actually be a LANA. (It's highly probable because
- * this is an unusual configuration, but not guaranteed.)
- *
- * See also other FIXMEs in the code.
- */
-
-#include <ctype.h>
-#include "config.h"
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "winsock2.h"
-#include "wine/debug.h"
-#include "winreg.h"
-#include "iphlpapi.h"
-
-#include "netbios.h"
-#include "nbnamecache.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netbios);
-
-#define PORT_NBNS 137
-#define PORT_NBDG 138
-#define PORT_NBSS 139
-
-#ifndef INADDR_NONE
-#define INADDR_NONE ~0UL
-#endif
-
-#define NBR_ADDWORD(p,word) (*(WORD *)(p)) = htons(word)
-#define NBR_GETWORD(p) ntohs(*(WORD *)(p))
-
-#define MIN_QUERIES 1
-#define MAX_QUERIES 0xffff
-#define MIN_QUERY_TIMEOUT 100
-#define MAX_QUERY_TIMEOUT 0xffffffff
-#define BCAST_QUERIES 3
-#define BCAST_QUERY_TIMEOUT 750
-#define WINS_QUERIES 3
-#define WINS_QUERY_TIMEOUT 750
-#define MAX_WINS_SERVERS 2
-#define MIN_CACHE_TIMEOUT 60000
-#define CACHE_TIMEOUT 360000
-
-#define MAX_NBT_NAME_SZ (NCBNAMSZ * 2 + MAX_DOMAIN_NAME_LEN + 2)
-#define SIMPLE_NAME_QUERY_PKT_SIZE 26 + MAX_NBT_NAME_SZ
-
-#define DEFAULT_NBT_SESSIONS 16
-
-#define NBNS_TYPE_NB 0x0020
-#define NBNS_TYPE_NBSTAT 0x0021
-#define NBNS_CLASS_INTERNET 0x00001
-#define NBNS_HEADER_SIZE (sizeof(WORD) * 6)
-#define NBNS_RESPONSE_AND_OPCODE 0xf800
-#define NBNS_RESPONSE_AND_QUERY 0x8000
-#define NBNS_REPLYCODE 0x0f
-
-#define NBSS_HDRSIZE 4
-
-#define NBSS_MSG 0x00
-#define NBSS_REQ 0x81
-#define NBSS_ACK 0x82
-#define NBSS_NACK 0x83
-#define NBSS_RETARGET 0x84
-#define NBSS_KEEPALIVE 0x85
-
-#define NBSS_ERR_NOT_LISTENING_ON_NAME 0x80
-#define NBSS_ERR_NOT_LISTENING_FOR_CALLER 0x81
-#define NBSS_ERR_BAD_NAME 0x82
-#define NBSS_ERR_INSUFFICIENT_RESOURCES 0x83
-
-#define NBSS_EXTENSION 0x01
-
-typedef struct _NetBTSession
-{
- CRITICAL_SECTION cs;
- SOCKET fd;
- DWORD bytesPending;
-} NetBTSession;
-
-typedef struct _NetBTAdapter
-{
- MIB_IPADDRROW ipr;
- WORD nameQueryXID;
- struct NBNameCache *nameCache;
- DWORD xmit_success;
- DWORD recv_success;
-} NetBTAdapter;
-
-static ULONG gTransportID;
-static BOOL gEnableDNS;
-static DWORD gBCastQueries;
-static DWORD gBCastQueryTimeout;
-static DWORD gWINSQueries;
-static DWORD gWINSQueryTimeout;
-static DWORD gWINSServers[MAX_WINS_SERVERS];
-static int gNumWINSServers;
-static char gScopeID[MAX_DOMAIN_NAME_LEN];
-static DWORD gCacheTimeout;
-static struct NBNameCache *gNameCache;
-
-/* Converts from a NetBIOS name into a Second Level Encoding-formatted name.
- * Assumes p is not NULL and is either NULL terminated or has at most NCBNAMSZ
- * bytes, and buffer has at least MAX_NBT_NAME_SZ bytes. Pads with space bytes
- * if p is NULL-terminated. Returns the number of bytes stored in buffer.
- */
-static int NetBTNameEncode(const UCHAR *p, UCHAR *buffer)
-{
- int i,len=0;
-
- if (!p) return 0;
- if (!buffer) return 0;
-
- buffer[len++] = NCBNAMSZ * 2;
- for (i = 0; p[i] && i < NCBNAMSZ; i++)
- {
- buffer[len++] = ((p[i] & 0xf0) >> 4) + 'A';
- buffer[len++] = (p[i] & 0x0f) + 'A';
- }
- while (len < NCBNAMSZ * 2)
- {
- buffer[len++] = 'C';
- buffer[len++] = 'A';
- }
- if (*gScopeID)
- {
- int scopeIDLen = strlen(gScopeID);
-
- memcpy(buffer + len, gScopeID, scopeIDLen);
- len += scopeIDLen;
- }
- buffer[len++] = 0; /* add second terminator */
- return len;
-}
-
-/* Creates a NBT name request packet for name in buffer. If broadcast is true,
- * creates a broadcast request, otherwise creates a unicast request.
- * Returns the number of bytes stored in buffer.
- */
-static DWORD NetBTNameReq(const UCHAR name[NCBNAMSZ], WORD xid, WORD qtype,
- BOOL broadcast, UCHAR *buffer, int len)
-{
- int i = 0;
-
- if (len < SIMPLE_NAME_QUERY_PKT_SIZE) return 0;
-
- NBR_ADDWORD(&buffer[i],xid); i+=2; /* transaction */
- if (broadcast)
- {
- NBR_ADDWORD(&buffer[i],0x0110); /* flags: r=req,op=query,rd=1,b=1 */
- i+=2;
- }
- else
- {
- NBR_ADDWORD(&buffer[i],0x0100); /* flags: r=req,op=query,rd=1,b=0 */
- i+=2;
- }
- NBR_ADDWORD(&buffer[i],0x0001); i+=2; /* one name query */
- NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero answers */
- NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero authorities */
- NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero additional */
-
- i += NetBTNameEncode(name, &buffer[i]);
-
- NBR_ADDWORD(&buffer[i],qtype); i+=2;
- NBR_ADDWORD(&buffer[i],NBNS_CLASS_INTERNET); i+=2;
-
- return i;
-}
-
-/* Sends a name query request for name on fd to destAddr. Sets SO_BROADCAST on
- * fd if broadcast is TRUE. Assumes fd is not INVALID_SOCKET, and name is not
- * NULL.
- * Returns 0 on success, -1 on failure.
- */
-static int NetBTSendNameQuery(SOCKET fd, const UCHAR name[NCBNAMSZ], WORD xid,
- WORD qtype, DWORD destAddr, BOOL broadcast)
-{
- int ret = 0, on = 1;
- struct in_addr addr;
-
- addr.s_addr = destAddr;
- TRACE("name %s, dest addr %s\n", name, inet_ntoa(addr));
-
- if (broadcast)
- ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (PUCHAR)&on, sizeof(on));
- if(ret == 0)
- {
- WSABUF wsaBuf;
- UCHAR buf[SIMPLE_NAME_QUERY_PKT_SIZE];
- struct sockaddr_in sin;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_addr.s_addr = destAddr;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(PORT_NBNS);
-
- wsaBuf.buf = buf;
- wsaBuf.len = NetBTNameReq(name, xid, qtype, broadcast, buf,
- sizeof(buf));
- if (wsaBuf.len > 0)
- {
- DWORD bytesSent;
-
- ret = WSASendTo(fd, &wsaBuf, 1, &bytesSent, 0,
- (struct sockaddr*)&sin, sizeof(sin), NULL, NULL);
- if (ret < 0 || bytesSent < wsaBuf.len)
- ret = -1;
- else
- ret = 0;
- }
- else
- ret = -1;
- }
- return ret;
-}
-
-typedef BOOL (*NetBTAnswerCallback)(void *data, WORD answerCount,
- WORD answerIndex, PUCHAR rData, WORD rdLength);
-
-/* Waits on fd until GetTickCount() returns a value greater than or equal to
- * waitUntil for a name service response. If a name response matching xid
- * is received, calls answerCallback once for each answer resource record in
- * the response. (The callback's answerCount will be the total number of
- * answers to expect, and answerIndex will be the 0-based index that's being
- * sent this time.) Quits parsing if answerCallback returns FALSE.
- * Returns NRC_GOODRET on timeout or a valid response received, something else
- * on error.
- */
-static UCHAR NetBTWaitForNameResponse(NetBTAdapter *adapter, SOCKET fd,
- DWORD waitUntil, NetBTAnswerCallback answerCallback, void *data)
-{
- BOOL found = FALSE;
- DWORD now;
- UCHAR ret = NRC_GOODRET;
-
- if (!adapter) return NRC_BADDR;
- if (fd == INVALID_SOCKET) return NRC_BADDR;
- if (!answerCallback) return NRC_BADDR;
-
- while (!found && ret == NRC_GOODRET && (now = GetTickCount()) < waitUntil)
- {
- DWORD msToWait = waitUntil - now;
- struct fd_set fds;
- struct timeval timeout = { msToWait / 1000, msToWait % 1000 };
- int r;
-
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- r = select(fd + 1, &fds, NULL, NULL, &timeout);
- if (r < 0)
- ret = NRC_SYSTEM;
- else if (r == 1)
- {
- /* FIXME: magic #, is this always enough? */
- UCHAR buffer[256];
- int fromsize;
- struct sockaddr_in fromaddr;
- WORD respXID, flags, queryCount, answerCount;
- WSABUF wsaBuf = { sizeof(buffer), buffer };
- DWORD bytesReceived, recvFlags = 0;
-
- fromsize = sizeof(fromaddr);
- r = WSARecvFrom(fd, &wsaBuf, 1, &bytesReceived, &recvFlags,
- (struct sockaddr*)&fromaddr, &fromsize, NULL, NULL);
- if(r < 0)
- {
- ret = NRC_SYSTEM;
- break;
- }
-
- if (bytesReceived < NBNS_HEADER_SIZE)
- continue;
-
- respXID = NBR_GETWORD(buffer);
- if (adapter->nameQueryXID != respXID)
- continue;
-
- flags = NBR_GETWORD(buffer + 2);
- queryCount = NBR_GETWORD(buffer + 4);
- answerCount = NBR_GETWORD(buffer + 6);
-
- /* a reply shouldn't contain a query, ignore bad packet */
- if (queryCount > 0)
- continue;
-
- if ((flags & NBNS_RESPONSE_AND_OPCODE) == NBNS_RESPONSE_AND_QUERY)
- {
- if ((flags & NBNS_REPLYCODE) != 0)
- ret = NRC_NAMERR;
- else if ((flags & NBNS_REPLYCODE) == 0 && answerCount > 0)
- {
- PUCHAR ptr = buffer + NBNS_HEADER_SIZE;
- BOOL shouldContinue = TRUE;
- WORD answerIndex = 0;
-
- found = TRUE;
- /* decode one answer at a time */
- while (ret == NRC_GOODRET && answerIndex < answerCount &&
- ptr - buffer < bytesReceived && shouldContinue)
- {
- WORD rLen;
-
- /* scan past name */
- for (; ptr[0] && ptr - buffer < bytesReceived; )
- ptr += ptr[0] + 1;
- ptr++;
- ptr += 2; /* scan past type */
- if (ptr - buffer < bytesReceived && ret == NRC_GOODRET
- && NBR_GETWORD(ptr) == NBNS_CLASS_INTERNET)
- ptr += sizeof(WORD);
- else
- ret = NRC_SYSTEM; /* parse error */
- ptr += sizeof(DWORD); /* TTL */
- rLen = NBR_GETWORD(ptr);
- rLen = min(rLen, bytesReceived - (ptr - buffer));
- ptr += sizeof(WORD);
- shouldContinue = answerCallback(data, answerCount,
- answerIndex, ptr, rLen);
- ptr += rLen;
- answerIndex++;
- }
- }
- }
- }
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-typedef struct _NetBTNameQueryData {
- NBNameCacheEntry *cacheEntry;
- UCHAR ret;
-} NetBTNameQueryData;
-
-/* Name query callback function for NetBTWaitForNameResponse, creates a cache
- * entry on the first answer, adds each address as it's called again (as long
- * as there's space). If there's an error that should be propagated as the
- * NetBIOS error, modifies queryData's ret member to the proper return code.
- */
-static BOOL NetBTFindNameAnswerCallback(void *pVoid, WORD answerCount,
- WORD answerIndex, PUCHAR rData, WORD rLen)
-{
- NetBTNameQueryData *queryData = (NetBTNameQueryData *)pVoid;
- BOOL ret;
-
- if (queryData)
- {
- if (queryData->cacheEntry == NULL)
- {
- queryData->cacheEntry = (NBNameCacheEntry *)HeapAlloc(
- GetProcessHeap(), 0, sizeof(NBNameCacheEntry) +
- (answerCount - 1) * sizeof(DWORD));
- if (queryData->cacheEntry)
- queryData->cacheEntry->numAddresses = 0;
- else
- {
- ret = FALSE;
- queryData->ret = NRC_OSRESNOTAV;
- }
- }
- if (rLen == 6 && queryData->cacheEntry &&
- queryData->cacheEntry->numAddresses < answerCount)
- {
- queryData->cacheEntry->addresses[queryData->cacheEntry->
- numAddresses++] = *(PDWORD)(rData + 2);
- ret = queryData->cacheEntry->numAddresses < answerCount;
- }
- else
- ret = FALSE;
- }
- else
- ret = FALSE;
- return ret;
-}
-
-/* Workhorse NetBT name lookup function. Sends a name lookup query for
- * ncb->ncb_callname to sendTo, as a broadcast if broadcast is TRUE, using
- * adapter->nameQueryXID as the transaction ID. Waits up to timeout
- * milliseconds, and retries up to maxQueries times, waiting for a reply.
- * If a valid response is received, stores the looked up addresses as a
- * NBNameCacheEntry in *cacheEntry.
- * Returns NRC_GOODRET on success, though this may not mean the name was
- * resolved--check whether *cacheEntry is NULL.
- */
-static UCHAR NetBTNameWaitLoop(NetBTAdapter *adapter, SOCKET fd, PNCB ncb,
- DWORD sendTo, BOOL broadcast, DWORD timeout, DWORD maxQueries,
- NBNameCacheEntry **cacheEntry)
-{
- int queries;
- NetBTNameQueryData queryData;
-
- if (!adapter) return NRC_BADDR;
- if (fd == INVALID_SOCKET) return NRC_BADDR;
- if (!ncb) return NRC_BADDR;
- if (!cacheEntry) return NRC_BADDR;
-
- queryData.cacheEntry = NULL;
- queryData.ret = NRC_GOODRET;
- for (queries = 0; queryData.cacheEntry == NULL && queries < maxQueries;
- queries++)
- {
- if (!NCB_CANCELLED(ncb))
- {
- int r = NetBTSendNameQuery(fd, ncb->ncb_callname,
- adapter->nameQueryXID, NBNS_TYPE_NB, sendTo, broadcast);
-
- if (r == 0)
- queryData.ret = NetBTWaitForNameResponse(adapter, fd,
- GetTickCount() + timeout, NetBTFindNameAnswerCallback,
- &queryData);
- else
- queryData.ret = NRC_SYSTEM;
- }
- else
- queryData.ret = NRC_CMDCAN;
- }
- if (queryData.cacheEntry)
- {
- memcpy(queryData.cacheEntry->name, ncb->ncb_callname, NCBNAMSZ);
- memcpy(queryData.cacheEntry->nbname, ncb->ncb_callname, NCBNAMSZ);
- }
- *cacheEntry = queryData.cacheEntry;
- return queryData.ret;
-}
-
-/* Attempts to add cacheEntry to the name cache in *nameCache; if *nameCache
- * has not yet been created, creates it, using gCacheTimeout as the cache
- * entry timeout. If memory allocation fails, or if NBNameCacheAddEntry fails,
- * frees cacheEntry.
- * Returns NRC_GOODRET on success, and something else on failure.
- */
-static UCHAR NetBTStoreCacheEntry(struct NBNameCache **nameCache,
- NBNameCacheEntry *cacheEntry)
-{
- UCHAR ret;
-
- if (!nameCache) return NRC_BADDR;
- if (!cacheEntry) return NRC_BADDR;
-
- if (!*nameCache)
- *nameCache = NBNameCacheCreate(GetProcessHeap(), gCacheTimeout);
- if (*nameCache)
- ret = NBNameCacheAddEntry(*nameCache, cacheEntry)
- ? NRC_GOODRET : NRC_OSRESNOTAV;
- else
- {
- HeapFree(GetProcessHeap(), 0, cacheEntry);
- ret = NRC_OSRESNOTAV;
- }
- return ret;
-}
-
-/* Attempts to resolve name using inet_addr(), then gethostbyname() if
- * gEnableDNS is TRUE, if the suffix byte is either <00> or <20>. If the name
- * can be looked up, returns 0 and stores the looked up addresses as a
- * NBNameCacheEntry in *cacheEntry.
- * Returns NRC_GOODRET on success, though this may not mean the name was
- * resolved--check whether *cacheEntry is NULL. Returns something else on
- * error.
- */
-static UCHAR NetBTinetResolve(const UCHAR name[NCBNAMSZ],
- NBNameCacheEntry **cacheEntry)
-{
- UCHAR ret = NRC_GOODRET;
-
- TRACE("name %s, cacheEntry %p\n", name, cacheEntry);
-
- if (!name) return NRC_BADDR;
- if (!cacheEntry) return NRC_BADDR;
-
- if (isalnum(name[0]) && (name[NCBNAMSZ - 1] == 0 ||
- name[NCBNAMSZ - 1] == 0x20))
- {
- UCHAR toLookup[NCBNAMSZ];
- int i;
-
- for (i = 0; i < NCBNAMSZ - 1 && name[i] && name[i] != ' '; i++)
- toLookup[i] = name[i];
- toLookup[i] = '\0';
-
- if (isdigit(toLookup[0]))
- {
- unsigned long addr = inet_addr(toLookup);
-
- if (addr != INADDR_NONE)
- {
- *cacheEntry = (NBNameCacheEntry *)HeapAlloc(GetProcessHeap(),
- 0, sizeof(NBNameCacheEntry));
- if (*cacheEntry)
- {
- memcpy((*cacheEntry)->name, name, NCBNAMSZ);
- memset((*cacheEntry)->nbname, 0, NCBNAMSZ);
- (*cacheEntry)->nbname[0] = '*';
- (*cacheEntry)->numAddresses = 1;
- (*cacheEntry)->addresses[0] = addr;
- }
- else
- ret = NRC_OSRESNOTAV;
- }
- }
- if (gEnableDNS && ret == NRC_GOODRET && !*cacheEntry)
- {
- struct hostent *host;
-
- if ((host = gethostbyname(toLookup)) != NULL)
- {
- for (i = 0; ret == NRC_GOODRET && host->h_addr_list &&
- host->h_addr_list[i]; i++)
- ;
- if (host->h_addr_list && host->h_addr_list[0])
- {
- *cacheEntry = (NBNameCacheEntry *)HeapAlloc(
- GetProcessHeap(), 0, sizeof(NBNameCacheEntry) +
- (i - 1) * sizeof(DWORD));
- if (*cacheEntry)
- {
- memcpy((*cacheEntry)->name, name, NCBNAMSZ);
- memset((*cacheEntry)->nbname, 0, NCBNAMSZ);
- (*cacheEntry)->nbname[0] = '*';
- (*cacheEntry)->numAddresses = i;
- for (i = 0; i < (*cacheEntry)->numAddresses; i++)
- (*cacheEntry)->addresses[i] =
- (DWORD)host->h_addr_list[i];
- }
- else
- ret = NRC_OSRESNOTAV;
- }
- }
- }
- }
-
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-/* Looks up the name in ncb->ncb_callname, first in the name caches (global
- * and this adapter's), then using gethostbyname(), next by WINS if configured,
- * and finally using broadcast NetBT name resolution. In NBT parlance, this
- * makes this an "H-node". Stores an entry in the appropriate name cache for a
- * found node, and returns it as *cacheEntry.
- * Assumes data, ncb, and cacheEntry are not NULL.
- * Returns NRC_GOODRET on success--which doesn't mean the name was resolved,
- * just that all name lookup operations completed successfully--and something
- * else on failure. *cacheEntry will be NULL if the name was not found.
- */
-static UCHAR NetBTInternalFindName(NetBTAdapter *adapter, PNCB ncb,
- const NBNameCacheEntry **cacheEntry)
-{
- UCHAR ret = NRC_GOODRET;
-
- TRACE("adapter %p, ncb %p, cacheEntry %p\n", adapter, ncb, cacheEntry);
-
- if (!cacheEntry) return NRC_BADDR;
- *cacheEntry = NULL;
-
- if (!adapter) return NRC_BADDR;
- if (!ncb) return NRC_BADDR;
-
- if (ncb->ncb_callname[0] == '*')
- ret = NRC_NOWILD;
- else
- {
- *cacheEntry = NBNameCacheFindEntry(gNameCache, ncb->ncb_callname);
- if (!*cacheEntry)
- *cacheEntry = NBNameCacheFindEntry(adapter->nameCache,
- ncb->ncb_callname);
- if (!*cacheEntry)
- {
- NBNameCacheEntry *newEntry = NULL;
-
- ret = NetBTinetResolve(ncb->ncb_callname, &newEntry);
- if (ret == NRC_GOODRET && newEntry)
- {
- ret = NetBTStoreCacheEntry(&gNameCache, newEntry);
- if (ret != NRC_GOODRET)
- newEntry = NULL;
- }
- else
- {
- SOCKET fd = WSASocketA(PF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL,
- 0, WSA_FLAG_OVERLAPPED);
-
- if(fd == INVALID_SOCKET)
- ret = NRC_OSRESNOTAV;
- else
- {
- int winsNdx;
-
- adapter->nameQueryXID++;
- for (winsNdx = 0; ret == NRC_GOODRET && *cacheEntry == NULL
- && winsNdx < gNumWINSServers; winsNdx++)
- ret = NetBTNameWaitLoop(adapter, fd, ncb,
- gWINSServers[winsNdx], FALSE, gWINSQueryTimeout,
- gWINSQueries, &newEntry);
- if (ret == NRC_GOODRET && newEntry)
- {
- ret = NetBTStoreCacheEntry(&gNameCache, newEntry);
- if (ret != NRC_GOODRET)
- newEntry = NULL;
- }
- if (ret == NRC_GOODRET && *cacheEntry == NULL)
- {
- DWORD bcastAddr =
- adapter->ipr.dwAddr & adapter->ipr.dwMask;
-
- if (adapter->ipr.dwBCastAddr)
- bcastAddr |= ~adapter->ipr.dwMask;
- ret = NetBTNameWaitLoop(adapter, fd, ncb, bcastAddr,
- TRUE, gBCastQueryTimeout, gBCastQueries, &newEntry);
- if (ret == NRC_GOODRET && newEntry)
- {
- ret = NetBTStoreCacheEntry(&adapter->nameCache,
- newEntry);
- if (ret != NRC_GOODRET)
- newEntry = NULL;
- }
- }
- closesocket(fd);
- }
- }
- *cacheEntry = newEntry;
- }
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-typedef struct _NetBTNodeQueryData
-{
- BOOL gotResponse;
- PADAPTER_STATUS astat;
- WORD astatLen;
-} NetBTNodeQueryData;
-
-/* Callback function for NetBTAstatRemote, parses the rData for the node
- * status and name list of the remote node. Always returns FALSE, since
- * there's never more than one answer we care about in a node status response.
- */
-static BOOL NetBTNodeStatusAnswerCallback(void *pVoid, WORD answerCount,
- WORD answerIndex, PUCHAR rData, WORD rLen)
-{
- NetBTNodeQueryData *data = (NetBTNodeQueryData *)pVoid;
-
- if (data && !data->gotResponse && rData && rLen >= 1)
- {
- /* num names is first byte; each name is NCBNAMSZ + 2 bytes */
- if (rLen >= rData[0] * (NCBNAMSZ + 2))
- {
- WORD i;
- PUCHAR src;
- PNAME_BUFFER dst;
-
- data->gotResponse = TRUE;
- data->astat->name_count = rData[0];
- for (i = 0, src = rData + 1,
- dst = (PNAME_BUFFER)((PUCHAR)data->astat +
- sizeof(ADAPTER_STATUS));
- i < data->astat->name_count && src - rData < rLen &&
- (PUCHAR)dst - (PUCHAR)data->astat < data->astatLen;
- i++, dst++, src += NCBNAMSZ + 2)
- {
- UCHAR flags = *(src + NCBNAMSZ);
-
- memcpy(dst->name, src, NCBNAMSZ);
- /* we won't actually see a registering name in the returned
- * response. It's useful to see if no other flags are set; if
- * none are, then the name is registered. */
- dst->name_flags = REGISTERING;
- if (flags & 0x80)
- dst->name_flags |= GROUP_NAME;
- if (flags & 0x10)
- dst->name_flags |= DEREGISTERED;
- if (flags & 0x08)
- dst->name_flags |= DUPLICATE;
- if (dst->name_flags == REGISTERING)
- dst->name_flags = REGISTERED;
- }
- /* arbitrarily set HW type to Ethernet */
- data->astat->adapter_type = 0xfe;
- if (src - rData < rLen)
- memcpy(data->astat->adapter_address, src,
- min(rLen - (src - rData), 6));
- }
- }
- return FALSE;
-}
-
-/* This uses the WINS timeout and query values, as they're the
- * UCAST_REQ_RETRY_TIMEOUT and UCAST_REQ_RETRY_COUNT according to the RFCs.
- */
-static UCHAR NetBTAstatRemote(NetBTAdapter *adapter, PNCB ncb)
-{
- UCHAR ret = NRC_GOODRET;
- const NBNameCacheEntry *cacheEntry = NULL;
-
- TRACE("adapter %p, NCB %p\n", adapter, ncb);
-
- if (!adapter) return NRC_BADDR;
- if (!ncb) return NRC_INVADDRESS;
-
- ret = NetBTInternalFindName(adapter, ncb, &cacheEntry);
- if (ret == NRC_GOODRET && cacheEntry)
- {
- if (cacheEntry->numAddresses > 0)
- {
- SOCKET fd = WSASocketA(PF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
- WSA_FLAG_OVERLAPPED);
-
- if(fd == INVALID_SOCKET)
- ret = NRC_OSRESNOTAV;
- else
- {
- NetBTNodeQueryData queryData;
- DWORD queries;
- PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer;
-
- adapter->nameQueryXID++;
- astat->name_count = 0;
- queryData.gotResponse = FALSE;
- queryData.astat = astat;
- queryData.astatLen = ncb->ncb_length;
- for (queries = 0; !queryData.gotResponse &&
- queries < gWINSQueries; queries++)
- {
- if (!NCB_CANCELLED(ncb))
- {
- int r = NetBTSendNameQuery(fd, ncb->ncb_callname,
- adapter->nameQueryXID, NBNS_TYPE_NBSTAT,
- cacheEntry->addresses[0], FALSE);
-
- if (r == 0)
- ret = NetBTWaitForNameResponse(adapter, fd,
- GetTickCount() + gWINSQueryTimeout,
- NetBTNodeStatusAnswerCallback, &queryData);
- else
- ret = NRC_SYSTEM;
- }
- else
- ret = NRC_CMDCAN;
- }
- closesocket(fd);
- }
- }
- else
- ret = NRC_CMDTMO;
- }
- else if (ret == NRC_CMDCAN)
- ; /* do nothing, we were cancelled */
- else
- ret = NRC_CMDTMO;
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR NetBTAstat(void *adapt, PNCB ncb)
-{
- NetBTAdapter *adapter = (NetBTAdapter *)adapt;
- UCHAR ret;
-
- TRACE("adapt %p, NCB %p\n", adapt, ncb);
-
- if (!adapter) return NRC_ENVNOTDEF;
- if (!ncb) return NRC_INVADDRESS;
- if (!ncb->ncb_buffer) return NRC_BADDR;
- if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN;
-
- if (ncb->ncb_callname[0] == '*')
- {
- DWORD physAddrLen;
- MIB_IFROW ifRow;
- PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer;
-
- memset(astat, 0, sizeof(ADAPTER_STATUS));
- astat->rev_major = 3;
- ifRow.dwIndex = adapter->ipr.dwIndex;
- if (GetIfEntry(&ifRow) != NO_ERROR)
- ret = NRC_BRIDGE;
- else
- {
- physAddrLen = min(ifRow.dwPhysAddrLen, 6);
- if (physAddrLen > 0)
- memcpy(astat->adapter_address, ifRow.bPhysAddr, physAddrLen);
- /* doubt anyone cares, but why not.. */
- if (ifRow.dwType == MIB_IF_TYPE_TOKENRING)
- astat->adapter_type = 0xff;
- else
- astat->adapter_type = 0xfe; /* for Ethernet */
- astat->max_sess_pkt_size = 0xffff;
- astat->xmit_success = adapter->xmit_success;
- astat->recv_success = adapter->recv_success;
- }
- ret = NRC_GOODRET;
- }
- else
- ret = NetBTAstatRemote(adapter, ncb);
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR NetBTFindName(void *adapt, PNCB ncb)
-{
- NetBTAdapter *adapter = (NetBTAdapter *)adapt;
- UCHAR ret;
- const NBNameCacheEntry *cacheEntry = NULL;
- PFIND_NAME_HEADER foundName;
-
- TRACE("adapt %p, NCB %p\n", adapt, ncb);
-
- if (!adapter) return NRC_ENVNOTDEF;
- if (!ncb) return NRC_INVADDRESS;
- if (!ncb->ncb_buffer) return NRC_BADDR;
- if (ncb->ncb_length < sizeof(FIND_NAME_HEADER)) return NRC_BUFLEN;
-
- foundName = (PFIND_NAME_HEADER)ncb->ncb_buffer;
- memset(foundName, 0, sizeof(FIND_NAME_HEADER));
-
- ret = NetBTInternalFindName(adapter, ncb, &cacheEntry);
- if (ret == NRC_GOODRET)
- {
- if (cacheEntry)
- {
- DWORD spaceFor = min((ncb->ncb_length - sizeof(FIND_NAME_HEADER)) /
- sizeof(FIND_NAME_BUFFER), cacheEntry->numAddresses);
- DWORD ndx;
-
- for (ndx = 0; ndx < spaceFor; ndx++)
- {
- PFIND_NAME_BUFFER findNameBuffer;
-
- findNameBuffer =
- (PFIND_NAME_BUFFER)((PUCHAR)foundName +
- sizeof(FIND_NAME_HEADER) + foundName->node_count *
- sizeof(FIND_NAME_BUFFER));
- memset(findNameBuffer->destination_addr, 0, 2);
- memcpy(findNameBuffer->destination_addr + 2,
- &adapter->ipr.dwAddr, sizeof(DWORD));
- memset(findNameBuffer->source_addr, 0, 2);
- memcpy(findNameBuffer->source_addr + 2,
- &cacheEntry->addresses[ndx], sizeof(DWORD));
- foundName->node_count++;
- }
- if (spaceFor < cacheEntry->numAddresses)
- ret = NRC_BUFLEN;
- }
- else
- ret = NRC_CMDTMO;
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR NetBTSessionReq(SOCKET fd, const UCHAR *calledName,
- const UCHAR *callingName)
-{
- UCHAR buffer[NBSS_HDRSIZE + MAX_DOMAIN_NAME_LEN * 2], ret;
- int len = 0, r;
- DWORD bytesSent, bytesReceived, recvFlags = 0;
- WSABUF wsaBuf;
-
- buffer[0] = NBSS_REQ;
- buffer[1] = 0;
-
- len += NetBTNameEncode(calledName, &buffer[NBSS_HDRSIZE]);
- len += NetBTNameEncode(callingName, &buffer[NBSS_HDRSIZE + len]);
-
- NBR_ADDWORD(&buffer[2], len);
-
- wsaBuf.len = len + NBSS_HDRSIZE;
- wsaBuf.buf = buffer;
-
- r = WSASend(fd, &wsaBuf, 1, &bytesSent, 0, NULL, NULL);
- if(r < 0 || bytesSent < len + NBSS_HDRSIZE)
- {
- ERR("send failed\n");
- return NRC_SABORT;
- }
-
- /* I've already set the recv timeout on this socket (if it supports it), so
- * just block. Hopefully we'll always receive the session acknowledgement
- * within one timeout.
- */
- wsaBuf.len = NBSS_HDRSIZE + 1;
- r = WSARecv(fd, &wsaBuf, 1, &bytesReceived, &recvFlags, NULL, NULL);
- if (r < 0 || bytesReceived < NBSS_HDRSIZE)
- ret = NRC_SABORT;
- else if (buffer[0] == NBSS_NACK)
- {
- if (r == NBSS_HDRSIZE + 1)
- {
- switch (buffer[NBSS_HDRSIZE])
- {
- case NBSS_ERR_INSUFFICIENT_RESOURCES:
- ret = NRC_REMTFUL;
- break;
- default:
- ret = NRC_NOCALL;
- }
- }
- else
- ret = NRC_NOCALL;
- }
- else if (buffer[0] == NBSS_RETARGET)
- {
- FIXME("Got a session retarget, can't deal\n");
- ret = NRC_NOCALL;
- }
- else if (buffer[0] == NBSS_ACK)
- ret = NRC_GOODRET;
- else
- ret = NRC_SYSTEM;
-
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR NetBTCall(void *adapt, PNCB ncb, void **sess)
-{
- NetBTAdapter *adapter = (NetBTAdapter *)adapt;
- UCHAR ret;
- const NBNameCacheEntry *cacheEntry = NULL;
-
- TRACE("adapt %p, ncb %p\n", adapt, ncb);
-
- if (!adapter) return NRC_ENVNOTDEF;
- if (!ncb) return NRC_INVADDRESS;
- if (!sess) return NRC_BADDR;
-
- ret = NetBTInternalFindName(adapter, ncb, &cacheEntry);
- if (ret == NRC_GOODRET)
- {
- if (cacheEntry && cacheEntry->numAddresses > 0)
- {
- SOCKET fd;
-
- fd = WSASocketA(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
- WSA_FLAG_OVERLAPPED);
- if (fd != INVALID_SOCKET)
- {
- DWORD timeout;
- struct sockaddr_in sin;
-
- if (ncb->ncb_rto > 0)
- {
- timeout = ncb->ncb_rto * 500;
- setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (PUCHAR)&timeout,
- sizeof(timeout));
- }
- if (ncb->ncb_rto > 0)
- {
- timeout = ncb->ncb_sto * 500;
- setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (PUCHAR)&timeout,
- sizeof(timeout));
- }
-
- memset(&sin, 0, sizeof(sin));
- memcpy(&sin.sin_addr, &cacheEntry->addresses[0],
- sizeof(sin.sin_addr));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(PORT_NBSS);
- /* FIXME: use nonblocking mode for the socket, check the
- * cancel flag periodically
- */
- if (connect(fd, (struct sockaddr *)&sin, sizeof(sin))
- == SOCKET_ERROR)
- ret = NRC_CMDTMO;
- else
- {
- static UCHAR fakedCalledName[] = "*SMBSERVER";
- const UCHAR *calledParty = cacheEntry->nbname[0] == '*'
- ? fakedCalledName : cacheEntry->nbname;
-
- ret = NetBTSessionReq(fd, calledParty, ncb->ncb_name);
- if (ret != NRC_GOODRET && calledParty[0] == '*')
- {
- FIXME("NBT session to \"*SMBSERVER\" refused,\n");
- FIXME("should try finding name using ASTAT\n");
- }
- }
- if (ret != NRC_GOODRET)
- closesocket(fd);
- else
- {
- NetBTSession *session = (NetBTSession *)HeapAlloc(
- GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NetBTSession));
-
- if (session)
- {
- session->fd = fd;
- InitializeCriticalSection(&session->cs);
- *sess = session;
- }
- else
- {
- ret = NRC_OSRESNOTAV;
- closesocket(fd);
- }
- }
- }
- else
- ret = NRC_OSRESNOTAV;
- }
- else
- ret = NRC_NAMERR;
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-/* Notice that I don't protect against multiple thread access to NetBTSend.
- * This is because I don't update any data in the adapter, and I only make a
- * single call to WSASend, which I assume to act atomically (not interleaving
- * data from other threads).
- * I don't lock, because I only depend on the fd being valid, and this won't be
- * true until a session setup is completed.
- */
-static UCHAR NetBTSend(void *adapt, void *sess, PNCB ncb)
-{
- NetBTAdapter *adapter = (NetBTAdapter *)adapt;
- NetBTSession *session = (NetBTSession *)sess;
- UCHAR buffer[NBSS_HDRSIZE], ret;
- int r;
- WSABUF wsaBufs[2];
- DWORD bytesSent;
-
- TRACE("adapt %p, session %p, NCB %p\n", adapt, session, ncb);
-
- if (!adapter) return NRC_ENVNOTDEF;
- if (!ncb) return NRC_INVADDRESS;
- if (!ncb->ncb_buffer) return NRC_BADDR;
- if (!session) return NRC_SNUMOUT;
- if (session->fd == INVALID_SOCKET) return NRC_SNUMOUT;
-
- buffer[0] = NBSS_MSG;
- buffer[1] = 0;
- NBR_ADDWORD(&buffer[2], ncb->ncb_length);
-
- wsaBufs[0].len = NBSS_HDRSIZE;
- wsaBufs[0].buf = buffer;
- wsaBufs[1].len = ncb->ncb_length;
- wsaBufs[1].buf = ncb->ncb_buffer;
-
- r = WSASend(session->fd, wsaBufs, sizeof(wsaBufs) / sizeof(wsaBufs[0]),
- &bytesSent, 0, NULL, NULL);
- if (r == SOCKET_ERROR)
- {
- NetBIOSHangupSession(ncb);
- ret = NRC_SABORT;
- }
- else if (bytesSent < NBSS_HDRSIZE + ncb->ncb_length)
- {
- FIXME("Only sent %ld bytes (of %d), hanging up session\n", bytesSent,
- NBSS_HDRSIZE + ncb->ncb_length);
- NetBIOSHangupSession(ncb);
- ret = NRC_SABORT;
- }
- else
- {
- ret = NRC_GOODRET;
- adapter->xmit_success++;
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR NetBTRecv(void *adapt, void *sess, PNCB ncb)
-{
- NetBTAdapter *adapter = (NetBTAdapter *)adapt;
- NetBTSession *session = (NetBTSession *)sess;
- UCHAR buffer[NBSS_HDRSIZE], ret;
- int r;
- WSABUF wsaBufs[2];
- DWORD bufferCount, bytesReceived, flags;
-
- TRACE("adapt %p, session %p, NCB %p\n", adapt, session, ncb);
-
- if (!adapter) return NRC_ENVNOTDEF;
- if (!ncb) return NRC_BADDR;
- if (!ncb->ncb_buffer) return NRC_BADDR;
- if (!session) return NRC_SNUMOUT;
- if (session->fd == INVALID_SOCKET) return NRC_SNUMOUT;
-
- EnterCriticalSection(&session->cs);
- bufferCount = 0;
- if (session->bytesPending == 0)
- {
- bufferCount++;
- wsaBufs[0].len = NBSS_HDRSIZE;
- wsaBufs[0].buf = buffer;
- }
- wsaBufs[bufferCount].len = ncb->ncb_length;
- wsaBufs[bufferCount].buf = ncb->ncb_buffer;
- bufferCount++;
-
- flags = 0;
- /* FIXME: should poll a bit so I can check the cancel flag */
- r = WSARecv(session->fd, wsaBufs, bufferCount, &bytesReceived, &flags,
- NULL, NULL);
- if (r == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
- {
- LeaveCriticalSection(&session->cs);
- ERR("Receive error, WSAGetLastError() returns %d\n", WSAGetLastError());
- NetBIOSHangupSession(ncb);
- ret = NRC_SABORT;
- }
- else if (NCB_CANCELLED(ncb))
- {
- LeaveCriticalSection(&session->cs);
- ret = NRC_CMDCAN;
- }
- else
- {
- if (bufferCount == 2)
- {
- if (buffer[0] == NBSS_KEEPALIVE)
- {
- LeaveCriticalSection(&session->cs);
- FIXME("Oops, received a session keepalive and lost my place\n");
- /* need to read another session header until we get a session
- * message header. */
- NetBIOSHangupSession(ncb);
- ret = NRC_SABORT;
- }
- else if (buffer[0] != NBSS_MSG)
- {
- LeaveCriticalSection(&session->cs);
- FIXME("Received unexpected session msg type %d\n", buffer[0]);
- NetBIOSHangupSession(ncb);
- ret = NRC_SABORT;
- }
- else
- {
- if (buffer[1] & NBSS_EXTENSION)
- {
- LeaveCriticalSection(&session->cs);
- FIXME("Received a message that's too long for my taste\n");
- NetBIOSHangupSession(ncb);
- ret = NRC_SABORT;
- }
- else
- {
- session->bytesPending = NBSS_HDRSIZE
- + NBR_GETWORD(&buffer[2]) - bytesReceived;
- ncb->ncb_length = bytesReceived - NBSS_HDRSIZE;
- LeaveCriticalSection(&session->cs);
- }
- }
- }
- else
- {
- if (bytesReceived < session->bytesPending)
- session->bytesPending -= bytesReceived;
- else
- session->bytesPending = 0;
- LeaveCriticalSection(&session->cs);
- ncb->ncb_length = bytesReceived;
- }
- if (session->bytesPending > 0)
- ret = NRC_INCOMP;
- else
- {
- ret = NRC_GOODRET;
- adapter->recv_success++;
- }
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR NetBTHangup(void *adapt, void *sess)
-{
- NetBTSession *session = (NetBTSession *)sess;
-
- TRACE("adapt %p, session %p\n", adapt, session);
-
- if (!session) return NRC_SNUMOUT;
-
- /* I don't lock the session, because NetBTRecv knows not to decrement
- * past 0, so if a receive completes after this it should still deal.
- */
- closesocket(session->fd);
- session->fd = INVALID_SOCKET;
- session->bytesPending = 0;
- DeleteCriticalSection(&session->cs);
- HeapFree(GetProcessHeap(), 0, session);
-
- return NRC_GOODRET;
-}
-
-static void NetBTCleanupAdapter(void *adapt)
-{
- TRACE("adapt %p\n", adapt);
- if (adapt)
- {
- NetBTAdapter *adapter = (NetBTAdapter *)adapt;
-
- if (adapter->nameCache)
- NBNameCacheDestroy(adapter->nameCache);
- HeapFree(GetProcessHeap(), 0, adapt);
- }
-}
-
-static void NetBTCleanup(void)
-{
- TRACE("\n");
- if (gNameCache)
- {
- NBNameCacheDestroy(gNameCache);
- gNameCache = NULL;
- }
-}
-
-static UCHAR NetBTRegisterAdapter(PMIB_IPADDRROW ipRow)
-{
- UCHAR ret;
- NetBTAdapter *adapter;
-
- if (!ipRow) return NRC_BADDR;
-
- adapter = (NetBTAdapter *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(NetBTAdapter));
- if (adapter)
- {
- memcpy(&adapter->ipr, ipRow, sizeof(MIB_IPADDRROW));
- if (!NetBIOSRegisterAdapter(gTransportID, ipRow->dwIndex, adapter))
- {
- NetBTCleanupAdapter(adapter);
- ret = NRC_SYSTEM;
- }
- else
- ret = NRC_GOODRET;
- }
- else
- ret = NRC_OSRESNOTAV;
- return ret;
-}
-
-/* Callback for NetBIOS adapter enumeration. Assumes closure is a pointer to
- * a MIB_IPADDRTABLE containing all the IP adapters needed to be added to the
- * NetBIOS adapter table. For each callback, checks if the passed-in adapt
- * has an entry in the table; if so, this adapter was enumerated previously,
- * and it's enabled. As a flag, the table's dwAddr entry is changed to
- * INADDR_LOOPBACK, since this is an invalid address for a NetBT adapter.
- * The NetBTEnum function will add any remaining adapters from the
- * MIB_IPADDRTABLE to the NetBIOS adapter table.
- */
-static BOOL NetBTEnumCallback(UCHAR totalLANAs, UCHAR lanaIndex,
- ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
-{
- BOOL ret;
- PMIB_IPADDRTABLE table = (PMIB_IPADDRTABLE)closure;
-
- if (table && data)
- {
- DWORD ndx;
-
- ret = FALSE;
- for (ndx = 0; !ret && ndx < table->dwNumEntries; ndx++)
- {
- const NetBTAdapter *adapter = (const NetBTAdapter *)data->data;
-
- if (table->table[ndx].dwIndex == adapter->ipr.dwIndex)
- {
- NetBIOSEnableAdapter(data->lana);
- table->table[ndx].dwAddr = INADDR_LOOPBACK;
- ret = TRUE;
- }
- }
- }
- else
- ret = FALSE;
- return ret;
-}
-
-/* Enumerates adapters by:
- * - retrieving the IP address table for the local machine
- * - eliminating loopback addresses from the table
- * - eliminating redundant addresses, that is, multiple addresses on the same
- * subnet
- * Calls NetBIOSEnumAdapters, passing the resulting table as the callback
- * data. The callback reenables each adapter that's already in the NetBIOS
- * table. After NetBIOSEnumAdapters returns, this function adds any remaining
- * adapters to the NetBIOS table.
- */
-static UCHAR NetBTEnum(void)
-{
- UCHAR ret;
- DWORD size = 0;
-
- TRACE("\n");
-
- if (GetIpAddrTable(NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER)
- {
- PMIB_IPADDRTABLE ipAddrs, coalesceTable = NULL;
- DWORD numIPAddrs = (size - sizeof(MIB_IPADDRTABLE)) /
- sizeof(MIB_IPADDRROW) + 1;
-
- ipAddrs = (PMIB_IPADDRTABLE)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, size);
- if (ipAddrs)
- coalesceTable = (PMIB_IPADDRTABLE)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, sizeof(MIB_IPADDRTABLE) +
- (min(numIPAddrs, MAX_LANA + 1) - 1) * sizeof(MIB_IPADDRROW));
- if (ipAddrs && coalesceTable)
- {
- if (GetIpAddrTable(ipAddrs, &size, FALSE) == ERROR_SUCCESS)
- {
- DWORD ndx;
-
- for (ndx = 0; ndx < ipAddrs->dwNumEntries; ndx++)
- {
- if ((ipAddrs->table[ndx].dwAddr &
- ipAddrs->table[ndx].dwMask) !=
- htonl((INADDR_LOOPBACK & IN_CLASSA_NET)))
- {
- BOOL newNetwork = TRUE;
- DWORD innerIndex;
-
- /* make sure we don't have more than one entry
- * for a subnet */
- for (innerIndex = 0; newNetwork &&
- innerIndex < coalesceTable->dwNumEntries; innerIndex++)
- if ((ipAddrs->table[ndx].dwAddr &
- ipAddrs->table[ndx].dwMask) ==
- (coalesceTable->table[innerIndex].dwAddr
- & coalesceTable->table[innerIndex].dwMask))
- newNetwork = FALSE;
-
- if (newNetwork)
- memcpy(&coalesceTable->table[
- coalesceTable->dwNumEntries++],
- &ipAddrs->table[ndx], sizeof(MIB_IPADDRROW));
- }
- }
-
- NetBIOSEnumAdapters(gTransportID, NetBTEnumCallback,
- coalesceTable);
- ret = NRC_GOODRET;
- for (ndx = 0; ret == NRC_GOODRET &&
- ndx < coalesceTable->dwNumEntries; ndx++)
- if (coalesceTable->table[ndx].dwAddr != INADDR_LOOPBACK)
- ret = NetBTRegisterAdapter(&coalesceTable->table[ndx]);
- }
- else
- ret = NRC_SYSTEM;
- HeapFree(GetProcessHeap(), 0, ipAddrs);
- HeapFree(GetProcessHeap(), 0, coalesceTable);
- }
- else
- ret = NRC_OSRESNOTAV;
- }
- else
- ret = NRC_SYSTEM;
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-/* Initializes global variables and registers the NetBT transport */
-void NetBTInit(void)
-{
- HKEY hKey;
- NetBIOSTransport transport;
- LONG ret;
-
- TRACE("\n");
-
- gEnableDNS = TRUE;
- gBCastQueries = BCAST_QUERIES;
- gBCastQueryTimeout = BCAST_QUERY_TIMEOUT;
- gWINSQueries = WINS_QUERIES;
- gWINSQueryTimeout = WINS_QUERY_TIMEOUT;
- gNumWINSServers = 0;
- memset(gWINSServers, 0, sizeof(gWINSServers));
- gScopeID[0] = '\0';
- gCacheTimeout = CACHE_TIMEOUT;
-
- /* Try to open the Win9x NetBT configuration key */
- ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
- /* If that fails, try the WinNT NetBT configuration key */
- if (ret != ERROR_SUCCESS)
- ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0,
- KEY_READ, &hKey);
- if (ret == ERROR_SUCCESS)
- {
- DWORD dword, size;
-
- size = sizeof(dword);
- if (RegQueryValueExA(hKey, "EnableDNS", NULL, NULL,
- (LPBYTE)&dword, &size) == ERROR_SUCCESS)
- gEnableDNS = dword;
- size = sizeof(dword);
- if (RegQueryValueExA(hKey, "BcastNameQueryCount", NULL, NULL,
- (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES
- && dword <= MAX_QUERIES)
- gBCastQueries = dword;
- size = sizeof(dword);
- if (RegQueryValueExA(hKey, "BcastNameQueryTimeout", NULL, NULL,
- (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT
- && dword <= MAX_QUERY_TIMEOUT)
- gBCastQueryTimeout = dword;
- size = sizeof(dword);
- if (RegQueryValueExA(hKey, "NameSrvQueryCount", NULL, NULL,
- (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES
- && dword <= MAX_QUERIES)
- gWINSQueries = dword;
- size = sizeof(dword);
- if (RegQueryValueExA(hKey, "NameSrvQueryTimeout", NULL, NULL,
- (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT
- && dword <= MAX_QUERY_TIMEOUT)
- gWINSQueryTimeout = dword;
- size = MAX_DOMAIN_NAME_LEN - 1;
- if (RegQueryValueExA(hKey, "ScopeID", NULL, NULL, gScopeID + 1, &size)
- == ERROR_SUCCESS)
- {
- /* convert into L2-encoded version, suitable for use by
- NetBTNameEncode */
- char *ptr, *lenPtr;
-
- for (ptr = gScopeID + 1; *ptr &&
- ptr - gScopeID < MAX_DOMAIN_NAME_LEN; )
- {
- for (lenPtr = ptr - 1, *lenPtr = 0; *ptr && *ptr != '.' &&
- ptr - gScopeID < MAX_DOMAIN_NAME_LEN; ptr++)
- *lenPtr += 1;
- ptr++;
- }
- }
- if (RegQueryValueExA(hKey, "CacheTimeout", NULL, NULL,
- (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_CACHE_TIMEOUT)
- gCacheTimeout = dword;
- RegCloseKey(hKey);
- }
- /* WINE-specific NetBT registry settings. Because our adapter naming is
- * different than MS', we can't do per-adapter WINS configuration in the
- * same place. Just do a global WINS configuration instead.
- */
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ, &hKey)
- == ERROR_SUCCESS)
- {
- static const char *nsValueNames[] = { "WinsServer", "BackupWinsServer" };
- char nsString[16];
- DWORD size, ndx;
-
- for (ndx = 0; ndx < sizeof(nsValueNames) / sizeof(nsValueNames[0]);
- ndx++)
- {
- size = sizeof(nsString) / sizeof(char);
- if (RegQueryValueExA(hKey, nsValueNames[ndx], NULL, NULL,
- (LPBYTE)nsString, &size) == ERROR_SUCCESS)
- {
- unsigned long addr = inet_addr(nsString);
-
- if (addr != INADDR_NONE && gNumWINSServers < MAX_WINS_SERVERS)
- gWINSServers[gNumWINSServers++] = addr;
- }
- }
- RegCloseKey(hKey);
- }
-
- transport.enumerate = NetBTEnum;
- transport.astat = NetBTAstat;
- transport.findName = NetBTFindName;
- transport.call = NetBTCall;
- transport.send = NetBTSend;
- transport.recv = NetBTRecv;
- transport.hangup = NetBTHangup;
- transport.cleanupAdapter = NetBTCleanupAdapter;
- transport.cleanup = NetBTCleanup;
- memcpy(&gTransportID, TRANSPORT_NBT, sizeof(ULONG));
- NetBIOSRegisterTransport(gTransportID, &transport);
-}
+++ /dev/null
-/* 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
- * 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 "netbios.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netbios);
-
-HMODULE NETAPI32_hModule = 0;
-
-BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
-
- switch (fdwReason) {
- case DLL_PROCESS_ATTACH:
- {
- DisableThreadLibraryCalls(hinstDLL);
- NETAPI32_hModule = hinstDLL;
- NetBIOSInit();
- NetBTInit();
- break;
- }
- case DLL_PROCESS_DETACH:
- {
- NetBIOSShutdown();
- break;
- }
- }
-
- return TRUE;
-}
-
-NET_API_STATUS WINAPI NetServerEnum(
- LPCWSTR servername,
- DWORD level,
- LPBYTE* bufptr,
- DWORD prefmaxlen,
- LPDWORD entriesread,
- LPDWORD totalentries,
- DWORD servertype,
- LPCWSTR domain,
- LPDWORD resume_handle
-)
-{
- FIXME("Stub (%p, %ld %p %ld %p %p %ld %s %p)\n",servername, level, bufptr,
- prefmaxlen, entriesread, totalentries, servertype, debugstr_w(domain), resume_handle);
-
- return ERROR_NO_BROWSER_SERVERS_FOUND;
-}
-
-NET_API_STATUS WINAPI
-NetServerGetInfo(LPWSTR servername, DWORD level, LPBYTE* bufptr)
-{
- FIXME("stub (%p, %ld, %p)\n", servername, level, bufptr);
- return ERROR_ACCESS_DENIED;
-}
-
-
-/************************************************************
- * NetStatisticsGet (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetStatisticsGet(LPWSTR server, LPWSTR service,
- DWORD level, DWORD options,
- PBYTE *bufptr)
-{
- TRACE("(%p, %p, %ld, %ld, %p)\n", server, service, level, options, bufptr);
- return NERR_InternalError;
-}
+++ /dev/null
-/* $Id$ */
-
-#define REACTOS_VERSION_DLL
-#define REACTOS_STR_FILE_DESCRIPTION "NetApi DLL\0"
-#define REACTOS_STR_INTERNAL_NAME "netapi32\0"
-#define REACTOS_STR_ORIGINAL_FILENAME "netapi32.dll\0"
-#include <reactos/version.rc>
+++ /dev/null
-@ stub I_BrowserDebugCall
-@ stub I_BrowserDebugTrace
-@ stdcall I_BrowserQueryEmulatedDomains(wstr ptr ptr)
-@ stub I_BrowserQueryOtherDomains
-@ stub I_BrowserQueryStatistics
-@ stub I_BrowserResetNetlogonState
-@ stub I_BrowserResetStatistics
-@ stub I_BrowserServerEnum
-@ stdcall I_BrowserSetNetlogonState(wstr wstr wstr long)
-@ stub I_NetAccountDeltas
-@ stub I_NetAccountSync
-@ stub I_NetDatabaseDeltas
-@ stub I_NetDatabaseRedo
-@ stub I_NetDatabaseSync
-@ stub I_NetDatabaseSync2
-@ stub I_NetDfsCreateExitPoint
-@ stub I_NetDfsCreateLocalPartition
-@ stub I_NetDfsDeleteExitPoint
-@ stub I_NetDfsDeleteLocalPartition
-@ stub I_NetDfsFixLocalVolume
-@ stub I_NetDfsGetVersion
-@ stub I_NetDfsIsThisADomainName
-@ stub I_NetDfsModifyPrefix
-@ stub I_NetDfsSetLocalVolumeState
-@ stub I_NetDfsSetServerInfo
-@ stub I_NetGetDCList
-@ stub I_NetListCanonicalize
-@ stub I_NetListTraverse
-@ stub I_NetLogonControl
-@ stub I_NetLogonControl2
-@ stub I_NetLogonSamLogoff
-@ stub I_NetLogonSamLogon
-@ stub I_NetLogonUasLogoff
-@ stub I_NetLogonUasLogon
-@ stub I_NetNameCanonicalize
-@ stub I_NetNameCompare
-@ stub I_NetNameValidate
-@ stub I_NetPathCanonicalize
-@ stub I_NetPathCompare
-@ stub I_NetPathType
-@ stub I_NetServerAuthenticate
-@ stub I_NetServerAuthenticate2
-@ stub I_NetServerPasswordSet
-@ stub I_NetServerReqChallenge
-@ stub I_NetServerSetServiceBits
-@ stub I_NetServerSetServiceBitsEx
-@ stub NetAlertRaise
-@ stub NetAlertRaiseEx
-@ stdcall NetApiBufferAllocate(long ptr)
-@ stdcall NetApiBufferFree(ptr)
-@ stdcall NetApiBufferReallocate(ptr long ptr)
-@ stdcall NetApiBufferSize(ptr ptr)
-@ stub NetAuditClear
-@ stub NetAuditRead
-@ stub NetAuditWrite
-@ stub NetBrowserStatisticsGet
-@ stub NetConfigGet
-@ stub NetConfigGetAll
-@ stub NetConfigSet
-@ stub NetConnectionEnum
-@ stub NetDfsAdd
-@ stub NetDfsEnum
-@ stub NetDfsGetInfo
-@ stub NetDfsManagerGetConfigInfo
-@ stub NetDfsMove
-@ stub NetDfsRemove
-@ stub NetDfsRename
-@ stub NetDfsSetInfo
-@ stub NetEnumerateTrustedDomains
-@ stub NetErrorLogClear
-@ stub NetErrorLogRead
-@ stub NetErrorLogWrite
-@ stub NetFileClose
-@ stub NetFileEnum
-@ stub NetFileGetInfo
-@ stub NetGetAnyDCName
-@ stdcall NetGetDCName(wstr wstr ptr)
-@ stub NetGetDisplayInformationIndex
-@ stub NetGroupAdd
-@ stub NetGroupAddUser
-@ stub NetGroupDel
-@ stub NetGroupDelUser
-@ stub NetGroupEnum
-@ stub NetGroupGetInfo
-@ stub NetGroupGetUsers
-@ stub NetGroupSetInfo
-@ stub NetGroupSetUsers
-@ stdcall NetLocalGroupAdd(wstr long ptr ptr)
-@ stub NetLocalGroupAddMember
-@ stub NetLocalGroupAddMembers
-@ stub NetLocalGroupDel
-@ stub NetLocalGroupDelMember
-@ stub NetLocalGroupDelMembers
-@ stub NetLocalGroupEnum
-@ stub NetLocalGroupGetInfo
-@ stub NetLocalGroupGetMembers
-@ stub NetLocalGroupSetInfo
-@ stdcall NetLocalGroupSetMembers(wstr wstr long ptr ptr)
-@ stub NetMessageBufferSend
-@ stub NetMessageNameAdd
-@ stub NetMessageNameDel
-@ stub NetMessageNameEnum
-@ stub NetMessageNameGetInfo
-@ stdcall NetQueryDisplayInformation(wstr long long long long ptr ptr)
-@ stub NetRemoteComputerSupports
-@ stub NetRemoteTOD
-@ stub NetReplExportDirAdd
-@ stub NetReplExportDirDel
-@ stub NetReplExportDirEnum
-@ stub NetReplExportDirGetInfo
-@ stub NetReplExportDirLock
-@ stub NetReplExportDirSetInfo
-@ stub NetReplExportDirUnlock
-@ stub NetReplGetInfo
-@ stub NetReplImportDirAdd
-@ stub NetReplImportDirDel
-@ stub NetReplImportDirEnum
-@ stub NetReplImportDirGetInfo
-@ stub NetReplImportDirLock
-@ stub NetReplImportDirUnlock
-@ stub NetReplSetInfo
-@ stub NetRplAdapterAdd
-@ stub NetRplAdapterDel
-@ stub NetRplAdapterEnum
-@ stub NetRplBootAdd
-@ stub NetRplBootDel
-@ stub NetRplBootEnum
-@ stub NetRplClose
-@ stub NetRplConfigAdd
-@ stub NetRplConfigDel
-@ stub NetRplConfigEnum
-@ stub NetRplGetInfo
-@ stub NetRplOpen
-@ stub NetRplProfileAdd
-@ stub NetRplProfileClone
-@ stub NetRplProfileDel
-@ stub NetRplProfileEnum
-@ stub NetRplProfileGetInfo
-@ stub NetRplProfileSetInfo
-@ stub NetRplSetInfo
-@ stub NetRplSetSecurity
-@ stub NetRplVendorAdd
-@ stub NetRplVendorDel
-@ stub NetRplVendorEnum
-@ stub NetRplWkstaAdd
-@ stub NetRplWkstaClone
-@ stub NetRplWkstaDel
-@ stub NetRplWkstaEnum
-@ stub NetRplWkstaGetInfo
-@ stub NetRplWkstaSetInfo
-@ stub NetScheduleJobAdd
-@ stub NetScheduleJobDel
-@ stub NetScheduleJobEnum
-@ stub NetScheduleJobGetInfo
-@ stub NetServerComputerNameAdd
-@ stub NetServerComputerNameDel
-@ stub NetServerDiskEnum
-@ stdcall NetServerEnum(wstr long ptr long ptr ptr long wstr ptr)
-@ stub NetServerEnumEx
-@ stdcall NetServerGetInfo(wstr long ptr)
-@ stub NetServerSetInfo
-@ stub NetServerTransportAdd
-@ stub NetServerTransportAddEx
-@ stub NetServerTransportDel
-@ stub NetServerTransportEnum
-@ stub NetServiceControl
-@ stub NetServiceEnum
-@ stub NetServiceGetInfo
-@ stub NetServiceInstall
-@ stub NetSessionDel
-@ stub NetSessionEnum
-@ stub NetSessionGetInfo
-@ stub NetShareAdd
-@ stub NetShareCheck
-@ stub NetShareDel
-@ stub NetShareDelSticky
-@ stdcall NetShareEnum(wstr long ptr long ptr ptr ptr)
-@ stub NetShareEnumSticky
-@ stub NetShareGetInfo
-@ stub NetShareSetInfo
-@ stdcall NetStatisticsGet(wstr wstr long long ptr)
-@ stub NetUseAdd
-@ stub NetUseDel
-@ stub NetUseEnum
-@ stub NetUseGetInfo
-@ stub NetUserAdd
-@ stub NetUserChangePassword
-@ stub NetUserDel
-@ stdcall NetUserEnum(wstr long long ptr long ptr ptr ptr)
-@ stub NetUserGetGroups
-@ stdcall NetUserGetInfo(wstr wstr long ptr)
-@ stub NetUserGetLocalGroups
-@ stdcall NetUserModalsGet(wstr long ptr)
-@ stub NetUserModalsSet
-@ stub NetUserSetGroups
-@ stub NetUserSetInfo
-@ stdcall NetWkstaGetInfo(wstr long ptr)
-@ stub NetWkstaSetInfo
-@ stub NetWkstaTransportAdd
-@ stub NetWkstaTransportDel
-@ stdcall NetWkstaTransportEnum (wstr long ptr long ptr ptr ptr)
-@ stub NetWkstaUserEnum
-@ stdcall NetWkstaUserGetInfo(wstr long ptr)
-@ stub NetWkstaUserSetInfo
-@ stdcall NetapipBufferAllocate(long ptr) NetApiBufferAllocate
-@ stdcall Netbios(ptr)
-@ stub NetpAccessCheck
-@ stub NetpAccessCheckAndAudit
-@ stub NetpAllocConfigName
-@ stub NetpAllocStrFromStr
-@ stub NetpAllocStrFromWStr
-@ stub NetpAllocTStrFromString
-@ stub NetpAllocWStrFromStr
-@ stub NetpAllocWStrFromWStr
-@ stub NetpApiStatusToNtStatus
-@ stub NetpAssertFailed
-@ stub NetpCloseConfigData
-@ stub NetpCopyStringToBuffer
-@ stub NetpCreateSecurityObject
-@ stub NetpDbgDisplayServerInfo
-@ stub NetpDbgPrint
-@ stdcall NetpDeleteSecurityObject(long) ntdll.RtlDeleteSecurityObject
-@ stdcall NetpGetComputerName(ptr)
-@ stub NetpGetConfigBool
-@ stub NetpGetConfigDword
-@ stub NetpGetConfigTStrArray
-@ stub NetpGetConfigValue
-@ stub NetpGetDomainName
-@ stub NetpGetFileSecurity
-@ stub NetpGetPrivilege
-@ stub NetpHexDump
-@ stdcall NetpInitOemString(ptr str) ntdll.RtlInitAnsiString
-@ stub NetpIsRemote
-@ stub NetpIsUncComputerNameValid
-@ stub NetpLocalTimeZoneOffset
-@ stub NetpLogonPutUnicodeString
-@ stub NetpNetBiosAddName
-@ stub NetpNetBiosCall
-@ stub NetpNetBiosDelName
-@ stub NetpNetBiosGetAdapterNumbers
-@ stub NetpNetBiosHangup
-@ stub NetpNetBiosReceive
-@ stub NetpNetBiosReset
-@ stub NetpNetBiosSend
-@ stub NetpNetBiosStatusToApiStatus
-@ stub NetpNtStatusToApiStatus
-@ stub NetpOpenConfigData
-@ stub NetpPackString
-@ stub NetpReleasePrivilege
-@ stub NetpSetConfigBool
-@ stub NetpSetConfigDword
-@ stub NetpSetConfigTStrArray
-@ stub NetpSetFileSecurity
-@ stub NetpSmbCheck
-@ stub NetpStringToNetBiosName
-@ stub NetpTStrArrayEntryCount
-@ stub NetpwNameCanonicalize
-@ stub NetpwNameCompare
-@ stub NetpwNameValidate
-@ stub NetpwPathCanonicalize
-@ stub NetpwPathCompare
-@ stub NetpwPathType
-@ stub NlBindingAddServerToCache
-@ stub NlBindingRemoveServerFromCache
-@ stub NlBindingSetAuthInfo
-@ stub RxNetAccessAdd
-@ stub RxNetAccessDel
-@ stub RxNetAccessEnum
-@ stub RxNetAccessGetInfo
-@ stub RxNetAccessGetUserPerms
-@ stub RxNetAccessSetInfo
-@ stub RxNetServerEnum
-@ stub RxNetUserPasswordSet
-@ stub RxRemoteApi
+++ /dev/null
-<module name="netapi32" type="win32dll" baseaddress="${BASEADDRESS_NETAPI32}" installbase="system32" installname="netapi32.dll" allowwarnings="true">
- <importlibrary definition="netapi32.spec.def" />
- <include base="netapi32">.</include>
- <include base="ReactOS">include/wine</include>
- <define name="__REACTOS__" />
- <define name="__USE_W32API" />
- <define name="_WIN32_IE">0x600</define>
- <define name="_WIN32_WINNT">0x501</define>
- <define name="WINVER">0x501</define>
- <define name="_SVRAPI_" />
- <library>wine</library>
- <library>ntdll</library>
- <library>kernel32</library>
- <library>advapi32</library>
- <library>ws2_32</library>
- <library>iphlpapi</library>
- <file>access.c</file>
- <file>apibuf.c</file>
- <file>browsr.c</file>
- <file>nbcmdqueue.c</file>
- <file>nbnamecache.c</file>
- <file>nbt.c</file>
- <file>netapi32.c</file>
- <file>netbios.c</file>
- <file>wksta.c</file>
- <file>netapi32.rc</file>
- <file>netapi32.spec</file>
-</module>
+++ /dev/null
-/*
- * Copyright 2002 Andriy Palamarchuk
- *
- * netapi32 internal functions.
- *
- * 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, writ
-e to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __WINE_NETAPI32_MISC_H
-#define __WINE_NETAPI32_MISC_H
-
-extern BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName);
-
-#define NETAPI_ForceLocalComputer(ServerName, FailureCode) \
- if (!NETAPI_IsLocalComputer(ServerName)) \
- { \
- FIXME("Action Implemented for local computer only. " \
- "Requested for server %s\n", debugstr_w(ServerName)); \
- return FailureCode; \
- }
-
-#endif
+++ /dev/null
-/* 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"
-#include "netbios.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netbios);
-
-/* This file provides a NetBIOS emulator that implements the NetBIOS interface,
- * including thread safety and asynchronous call support. The protocol
- * implementation is separate, with blocking (synchronous) functions.
- */
-
-#define ADAPTERS_INCR 8
-#define DEFAULT_NUM_SESSIONS 16
-
-typedef struct _NetBIOSTransportTableEntry
-{
- ULONG id;
- NetBIOSTransport transport;
-} NetBIOSTransportTableEntry;
-
-typedef struct _NetBIOSSession
-{
- BOOL inUse;
- UCHAR state;
- UCHAR local_name[NCBNAMSZ];
- UCHAR remote_name[NCBNAMSZ];
- void *data;
-} NetBIOSSession;
-
-/* This struct needs a little explanation, unfortunately. enabled is only
- * used by nbInternalEnum (see). If transport_id is not 0 and transport
- * is not NULL, the adapter is considered valid. (transport is a pointer to
- * an entry in a NetBIOSTransportTableEntry.) data has data for the callers of
- * NetBIOSEnumAdapters to be able to see. The lana is repeated there, even
- * though I don't use it internally--it's for transports to use reenabling
- * adapters using NetBIOSEnableAdapter.
- */
-typedef struct _NetBIOSAdapter
-{
- BOOL enabled;
- BOOL shuttingDown;
- ULONG resetting;
- ULONG transport_id;
- NetBIOSTransport *transport;
- NetBIOSAdapterImpl impl;
- struct NBCmdQueue *cmdQueue;
- CRITICAL_SECTION cs;
- DWORD sessionsLen;
- NetBIOSSession *sessions;
-} NetBIOSAdapter;
-
-typedef struct _NetBIOSAdapterTable {
- CRITICAL_SECTION cs;
- BOOL enumerated;
- BOOL enumerating;
- UCHAR tableSize;
- NetBIOSAdapter *table;
-} NetBIOSAdapterTable;
-
-/* Just enough space for NBT right now */
-static NetBIOSTransportTableEntry gTransports[1];
-static UCHAR gNumTransports = 0;
-static NetBIOSAdapterTable gNBTable;
-
-static UCHAR nbResizeAdapterTable(UCHAR newSize)
-{
- UCHAR ret;
-
- if (gNBTable.table)
- gNBTable.table = (NetBIOSAdapter *)HeapReAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, gNBTable.table,
- newSize * sizeof(NetBIOSAdapter));
- else
- gNBTable.table = (NetBIOSAdapter *)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, newSize * sizeof(NetBIOSAdapter));
- if (gNBTable.table)
- {
- gNBTable.tableSize = newSize;
- ret = NRC_GOODRET;
- }
- else
- ret = NRC_OSRESNOTAV;
- return ret;
-}
-
-void NetBIOSInit(void)
-{
- memset(&gNBTable, 0, sizeof(gNBTable));
- InitializeCriticalSection(&gNBTable.cs);
-}
-
-void NetBIOSShutdown(void)
-{
- UCHAR i;
-
- EnterCriticalSection(&gNBTable.cs);
- for (i = 0; i < gNBTable.tableSize; i++)
- {
- if (gNBTable.table[i].transport &&
- gNBTable.table[i].transport->cleanupAdapter)
- gNBTable.table[i].transport->cleanupAdapter(
- gNBTable.table[i].impl.data);
- }
- for (i = 0; i < gNumTransports; i++)
- if (gTransports[i].transport.cleanup)
- gTransports[i].transport.cleanup();
- LeaveCriticalSection(&gNBTable.cs);
- DeleteCriticalSection(&gNBTable.cs);
- HeapFree(GetProcessHeap(), 0, gNBTable.table);
-}
-
-BOOL NetBIOSRegisterTransport(ULONG id, NetBIOSTransport *transport)
-{
- BOOL ret;
-
- TRACE(": transport 0x%08lx, p %p\n", id, transport);
- if (!transport)
- ret = FALSE;
- else if (gNumTransports >= sizeof(gTransports) / sizeof(gTransports[0]))
- {
- FIXME("You tried to add %d transports, but I only have space for %d\n",
- gNumTransports + 1, sizeof(gTransports) / sizeof(gTransports[0]));
- ret = FALSE;
- }
- else
- {
- UCHAR i;
-
- ret = FALSE;
- for (i = 0; !ret && i < gNumTransports; i++)
- {
- if (gTransports[i].id == id)
- {
- WARN("Replacing NetBIOS transport ID %ld\n", id);
- memcpy(&gTransports[i].transport, transport,
- sizeof(NetBIOSTransport));
- ret = TRUE;
- }
- }
- if (!ret)
- {
- gTransports[gNumTransports].id = id;
- memcpy(&gTransports[gNumTransports].transport, transport,
- sizeof(NetBIOSTransport));
- gNumTransports++;
- ret = TRUE;
- }
- }
- TRACE("returning %d\n", ret);
- return ret;
-}
-
-/* In this, I acquire the table lock to make sure no one else is modifying it.
- * This is _probably_ overkill since it should only be called during the
- * context of a NetBIOSEnum call, but just to be safe..
- */
-BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *data)
-{
- BOOL ret;
- UCHAR i;
-
- TRACE(": transport 0x%08lx, ifIndex 0x%08lx, data %p\n", transport, ifIndex,
- data);
- for (i = 0; i < gNumTransports && gTransports[i].id != transport; i++)
- ;
- if (gTransports[i].id == transport)
- {
- NetBIOSTransport *transportPtr = &gTransports[i].transport;
-
- TRACE(": found transport %p for id 0x%08lx\n", transportPtr, transport);
-
- EnterCriticalSection(&gNBTable.cs);
- ret = FALSE;
- for (i = 0; i < gNBTable.tableSize &&
- gNBTable.table[i].transport != 0; i++)
- ;
- if (i == gNBTable.tableSize && gNBTable.tableSize < MAX_LANA + 1)
- {
- UCHAR newSize;
-
- if (gNBTable.tableSize < (MAX_LANA + 1) - ADAPTERS_INCR)
- newSize = gNBTable.tableSize + ADAPTERS_INCR;
- else
- newSize = MAX_LANA + 1;
- nbResizeAdapterTable(newSize);
- }
- if (i < gNBTable.tableSize && gNBTable.table[i].transport == 0)
- {
- TRACE(": registering as LANA %d\n", i);
- gNBTable.table[i].transport_id = transport;
- gNBTable.table[i].transport = transportPtr;
- gNBTable.table[i].impl.lana = i;
- gNBTable.table[i].impl.ifIndex = ifIndex;
- gNBTable.table[i].impl.data = data;
- gNBTable.table[i].cmdQueue = NBCmdQueueCreate(GetProcessHeap());
- InitializeCriticalSection(&gNBTable.table[i].cs);
- gNBTable.table[i].enabled = TRUE;
- ret = TRUE;
- }
- LeaveCriticalSection(&gNBTable.cs);
- }
- else
- ret = FALSE;
- TRACE("returning %d\n", ret);
- return ret;
-}
-
-/* In this, I acquire the table lock to make sure no one else is modifying it.
- * This is _probably_ overkill since it should only be called during the
- * context of a NetBIOSEnum call, but just to be safe..
- */
-void NetBIOSEnableAdapter(UCHAR lana)
-{
- TRACE(": %d\n", lana);
- if (lana < gNBTable.tableSize)
- {
- EnterCriticalSection(&gNBTable.cs);
- if (gNBTable.table[lana].transport != 0)
- gNBTable.table[lana].enabled = TRUE;
- LeaveCriticalSection(&gNBTable.cs);
- }
-}
-
-static void nbShutdownAdapter(NetBIOSAdapter *adapter)
-{
- if (adapter)
- {
- adapter->shuttingDown = TRUE;
- NBCmdQueueCancelAll(adapter->cmdQueue);
- if (adapter->transport->cleanupAdapter)
- adapter->transport->cleanupAdapter(adapter->impl.data);
- NBCmdQueueDestroy(adapter->cmdQueue);
- DeleteCriticalSection(&adapter->cs);
- memset(adapter, 0, sizeof(NetBIOSAdapter));
- }
-}
-
-static void nbInternalEnum(void)
-{
- UCHAR i;
-
- EnterCriticalSection(&gNBTable.cs);
- TRACE("before mark\n");
- /* mark: */
- for (i = 0; i < gNBTable.tableSize; i++)
- if (gNBTable.table[i].enabled && gNBTable.table[i].transport != 0)
- gNBTable.table[i].enabled = FALSE;
-
- TRACE("marked, before store, %d transports\n", gNumTransports);
- /* store adapters: */
- for (i = 0; i < gNumTransports; i++)
- if (gTransports[i].transport.enumerate)
- gTransports[i].transport.enumerate();
-
- TRACE("before sweep\n");
- /* sweep: */
- for (i = 0; i < gNBTable.tableSize; i++)
- if (!gNBTable.table[i].enabled && gNBTable.table[i].transport != 0)
- nbShutdownAdapter(&gNBTable.table[i]);
- gNBTable.enumerated = TRUE;
- LeaveCriticalSection(&gNBTable.cs);
-}
-
-UCHAR NetBIOSNumAdapters(void)
-{
- UCHAR ret, i;
-
- if (!gNBTable.enumerated)
- nbInternalEnum();
- for (i = 0, ret = 0; i < gNBTable.tableSize; i++)
- if (gNBTable.table[i].transport != 0)
- ret++;
- return ret;
-}
-
-void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb,
- void *closure)
-{
- TRACE("transport 0x%08lx, callback %p, closure %p\n", transport, cb,
- closure);
- if (cb)
- {
- BOOL enumAll = memcmp(&transport, ALL_TRANSPORTS, sizeof(ULONG)) == 0;
- UCHAR i, numLANAs = 0;
-
- EnterCriticalSection(&gNBTable.cs);
- if (!gNBTable.enumerating)
- {
- gNBTable.enumerating = TRUE;
- nbInternalEnum();
- gNBTable.enumerating = FALSE;
- }
- for (i = 0; i < gNBTable.tableSize; i++)
- if (enumAll || gNBTable.table[i].transport_id == transport)
- numLANAs++;
- if (numLANAs > 0)
- {
- UCHAR lanaIndex = 0;
-
- for (i = 0; i < gNBTable.tableSize; i++)
- if (gNBTable.table[i].transport_id != 0 &&
- (enumAll || gNBTable.table[i].transport_id == transport))
- cb(numLANAs, lanaIndex++, gNBTable.table[i].transport_id,
- &gNBTable.table[i].impl, closure);
- }
- LeaveCriticalSection(&gNBTable.cs);
- }
-}
-
-static NetBIOSAdapter *nbGetAdapter(UCHAR lana)
-{
- NetBIOSAdapter *ret = NULL;
-
- TRACE(": lana %d, num allocated adapters %d\n", lana, gNBTable.tableSize);
- if (lana < gNBTable.tableSize && gNBTable.table[lana].transport_id != 0
- && gNBTable.table[lana].transport)
- ret = &gNBTable.table[lana];
- TRACE("returning %p\n", ret);
- return ret;
-}
-
-static UCHAR nbEnum(PNCB ncb)
-{
- PLANA_ENUM lanas = (PLANA_ENUM)ncb->ncb_buffer;
- UCHAR i, ret;
-
- TRACE(": ncb %p\n", ncb);
-
- if (!lanas)
- ret = NRC_BUFLEN;
- else if (ncb->ncb_length < sizeof(LANA_ENUM))
- ret = NRC_BUFLEN;
- else
- {
- nbInternalEnum();
- lanas->length = 0;
- for (i = 0; i < gNBTable.tableSize; i++)
- if (gNBTable.table[i].transport)
- {
- lanas->length++;
- lanas->lana[i] = i;
- }
- ret = NRC_GOODRET;
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session);
-
-static UCHAR nbCancel(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret;
-
- TRACE(": adapter %p, ncb %p\n", adapter, ncb);
-
- if (!adapter) return NRC_BRIDGE;
- if (!ncb) return NRC_INVADDRESS;
-
- switch (ncb->ncb_command & 0x7f)
- {
- case NCBCANCEL:
- case NCBADDNAME:
- case NCBADDGRNAME:
- case NCBDELNAME:
- case NCBRESET:
- case NCBSSTAT:
- ret = NRC_CANCEL;
- break;
-
- /* NCBCALL, NCBCHAINSEND/NCBSEND, NCBHANGUP all close the associated
- * session if cancelled */
- case NCBCALL:
- case NCBSEND:
- case NCBCHAINSEND:
- case NCBSENDNA:
- case NCBCHAINSENDNA:
- case NCBHANGUP:
- {
- if (ncb->ncb_lsn >= adapter->sessionsLen)
- ret = NRC_SNUMOUT;
- else if (!adapter->sessions[ncb->ncb_lsn].inUse)
- ret = NRC_SNUMOUT;
- else
- {
- ret = NBCmdQueueCancel(adapter->cmdQueue, ncb);
- if (ret == NRC_CMDCAN || ret == NRC_CANOCCR)
- nbInternalHangup(adapter, &adapter->sessions[ncb->ncb_lsn]);
- }
- break;
- }
-
- default:
- ret = NBCmdQueueCancel(adapter->cmdQueue, ncb);
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-/* Resizes adapter to contain space for at least sessionsLen sessions.
- * If allocating more space for sessions, sets the adapter's sessionsLen to
- * sessionsLen. If the adapter's sessionsLen was already at least sessionsLen,
- * does nothing. Does not modify existing sessions. Assumes the adapter is
- * locked.
- * Returns NRC_GOODRET on success, and something else on failure.
- */
-static UCHAR nbResizeAdapter(NetBIOSAdapter *adapter, UCHAR sessionsLen)
-{
- UCHAR ret = NRC_GOODRET;
-
- if (adapter && adapter->sessionsLen < sessionsLen)
- {
- NetBIOSSession *newSessions;
-
- if (adapter->sessions)
- newSessions = (NetBIOSSession *)HeapReAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, adapter->sessions, sessionsLen *
- sizeof(NetBIOSSession));
- else
- newSessions = (NetBIOSSession *)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, sessionsLen * sizeof(NetBIOSSession));
- if (newSessions)
- {
- adapter->sessions = newSessions;
- adapter->sessionsLen = sessionsLen;
- }
- else
- ret = NRC_OSRESNOTAV;
- }
- return ret;
-}
-
-static UCHAR nbReset(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret;
-
- TRACE(": adapter %p, ncb %p\n", adapter, ncb);
-
- if (!adapter) return NRC_BRIDGE;
- if (!ncb) return NRC_INVADDRESS;
-
- if (InterlockedIncrement(&adapter->resetting) == 1)
- {
- UCHAR i, resizeTo;
-
- NBCmdQueueCancelAll(adapter->cmdQueue);
-
- EnterCriticalSection(&adapter->cs);
- for (i = 0; i < adapter->sessionsLen; i++)
- if (adapter->sessions[i].inUse)
- nbInternalHangup(adapter, &adapter->sessions[i]);
- if (!ncb->ncb_lsn)
- resizeTo = ncb->ncb_callname[0] == 0 ? DEFAULT_NUM_SESSIONS :
- ncb->ncb_callname[0];
- else if (adapter->sessionsLen == 0)
- resizeTo = DEFAULT_NUM_SESSIONS;
- else
- resizeTo = 0;
- if (resizeTo > 0)
- ret = nbResizeAdapter(adapter, resizeTo);
- else
- ret = NRC_GOODRET;
- LeaveCriticalSection(&adapter->cs);
- }
- else
- ret = NRC_TOOMANY;
- InterlockedDecrement(&adapter->resetting);
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR nbSStat(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret, i, spaceFor;
- PSESSION_HEADER sstat;
-
- TRACE(": adapter %p, NCB %p\n", adapter, ncb);
-
- if (!adapter) return NRC_BADDR;
- if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
- if (!ncb) return NRC_INVADDRESS;
- if (!ncb->ncb_buffer) return NRC_BADDR;
- if (ncb->ncb_length < sizeof(SESSION_HEADER)) return NRC_BUFLEN;
-
- sstat = (PSESSION_HEADER)ncb->ncb_buffer;
- ret = NRC_GOODRET;
- memset(sstat, 0, sizeof(SESSION_HEADER));
- spaceFor = (ncb->ncb_length - sizeof(SESSION_HEADER)) /
- sizeof(SESSION_BUFFER);
- EnterCriticalSection(&adapter->cs);
- for (i = 0; ret == NRC_GOODRET && i < adapter->sessionsLen; i++)
- {
- if (adapter->sessions[i].inUse && (ncb->ncb_name[0] == '*' ||
- !memcmp(ncb->ncb_name, adapter->sessions[i].local_name, NCBNAMSZ)))
- {
- if (sstat->num_sess < spaceFor)
- {
- PSESSION_BUFFER buf;
-
- buf = (PSESSION_BUFFER)((PUCHAR)sstat + sizeof(SESSION_HEADER)
- + sstat->num_sess * sizeof(SESSION_BUFFER));
- buf->lsn = i;
- buf->state = adapter->sessions[i].state;
- memcpy(buf->local_name, adapter->sessions[i].local_name,
- NCBNAMSZ);
- memcpy(buf->remote_name, adapter->sessions[i].remote_name,
- NCBNAMSZ);
- buf->rcvs_outstanding = buf->sends_outstanding = 0;
- sstat->num_sess++;
- }
- else
- ret = NRC_BUFLEN;
- }
- }
- LeaveCriticalSection(&adapter->cs);
-
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR nbCall(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret, i;
-
- TRACE(": adapter %p, NCB %p\n", adapter, ncb);
-
- if (!adapter) return NRC_BRIDGE;
- if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
- if (!adapter->transport->call) return NRC_ILLCMD;
- if (!ncb) return NRC_INVADDRESS;
-
- EnterCriticalSection(&adapter->cs);
- for (i = 0; i < adapter->sessionsLen && adapter->sessions[i].inUse; i++)
- ;
- if (i < adapter->sessionsLen)
- {
- adapter->sessions[i].inUse = TRUE;
- adapter->sessions[i].state = CALL_PENDING;
- memcpy(adapter->sessions[i].local_name, ncb->ncb_name, NCBNAMSZ);
- memcpy(adapter->sessions[i].remote_name, ncb->ncb_callname, NCBNAMSZ);
- ret = NRC_GOODRET;
- }
- else
- ret = NRC_LOCTFUL;
- LeaveCriticalSection(&adapter->cs);
-
- if (ret == NRC_GOODRET)
- {
- ret = adapter->transport->call(adapter->impl.data, ncb,
- &adapter->sessions[i].data);
- if (ret == NRC_GOODRET)
- {
- ncb->ncb_lsn = i;
- adapter->sessions[i].state = SESSION_ESTABLISHED;
- }
- else
- {
- adapter->sessions[i].inUse = FALSE;
- adapter->sessions[i].state = 0;
- }
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static UCHAR nbSend(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret;
- NetBIOSSession *session;
-
- if (!adapter) return NRC_BRIDGE;
- if (!adapter->transport->send) return NRC_ILLCMD;
- if (!ncb) return NRC_INVADDRESS;
- if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
- if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
- if (!ncb->ncb_buffer) return NRC_BADDR;
-
- session = &adapter->sessions[ncb->ncb_lsn];
- if (session->state != SESSION_ESTABLISHED)
- ret = NRC_SNUMOUT;
- else
- ret = adapter->transport->send(adapter->impl.data, session->data, ncb);
- return ret;
-}
-
-static UCHAR nbRecv(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret;
- NetBIOSSession *session;
-
- if (!adapter) return NRC_BRIDGE;
- if (!adapter->transport->recv) return NRC_ILLCMD;
- if (!ncb) return NRC_INVADDRESS;
- if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
- if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
- if (!ncb->ncb_buffer) return NRC_BADDR;
-
- session = &adapter->sessions[ncb->ncb_lsn];
- if (session->state != SESSION_ESTABLISHED)
- ret = NRC_SNUMOUT;
- else
- ret = adapter->transport->recv(adapter->impl.data, session->data, ncb);
- return ret;
-}
-
-static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session)
-{
- UCHAR ret;
-
- if (!adapter) return NRC_BRIDGE;
- if (!session) return NRC_SNUMOUT;
-
- if (adapter->transport->hangup)
- ret = adapter->transport->hangup(adapter->impl.data, session->data);
- else
- ret = NRC_ILLCMD;
- EnterCriticalSection(&adapter->cs);
- memset(session, 0, sizeof(NetBIOSSession));
- LeaveCriticalSection(&adapter->cs);
- return NRC_GOODRET;
-}
-
-static UCHAR nbHangup(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret;
- NetBIOSSession *session;
-
- if (!adapter) return NRC_BRIDGE;
- if (!ncb) return NRC_INVADDRESS;
- if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
- if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
-
- session = &adapter->sessions[ncb->ncb_lsn];
- if (session->state != SESSION_ESTABLISHED)
- ret = NRC_SNUMOUT;
- else
- {
- session->state = HANGUP_PENDING;
- ret = nbInternalHangup(adapter, session);
- }
- return ret;
-}
-
-void NetBIOSHangupSession(PNCB ncb)
-{
- NetBIOSAdapter *adapter;
-
- if (!ncb) return;
-
- adapter = nbGetAdapter(ncb->ncb_lana_num);
- if (adapter)
- {
- if (ncb->ncb_lsn < adapter->sessionsLen &&
- adapter->sessions[ncb->ncb_lsn].inUse)
- nbHangup(adapter, ncb);
- }
-}
-
-static UCHAR nbAStat(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret;
-
- if (!adapter) return NRC_BRIDGE;
- if (!adapter->transport->astat) return NRC_ILLCMD;
- if (!ncb) return NRC_INVADDRESS;
- if (!ncb->ncb_buffer) return NRC_BADDR;
- if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN;
-
- ret = adapter->transport->astat(adapter->impl.data, ncb);
- if (ncb->ncb_callname[0] == '*')
- {
- PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer;
-
- astat->max_sess = astat->max_cfg_sess = adapter->sessionsLen;
- }
- return ret;
-}
-
-static UCHAR nbDispatch(NetBIOSAdapter *adapter, PNCB ncb)
-{
- UCHAR ret, cmd;
-
- TRACE(": adapter %p, ncb %p\n", adapter, ncb);
-
- if (!adapter) return NRC_BRIDGE;
- if (!ncb) return NRC_INVADDRESS;
-
- cmd = ncb->ncb_command & 0x7f;
- if (cmd == NCBRESET)
- ret = nbReset(adapter, ncb);
- else
- {
- ret = NBCmdQueueAdd(adapter->cmdQueue, ncb);
- if (ret == NRC_GOODRET)
- {
- switch (cmd)
- {
- case NCBCALL:
- ret = nbCall(adapter, ncb);
- break;
-
- /* WinNT doesn't chain sends, it always sends immediately.
- * Doubt there's any real significance to the NA variants.
- */
- case NCBSEND:
- case NCBSENDNA:
- case NCBCHAINSEND:
- case NCBCHAINSENDNA:
- ret = nbSend(adapter, ncb);
- break;
-
- case NCBRECV:
- ret = nbRecv(adapter, ncb);
- break;
-
- case NCBHANGUP:
- ret = nbHangup(adapter, ncb);
- break;
-
- case NCBASTAT:
- ret = nbAStat(adapter, ncb);
- break;
-
- case NCBFINDNAME:
- if (adapter->transport->findName)
- ret = adapter->transport->findName(adapter->impl.data,
- ncb);
- else
- ret = NRC_ILLCMD;
- break;
-
- default:
- FIXME("(%p): command code 0x%02x\n", ncb, ncb->ncb_command);
- ret = NRC_ILLCMD;
- }
- NBCmdQueueComplete(adapter->cmdQueue, ncb, ret);
- }
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
-
-static DWORD WINAPI nbCmdThread(LPVOID lpVoid)
-{
- PNCB ncb = (PNCB)lpVoid;
-
- if (ncb)
- {
- UCHAR ret;
- NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num);
-
- if (adapter)
- ret = nbDispatch(adapter, ncb);
- else
- ret = NRC_BRIDGE;
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret;
- if (ncb->ncb_post)
- ncb->ncb_post(ncb);
- else if (ncb->ncb_event)
- SetEvent(ncb->ncb_event);
- }
- return 0;
-}
-
-UCHAR WINAPI Netbios(PNCB ncb)
-{
- UCHAR ret, cmd;
-
- TRACE("ncb = %p\n", ncb);
-
- if (!ncb) return NRC_INVADDRESS;
-
- TRACE("ncb_command 0x%02x, ncb_lana_num %d, ncb_buffer %p, ncb_length %d\n",
- ncb->ncb_command, ncb->ncb_lana_num, ncb->ncb_buffer, ncb->ncb_length);
- cmd = ncb->ncb_command & 0x7f;
-
- if (cmd == NCBENUM)
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = nbEnum(ncb);
- else
- {
- NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num);
-
- if (!adapter)
- ret = NRC_BRIDGE;
- else
- {
- if (adapter->shuttingDown)
- ret = NRC_IFBUSY;
- else if (adapter->resetting)
- ret = NRC_TOOMANY;
- else
- {
- /* non-asynch commands first */
- if (cmd == NCBCANCEL)
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
- nbCancel(adapter, ncb);
- else if (cmd == NCBSSTAT)
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
- nbSStat(adapter, ncb);
- else
- {
- if (ncb->ncb_command & ASYNCH)
- {
- HANDLE thread = CreateThread(NULL, 0, nbCmdThread, ncb,
- CREATE_SUSPENDED, NULL);
-
- if (thread != NULL)
- {
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = NRC_PENDING;
- if (ncb->ncb_event)
- ResetEvent(ncb->ncb_event);
- ResumeThread(thread);
- CloseHandle(thread);
- ret = NRC_GOODRET;
- }
- else
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
- NRC_OSRESNOTAV;
- }
- else
- ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
- nbDispatch(adapter, ncb);
- }
- }
- }
- }
- TRACE("returning 0x%02x\n", ret);
- return ret;
-}
+++ /dev/null
-/* 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_reserve)
-
-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__ */
+++ /dev/null
-/*
- * Copyright 2002 Andriy Palamarchuk
- *
- * Net API buffer calls
- *
- * 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/port.h"
-
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "lmcons.h"
-#include "lmapibuf.h"
-#include "lmerr.h"
-#include "winerror.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-
-/************************************************************
- * NetApiBufferFree (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
-{
- FIXME("(%p)\n", Buffer);
- return NERR_Success;
-}
-
-/************************************************************
- * NetUserGetInfo (NETAPI32.@)
- */
-NET_API_STATUS WINAPI
-NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
- LPBYTE* bufptr)
-{
- FIXME("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username),
- level, bufptr);
- return NERR_Success;
-}
-
-/************************************************************
- * NetWkstaUserGetInfo (NETAPI32.@)
- */
-NET_API_STATUS NetWkstaUserGetInfo(LPWSTR reserved, DWORD level,
- LPBYTE* bufptr)
-{
- return NERR_Success;
-}
+++ /dev/null
-/* Copyright 2002 Andriy Palamarchuk
- * Copyright (c) 2003 Juan Lang
- *
- * netapi32 user functions
- *
- * 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/port.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "winsock2.h"
-#include "nb30.h"
-#include "lmcons.h"
-#include "lmapibuf.h"
-#include "lmerr.h"
-#include "lmwksta.h"
-#include "iphlpapi.h"
-#include "winerror.h"
-#include "ntsecapi.h"
-#include "winreg.h"
-#include "netbios.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-
-/************************************************************
- * NETAPI_IsLocalComputer
- *
- * Checks whether the server name indicates local machine.
- */
-BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName)
-{
- if (!ServerName)
- {
- return TRUE;
- }
- else
- {
- DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
- BOOL Result;
- LPWSTR buf;
-
- NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf);
- Result = GetComputerNameW(buf, &dwSize);
- if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
- ServerName += 2;
- Result = Result && !lstrcmpW(ServerName, buf);
- NetApiBufferFree(buf);
-
- return Result;
- }
-}
-
-static void wprint_mac(WCHAR* buffer, int len, PMIB_IFROW ifRow)
-{
- int i;
- unsigned char val;
-
- if (!buffer)
- return;
- if (len < 1)
- return;
- if (!ifRow)
- {
- *buffer = '\0';
- return;
- }
-
- for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
- {
- val = ifRow->bPhysAddr[i];
- if ((val >>4) >9)
- buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
- else
- buffer[2*i] = (WCHAR)((val >>4) + '0');
- if ((val & 0xf ) >9)
- buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
- else
- buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
- }
- buffer[2*i]=(WCHAR)0;
-}
-
-/* Theoretically this could be too short, except that MS defines
- * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
- * represent a count of WCHARs, so even with an extroardinarily long header
- * this will be plenty
- */
-#define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
-#define MAX_TRANSPORT_ADDR 13
-
-#define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
-#define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
-
-static void wprint_name(WCHAR *buffer, int len, ULONG transport,
- PMIB_IFROW ifRow)
-{
- WCHAR *ptr1, *ptr2;
- const char *name;
-
- if (!buffer)
- return;
- if (!ifRow)
- {
- *buffer = '\0';
- return;
- }
-
- if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
- name = NBT_TRANSPORT_NAME_HEADER;
- else
- name = UNKNOWN_TRANSPORT_NAME_HEADER;
-
- for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
- *ptr1 = *name;
- for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
- *ptr1 = *ptr2;
- *ptr1 = '\0';
-}
-
-struct WkstaTransportEnumData
-{
- UCHAR n_adapt;
- UCHAR n_read;
- DWORD prefmaxlen;
- LPBYTE *pbuf;
- NET_API_STATUS ret;
-};
-
-static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
- ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
-{
- BOOL ret;
- struct WkstaTransportEnumData *enumData = (struct WkstaTransportEnumData *)
- closure;
-
- if (enumData && enumData->pbuf)
- {
- if (lanaIndex == 0)
- {
- DWORD toAllocate;
-
- enumData->n_adapt = totalLANAs;
- enumData->n_read = 0;
-
- toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
- + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
- MAX_TRANSPORT_ADDR * sizeof(WCHAR));
- if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
- toAllocate = enumData->prefmaxlen;
- NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
- }
- if (*(enumData->pbuf))
- {
- UCHAR spaceFor;
-
- if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
- spaceFor = totalLANAs;
- else
- spaceFor = enumData->prefmaxlen /
- (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
- MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
- if (enumData->n_read < spaceFor)
- {
- PWKSTA_TRANSPORT_INFO_0 ti;
- LPWSTR transport_name, transport_addr;
- MIB_IFROW ifRow;
-
- ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
- enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
- transport_name = (LPWSTR)(*(enumData->pbuf) +
- totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
- enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
- transport_addr = (LPWSTR)(*(enumData->pbuf) +
- totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
- MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
- enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
-
- ifRow.dwIndex = data->ifIndex;
- GetIfEntry(&ifRow);
- ti->wkti0_quality_of_service = 0;
- ti->wkti0_number_of_vcs = 0;
- ti->wkti0_transport_name = transport_name;
- wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
- transport, &ifRow);
- ti->wkti0_transport_address = transport_addr;
- wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
- &ifRow);
- if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
- ti->wkti0_wan_ish = TRUE;
- else
- ti->wkti0_wan_ish = FALSE;
- TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
- TRACE("transport_name at %p %s\n",
- ti->wkti0_transport_name,
- debugstr_w(ti->wkti0_transport_name));
- TRACE("transport_address at %p %s\n",
- ti->wkti0_transport_address,
- debugstr_w(ti->wkti0_transport_address));
- enumData->n_read++;
- enumData->ret = NERR_Success;
- ret = TRUE;
- }
- else
- {
- enumData->ret = ERROR_MORE_DATA;
- ret = FALSE;
- }
- }
- else
- {
- enumData->ret = ERROR_OUTOFMEMORY;
- ret = FALSE;
- }
- }
- else
- ret = FALSE;
- return ret;
-}
-
-NET_API_STATUS WINAPI
-NetWkstaTransportEnum(LPWSTR ServerName, DWORD level, PBYTE* pbuf,
- DWORD prefmaxlen, LPDWORD read_entries,
- PDWORD total_entries, PDWORD hresume)
-{
- NET_API_STATUS ret;
-
- TRACE(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName),
- level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
- if (!NETAPI_IsLocalComputer(ServerName))
- {
- FIXME(":not implemented for non-local computers\n");
- ret = ERROR_INVALID_LEVEL;
- }
- else
- {
- if (hresume && *hresume)
- {
- FIXME(":resume handle not implemented\n");
- return ERROR_INVALID_LEVEL;
- }
-
- switch (level)
- {
- case 0: /* transport info */
- {
- ULONG allTransports;
- struct WkstaTransportEnumData enumData;
-
- if (NetBIOSNumAdapters() == 0)
- return ERROR_NETWORK_UNREACHABLE;
- if (!read_entries)
- return STATUS_ACCESS_VIOLATION;
- if (!total_entries || !pbuf)
- return RPC_X_NULL_REF_POINTER;
-
- enumData.prefmaxlen = prefmaxlen;
- enumData.pbuf = pbuf;
- memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
- NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
- &enumData);
- *read_entries = enumData.n_read;
- *total_entries = enumData.n_adapt;
- if (hresume) *hresume= 0;
- ret = enumData.ret;
- break;
- }
- default:
- ERR("Invalid level %ld is specified\n", level);
- ret = ERROR_INVALID_LEVEL;
- }
- }
- return ret;
-}
-
-
-/************************************************************
- * NetWkstaUserGetInfo (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetWkstaUserGetInfo(LPWSTR reserved, DWORD level,
- LPBYTE* bufptr)
-{
- FIXME("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr);
- switch (level)
- {
- case 0:
- {
- PWKSTA_USER_INFO_0 ui;
- DWORD dwSize = UNLEN + 1;
-
- /* set up buffer */
- NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
- (LPVOID *) bufptr);
-
- ui = (PWKSTA_USER_INFO_0) *bufptr;
- ui->wkui0_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
-
- /* get data */
- if (!GetUserNameW(ui->wkui0_username, &dwSize))
- {
- NetApiBufferFree(ui);
- FIXME("NetWkstaUserGetInfo - ERROR_NOT_ENOUGH_MEMORY\n");
- return ERROR_NOT_ENOUGH_MEMORY;
- }
- else
- FIXME("NetWkstaUserGetInfo - trying NetApiBufferReallocate\n");
- NetApiBufferReallocate(
- *bufptr, sizeof(WKSTA_USER_INFO_0) +
- (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
- (LPVOID *) bufptr);
- break;
- }
-
- case 1:
- {
- PWKSTA_USER_INFO_1 ui;
- PWKSTA_USER_INFO_0 ui0;
- DWORD dwSize;
- LSA_OBJECT_ATTRIBUTES ObjectAttributes;
- LSA_HANDLE PolicyHandle;
- PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
- NTSTATUS NtStatus;
-
- /* sizes of the field buffers in WCHARS */
- int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
-
- FIXME("Level 1 processing is partially implemented\n");
- oth_domains_sz = 1;
- logon_server_sz = 1;
-
- /* get some information first to estimate size of the buffer */
- ui0 = NULL;
- FIXME("NetWkstaUserGetInfo - ??NetWkstaUserGetInfo\n");
- NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
- username_sz = lstrlenW(ui0->wkui0_username) + 1;
-
- ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
- NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
- POLICY_VIEW_LOCAL_INFORMATION,
- &PolicyHandle);
- if (NtStatus != STATUS_SUCCESS)
- {
- ERR("LsaOpenPolicyFailed with NT status %lx\n",
- LsaNtStatusToWinError(NtStatus));
- NetApiBufferFree(ui0);
- return ERROR_NOT_ENOUGH_MEMORY;
- }
- LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
- (PVOID*) &DomainInfo);
- logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
- LsaClose(PolicyHandle);
-
- /* set up buffer */
- NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
- (username_sz + logon_domain_sz +
- oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
- (LPVOID *) bufptr);
- ui = (WKSTA_USER_INFO_1 *) *bufptr;
- ui->wkui1_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
- ui->wkui1_logon_domain = (LPWSTR) (
- ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
- ui->wkui1_oth_domains = (LPWSTR) (
- ((PBYTE) ui->wkui1_logon_domain) +
- logon_domain_sz * sizeof(WCHAR));
- ui->wkui1_logon_server = (LPWSTR) (
- ((PBYTE) ui->wkui1_oth_domains) +
- oth_domains_sz * sizeof(WCHAR));
-
- /* get data */
- dwSize = username_sz;
- lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
- NetApiBufferFree(ui0);
-
- lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
- logon_domain_sz);
- LsaFreeMemory(DomainInfo);
-
- /* FIXME. Not implemented. Populated with empty strings */
- ui->wkui1_oth_domains[0] = 0;
- ui->wkui1_logon_server[0] = 0;
- break;
- }
- case 1101:
- {
- PWKSTA_USER_INFO_1101 ui;
- DWORD dwSize = 1;
-
- FIXME("Stub. Level 1101 processing is not implemented\n");
- /* FIXME see also wkui1_oth_domains for level 1 */
-
- /* set up buffer */
- NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
- (LPVOID *) bufptr);
-
- ui = (PWKSTA_USER_INFO_1101) *bufptr;
- ui->wkui1101_oth_domains = (LPWSTR)(ui + 1);
-
- /* get data */
- ui->wkui1101_oth_domains[0] = 0;
- break;
- }
- default:
- ERR("Invalid level %ld is specified\n", level);
- return ERROR_INVALID_LEVEL;
- }
- FIXME("NetWkstaUserGetInfo - ERROR_NOT_ENOUGH_MEMORY\n");
- return NERR_Success;
-}
-
-/************************************************************
- * NetpGetComputerName (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
-{
- DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
-
- TRACE("(%p)\n", Buffer);
- NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
- if (GetComputerNameW(*Buffer, &dwSize))
- {
- NetApiBufferReallocate(
- *Buffer, dwSize * sizeof(WCHAR),
- (LPVOID *) Buffer);
- return NERR_Success;
- }
- else
- {
- NetApiBufferFree(*Buffer);
- return ERROR_NOT_ENOUGH_MEMORY;
- }
-}
-
-NET_API_STATUS WINAPI NetWkstaGetInfo( LPWSTR servername, DWORD level,
- LPBYTE* bufptr)
-{
- NET_API_STATUS ret;
-
- TRACE("%p %ld %p\n", debugstr_w( servername ), level, bufptr );
- if (servername)
- {
- FIXME("remote computers not supported\n");
- return ERROR_INVALID_LEVEL;
- }
- if (!bufptr) return ERROR_INVALID_PARAMETER;
-
- switch (level)
- {
- case 100:
- {
- DWORD computerNameLen, domainNameLen, size;
- WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
- LSA_OBJECT_ATTRIBUTES ObjectAttributes;
- LSA_HANDLE PolicyHandle;
- NTSTATUS NtStatus;
-
- computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
- GetComputerNameW(computerName, &computerNameLen);
- computerNameLen++; /* include NULL terminator */
-
- ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
- NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
- POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
- if (NtStatus != STATUS_SUCCESS)
- ret = LsaNtStatusToWinError(NtStatus);
- else
- {
- PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
-
- LsaQueryInformationPolicy(PolicyHandle,
- PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
- domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
- size = sizeof(WKSTA_INFO_100) + computerNameLen * sizeof(WCHAR)
- + domainNameLen * sizeof(WCHAR);
- ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
- if (ret == NERR_Success)
- {
- PWKSTA_INFO_100 info = (PWKSTA_INFO_100)*bufptr;
- OSVERSIONINFOW verInfo;
-
- info->wki100_platform_id = PLATFORM_ID_NT;
- info->wki100_computername = (LPWSTR)(*bufptr +
- sizeof(WKSTA_INFO_100));
- memcpy(info->wki100_computername, computerName,
- computerNameLen * sizeof(WCHAR));
- info->wki100_langroup = (LPWSTR)(*bufptr +
- sizeof(WKSTA_INFO_100) + computerNameLen * sizeof(WCHAR));
- memcpy(info->wki100_langroup, DomainInfo->DomainName.Buffer,
- domainNameLen * sizeof(WCHAR));
- memset(&verInfo, 0, sizeof(verInfo));
- verInfo.dwOSVersionInfoSize = sizeof(verInfo);
- GetVersionExW(&verInfo);
- info->wki100_ver_major = verInfo.dwMajorVersion;
- info->wki100_ver_minor = verInfo.dwMinorVersion;
- }
- LsaFreeMemory(DomainInfo);
- LsaClose(PolicyHandle);
- }
- break;
- }
-
- default:
- FIXME("level %ld unimplemented\n", level);
- ret = ERROR_INVALID_LEVEL;
- }
- return ret;
-}