Fixed a few bugs in network interface handling (code & test).
[wine.git] / dlls / netapi32 / wksta.c
blob0c61e00bbb96c7b6051617f7a300328e33d190ba
1 /*
2 * Copyright 2002 Andriy Palamarchuk
4 * netapi32 user functions
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdlib.h>
22 #include "winbase.h"
23 #include "nb30.h"
24 #include "lmcons.h"
25 #include "lmapibuf.h"
26 #include "lmerr.h"
27 #include "lmwksta.h"
28 #include "iphlpapi.h"
29 #include "winerror.h"
30 #include "winternl.h"
31 #include "ntsecapi.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
36 /************************************************************
37 * NETAPI_IsLocalComputer
39 * Checks whether the server name indicates local machine.
41 BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName)
43 if (!ServerName)
45 return TRUE;
47 else
49 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
50 BOOL Result;
51 LPWSTR buf;
53 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf);
54 Result = GetComputerNameW(buf, &dwSize);
55 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
56 ServerName += 2;
57 Result = Result && !lstrcmpW(ServerName, buf);
58 NetApiBufferFree(buf);
60 return Result;
64 static void wprint_mac(WCHAR* buffer, PIP_ADAPTER_INFO adapter)
66 if (adapter != NULL)
68 int i;
69 unsigned char val;
71 for (i = 0; i<max(adapter->AddressLength, 6); i++)
73 val = adapter->Address[i];
74 if ((val >>4) >9)
75 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
76 else
77 buffer[2*i] = (WCHAR)((val >>4) + '0');
78 if ((val & 0xf ) >9)
79 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
80 else
81 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
83 buffer[12]=(WCHAR)0;
85 else
86 buffer[0] = 0;
89 #define TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
90 #define TRANSPORT_NAME_LEN \
91 (sizeof(TRANSPORT_NAME_HEADER) + MAX_ADAPTER_NAME_LENGTH)
93 static void wprint_name(WCHAR *buffer, int len, PIP_ADAPTER_INFO adapter)
95 WCHAR *ptr;
96 const char *name;
98 if (!buffer)
99 return;
100 if (!adapter)
101 return;
103 for (ptr = buffer, name = TRANSPORT_NAME_HEADER; *name && ptr < buffer + len;
104 ptr++, name++)
105 *ptr = *name;
106 for (name = adapter->AdapterName; name && *name && ptr < buffer + len;
107 ptr++, name++)
108 *ptr = *name;
109 *ptr = '\0';
112 NET_API_STATUS WINAPI
113 NetWkstaTransportEnum(LPCWSTR ServerName, DWORD level, LPBYTE* pbuf,
114 DWORD prefmaxlen, LPDWORD read_entries,
115 LPDWORD total_entries, LPDWORD hresume)
117 FIXME(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName),
118 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
119 if (!NETAPI_IsLocalComputer(ServerName))
121 FIXME(":not implemented for non-local computers\n");
122 return ERROR_INVALID_LEVEL;
124 else
126 if (hresume && *hresume)
128 FIXME(":resume handle not implemented\n");
129 return ERROR_INVALID_LEVEL;
132 switch (level)
134 case 0: /* transport info */
136 PWKSTA_TRANSPORT_INFO_0 ti;
137 int i,size_needed,n_adapt;
138 DWORD apiReturn, adaptInfoSize = 0;
139 PIP_ADAPTER_INFO info, ptr;
141 apiReturn = GetAdaptersInfo(NULL, &adaptInfoSize);
142 if (apiReturn == ERROR_NO_DATA)
143 return ERROR_NETWORK_UNREACHABLE;
144 if (!read_entries)
145 return STATUS_ACCESS_VIOLATION;
146 if (!total_entries || !pbuf)
147 return RPC_X_NULL_REF_POINTER;
149 info = (PIP_ADAPTER_INFO)malloc(adaptInfoSize);
150 apiReturn = GetAdaptersInfo(info, &adaptInfoSize);
151 if (apiReturn != NO_ERROR)
153 free(info);
154 return apiReturn;
157 for (n_adapt = 0, ptr = info; ptr; ptr = ptr->Next)
158 n_adapt++;
159 size_needed = n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0)
160 + n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
161 + n_adapt * 13 * sizeof (WCHAR);
162 if (prefmaxlen == MAX_PREFERRED_LENGTH)
163 NetApiBufferAllocate( size_needed, (LPVOID *) pbuf);
164 else
166 if (size_needed > prefmaxlen)
168 free(info);
169 return ERROR_MORE_DATA;
171 NetApiBufferAllocate(prefmaxlen,
172 (LPVOID *) pbuf);
174 for (i = 0, ptr = info; ptr; ptr = ptr->Next, i++)
176 ti = (PWKSTA_TRANSPORT_INFO_0)
177 ((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0));
178 ti->wkti0_quality_of_service=0;
179 ti->wkti0_number_of_vcs=0;
180 ti->wkti0_transport_name= (LPWSTR)
181 ((PBYTE )*pbuf +
182 n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0)
183 + i * TRANSPORT_NAME_LEN * sizeof (WCHAR));
184 wprint_name(ti->wkti0_transport_name,TRANSPORT_NAME_LEN, ptr);
185 ti->wkti0_transport_address= (LPWSTR)
186 ((PBYTE )*pbuf +
187 n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) +
188 n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
189 + i * 13 * sizeof (WCHAR));
190 ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/
191 wprint_mac(ti->wkti0_transport_address, ptr);
192 TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt,
193 ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address));
195 *read_entries = n_adapt;
196 *total_entries = n_adapt;
197 free(info);
198 if(hresume) *hresume= 0;
199 break;
201 default:
202 ERR("Invalid level %ld is specified\n", level);
203 return ERROR_INVALID_LEVEL;
205 return NERR_Success;
210 /************************************************************
211 * NetWkstaUserGetInfo (NETAPI32.@)
213 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LPWSTR reserved, DWORD level,
214 PBYTE* bufptr)
216 TRACE("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr);
217 switch (level)
219 case 0:
221 PWKSTA_USER_INFO_0 ui;
222 DWORD dwSize = UNLEN + 1;
224 /* set up buffer */
225 NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
226 (LPVOID *) bufptr);
228 ui = (PWKSTA_USER_INFO_0) *bufptr;
229 ui->wkui0_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
231 /* get data */
232 if (!GetUserNameW(ui->wkui0_username, &dwSize))
234 NetApiBufferFree(ui);
235 return ERROR_NOT_ENOUGH_MEMORY;
237 else
238 NetApiBufferReallocate(
239 *bufptr, sizeof(WKSTA_USER_INFO_0) +
240 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
241 (LPVOID *) bufptr);
242 break;
245 case 1:
247 PWKSTA_USER_INFO_1 ui;
248 PWKSTA_USER_INFO_0 ui0;
249 DWORD dwSize;
250 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
251 LSA_HANDLE PolicyHandle;
252 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
253 NTSTATUS NtStatus;
255 /* sizes of the field buffers in WCHARS */
256 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
258 FIXME("Level 1 processing is partially implemented\n");
259 oth_domains_sz = 1;
260 logon_server_sz = 1;
262 /* get some information first to estimate size of the buffer */
263 ui0 = NULL;
264 NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
265 username_sz = lstrlenW(ui0->wkui0_username) + 1;
267 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
268 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
269 POLICY_VIEW_LOCAL_INFORMATION,
270 &PolicyHandle);
271 if (NtStatus != STATUS_SUCCESS)
273 ERR("LsaOpenPolicyFailed with NT status %lx\n",
274 LsaNtStatusToWinError(NtStatus));
275 NetApiBufferFree(ui0);
276 return ERROR_NOT_ENOUGH_MEMORY;
278 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
279 (PVOID*) &DomainInfo);
280 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
281 LsaClose(PolicyHandle);
283 /* set up buffer */
284 NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
285 (username_sz + logon_domain_sz +
286 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
287 (LPVOID *) bufptr);
288 ui = (WKSTA_USER_INFO_1 *) *bufptr;
289 ui->wkui1_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
290 ui->wkui1_logon_domain = (LPWSTR) (
291 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
292 ui->wkui1_oth_domains = (LPWSTR) (
293 ((PBYTE) ui->wkui1_logon_domain) +
294 logon_domain_sz * sizeof(WCHAR));
295 ui->wkui1_logon_server = (LPWSTR) (
296 ((PBYTE) ui->wkui1_oth_domains) +
297 oth_domains_sz * sizeof(WCHAR));
299 /* get data */
300 dwSize = username_sz;
301 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
302 NetApiBufferFree(ui0);
304 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
305 logon_domain_sz);
306 LsaFreeMemory(DomainInfo);
308 /* FIXME. Not implemented. Populated with empty strings */
309 ui->wkui1_oth_domains[0] = 0;
310 ui->wkui1_logon_server[0] = 0;
311 break;
313 case 1101:
315 PWKSTA_USER_INFO_1101 ui;
316 DWORD dwSize = 1;
318 FIXME("Stub. Level 1101 processing is not implemented\n");
319 /* FIXME see also wkui1_oth_domains for level 1 */
321 /* set up buffer */
322 NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
323 (LPVOID *) bufptr);
325 ui = (PWKSTA_USER_INFO_1101) *bufptr;
326 ui->wkui1101_oth_domains = (LPWSTR)(ui + 1);
328 /* get data */
329 ui->wkui1101_oth_domains[0] = 0;
330 break;
332 default:
333 ERR("Invalid level %ld is specified\n", level);
334 return ERROR_INVALID_LEVEL;
336 return NERR_Success;
339 /************************************************************
340 * NetpGetComputerName (NETAPI32.@)
342 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
344 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
346 TRACE("(%p)\n", Buffer);
347 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
348 if (GetComputerNameW(*Buffer, &dwSize))
350 NetApiBufferReallocate(
351 *Buffer, dwSize * sizeof(WCHAR),
352 (LPVOID *) Buffer);
353 return NERR_Success;
355 else
357 NetApiBufferFree(*Buffer);
358 return ERROR_NOT_ENOUGH_MEMORY;