/* * Copyright 2002 Andriy Palamarchuk * * 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 #include "winbase.h" #include "nb30.h" #include "lmcons.h" #include "lmapibuf.h" #include "lmerr.h" #include "lmwksta.h" #include "iphlpapi.h" #include "winerror.h" #include "winternl.h" #include "ntsecapi.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, PIP_ADAPTER_INFO adapter) { if (adapter != NULL) { int i; unsigned char val; for (i = 0; iAddressLength, 6); i++) { val = adapter->Address[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[12]=(WCHAR)0; } else buffer[0] = 0; } #define TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_" #define TRANSPORT_NAME_LEN \ (sizeof(TRANSPORT_NAME_HEADER) + MAX_ADAPTER_NAME_LENGTH) static void wprint_name(WCHAR *buffer, int len, PIP_ADAPTER_INFO adapter) { WCHAR *ptr; const char *name; if (!buffer) return; if (!adapter) return; for (ptr = buffer, name = TRANSPORT_NAME_HEADER; *name && ptr < buffer + len; ptr++, name++) *ptr = *name; for (name = adapter->AdapterName; name && *name && ptr < buffer + len; ptr++, name++) *ptr = *name; *ptr = '\0'; } NET_API_STATUS WINAPI NetWkstaTransportEnum(LPCWSTR ServerName, DWORD level, LPBYTE* pbuf, DWORD prefmaxlen, LPDWORD read_entries, LPDWORD total_entries, LPDWORD hresume) { FIXME(":%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"); return ERROR_INVALID_LEVEL; } else { if (hresume && *hresume) { FIXME(":resume handle not implemented\n"); return ERROR_INVALID_LEVEL; } switch (level) { case 0: /* transport info */ { PWKSTA_TRANSPORT_INFO_0 ti; int i,size_needed,n_adapt; DWORD apiReturn, adaptInfoSize = 0; PIP_ADAPTER_INFO info, ptr; apiReturn = GetAdaptersInfo(NULL, &adaptInfoSize); if (apiReturn == ERROR_NO_DATA) return ERROR_NETWORK_UNREACHABLE; if (!read_entries) return STATUS_ACCESS_VIOLATION; if (!total_entries || !pbuf) return RPC_X_NULL_REF_POINTER; info = (PIP_ADAPTER_INFO)malloc(adaptInfoSize); apiReturn = GetAdaptersInfo(info, &adaptInfoSize); if (apiReturn != NO_ERROR) { free(info); return apiReturn; } for (n_adapt = 0, ptr = info; ptr; ptr = ptr->Next) n_adapt++; size_needed = n_adapt * (sizeof(WKSTA_TRANSPORT_INFO_0) + n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR) + n_adapt * 13 * sizeof (WCHAR)); if (prefmaxlen == MAX_PREFERRED_LENGTH) NetApiBufferAllocate( size_needed, (LPVOID *) pbuf); else { if (size_needed > prefmaxlen) { free(info); return ERROR_MORE_DATA; } NetApiBufferAllocate(prefmaxlen, (LPVOID *) pbuf); } for (i = 0, ptr = info; ptr; ptr = ptr->Next, i++) { ti = (PWKSTA_TRANSPORT_INFO_0) ((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0)); ti->wkti0_quality_of_service=0; ti->wkti0_number_of_vcs=0; ti->wkti0_transport_name= (LPWSTR) ((PBYTE )*pbuf + n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) + i * TRANSPORT_NAME_LEN * sizeof (WCHAR)); wprint_name(ti->wkti0_transport_name,TRANSPORT_NAME_LEN, ptr); ti->wkti0_transport_address= (LPWSTR) ((PBYTE )*pbuf + n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) + n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR) + i * 13 * sizeof (WCHAR)); ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/ wprint_mac(ti->wkti0_transport_address, ptr); TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt, ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address)); } *read_entries = n_adapt; *total_entries = n_adapt; free(info); if(hresume) *hresume= 0; break; } default: ERR("Invalid level %ld is specified\n", level); return ERROR_INVALID_LEVEL; } return NERR_Success; } } /************************************************************ * NetWkstaUserGetInfo (NETAPI32.@) */ NET_API_STATUS WINAPI NetWkstaUserGetInfo(LPWSTR reserved, DWORD level, PBYTE* bufptr) { TRACE("(%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); return ERROR_NOT_ENOUGH_MEMORY; } else 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; 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; } 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; } }