netapi32: Avoid process heap allocations.
[wine.git] / dlls / netapi32 / netapi32.c
blob1efdab61be129d91c6f92e8c39a90450c3fe4e6f
1 /* Copyright 2001 Mike McCormack
2 * Copyright 2002 Andriy Palamarchuk
3 * Copyright 2003 Juan Lang
4 * Copyright 2005,2006 Paul Vriens
5 * Copyright 2006 Robert Reif
6 * Copyright 2013 Hans Leidekker for CodeWeavers
7 * Copyright 2020 Dmitry Timoshkov
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <stdarg.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winternl.h"
31 #include "winsock2.h"
32 #include "ws2ipdef.h"
33 #include "windns.h"
34 #include "lm.h"
35 #include "lmaccess.h"
36 #include "atsvc.h"
37 #include "lmapibuf.h"
38 #include "lmbrowsr.h"
39 #include "lmshare.h"
40 #include "lmwksta.h"
41 #include "netbios.h"
42 #include "ifmib.h"
43 #include "iphlpapi.h"
44 #include "ntsecapi.h"
45 #include "dsrole.h"
46 #include "dsgetdc.h"
47 #include "davclnt.h"
48 #include "wine/debug.h"
49 #include "wine/list.h"
50 #include "initguid.h"
52 #include "unixlib.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
56 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
58 static HINSTANCE netapi32_instance;
60 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
62 static const struct samba_funcs *samba_funcs;
64 static BOOL WINAPI load_samba( INIT_ONCE *once, void *param, void **context )
66 __wine_init_unix_lib( netapi32_instance, DLL_PROCESS_ATTACH, NULL, &samba_funcs );
67 return TRUE;
70 static BOOL samba_init(void)
72 return InitOnceExecuteOnce( &init_once, load_samba, NULL, NULL ) && samba_funcs;
75 /************************************************************
76 * NETAPI_IsLocalComputer
78 * Checks whether the server name indicates local machine.
80 static BOOL NETAPI_IsLocalComputer( LMCSTR name )
82 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
83 DWORD size = ARRAY_SIZE(buf);
84 BOOL ret;
86 if (!name || !name[0]) return TRUE;
88 ret = GetComputerNameW( buf, &size );
89 if (ret && name[0] == '\\' && name[1] == '\\') name += 2;
90 return ret && !wcsicmp( name, buf );
93 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
95 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
97 switch (fdwReason) {
98 case DLL_PROCESS_ATTACH:
99 netapi32_instance = hinstDLL;
100 DisableThreadLibraryCalls(hinstDLL);
101 NetBIOSInit();
102 NetBTInit();
103 break;
104 case DLL_PROCESS_DETACH:
105 if (lpvReserved) break;
106 NetBIOSShutdown();
107 break;
110 return TRUE;
113 /************************************************************
114 * NetServerEnum (NETAPI32.@)
116 NET_API_STATUS WINAPI NetServerEnum(
117 LMCSTR servername,
118 DWORD level,
119 LPBYTE* bufptr,
120 DWORD prefmaxlen,
121 LPDWORD entriesread,
122 LPDWORD totalentries,
123 DWORD servertype,
124 LMCSTR domain,
125 LPDWORD resume_handle
128 FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(servername),
129 level, bufptr, prefmaxlen, entriesread, totalentries, servertype,
130 debugstr_w(domain), resume_handle);
132 return ERROR_NO_BROWSER_SERVERS_FOUND;
135 /************************************************************
136 * NetServerEnumEx (NETAPI32.@)
138 NET_API_STATUS WINAPI NetServerEnumEx(
139 LMCSTR ServerName,
140 DWORD Level,
141 LPBYTE *Bufptr,
142 DWORD PrefMaxlen,
143 LPDWORD EntriesRead,
144 LPDWORD totalentries,
145 DWORD servertype,
146 LMCSTR domain,
147 LMCSTR FirstNameToReturn)
149 FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
150 debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
151 servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
153 return ERROR_NO_BROWSER_SERVERS_FOUND;
156 /************************************************************
157 * NetServerDiskEnum (NETAPI32.@)
159 NET_API_STATUS WINAPI NetServerDiskEnum(
160 LMCSTR ServerName,
161 DWORD Level,
162 LPBYTE *Bufptr,
163 DWORD PrefMaxlen,
164 LPDWORD EntriesRead,
165 LPDWORD totalentries,
166 LPDWORD Resume_Handle)
168 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName),
169 Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
171 return ERROR_NO_BROWSER_SERVERS_FOUND;
174 /************************************************************
175 * NetServerGetInfo (NETAPI32.@)
177 NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr)
179 NET_API_STATUS ret;
180 BOOL local = NETAPI_IsLocalComputer( servername );
182 TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr );
184 if (!local)
186 if (samba_init())
188 ULONG size = 1024;
190 for (;;)
192 if (!(*bufptr = malloc( size ))) return ERROR_OUTOFMEMORY;
193 ret = samba_funcs->server_getinfo( servername, level, *bufptr, &size );
194 if (ret) free( *bufptr );
195 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
198 FIXME( "remote computers not supported\n" );
199 return ERROR_INVALID_LEVEL;
201 if (!bufptr) return ERROR_INVALID_PARAMETER;
203 switch (level)
205 case 100:
206 case 101:
208 DWORD computerNameLen, size;
209 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
211 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
212 GetComputerNameW(computerName, &computerNameLen);
213 computerNameLen++; /* include NULL terminator */
215 /* Plus 1 for empty comment */
216 size = sizeof(SERVER_INFO_101) + (computerNameLen + 1) * sizeof(WCHAR);
217 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
218 if (ret == NERR_Success)
220 /* INFO_100 structure is a subset of INFO_101 */
221 PSERVER_INFO_101 info = (PSERVER_INFO_101)*bufptr;
222 OSVERSIONINFOW verInfo;
224 info->sv101_platform_id = PLATFORM_ID_NT;
225 info->sv101_name = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101));
226 memcpy(info->sv101_name, computerName,
227 computerNameLen * sizeof(WCHAR));
228 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
229 GetVersionExW(&verInfo);
230 info->sv101_version_major = verInfo.dwMajorVersion;
231 info->sv101_version_minor = verInfo.dwMinorVersion;
232 /* Use generic type as no wine equivalent of DC / Server */
233 info->sv101_type = SV_TYPE_NT;
234 info->sv101_comment = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101)
235 + computerNameLen * sizeof(WCHAR));
236 info->sv101_comment[0] = '\0';
238 break;
241 default:
242 FIXME("level %d unimplemented\n", level);
243 ret = ERROR_INVALID_LEVEL;
245 return ret;
249 /************************************************************
250 * NetStatisticsGet (NETAPI32.@)
252 NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
253 DWORD level, DWORD options,
254 LPBYTE *bufptr)
256 int res;
257 union
259 STAT_WORKSTATION_0 workst;
260 STAT_SERVER_0 server;
261 } *stat;
262 void *dataptr;
264 TRACE("(server %s, service %s, level %d, options %d, buffer %p): stub\n",
265 debugstr_w(server), debugstr_w(service), level, options, bufptr);
267 res = NetApiBufferAllocate(sizeof(*stat), &dataptr);
268 if (res != NERR_Success) return res;
270 res = NERR_InternalError;
271 stat = dataptr;
272 switch (level)
274 case 0:
275 if (!wcscmp( service, L"Lanman Workstation" ))
277 /* Fill the struct STAT_WORKSTATION_0 properly */
278 memset(&stat->workst, 0, sizeof(stat->workst));
279 res = NERR_Success;
281 else if (!wcscmp( service, L"Lanman Server" ))
283 /* Fill the struct STAT_SERVER_0 properly */
284 memset(&stat->server, 0, sizeof(stat->server));
285 res = NERR_Success;
287 break;
289 if (res != NERR_Success)
290 NetApiBufferFree(dataptr);
291 else
292 *bufptr = dataptr;
294 return res;
297 NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize,
298 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle)
300 FIXME("stub (%p, %d, %p, %d, %p, %p, %p)\n", server, level, bufptr, prefmaxsize,
301 entriesread, totalentries, resumehandle);
302 return ERROR_NOT_SUPPORTED;
305 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
307 TRACE("(%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
308 return NetrJobAdd(server, (AT_INFO *)bufptr, jobid);
311 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
313 TRACE("(%s, %u, %u)\n", debugstr_w(server), minjobid, maxjobid);
314 return NetrJobDel(server, minjobid, maxjobid);
317 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
318 LPDWORD totalentries, LPDWORD resumehandle)
320 AT_ENUM_CONTAINER container;
321 NET_API_STATUS ret;
323 TRACE("(%s, %p, %u, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
325 container.EntriesRead = 0;
326 container.Buffer = NULL;
327 ret = NetrJobEnum(server, &container, prefmaxsize, totalentries, resumehandle);
328 if (ret == ERROR_SUCCESS)
330 *bufptr = (LPBYTE)container.Buffer;
331 *entriesread = container.EntriesRead;
333 return ret;
336 NET_API_STATUS WINAPI NetScheduleJobGetInfo(LPCWSTR server, DWORD jobid, LPBYTE *bufptr)
338 TRACE("(%s, %u, %p)\n", debugstr_w(server), jobid, bufptr);
339 return NetrJobGetInfo(server, jobid, (LPAT_INFO *)bufptr);
342 NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
344 FIXME("stub (%p, %p, %d, %p)\n", server, name, level, bufptr);
345 return ERROR_NOT_SUPPORTED;
349 /************************************************************
350 * NetApiBufferAllocate (NETAPI32.@)
352 NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
354 TRACE("(%d, %p)\n", ByteCount, Buffer);
356 if (Buffer == NULL) return ERROR_INVALID_PARAMETER;
357 *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
358 if (*Buffer)
359 return NERR_Success;
360 else
361 return GetLastError();
364 /************************************************************
365 * NetApiBufferFree (NETAPI32.@)
367 NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
369 TRACE("(%p)\n", Buffer);
370 MIDL_user_free(Buffer);
371 return NERR_Success;
374 /************************************************************
375 * NetApiBufferReallocate (NETAPI32.@)
377 NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
378 LPVOID* NewBuffer)
380 TRACE("(%p, %d, %p)\n", OldBuffer, NewByteCount, NewBuffer);
381 if (NewByteCount)
383 if (OldBuffer)
384 *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
385 else
386 *NewBuffer = HeapAlloc(GetProcessHeap(), 0, NewByteCount);
387 return *NewBuffer ? NERR_Success : GetLastError();
389 else
391 if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
392 *NewBuffer = 0;
393 return NERR_Success;
397 /************************************************************
398 * NetApiBufferSize (NETAPI32.@)
400 NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
402 DWORD dw;
404 TRACE("(%p, %p)\n", Buffer, ByteCount);
405 if (Buffer == NULL)
406 return ERROR_INVALID_PARAMETER;
407 dw = HeapSize(GetProcessHeap(), 0, Buffer);
408 TRACE("size: %d\n", dw);
409 if (dw != 0xFFFFFFFF)
410 *ByteCount = dw;
411 else
412 *ByteCount = 0;
414 return NERR_Success;
417 /************************************************************
418 * NetSessionEnum (NETAPI32.@)
420 * PARAMS
421 * servername [I] Pointer to a string with the name of the server
422 * UncClientName [I] Pointer to a string with the name of the session
423 * username [I] Pointer to a string with the name of the user
424 * level [I] Data information level
425 * bufptr [O] Buffer to the data
426 * prefmaxlen [I] Preferred maximum length of the data
427 * entriesread [O] Pointer to the number of entries enumerated
428 * totalentries [O] Pointer to the possible number of entries
429 * resume_handle [I/O] Pointer to a handle for subsequent searches
431 * RETURNS
432 * If successful, the function returns NERR_Success
433 * On failure it returns:
434 * ERROR_ACCESS_DENIED User has no access to the requested information
435 * ERROR_INVALID_LEVEL Value of 'level' is not correct
436 * ERROR_INVALID_PARAMETER Wrong parameter
437 * ERROR_MORE_DATA Need a larger buffer
438 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
439 * NERR_ClientNameNotFound A session does not exist on a given computer
440 * NERR_InvalidComputer Invalid computer name
441 * NERR_UserNotFound User name could not be found.
443 NET_API_STATUS WINAPI NetSessionEnum(LMSTR servername, LMSTR UncClientName,
444 LMSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread,
445 LPDWORD totalentries, LPDWORD resume_handle)
447 FIXME("Stub (%s %s %s %d %p %d %p %p %p)\n", debugstr_w(servername),
448 debugstr_w(UncClientName), debugstr_w(username),
449 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
451 return NERR_Success;
454 /************************************************************
455 * NetShareEnum (NETAPI32.@)
457 * PARAMS
458 * servername [I] Pointer to a string with the name of the server
459 * level [I] Data information level
460 * bufptr [O] Buffer to the data
461 * prefmaxlen [I] Preferred maximum length of the data
462 * entriesread [O] Pointer to the number of entries enumerated
463 * totalentries [O] Pointer to the possible number of entries
464 * resume_handle [I/O] Pointer to a handle for subsequent searches
466 * RETURNS
467 * If successful, the function returns NERR_Success
468 * On failure it returns a system error code (FIXME: find out which)
471 NET_API_STATUS WINAPI NetShareEnum( LMSTR servername, DWORD level, LPBYTE* bufptr,
472 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
474 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(servername), level, bufptr,
475 prefmaxlen, entriesread, totalentries, resume_handle);
477 return ERROR_NOT_SUPPORTED;
480 /************************************************************
481 * NetShareDel (NETAPI32.@)
483 NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserved)
485 BOOL local = NETAPI_IsLocalComputer( servername );
487 TRACE("%s %s %d\n", debugstr_w(servername), debugstr_w(netname), reserved);
489 if (!local)
491 if (samba_init()) return samba_funcs->share_del( servername, netname, reserved );
492 FIXME( "remote computers not supported\n" );
495 FIXME("%s %s %d\n", debugstr_w(servername), debugstr_w(netname), reserved);
496 return NERR_Success;
499 /************************************************************
500 * NetShareGetInfo (NETAPI32.@)
502 NET_API_STATUS WINAPI NetShareGetInfo(LMSTR servername, LMSTR netname,
503 DWORD level, LPBYTE *bufptr)
505 FIXME("Stub (%s %s %d %p)\n", debugstr_w(servername),
506 debugstr_w(netname),level, bufptr);
507 return NERR_NetNameNotFound;
510 /************************************************************
511 * NetShareAdd (NETAPI32.@)
513 NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
514 DWORD level, LPBYTE buf, LPDWORD parm_err)
516 BOOL local = NETAPI_IsLocalComputer( servername );
518 TRACE("%s %d %p %p\n", debugstr_w(servername), level, buf, parm_err);
520 if (!local)
522 if (samba_init()) return samba_funcs->share_add( servername, level, buf, parm_err );
523 FIXME( "remote computers not supported\n" );
526 FIXME("%s %d %p %p\n", debugstr_w(servername), level, buf, parm_err);
527 return ERROR_NOT_SUPPORTED;
530 /************************************************************
531 * NetFileEnum (NETAPI32.@)
533 NET_API_STATUS WINAPI NetFileEnum(
534 LPWSTR ServerName, LPWSTR BasePath, LPWSTR UserName,
535 DWORD Level, LPBYTE* BufPtr, DWORD PrefMaxLen,
536 LPDWORD EntriesRead, LPDWORD TotalEntries, PDWORD_PTR ResumeHandle)
538 FIXME("(%s, %s, %s, %u): stub\n", debugstr_w(ServerName), debugstr_w(BasePath),
539 debugstr_w(UserName), Level);
540 return ERROR_NOT_SUPPORTED;
543 static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)
545 int i;
546 unsigned char val;
548 if (!buffer)
549 return;
550 if (len < 1)
551 return;
552 if (!ifRow)
554 *buffer = '\0';
555 return;
558 for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
560 val = ifRow->bPhysAddr[i];
561 if ((val >>4) >9)
562 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
563 else
564 buffer[2*i] = (WCHAR)((val >>4) + '0');
565 if ((val & 0xf ) >9)
566 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
567 else
568 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
570 buffer[2*i]=0;
573 /* Theoretically this could be too short, except that MS defines
574 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
575 * represent a count of WCHARs, so even with an extraordinarily long header
576 * this will be plenty
578 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
579 #define MAX_TRANSPORT_ADDR 13
581 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
582 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
584 static void wprint_name(WCHAR *buffer, int len, ULONG transport,
585 PMIB_IFROW ifRow)
587 WCHAR *ptr1, *ptr2;
588 const char *name;
590 if (!buffer)
591 return;
592 if (!ifRow)
594 *buffer = '\0';
595 return;
598 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
599 name = NBT_TRANSPORT_NAME_HEADER;
600 else
601 name = UNKNOWN_TRANSPORT_NAME_HEADER;
603 for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
604 *ptr1 = *name;
605 for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
606 *ptr1 = *ptr2;
607 *ptr1 = '\0';
610 /***********************************************************************
611 * NetWkstaTransportEnum (NETAPI32.@)
614 struct WkstaTransportEnumData
616 UCHAR n_adapt;
617 UCHAR n_read;
618 DWORD prefmaxlen;
619 LPBYTE *pbuf;
620 NET_API_STATUS ret;
623 /**********************************************************************/
625 static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
626 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
628 BOOL ret;
629 struct WkstaTransportEnumData *enumData = closure;
631 if (enumData && enumData->pbuf)
633 if (lanaIndex == 0)
635 DWORD toAllocate;
637 enumData->n_adapt = totalLANAs;
638 enumData->n_read = 0;
640 toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
641 + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
642 MAX_TRANSPORT_ADDR * sizeof(WCHAR));
643 if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
644 toAllocate = enumData->prefmaxlen;
645 NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
647 if (*(enumData->pbuf))
649 UCHAR spaceFor;
651 if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
652 spaceFor = totalLANAs;
653 else
654 spaceFor = enumData->prefmaxlen /
655 (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
656 MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
657 if (enumData->n_read < spaceFor)
659 PWKSTA_TRANSPORT_INFO_0 ti;
660 LMSTR transport_name, transport_addr;
661 MIB_IFROW ifRow;
663 ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
664 enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
665 transport_name = (LMSTR)(*(enumData->pbuf) +
666 totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
667 enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
668 transport_addr = (LMSTR)(*(enumData->pbuf) +
669 totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
670 MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
671 enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
673 ifRow.dwIndex = data->ifIndex;
674 GetIfEntry(&ifRow);
675 ti->wkti0_quality_of_service = 0;
676 ti->wkti0_number_of_vcs = 0;
677 ti->wkti0_transport_name = transport_name;
678 wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
679 transport, &ifRow);
680 ti->wkti0_transport_address = transport_addr;
681 wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
682 &ifRow);
683 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
684 ti->wkti0_wan_ish = TRUE;
685 else
686 ti->wkti0_wan_ish = FALSE;
687 TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
688 TRACE("transport_name at %p %s\n",
689 ti->wkti0_transport_name,
690 debugstr_w(ti->wkti0_transport_name));
691 TRACE("transport_address at %p %s\n",
692 ti->wkti0_transport_address,
693 debugstr_w(ti->wkti0_transport_address));
694 enumData->n_read++;
695 enumData->ret = NERR_Success;
696 ret = TRUE;
698 else
700 enumData->ret = ERROR_MORE_DATA;
701 ret = FALSE;
704 else
706 enumData->ret = ERROR_OUTOFMEMORY;
707 ret = FALSE;
710 else
711 ret = FALSE;
712 return ret;
715 /**********************************************************************/
717 NET_API_STATUS WINAPI
718 NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
719 DWORD prefmaxlen, LPDWORD read_entries,
720 PDWORD total_entries, PDWORD hresume)
722 NET_API_STATUS ret;
724 TRACE(":%s, 0x%08x, %p, 0x%08x, %p, %p, %p\n", debugstr_w(ServerName),
725 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
726 if (!NETAPI_IsLocalComputer(ServerName))
728 FIXME(":not implemented for non-local computers\n");
729 ret = ERROR_INVALID_LEVEL;
731 else
733 if (hresume && *hresume)
735 FIXME(":resume handle not implemented\n");
736 return ERROR_INVALID_LEVEL;
739 switch (level)
741 case 0: /* transport info */
743 ULONG allTransports;
744 struct WkstaTransportEnumData enumData;
746 if (NetBIOSNumAdapters() == 0)
747 return ERROR_NETWORK_UNREACHABLE;
748 if (!read_entries)
749 return STATUS_ACCESS_VIOLATION;
750 if (!total_entries || !pbuf)
751 return RPC_X_NULL_REF_POINTER;
753 enumData.prefmaxlen = prefmaxlen;
754 enumData.pbuf = pbuf;
755 memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
756 NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
757 &enumData);
758 *read_entries = enumData.n_read;
759 *total_entries = enumData.n_adapt;
760 if (hresume) *hresume= 0;
761 ret = enumData.ret;
762 break;
764 default:
765 TRACE("Invalid level %d is specified\n", level);
766 ret = ERROR_INVALID_LEVEL;
769 return ret;
772 /************************************************************
773 * NetWkstaUserGetInfo (NETAPI32.@)
775 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
776 PBYTE* bufptr)
778 NET_API_STATUS nastatus;
780 TRACE("(%s, %d, %p)\n", debugstr_w(reserved), level, bufptr);
781 switch (level)
783 case 0:
785 PWKSTA_USER_INFO_0 ui;
786 DWORD dwSize = UNLEN + 1;
788 /* set up buffer */
789 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
790 (LPVOID *) bufptr);
791 if (nastatus != NERR_Success)
792 return ERROR_NOT_ENOUGH_MEMORY;
794 ui = (PWKSTA_USER_INFO_0) *bufptr;
795 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
797 /* get data */
798 if (!GetUserNameW(ui->wkui0_username, &dwSize))
800 NetApiBufferFree(ui);
801 return ERROR_NOT_ENOUGH_MEMORY;
803 else {
804 nastatus = NetApiBufferReallocate(
805 *bufptr, sizeof(WKSTA_USER_INFO_0) +
806 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
807 (LPVOID *) bufptr);
808 if (nastatus != NERR_Success)
810 NetApiBufferFree(ui);
811 return nastatus;
813 ui = (PWKSTA_USER_INFO_0) *bufptr;
814 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
816 break;
819 case 1:
821 PWKSTA_USER_INFO_1 ui;
822 PWKSTA_USER_INFO_0 ui0;
823 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
824 LSA_HANDLE PolicyHandle;
825 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
826 NTSTATUS NtStatus;
828 /* sizes of the field buffers in WCHARS */
829 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
831 FIXME("Level 1 processing is partially implemented\n");
832 oth_domains_sz = 1;
833 logon_server_sz = 1;
835 /* get some information first to estimate size of the buffer */
836 ui0 = NULL;
837 nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
838 if (nastatus != NERR_Success)
839 return nastatus;
840 username_sz = lstrlenW(ui0->wkui0_username) + 1;
842 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
843 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
844 POLICY_VIEW_LOCAL_INFORMATION,
845 &PolicyHandle);
846 if (NtStatus != STATUS_SUCCESS)
848 TRACE("LsaOpenPolicyFailed with NT status %x\n",
849 LsaNtStatusToWinError(NtStatus));
850 NetApiBufferFree(ui0);
851 return ERROR_NOT_ENOUGH_MEMORY;
853 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
854 (PVOID*) &DomainInfo);
855 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
856 LsaClose(PolicyHandle);
858 /* set up buffer */
859 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
860 (username_sz + logon_domain_sz +
861 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
862 (LPVOID *) bufptr);
863 if (nastatus != NERR_Success) {
864 NetApiBufferFree(ui0);
865 return nastatus;
867 ui = (WKSTA_USER_INFO_1 *) *bufptr;
868 ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
869 ui->wkui1_logon_domain = (LMSTR) (
870 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
871 ui->wkui1_oth_domains = (LMSTR) (
872 ((PBYTE) ui->wkui1_logon_domain) +
873 logon_domain_sz * sizeof(WCHAR));
874 ui->wkui1_logon_server = (LMSTR) (
875 ((PBYTE) ui->wkui1_oth_domains) +
876 oth_domains_sz * sizeof(WCHAR));
878 /* get data */
879 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
880 NetApiBufferFree(ui0);
882 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
883 logon_domain_sz);
884 LsaFreeMemory(DomainInfo);
886 /* FIXME. Not implemented. Populated with empty strings */
887 ui->wkui1_oth_domains[0] = 0;
888 ui->wkui1_logon_server[0] = 0;
889 break;
891 case 1101:
893 PWKSTA_USER_INFO_1101 ui;
894 DWORD dwSize = 1;
896 FIXME("Stub. Level 1101 processing is not implemented\n");
897 /* FIXME see also wkui1_oth_domains for level 1 */
899 /* set up buffer */
900 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
901 (LPVOID *) bufptr);
902 if (nastatus != NERR_Success)
903 return nastatus;
904 ui = (PWKSTA_USER_INFO_1101) *bufptr;
905 ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
907 /* get data */
908 ui->wkui1101_oth_domains[0] = 0;
909 break;
911 default:
912 TRACE("Invalid level %d is specified\n", level);
913 return ERROR_INVALID_LEVEL;
915 return NERR_Success;
918 /************************************************************
919 * NetWkstaUserEnum (NETAPI32.@)
921 NET_API_STATUS WINAPI
922 NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr,
923 DWORD prefmaxlen, LPDWORD entriesread,
924 LPDWORD totalentries, LPDWORD resumehandle)
926 FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername),
927 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
928 return ERROR_INVALID_PARAMETER;
931 /************************************************************
932 * NetpGetComputerName (NETAPI32.@)
934 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
936 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
938 TRACE("(%p)\n", Buffer);
939 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
940 if (GetComputerNameW(*Buffer, &dwSize))
942 return NetApiBufferReallocate(
943 *Buffer, (dwSize + 1) * sizeof(WCHAR),
944 (LPVOID *) Buffer);
946 else
948 NetApiBufferFree(*Buffer);
949 return ERROR_NOT_ENOUGH_MEMORY;
953 NET_API_STATUS WINAPI I_NetNameCompare(LPVOID p1, LPWSTR wkgrp, LPWSTR comp,
954 LPVOID p4, LPVOID p5)
956 FIXME("(%p %s %s %p %p): stub\n", p1, debugstr_w(wkgrp), debugstr_w(comp),
957 p4, p5);
958 return ERROR_INVALID_PARAMETER;
961 NET_API_STATUS WINAPI I_NetNameValidate(LPVOID p1, LPWSTR wkgrp, LPVOID p3,
962 LPVOID p4)
964 FIXME("(%p %s %p %p): stub\n", p1, debugstr_w(wkgrp), p3, p4);
965 return ERROR_INVALID_PARAMETER;
968 NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
969 LPBYTE* bufptr)
971 NET_API_STATUS ret;
972 BOOL local = NETAPI_IsLocalComputer( servername );
974 TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr );
976 if (!local)
978 if (samba_init())
980 ULONG size = 1024;
982 for (;;)
984 if (!(*bufptr = malloc( size ))) return ERROR_OUTOFMEMORY;
985 ret = samba_funcs->wksta_getinfo( servername, level, *bufptr, &size );
986 if (ret) free( *bufptr );
987 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
990 FIXME( "remote computers not supported\n" );
991 return ERROR_INVALID_LEVEL;
993 if (!bufptr) return ERROR_INVALID_PARAMETER;
995 switch (level)
997 case 100:
998 case 101:
999 case 102:
1001 static const WCHAR lanroot[] = L"c:\\lanman"; /* FIXME */
1002 DWORD computerNameLen, domainNameLen, size;
1003 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1004 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1005 LSA_HANDLE PolicyHandle;
1006 NTSTATUS NtStatus;
1008 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1009 GetComputerNameW(computerName, &computerNameLen);
1010 computerNameLen++; /* include NULL terminator */
1012 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1013 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1014 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
1015 if (NtStatus != STATUS_SUCCESS)
1016 ret = LsaNtStatusToWinError(NtStatus);
1017 else
1019 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1021 LsaQueryInformationPolicy(PolicyHandle,
1022 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
1023 domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1024 size = sizeof(WKSTA_INFO_102) + computerNameLen * sizeof(WCHAR)
1025 + domainNameLen * sizeof(WCHAR) + sizeof(lanroot);
1026 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1027 if (ret == NERR_Success)
1029 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1030 PWKSTA_INFO_102 info = (PWKSTA_INFO_102)*bufptr;
1031 OSVERSIONINFOW verInfo;
1033 info->wki102_platform_id = PLATFORM_ID_NT;
1034 info->wki102_computername = (LMSTR)(*bufptr +
1035 sizeof(WKSTA_INFO_102));
1036 memcpy(info->wki102_computername, computerName,
1037 computerNameLen * sizeof(WCHAR));
1038 info->wki102_langroup = info->wki102_computername + computerNameLen;
1039 memcpy(info->wki102_langroup, DomainInfo->DomainName.Buffer,
1040 domainNameLen * sizeof(WCHAR));
1041 info->wki102_lanroot = info->wki102_langroup + domainNameLen;
1042 memcpy(info->wki102_lanroot, lanroot, sizeof(lanroot));
1043 memset(&verInfo, 0, sizeof(verInfo));
1044 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1045 GetVersionExW(&verInfo);
1046 info->wki102_ver_major = verInfo.dwMajorVersion;
1047 info->wki102_ver_minor = verInfo.dwMinorVersion;
1048 info->wki102_logged_on_users = 1;
1050 LsaFreeMemory(DomainInfo);
1051 LsaClose(PolicyHandle);
1053 break;
1056 default:
1057 FIXME("level %d unimplemented\n", level);
1058 ret = ERROR_INVALID_LEVEL;
1060 return ret;
1063 /************************************************************
1064 * NetGetJoinInformation (NETAPI32.@)
1066 NET_API_STATUS NET_API_FUNCTION NetGetJoinInformation(
1067 LPCWSTR Server,
1068 LPWSTR *Name,
1069 PNETSETUP_JOIN_STATUS type)
1071 static const WCHAR workgroupW[] = L"Workgroup";
1073 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server), Name, type);
1075 if (!Name || !type)
1076 return ERROR_INVALID_PARAMETER;
1078 NetApiBufferAllocate(sizeof(workgroupW), (LPVOID *)Name);
1079 lstrcpyW(*Name, workgroupW);
1080 *type = NetSetupWorkgroupName;
1082 return NERR_Success;
1085 /************************************************************
1086 * NetUserGetGroups (NETAPI32.@)
1088 NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
1089 LPCWSTR servername,
1090 LPCWSTR username,
1091 DWORD level,
1092 LPBYTE *bufptr,
1093 DWORD prefixmaxlen,
1094 LPDWORD entriesread,
1095 LPDWORD totalentries)
1097 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
1098 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
1099 totalentries);
1101 *bufptr = NULL;
1102 *entriesread = 0;
1103 *totalentries = 0;
1105 return ERROR_INVALID_LEVEL;
1108 struct sam_user
1110 struct list entry;
1111 WCHAR user_name[LM20_UNLEN+1];
1112 WCHAR user_password[PWLEN + 1];
1113 DWORD sec_since_passwd_change;
1114 DWORD user_priv;
1115 LPWSTR home_dir;
1116 LPWSTR user_comment;
1117 DWORD user_flags;
1118 LPWSTR user_logon_script_path;
1121 static struct list user_list = LIST_INIT( user_list );
1123 /************************************************************
1124 * NETAPI_ValidateServername
1126 * Validates server name
1128 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
1130 if (ServerName)
1132 if (ServerName[0] == 0)
1133 return ERROR_BAD_NETPATH;
1134 else if (
1135 ((ServerName[0] == '\\') &&
1136 (ServerName[1] != '\\'))
1138 ((ServerName[0] == '\\') &&
1139 (ServerName[1] == '\\') &&
1140 (ServerName[2] == 0))
1142 return ERROR_INVALID_NAME;
1144 return NERR_Success;
1147 /************************************************************
1148 * NETAPI_FindUser
1150 * Looks for a user in the user database.
1151 * Returns a pointer to the entry in the user list when the user
1152 * is found, NULL otherwise.
1154 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
1156 struct sam_user *user;
1158 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
1160 if(wcscmp(user->user_name, UserName) == 0)
1161 return user;
1163 return NULL;
1166 static BOOL NETAPI_IsCurrentUser(LPCWSTR username)
1168 LPWSTR curr_user = NULL;
1169 DWORD dwSize;
1170 BOOL ret = FALSE;
1172 dwSize = LM20_UNLEN+1;
1173 curr_user = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
1174 if(!curr_user)
1176 ERR("Failed to allocate memory for user name.\n");
1177 goto end;
1179 if(!GetUserNameW(curr_user, &dwSize))
1181 ERR("Failed to get current user's user name.\n");
1182 goto end;
1184 if (!wcscmp(curr_user, username))
1186 ret = TRUE;
1189 end:
1190 HeapFree(GetProcessHeap(), 0, curr_user);
1191 return ret;
1194 /************************************************************
1195 * NetUserAdd (NETAPI32.@)
1197 NET_API_STATUS WINAPI NetUserAdd(LPCWSTR servername,
1198 DWORD level, LPBYTE bufptr, LPDWORD parm_err)
1200 NET_API_STATUS status;
1201 struct sam_user * su = NULL;
1203 FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err);
1205 if((status = NETAPI_ValidateServername(servername)) != NERR_Success)
1206 return status;
1208 switch(level)
1210 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
1211 case 4:
1212 case 3:
1213 FIXME("Level 3 and 4 not implemented.\n");
1214 /* Fall through */
1215 case 2:
1216 FIXME("Level 2 not implemented.\n");
1217 /* Fall through */
1218 case 1:
1220 PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
1221 su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
1222 if(!su)
1224 status = NERR_InternalError;
1225 break;
1228 if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
1230 status = NERR_BadUsername;
1231 break;
1234 /*FIXME: do other checks for a valid username */
1235 lstrcpyW(su->user_name, ui->usri1_name);
1237 if(lstrlenW(ui->usri1_password) > PWLEN)
1239 /* Always return PasswordTooShort on invalid passwords. */
1240 status = NERR_PasswordTooShort;
1241 break;
1243 lstrcpyW(su->user_password, ui->usri1_password);
1245 su->sec_since_passwd_change = ui->usri1_password_age;
1246 su->user_priv = ui->usri1_priv;
1247 su->user_flags = ui->usri1_flags;
1249 /*FIXME: set the other LPWSTRs to NULL for now */
1250 su->home_dir = NULL;
1251 su->user_comment = NULL;
1252 su->user_logon_script_path = NULL;
1254 list_add_head(&user_list, &su->entry);
1255 return NERR_Success;
1257 default:
1258 TRACE("Invalid level %d specified.\n", level);
1259 status = ERROR_INVALID_LEVEL;
1260 break;
1263 HeapFree(GetProcessHeap(), 0, su);
1265 return status;
1268 /************************************************************
1269 * NetUserDel (NETAPI32.@)
1271 NET_API_STATUS WINAPI NetUserDel(LPCWSTR servername, LPCWSTR username)
1273 NET_API_STATUS status;
1274 struct sam_user *user;
1276 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
1278 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
1279 return status;
1281 if ((user = NETAPI_FindUser(username)) == NULL)
1282 return NERR_UserNotFound;
1284 list_remove(&user->entry);
1286 HeapFree(GetProcessHeap(), 0, user->home_dir);
1287 HeapFree(GetProcessHeap(), 0, user->user_comment);
1288 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
1289 HeapFree(GetProcessHeap(), 0, user);
1291 return NERR_Success;
1294 /************************************************************
1295 * NetUserGetInfo (NETAPI32.@)
1297 NET_API_STATUS WINAPI
1298 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
1299 LPBYTE* bufptr)
1301 NET_API_STATUS status;
1302 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername), debugstr_w(username),
1303 level, bufptr);
1304 status = NETAPI_ValidateServername(servername);
1305 if (status != NERR_Success)
1306 return status;
1308 if(!NETAPI_IsLocalComputer(servername))
1310 FIXME("Only implemented for local computer, but remote server"
1311 "%s was requested.\n", debugstr_w(servername));
1312 return NERR_InvalidComputer;
1315 if(!NETAPI_FindUser(username) && !NETAPI_IsCurrentUser(username))
1317 TRACE("User %s is unknown.\n", debugstr_w(username));
1318 return NERR_UserNotFound;
1321 switch (level)
1323 case 0:
1325 PUSER_INFO_0 ui;
1326 int name_sz;
1328 name_sz = lstrlenW(username) + 1;
1330 /* set up buffer */
1331 NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
1332 (LPVOID *) bufptr);
1334 ui = (PUSER_INFO_0) *bufptr;
1335 ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
1337 /* get data */
1338 lstrcpyW(ui->usri0_name, username);
1339 break;
1342 case 10:
1344 PUSER_INFO_10 ui;
1345 PUSER_INFO_0 ui0;
1346 /* sizes of the field buffers in WCHARS */
1347 int name_sz, comment_sz, usr_comment_sz, full_name_sz;
1349 comment_sz = 1;
1350 usr_comment_sz = 1;
1351 full_name_sz = 1;
1353 /* get data */
1354 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1355 if (status != NERR_Success)
1357 NetApiBufferFree(ui0);
1358 return status;
1360 name_sz = lstrlenW(ui0->usri0_name) + 1;
1362 /* set up buffer */
1363 NetApiBufferAllocate(sizeof(USER_INFO_10) +
1364 (name_sz + comment_sz + usr_comment_sz +
1365 full_name_sz) * sizeof(WCHAR),
1366 (LPVOID *) bufptr);
1367 ui = (PUSER_INFO_10) *bufptr;
1368 ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
1369 ui->usri10_comment = (LPWSTR) (
1370 ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
1371 ui->usri10_usr_comment = (LPWSTR) (
1372 ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
1373 ui->usri10_full_name = (LPWSTR) (
1374 ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
1376 /* set data */
1377 lstrcpyW(ui->usri10_name, ui0->usri0_name);
1378 NetApiBufferFree(ui0);
1379 ui->usri10_comment[0] = 0;
1380 ui->usri10_usr_comment[0] = 0;
1381 ui->usri10_full_name[0] = 0;
1382 break;
1385 case 1:
1387 PUSER_INFO_1 ui;
1388 PUSER_INFO_0 ui0;
1389 /* sizes of the field buffers in WCHARS */
1390 int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
1392 password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
1393 comment_sz = 1;
1394 script_path_sz = 1;
1396 /* get data */
1397 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1398 if (status != NERR_Success)
1400 NetApiBufferFree(ui0);
1401 return status;
1403 name_sz = lstrlenW(ui0->usri0_name) + 1;
1404 home_dir_sz = GetEnvironmentVariableW(L"HOME", NULL,0);
1405 /* set up buffer */
1406 NetApiBufferAllocate(sizeof(USER_INFO_1) +
1407 (name_sz + password_sz + home_dir_sz +
1408 comment_sz + script_path_sz) * sizeof(WCHAR),
1409 (LPVOID *) bufptr);
1411 ui = (PUSER_INFO_1) *bufptr;
1412 ui->usri1_name = (LPWSTR) (ui + 1);
1413 ui->usri1_password = ui->usri1_name + name_sz;
1414 ui->usri1_home_dir = ui->usri1_password + password_sz;
1415 ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
1416 ui->usri1_script_path = ui->usri1_comment + comment_sz;
1417 /* set data */
1418 lstrcpyW(ui->usri1_name, ui0->usri0_name);
1419 NetApiBufferFree(ui0);
1420 ui->usri1_password[0] = 0;
1421 ui->usri1_password_age = 0;
1422 ui->usri1_priv = 0;
1423 GetEnvironmentVariableW(L"HOME", ui->usri1_home_dir,home_dir_sz);
1424 ui->usri1_comment[0] = 0;
1425 ui->usri1_flags = 0;
1426 ui->usri1_script_path[0] = 0;
1427 break;
1429 case 2:
1430 case 3:
1431 case 4:
1432 case 11:
1433 case 20:
1434 case 23:
1435 case 1003:
1436 case 1005:
1437 case 1006:
1438 case 1007:
1439 case 1008:
1440 case 1009:
1441 case 1010:
1442 case 1011:
1443 case 1012:
1444 case 1013:
1445 case 1014:
1446 case 1017:
1447 case 1018:
1448 case 1020:
1449 case 1023:
1450 case 1024:
1451 case 1025:
1452 case 1051:
1453 case 1052:
1454 case 1053:
1456 FIXME("Level %d is not implemented\n", level);
1457 return NERR_InternalError;
1459 default:
1460 TRACE("Invalid level %d is specified\n", level);
1461 return ERROR_INVALID_LEVEL;
1463 return NERR_Success;
1466 /************************************************************
1467 * NetUserGetLocalGroups (NETAPI32.@)
1469 NET_API_STATUS WINAPI
1470 NetUserGetLocalGroups(LPCWSTR servername, LPCWSTR username, DWORD level,
1471 DWORD flags, LPBYTE* bufptr, DWORD prefmaxlen,
1472 LPDWORD entriesread, LPDWORD totalentries)
1474 static const WCHAR admins[] = L"Administrators";
1475 NET_API_STATUS status;
1476 LPWSTR currentuser;
1477 LOCALGROUP_USERS_INFO_0* info;
1478 DWORD size;
1480 FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
1481 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
1482 prefmaxlen, entriesread, totalentries);
1484 status = NETAPI_ValidateServername(servername);
1485 if (status != NERR_Success)
1486 return status;
1488 size = UNLEN + 1;
1489 NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)&currentuser);
1490 if (!GetUserNameW(currentuser, &size)) {
1491 NetApiBufferFree(currentuser);
1492 return ERROR_NOT_ENOUGH_MEMORY;
1495 if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
1497 NetApiBufferFree(currentuser);
1498 return NERR_UserNotFound;
1501 NetApiBufferFree(currentuser);
1502 *totalentries = 1;
1503 size = sizeof(*info) + sizeof(admins);
1505 if(prefmaxlen < size)
1506 status = ERROR_MORE_DATA;
1507 else
1508 status = NetApiBufferAllocate(size, (LPVOID*)&info);
1510 if(status != NERR_Success)
1512 *bufptr = NULL;
1513 *entriesread = 0;
1514 return status;
1517 info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
1518 lstrcpyW(info->lgrui0_name, admins);
1520 *bufptr = (LPBYTE)info;
1521 *entriesread = 1;
1523 return NERR_Success;
1526 /************************************************************
1527 * NetUserEnum (NETAPI32.@)
1529 NET_API_STATUS WINAPI
1530 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
1531 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
1532 LPDWORD resume_handle)
1534 NET_API_STATUS status;
1535 WCHAR user[UNLEN + 1];
1536 DWORD size, len = ARRAY_SIZE(user);
1538 TRACE("(%s, %u, 0x%x, %p, %u, %p, %p, %p)\n", debugstr_w(servername), level,
1539 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1541 status = NETAPI_ValidateServername(servername);
1542 if (status != NERR_Success)
1543 return status;
1545 if (!NETAPI_IsLocalComputer(servername))
1547 FIXME("Only implemented for local computer, but remote server"
1548 "%s was requested.\n", debugstr_w(servername));
1549 return NERR_InvalidComputer;
1552 if (!GetUserNameW(user, &len)) return GetLastError();
1554 switch (level)
1556 case 0:
1558 USER_INFO_0 *info;
1560 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1562 if (prefmaxlen < size)
1563 status = ERROR_MORE_DATA;
1564 else
1565 status = NetApiBufferAllocate(size, (void **)&info);
1567 if (status != NERR_Success)
1568 return status;
1570 info->usri0_name = (WCHAR *)((char *)info + sizeof(*info));
1571 wcscpy(info->usri0_name, user);
1573 *bufptr = (BYTE *)info;
1574 *entriesread = *totalentries = 1;
1575 break;
1577 case 20:
1579 USER_INFO_20 *info;
1580 SID *sid;
1581 UCHAR *count;
1582 DWORD *rid;
1583 SID_NAME_USE use;
1585 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1587 if (prefmaxlen < size)
1588 status = ERROR_MORE_DATA;
1589 else
1590 status = NetApiBufferAllocate(size, (void **)&info);
1592 if (status != NERR_Success)
1593 return status;
1595 size = len = 0;
1596 LookupAccountNameW(NULL, user, NULL, &size, NULL, &len, &use);
1597 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1598 return GetLastError();
1600 status = NetApiBufferAllocate(size, (void **)&sid);
1601 if (status != NERR_Success)
1602 return status;
1604 if (!LookupAccountNameW(NULL, user, sid, &size, NULL, &len, &use))
1605 return GetLastError();
1607 count = GetSidSubAuthorityCount(sid);
1608 rid = GetSidSubAuthority(sid, *count - 1);
1610 info->usri20_name = (WCHAR *)((char *)info + sizeof(*info));
1611 wcscpy(info->usri20_name, user);
1612 info->usri20_full_name = NULL;
1613 info->usri20_comment = NULL;
1614 info->usri20_flags = UF_NORMAL_ACCOUNT;
1615 info->usri20_user_id = *rid;
1617 *bufptr = (BYTE *)info;
1618 *entriesread = *totalentries = 1;
1620 NetApiBufferFree(sid);
1621 break;
1623 default:
1624 FIXME("level %u not supported\n", level);
1625 return ERROR_INVALID_LEVEL;
1627 return NERR_Success;
1630 /************************************************************
1631 * ACCESS_QueryAdminDisplayInformation
1633 * Creates a buffer with information for the Admin User
1635 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1637 static const WCHAR sAdminUserName[] = L"Administrator";
1639 /* sizes of the field buffers in WCHARS */
1640 int name_sz, comment_sz, full_name_sz;
1641 PNET_DISPLAY_USER usr;
1643 /* set up buffer */
1644 name_sz = lstrlenW(sAdminUserName) + 1;
1645 comment_sz = 1;
1646 full_name_sz = 1;
1648 *pdwSize = sizeof(NET_DISPLAY_USER);
1649 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1650 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1652 usr = *buf;
1653 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1654 usr->usri1_comment = (LPWSTR) (
1655 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1656 usr->usri1_full_name = (LPWSTR) (
1657 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1659 /* set data */
1660 lstrcpyW(usr->usri1_name, sAdminUserName);
1661 usr->usri1_comment[0] = 0;
1662 usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1663 usr->usri1_full_name[0] = 0;
1664 usr->usri1_user_id = DOMAIN_USER_RID_ADMIN;
1665 usr->usri1_next_index = 0;
1668 /************************************************************
1669 * ACCESS_QueryGuestDisplayInformation
1671 * Creates a buffer with information for the Guest User
1673 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1675 static const WCHAR sGuestUserName[] = L"Guest";
1677 /* sizes of the field buffers in WCHARS */
1678 int name_sz, comment_sz, full_name_sz;
1679 PNET_DISPLAY_USER usr;
1681 /* set up buffer */
1682 name_sz = lstrlenW(sGuestUserName) + 1;
1683 comment_sz = 1;
1684 full_name_sz = 1;
1686 *pdwSize = sizeof(NET_DISPLAY_USER);
1687 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1688 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1690 usr = *buf;
1691 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1692 usr->usri1_comment = (LPWSTR) (
1693 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1694 usr->usri1_full_name = (LPWSTR) (
1695 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1697 /* set data */
1698 lstrcpyW(usr->usri1_name, sGuestUserName);
1699 usr->usri1_comment[0] = 0;
1700 usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
1701 UF_DONT_EXPIRE_PASSWD;
1702 usr->usri1_full_name[0] = 0;
1703 usr->usri1_user_id = DOMAIN_USER_RID_GUEST;
1704 usr->usri1_next_index = 0;
1707 /************************************************************
1708 * Copies NET_DISPLAY_USER record.
1710 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER *dest, LPWSTR *dest_buf,
1711 PNET_DISPLAY_USER src)
1713 LPWSTR str = *dest_buf;
1715 src->usri1_name = str;
1716 lstrcpyW(src->usri1_name, dest->usri1_name);
1717 str = (LPWSTR) (
1718 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1720 src->usri1_comment = str;
1721 lstrcpyW(src->usri1_comment, dest->usri1_comment);
1722 str = (LPWSTR) (
1723 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1725 src->usri1_flags = dest->usri1_flags;
1727 src->usri1_full_name = str;
1728 lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
1729 str = (LPWSTR) (
1730 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1732 src->usri1_user_id = dest->usri1_user_id;
1733 src->usri1_next_index = dest->usri1_next_index;
1734 *dest_buf = str;
1737 /************************************************************
1738 * NetQueryDisplayInformation (NETAPI32.@)
1740 * The buffer structure:
1741 * - array of fixed size record of the level type
1742 * - strings, referenced by the record of the level type
1744 NET_API_STATUS WINAPI
1745 NetQueryDisplayInformation(
1746 LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
1747 DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
1748 PVOID *SortedBuffer)
1750 TRACE("(%s, %d, %d, %d, %d, %p, %p)\n", debugstr_w(ServerName),
1751 Level, Index, EntriesRequested, PreferredMaximumLength,
1752 ReturnedEntryCount, SortedBuffer);
1754 if(!NETAPI_IsLocalComputer(ServerName))
1756 FIXME("Only implemented on local computer, but requested for "
1757 "remote server %s\n", debugstr_w(ServerName));
1758 return ERROR_ACCESS_DENIED;
1761 switch (Level)
1763 case 1:
1765 /* current record */
1766 PNET_DISPLAY_USER inf;
1767 /* current available strings buffer */
1768 LPWSTR str;
1769 PNET_DISPLAY_USER admin, guest;
1770 DWORD admin_size, guest_size;
1771 LPWSTR name = NULL;
1772 DWORD dwSize;
1774 /* sizes of the field buffers in WCHARS */
1775 int name_sz, comment_sz, full_name_sz;
1777 /* number of the records, returned in SortedBuffer
1778 3 - for current user, Administrator and Guest users
1780 int records = 3;
1782 FIXME("Level %d partially implemented\n", Level);
1783 *ReturnedEntryCount = records;
1784 comment_sz = 1;
1785 full_name_sz = 1;
1787 /* get data */
1788 dwSize = UNLEN + 1;
1789 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &name);
1790 if (!GetUserNameW(name, &dwSize))
1792 NetApiBufferFree(name);
1793 return ERROR_ACCESS_DENIED;
1795 name_sz = dwSize;
1796 ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
1797 ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
1799 /* set up buffer */
1800 dwSize = sizeof(NET_DISPLAY_USER) * records;
1801 dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1803 NetApiBufferAllocate(dwSize +
1804 admin_size - sizeof(NET_DISPLAY_USER) +
1805 guest_size - sizeof(NET_DISPLAY_USER),
1806 SortedBuffer);
1807 inf = *SortedBuffer;
1808 str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
1809 inf->usri1_name = str;
1810 str = (LPWSTR) (
1811 ((PBYTE) str) + name_sz * sizeof(WCHAR));
1812 inf->usri1_comment = str;
1813 str = (LPWSTR) (
1814 ((PBYTE) str) + comment_sz * sizeof(WCHAR));
1815 inf->usri1_full_name = str;
1816 str = (LPWSTR) (
1817 ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
1819 /* set data */
1820 lstrcpyW(inf->usri1_name, name);
1821 NetApiBufferFree(name);
1822 inf->usri1_comment[0] = 0;
1823 inf->usri1_flags =
1824 UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1825 inf->usri1_full_name[0] = 0;
1826 inf->usri1_user_id = 0;
1827 inf->usri1_next_index = 0;
1829 inf++;
1830 ACCESS_CopyDisplayUser(admin, &str, inf);
1831 NetApiBufferFree(admin);
1833 inf++;
1834 ACCESS_CopyDisplayUser(guest, &str, inf);
1835 NetApiBufferFree(guest);
1836 break;
1839 case 2:
1840 case 3:
1842 FIXME("Level %d is not implemented\n", Level);
1843 break;
1846 default:
1847 TRACE("Invalid level %d is specified\n", Level);
1848 return ERROR_INVALID_LEVEL;
1850 return NERR_Success;
1853 /************************************************************
1854 * NetGetDCName (NETAPI32.@)
1856 * Return the name of the primary domain controller (PDC)
1859 NET_API_STATUS WINAPI
1860 NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1862 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1863 debugstr_w(domainname), bufptr);
1864 return NERR_DCNotFound; /* say we can't find a domain controller */
1867 /************************************************************
1868 * NetGetAnyDCName (NETAPI32.@)
1870 * Return the name of any domain controller (DC) for a
1871 * domain that is directly trusted by the specified server
1874 NET_API_STATUS WINAPI NetGetAnyDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1876 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1877 debugstr_w(domainname), bufptr);
1878 return ERROR_NO_SUCH_DOMAIN;
1881 /************************************************************
1882 * NetGroupAddUser (NETAPI32.@)
1884 NET_API_STATUS WINAPI
1885 NetGroupAddUser(LPCWSTR servername, LPCWSTR groupname, LPCWSTR username)
1887 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername),
1888 debugstr_w(groupname), debugstr_w(username));
1889 return NERR_Success;
1892 /************************************************************
1893 * NetGroupEnum (NETAPI32.@)
1896 NET_API_STATUS WINAPI
1897 NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen,
1898 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
1900 FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername),
1901 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1902 return ERROR_ACCESS_DENIED;
1905 /************************************************************
1906 * NetGroupGetInfo (NETAPI32.@)
1909 NET_API_STATUS WINAPI NetGroupGetInfo(LPCWSTR servername, LPCWSTR groupname, DWORD level, LPBYTE *bufptr)
1911 FIXME("(%s, %s, %d, %p) stub!\n", debugstr_w(servername), debugstr_w(groupname), level, bufptr);
1912 return ERROR_ACCESS_DENIED;
1915 /******************************************************************************
1916 * NetUserModalsGet (NETAPI32.@)
1918 * Retrieves global information for all users and global groups in the security
1919 * database.
1921 * PARAMS
1922 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
1923 * on which the function is to execute.
1924 * level [I] Information level of the data.
1925 * 0 Return global passwords parameters. bufptr points to a
1926 * USER_MODALS_INFO_0 struct.
1927 * 1 Return logon server and domain controller information. bufptr
1928 * points to a USER_MODALS_INFO_1 struct.
1929 * 2 Return domain name and identifier. bufptr points to a
1930 * USER_MODALS_INFO_2 struct.
1931 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
1932 * struct.
1933 * pbuffer [I] Buffer that receives the data.
1935 * RETURNS
1936 * Success: NERR_Success.
1937 * Failure:
1938 * ERROR_ACCESS_DENIED - the user does not have access to the info.
1939 * NERR_InvalidComputer - computer name is invalid.
1941 NET_API_STATUS WINAPI NetUserModalsGet(
1942 LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
1944 TRACE("(%s %d %p)\n", debugstr_w(szServer), level, pbuffer);
1946 switch (level)
1948 case 0:
1949 /* return global passwords parameters */
1950 FIXME("level 0 not implemented!\n");
1951 *pbuffer = NULL;
1952 return NERR_InternalError;
1953 case 1:
1954 /* return logon server and domain controller info */
1955 FIXME("level 1 not implemented!\n");
1956 *pbuffer = NULL;
1957 return NERR_InternalError;
1958 case 2:
1960 /* return domain name and identifier */
1961 PUSER_MODALS_INFO_2 umi;
1962 LSA_HANDLE policyHandle;
1963 LSA_OBJECT_ATTRIBUTES objectAttributes;
1964 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo;
1965 NTSTATUS ntStatus;
1966 PSID domainIdentifier = NULL;
1967 int domainNameLen;
1969 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
1970 objectAttributes.Length = sizeof(objectAttributes);
1972 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
1973 POLICY_VIEW_LOCAL_INFORMATION,
1974 &policyHandle);
1975 if (ntStatus != STATUS_SUCCESS)
1977 WARN("LsaOpenPolicy failed with NT status %x\n",
1978 LsaNtStatusToWinError(ntStatus));
1979 return ntStatus;
1982 ntStatus = LsaQueryInformationPolicy(policyHandle,
1983 PolicyAccountDomainInformation,
1984 (PVOID *)&domainInfo);
1985 if (ntStatus != STATUS_SUCCESS)
1987 WARN("LsaQueryInformationPolicy failed with NT status %x\n",
1988 LsaNtStatusToWinError(ntStatus));
1989 LsaClose(policyHandle);
1990 return ntStatus;
1993 domainIdentifier = domainInfo->DomainSid;
1994 domainNameLen = lstrlenW(domainInfo->DomainName.Buffer) + 1;
1995 LsaClose(policyHandle);
1997 ntStatus = NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2) +
1998 GetLengthSid(domainIdentifier) +
1999 domainNameLen * sizeof(WCHAR),
2000 (LPVOID *)pbuffer);
2002 if (ntStatus != NERR_Success)
2004 WARN("NetApiBufferAllocate() failed\n");
2005 LsaFreeMemory(domainInfo);
2006 return ntStatus;
2009 umi = (USER_MODALS_INFO_2 *) *pbuffer;
2010 umi->usrmod2_domain_id = *pbuffer + sizeof(USER_MODALS_INFO_2);
2011 umi->usrmod2_domain_name = (LPWSTR)(*pbuffer +
2012 sizeof(USER_MODALS_INFO_2) + GetLengthSid(domainIdentifier));
2014 lstrcpynW(umi->usrmod2_domain_name,
2015 domainInfo->DomainName.Buffer,
2016 domainNameLen);
2017 CopySid(GetLengthSid(domainIdentifier), umi->usrmod2_domain_id,
2018 domainIdentifier);
2020 LsaFreeMemory(domainInfo);
2022 break;
2024 case 3:
2025 /* return lockout information */
2026 FIXME("level 3 not implemented!\n");
2027 *pbuffer = NULL;
2028 return NERR_InternalError;
2029 default:
2030 TRACE("Invalid level %d is specified\n", level);
2031 *pbuffer = NULL;
2032 return ERROR_INVALID_LEVEL;
2035 return NERR_Success;
2038 /******************************************************************************
2039 * NetUserChangePassword (NETAPI32.@)
2040 * PARAMS
2041 * domainname [I] Optional. Domain on which the user resides or the logon
2042 * domain of the current user if NULL.
2043 * username [I] Optional. Username to change the password for or the name
2044 * of the current user if NULL.
2045 * oldpassword [I] The user's current password.
2046 * newpassword [I] The password that the user will be changed to using.
2048 * RETURNS
2049 * Success: NERR_Success.
2050 * Failure: NERR_* failure code or win error code.
2053 NET_API_STATUS WINAPI NetUserChangePassword(LPCWSTR domainname, LPCWSTR username,
2054 LPCWSTR oldpassword, LPCWSTR newpassword)
2056 struct sam_user *user;
2058 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2060 if (!samba_init()) return ERROR_DLL_INIT_FAILED;
2062 if (!samba_funcs->change_password( domainname, username, oldpassword, newpassword ))
2063 return NERR_Success;
2065 if(domainname)
2066 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
2068 if((user = NETAPI_FindUser(username)) == NULL)
2069 return NERR_UserNotFound;
2071 if(wcscmp(user->user_password, oldpassword) != 0)
2072 return ERROR_INVALID_PASSWORD;
2074 if(lstrlenW(newpassword) > PWLEN)
2075 return ERROR_PASSWORD_RESTRICTION;
2077 lstrcpyW(user->user_password, newpassword);
2079 return NERR_Success;
2082 NET_API_STATUS WINAPI NetUseAdd(LMSTR servername, DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2084 FIXME("%s %d %p %p stub\n", debugstr_w(servername), level, bufptr, parm_err);
2085 return NERR_Success;
2088 NET_API_STATUS WINAPI NetUseDel(LMSTR servername, LMSTR usename, DWORD forcecond)
2090 FIXME("%s %s %d stub\n", debugstr_w(servername), debugstr_w(usename), forcecond);
2091 return NERR_Success;
2094 /************************************************************
2095 * I_BrowserSetNetlogonState (NETAPI32.@)
2097 NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
2098 LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
2099 DWORD Role)
2101 return ERROR_NOT_SUPPORTED;
2104 /************************************************************
2105 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
2107 NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
2108 LPWSTR ServerName, PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
2109 LPDWORD EntriesRead)
2111 return ERROR_NOT_SUPPORTED;
2114 #define NS_MAXDNAME 1025
2116 static DWORD get_dc_info(const WCHAR *domain, WCHAR *dc, WCHAR *ip)
2118 WCHAR name[NS_MAXDNAME];
2119 DWORD ret, size;
2120 DNS_RECORDW *rec;
2122 wcscpy( name, L"_ldap._tcp.dc._msdcs." );
2123 wcscat( name, domain );
2125 ret = DnsQuery_W(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2126 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(domain), ret);
2127 if (ret == ERROR_SUCCESS)
2129 TRACE("target %s, port %d\n", wine_dbgstr_w(rec->Data.Srv.pNameTarget), rec->Data.Srv.wPort);
2131 lstrcpynW(dc, rec->Data.Srv.pNameTarget, NS_MAXDNAME);
2132 DnsRecordListFree(rec, DnsFreeRecordList);
2134 /* IPv4 */
2135 ret = DnsQuery_W(dc, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2136 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc), ret);
2137 if (ret == ERROR_SUCCESS)
2139 SOCKADDR_IN addr;
2141 addr.sin_family = AF_INET;
2142 addr.sin_port = 0;
2143 addr.sin_addr.s_addr = rec->Data.A.IpAddress;
2144 size = IP6_ADDRESS_STRING_LENGTH;
2145 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2146 if (!ret)
2147 TRACE("WSAAddressToStringW => %d, %s\n", ret, wine_dbgstr_w(ip));
2149 DnsRecordListFree(rec, DnsFreeRecordList);
2151 return ret;
2154 /* IPv6 */
2155 ret = DnsQuery_W(dc, DNS_TYPE_AAAA, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2156 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc), ret);
2157 if (ret == ERROR_SUCCESS)
2159 SOCKADDR_IN6 addr;
2161 addr.sin6_family = AF_INET6;
2162 addr.sin6_port = 0;
2163 addr.sin6_scope_id = 0;
2164 memcpy(addr.sin6_addr.s6_addr, &rec->Data.AAAA.Ip6Address, sizeof(rec->Data.AAAA.Ip6Address));
2165 size = IP6_ADDRESS_STRING_LENGTH;
2166 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2167 if (!ret)
2168 TRACE("WSAAddressToStringW => %d, %s\n", ret, wine_dbgstr_w(ip));
2170 DnsRecordListFree(rec, DnsFreeRecordList);
2174 return ret;
2177 DWORD WINAPI DsGetDcNameW(LPCWSTR computer, LPCWSTR domain, GUID *domain_guid,
2178 LPCWSTR site, ULONG flags, PDOMAIN_CONTROLLER_INFOW *dc_info)
2180 static const WCHAR pfxW[] = {'\\','\\'};
2181 static const WCHAR default_site_nameW[] = L"Default-First-Site-Name";
2182 NTSTATUS status;
2183 POLICY_DNS_DOMAIN_INFO *dns_domain_info = NULL;
2184 DOMAIN_CONTROLLER_INFOW *info;
2185 WCHAR dc[NS_MAXDNAME], ip[IP6_ADDRESS_STRING_LENGTH];
2186 DWORD size;
2188 FIXME("(%s, %s, %s, %s, %08x, %p): semi-stub\n", debugstr_w(computer),
2189 debugstr_w(domain), debugstr_guid(domain_guid), debugstr_w(site), flags, dc_info);
2191 if (!dc_info) return ERROR_INVALID_PARAMETER;
2193 if (!domain)
2195 LSA_OBJECT_ATTRIBUTES attrs;
2196 LSA_HANDLE lsa;
2198 memset(&attrs, 0, sizeof(attrs));
2199 attrs.Length = sizeof(attrs);
2200 status = LsaOpenPolicy(NULL, &attrs, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
2201 if (status)
2202 return LsaNtStatusToWinError(status);
2204 status = LsaQueryInformationPolicy(lsa, PolicyDnsDomainInformation, (void **)&dns_domain_info);
2205 LsaClose(lsa);
2206 if (status)
2207 return LsaNtStatusToWinError(status);
2209 domain = dns_domain_info->DnsDomainName.Buffer;
2212 status = get_dc_info(domain, dc, ip);
2213 if (status) return status;
2215 size = sizeof(DOMAIN_CONTROLLER_INFOW) + lstrlenW(domain) * sizeof(WCHAR) +
2216 sizeof(pfxW) * 2 + (lstrlenW(dc) + 1 + lstrlenW(ip) + 1) * sizeof(WCHAR) +
2217 lstrlenW(domain) * sizeof(WCHAR) /* assume forest == domain */ +
2218 sizeof(default_site_nameW) * 2;
2219 status = NetApiBufferAllocate(size, (void **)&info);
2220 if (status != NERR_Success)
2222 LsaFreeMemory(dns_domain_info);
2223 return ERROR_NOT_ENOUGH_MEMORY;
2226 info->DomainControllerName = (WCHAR *)(info + 1);
2227 memcpy(info->DomainControllerName, pfxW, sizeof(pfxW));
2228 lstrcpyW(info->DomainControllerName + 2, dc);
2229 info->DomainControllerAddress = (WCHAR *)((char *)info->DomainControllerName + (wcslen(info->DomainControllerName) + 1) * sizeof(WCHAR));
2230 memcpy(info->DomainControllerAddress, pfxW, sizeof(pfxW));
2231 lstrcpyW(info->DomainControllerAddress + 2, ip);
2232 info->DomainControllerAddressType = DS_INET_ADDRESS;
2233 info->DomainGuid = dns_domain_info ? dns_domain_info->DomainGuid : GUID_NULL /* FIXME */;
2234 info->DomainName = (WCHAR *)((char *)info->DomainControllerAddress + (wcslen(info->DomainControllerAddress) + 1) * sizeof(WCHAR));
2235 lstrcpyW(info->DomainName, domain);
2236 info->DnsForestName = (WCHAR *)((char *)info->DomainName + (lstrlenW(info->DomainName) + 1) * sizeof(WCHAR));
2237 lstrcpyW(info->DnsForestName, domain);
2238 info->DcSiteName = (WCHAR *)((char *)info->DnsForestName + (lstrlenW(info->DnsForestName) + 1) * sizeof(WCHAR));
2239 lstrcpyW(info->DcSiteName, default_site_nameW);
2240 info->ClientSiteName = (WCHAR *)((char *)info->DcSiteName + sizeof(default_site_nameW));
2241 lstrcpyW(info->ClientSiteName, default_site_nameW);
2242 info->Flags = DS_DNS_DOMAIN_FLAG | DS_DNS_FOREST_FLAG;
2244 LsaFreeMemory(dns_domain_info);
2246 *dc_info = info;
2248 return ERROR_SUCCESS;
2251 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
2252 GUID* DomainGuid, LPCSTR SiteName, ULONG Flags,
2253 PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo)
2255 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_a(ComputerName),
2256 debugstr_a(AvoidDCName), debugstr_guid(DomainGuid),
2257 debugstr_a(SiteName), Flags, DomainControllerInfo);
2258 return ERROR_CALL_NOT_IMPLEMENTED;
2261 DWORD WINAPI DsGetSiteNameW(LPCWSTR ComputerName, LPWSTR *SiteName)
2263 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName), SiteName);
2264 return ERROR_CALL_NOT_IMPLEMENTED;
2267 DWORD WINAPI DsGetSiteNameA(LPCSTR ComputerName, LPSTR *SiteName)
2269 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName), SiteName);
2270 return ERROR_CALL_NOT_IMPLEMENTED;
2273 /************************************************************
2274 * DsRoleFreeMemory (NETAPI32.@)
2276 * PARAMS
2277 * Buffer [I] Pointer to the to-be-freed buffer.
2279 * RETURNS
2280 * Nothing
2282 VOID WINAPI DsRoleFreeMemory(PVOID Buffer)
2284 TRACE("(%p)\n", Buffer);
2285 HeapFree(GetProcessHeap(), 0, Buffer);
2288 /************************************************************
2289 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
2291 * PARAMS
2292 * lpServer [I] Pointer to UNICODE string with ComputerName
2293 * InfoLevel [I] Type of data to retrieve
2294 * Buffer [O] Pointer to to the requested data
2296 * RETURNS
2298 * NOTES
2299 * When lpServer is NULL, use the local computer
2301 DWORD WINAPI DsRoleGetPrimaryDomainInformation(
2302 LPCWSTR lpServer, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
2303 PBYTE* Buffer)
2305 DWORD ret;
2307 FIXME("(%p, %d, %p) stub\n", lpServer, InfoLevel, Buffer);
2309 /* Check some input parameters */
2311 if (!Buffer) return ERROR_INVALID_PARAMETER;
2312 if ((InfoLevel < DsRolePrimaryDomainInfoBasic) || (InfoLevel > DsRoleOperationState)) return ERROR_INVALID_PARAMETER;
2314 *Buffer = NULL;
2315 switch (InfoLevel)
2317 case DsRolePrimaryDomainInfoBasic:
2319 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
2320 LSA_HANDLE PolicyHandle;
2321 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
2322 NTSTATUS NtStatus;
2323 int logon_domain_sz;
2324 DWORD size;
2325 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic;
2327 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
2328 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
2329 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
2330 if (NtStatus != STATUS_SUCCESS)
2332 TRACE("LsaOpenPolicyFailed with NT status %x\n",
2333 LsaNtStatusToWinError(NtStatus));
2334 return ERROR_OUTOFMEMORY;
2336 LsaQueryInformationPolicy(PolicyHandle,
2337 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
2338 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
2339 LsaClose(PolicyHandle);
2341 size = sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC) +
2342 logon_domain_sz * sizeof(WCHAR);
2343 basic = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2344 if (basic)
2346 basic->MachineRole = DsRole_RoleStandaloneWorkstation;
2347 basic->DomainNameFlat = (LPWSTR)((LPBYTE)basic +
2348 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
2349 lstrcpyW(basic->DomainNameFlat, DomainInfo->DomainName.Buffer);
2350 ret = ERROR_SUCCESS;
2352 else
2353 ret = ERROR_OUTOFMEMORY;
2354 *Buffer = (PBYTE)basic;
2355 LsaFreeMemory(DomainInfo);
2357 break;
2358 default:
2359 ret = ERROR_CALL_NOT_IMPLEMENTED;
2361 return ret;
2364 /************************************************************
2365 * NetLocalGroupAdd (NETAPI32.@)
2367 NET_API_STATUS WINAPI NetLocalGroupAdd(
2368 LPCWSTR servername,
2369 DWORD level,
2370 LPBYTE buf,
2371 LPDWORD parm_err)
2373 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
2374 parm_err);
2375 return NERR_Success;
2378 /************************************************************
2379 * NetLocalGroupAddMember (NETAPI32.@)
2381 NET_API_STATUS WINAPI NetLocalGroupAddMember(
2382 LPCWSTR servername,
2383 LPCWSTR groupname,
2384 PSID membersid)
2386 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2387 debugstr_w(groupname), membersid);
2388 return NERR_Success;
2391 /************************************************************
2392 * NetLocalGroupAddMembers (NETAPI32.@)
2394 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
2395 LPCWSTR servername,
2396 LPCWSTR groupname,
2397 DWORD level,
2398 LPBYTE buf,
2399 DWORD totalentries)
2401 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
2402 debugstr_w(groupname), level, buf, totalentries);
2403 return NERR_Success;
2406 /************************************************************
2407 * NetLocalGroupDel (NETAPI32.@)
2409 NET_API_STATUS WINAPI NetLocalGroupDel(
2410 LPCWSTR servername,
2411 LPCWSTR groupname)
2413 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
2414 return NERR_Success;
2417 /************************************************************
2418 * NetLocalGroupDelMember (NETAPI32.@)
2420 NET_API_STATUS WINAPI NetLocalGroupDelMember(
2421 LPCWSTR servername,
2422 LPCWSTR groupname,
2423 PSID membersid)
2425 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2426 debugstr_w(groupname), membersid);
2427 return NERR_Success;
2430 /************************************************************
2431 * NetLocalGroupDelMembers (NETAPI32.@)
2433 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
2434 LPCWSTR servername,
2435 LPCWSTR groupname,
2436 DWORD level,
2437 LPBYTE buf,
2438 DWORD totalentries)
2440 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
2441 debugstr_w(groupname), level, buf, totalentries);
2442 return NERR_Success;
2445 /************************************************************
2446 * NetLocalGroupEnum (NETAPI32.@)
2448 NET_API_STATUS WINAPI NetLocalGroupEnum(
2449 LPCWSTR servername,
2450 DWORD level,
2451 LPBYTE* bufptr,
2452 DWORD prefmaxlen,
2453 LPDWORD entriesread,
2454 LPDWORD totalentries,
2455 PDWORD_PTR resumehandle)
2457 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
2458 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
2459 *entriesread = 0;
2460 *totalentries = 0;
2461 return NERR_Success;
2464 /************************************************************
2465 * NetLocalGroupGetInfo (NETAPI32.@)
2467 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
2468 LPCWSTR servername,
2469 LPCWSTR groupname,
2470 DWORD level,
2471 LPBYTE* bufptr)
2473 static const WCHAR commentW[] = L"No comment";
2474 LOCALGROUP_INFO_1* info;
2475 DWORD size;
2477 FIXME("(%s %s %d %p) semi-stub!\n", debugstr_w(servername),
2478 debugstr_w(groupname), level, bufptr);
2480 size = sizeof(*info) + sizeof(WCHAR) * (lstrlenW(groupname)+1) + sizeof(commentW);
2481 NetApiBufferAllocate(size, (LPVOID*)&info);
2483 info->lgrpi1_name = (LPWSTR)(info + 1);
2484 lstrcpyW(info->lgrpi1_name, groupname);
2486 info->lgrpi1_comment = info->lgrpi1_name + lstrlenW(groupname) + 1;
2487 lstrcpyW(info->lgrpi1_comment, commentW);
2489 *bufptr = (LPBYTE)info;
2491 return NERR_Success;
2494 /************************************************************
2495 * NetLocalGroupGetMembers (NETAPI32.@)
2497 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
2498 LPCWSTR servername,
2499 LPCWSTR localgroupname,
2500 DWORD level,
2501 LPBYTE* bufptr,
2502 DWORD prefmaxlen,
2503 LPDWORD entriesread,
2504 LPDWORD totalentries,
2505 PDWORD_PTR resumehandle)
2507 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
2508 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
2509 totalentries, resumehandle);
2511 if (level == 3)
2513 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
2514 DWORD userNameLen;
2515 DWORD len,needlen;
2516 PLOCALGROUP_MEMBERS_INFO_3 ptr;
2518 /* still a stub, current user is belonging to all groups */
2520 *totalentries = 1;
2521 *entriesread = 0;
2523 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
2524 if (!GetUserNameW(userName,&userNameLen))
2525 return ERROR_NOT_ENOUGH_MEMORY;
2527 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
2528 (userNameLen+2) * sizeof(WCHAR);
2529 if (prefmaxlen != MAX_PREFERRED_LENGTH)
2530 len = min(prefmaxlen,needlen);
2531 else
2532 len = needlen;
2534 NetApiBufferAllocate(len, (LPVOID *) bufptr);
2535 if (len < needlen)
2536 return ERROR_MORE_DATA;
2538 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
2539 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
2540 lstrcpyW(ptr->lgrmi3_domainandname,userName);
2542 *entriesread = 1;
2545 return NERR_Success;
2548 /************************************************************
2549 * NetLocalGroupSetInfo (NETAPI32.@)
2551 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
2552 LPCWSTR servername,
2553 LPCWSTR groupname,
2554 DWORD level,
2555 LPBYTE buf,
2556 LPDWORD parm_err)
2558 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
2559 debugstr_w(groupname), level, buf, parm_err);
2560 return NERR_Success;
2563 /************************************************************
2564 * NetLocalGroupSetMember (NETAPI32.@)
2566 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
2567 LPCWSTR servername,
2568 LPCWSTR groupname,
2569 DWORD level,
2570 LPBYTE buf,
2571 DWORD totalentries)
2573 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
2574 debugstr_w(groupname), level, buf, totalentries);
2575 return NERR_Success;
2578 /************************************************************
2579 * DavGetHTTPFromUNCPath (NETAPI32.@)
2581 DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buflen)
2583 static const WCHAR httpW[] = L"http://";
2584 static const WCHAR httpsW[] = L"https://";
2585 const WCHAR *p = unc_path, *q, *server, *path, *scheme = httpW;
2586 UINT i, len_server, len_path = 0, len_port = 0, len, port = 0;
2587 WCHAR *end, portbuf[12];
2589 TRACE("(%s %p %p)\n", debugstr_w(unc_path), buf, buflen);
2591 if (p[0] != '\\' || p[1] != '\\' || !p[2]) return ERROR_INVALID_PARAMETER;
2592 q = p += 2;
2593 while (*q && *q != '\\' && *q != '/' && *q != '@') q++;
2594 server = p;
2595 len_server = q - p;
2596 if (*q == '@')
2598 p = ++q;
2599 while (*p && (*p != '\\' && *p != '/' && *p != '@')) p++;
2600 if (p - q == 3 && !wcsnicmp( q, L"SSL", 3 ))
2602 scheme = httpsW;
2603 q = p;
2605 else if ((port = wcstol( q, &end, 10 ))) q = end;
2606 else return ERROR_INVALID_PARAMETER;
2608 if (*q == '@')
2610 if (!(port = wcstol( ++q, &end, 10 ))) return ERROR_INVALID_PARAMETER;
2611 q = end;
2613 if (*q == '\\' || *q == '/') q++;
2614 path = q;
2615 while (*q++) len_path++;
2616 if (len_path && (path[len_path - 1] == '\\' || path[len_path - 1] == '/'))
2617 len_path--; /* remove trailing slash */
2619 swprintf( portbuf, ARRAY_SIZE(portbuf), L":%u", port );
2620 if (scheme == httpsW)
2622 len = wcslen( httpsW );
2623 if (port && port != 443) len_port = wcslen( portbuf );
2625 else
2627 len = wcslen( httpW );
2628 if (port && port != 80) len_port = wcslen( portbuf );
2630 len += len_server;
2631 len += len_port;
2632 if (len_path) len += len_path + 1; /* leading '/' */
2633 len++; /* nul */
2635 if (*buflen < len)
2637 *buflen = len;
2638 return ERROR_INSUFFICIENT_BUFFER;
2641 memcpy( buf, scheme, wcslen(scheme) * sizeof(WCHAR) );
2642 buf += wcslen( scheme );
2643 memcpy( buf, server, len_server * sizeof(WCHAR) );
2644 buf += len_server;
2645 if (len_port)
2647 memcpy( buf, portbuf, len_port * sizeof(WCHAR) );
2648 buf += len_port;
2650 if (len_path)
2652 *buf++ = '/';
2653 for (i = 0; i < len_path; i++)
2655 if (path[i] == '\\') *buf++ = '/';
2656 else *buf++ = path[i];
2659 *buf = 0;
2660 *buflen = len;
2662 return ERROR_SUCCESS;
2665 /************************************************************
2666 * DavGetUNCFromHTTPPath (NETAPI32.@)
2668 DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen)
2670 static const WCHAR httpW[] = {'h','t','t','p'};
2671 static const WCHAR httpsW[] = {'h','t','t','p','s'};
2672 static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
2673 static const WCHAR sslW[] = {'@','S','S','L'};
2674 static const WCHAR port80W[] = {'8','0'};
2675 static const WCHAR port443W[] = {'4','4','3'};
2676 const WCHAR *p = http_path, *server, *port = NULL, *path = NULL;
2677 DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0;
2678 BOOL ssl;
2680 TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen);
2682 while (*p && *p != ':') { p++; len++; };
2683 if (len == ARRAY_SIZE(httpW) && !wcsnicmp( http_path, httpW, len )) ssl = FALSE;
2684 else if (len == ARRAY_SIZE(httpsW) && !wcsnicmp( http_path, httpsW, len )) ssl = TRUE;
2685 else return ERROR_INVALID_PARAMETER;
2687 if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER;
2688 server = p += 3;
2690 while (*p && *p != ':' && *p != '/') { p++; len_server++; };
2691 if (!len_server) return ERROR_BAD_NET_NAME;
2692 if (*p == ':')
2694 port = ++p;
2695 while (*p >= '0' && *p <= '9') { p++; len_port++; };
2696 if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL;
2697 else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL;
2698 path = p;
2700 else if (*p == '/') path = p;
2702 while (*p)
2704 if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME;
2705 p++; len_path++;
2707 if (len_path && path[len_path - 1] == '/') len_path--;
2709 len = len_server + 2; /* \\ */
2710 if (ssl) len += 4; /* @SSL */
2711 if (port) len += len_port + 1 /* @ */;
2712 len += ARRAY_SIZE(davrootW);
2713 len += len_path + 1; /* nul */
2715 if (*buflen < len)
2717 *buflen = len;
2718 return ERROR_INSUFFICIENT_BUFFER;
2721 buf[0] = buf[1] = '\\';
2722 buf += 2;
2723 memcpy( buf, server, len_server * sizeof(WCHAR) );
2724 buf += len_server;
2725 if (ssl)
2727 memcpy( buf, sslW, sizeof(sslW) );
2728 buf += 4;
2730 if (port)
2732 *buf++ = '@';
2733 memcpy( buf, port, len_port * sizeof(WCHAR) );
2734 buf += len_port;
2736 memcpy( buf, davrootW, sizeof(davrootW) );
2737 buf += ARRAY_SIZE(davrootW);
2738 for (i = 0; i < len_path; i++)
2740 if (path[i] == '/') *buf++ = '\\';
2741 else *buf++ = path[i];
2744 *buf = 0;
2745 *buflen = len;
2747 return ERROR_SUCCESS;
2750 /************************************************************
2751 * DsEnumerateDomainTrustsA (NETAPI32.@)
2753 DWORD WINAPI DsEnumerateDomainTrustsA(LPSTR server, ULONG flags, PDS_DOMAIN_TRUSTSA* domains, PULONG count)
2755 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_a(server), flags, domains, count);
2756 return ERROR_NO_LOGON_SERVERS;
2759 /************************************************************
2760 * DsEnumerateDomainTrustsW (NETAPI32.@)
2762 DWORD WINAPI DsEnumerateDomainTrustsW(LPWSTR server, ULONG flags, PDS_DOMAIN_TRUSTSW* domains, PULONG count)
2764 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_w(server), flags, domains, count);
2765 return ERROR_NO_LOGON_SERVERS;
2768 DECLSPEC_HIDDEN void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
2770 return HeapAlloc(GetProcessHeap(), 0, n);
2773 DECLSPEC_HIDDEN void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
2775 HeapFree(GetProcessHeap(), 0, p);
2778 DECLSPEC_HIDDEN handle_t __RPC_USER ATSVC_HANDLE_bind(ATSVC_HANDLE str)
2780 static unsigned char ncalrpc[] = "ncalrpc";
2781 unsigned char *binding_str;
2782 handle_t rpc_handle = 0;
2784 if (RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str) == RPC_S_OK)
2786 RpcBindingFromStringBindingA(binding_str, &rpc_handle);
2787 RpcStringFreeA(&binding_str);
2789 return rpc_handle;
2792 DECLSPEC_HIDDEN void __RPC_USER ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, handle_t rpc_handle)
2794 RpcBindingFree(&rpc_handle);