include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / netapi32 / netapi32.c
blobf7885f6e2c32a502129ca92f4ab2593850991023
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 "lmremutl.h"
40 #include "lmshare.h"
41 #include "lmwksta.h"
42 #include "netbios.h"
43 #include "ifmib.h"
44 #include "iphlpapi.h"
45 #include "ntsecapi.h"
46 #include "dsrole.h"
47 #include "dsgetdc.h"
48 #include "davclnt.h"
49 #include "wine/debug.h"
50 #include "wine/list.h"
51 #include "initguid.h"
53 #include "unixlib.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
57 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
59 #define SAMBA_CALL(func, args) WINE_UNIX_CALL( unix_ ## func, args )
61 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
63 static BOOL WINAPI load_samba( INIT_ONCE *once, void *param, void **context )
65 SAMBA_CALL( netapi_init, NULL );
66 return TRUE;
69 static BOOL samba_init(void)
71 return __wine_unixlib_handle && InitOnceExecuteOnce( &init_once, load_samba, NULL, NULL );
74 /************************************************************
75 * NETAPI_IsLocalComputer
77 * Checks whether the server name indicates local machine.
79 static BOOL NETAPI_IsLocalComputer( LMCSTR name )
81 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
82 DWORD size = ARRAY_SIZE(buf);
83 BOOL ret;
85 if (!name || !name[0]) return TRUE;
87 ret = GetComputerNameW( buf, &size );
88 if (ret && name[0] == '\\' && name[1] == '\\') name += 2;
89 return ret && !wcsicmp( name, buf );
92 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
94 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
96 switch (fdwReason) {
97 case DLL_PROCESS_ATTACH:
98 __wine_init_unix_call();
99 DisableThreadLibraryCalls(hinstDLL);
100 NetBIOSInit();
101 NetBTInit();
102 break;
103 case DLL_PROCESS_DETACH:
104 if (lpvReserved) break;
105 NetBIOSShutdown();
106 break;
109 return TRUE;
112 /************************************************************
113 * NetServerEnum (NETAPI32.@)
115 NET_API_STATUS WINAPI NetServerEnum(
116 LMCSTR servername,
117 DWORD level,
118 LPBYTE* bufptr,
119 DWORD prefmaxlen,
120 LPDWORD entriesread,
121 LPDWORD totalentries,
122 DWORD servertype,
123 LMCSTR domain,
124 LPDWORD resume_handle
127 FIXME("Stub (%s %ld %p %ld %p %p %ld %s %p)\n", debugstr_w(servername),
128 level, bufptr, prefmaxlen, entriesread, totalentries, servertype,
129 debugstr_w(domain), resume_handle);
131 return ERROR_NO_BROWSER_SERVERS_FOUND;
134 /************************************************************
135 * NetServerEnumEx (NETAPI32.@)
137 NET_API_STATUS WINAPI NetServerEnumEx(
138 LMCSTR ServerName,
139 DWORD Level,
140 LPBYTE *Bufptr,
141 DWORD PrefMaxlen,
142 LPDWORD EntriesRead,
143 LPDWORD totalentries,
144 DWORD servertype,
145 LMCSTR domain,
146 LMCSTR FirstNameToReturn)
148 FIXME("Stub (%s %ld %p %ld %p %p %ld %s %s)\n",
149 debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
150 servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
152 return ERROR_NO_BROWSER_SERVERS_FOUND;
155 /************************************************************
156 * NetServerDiskEnum (NETAPI32.@)
158 NET_API_STATUS WINAPI NetServerDiskEnum(
159 LMCSTR ServerName,
160 DWORD Level,
161 LPBYTE *Bufptr,
162 DWORD PrefMaxlen,
163 LPDWORD EntriesRead,
164 LPDWORD totalentries,
165 LPDWORD Resume_Handle)
167 FIXME("Stub (%s %ld %p %ld %p %p %p)\n", debugstr_w(ServerName),
168 Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
170 return ERROR_NO_BROWSER_SERVERS_FOUND;
173 /************************************************************
174 * NetServerGetInfo (NETAPI32.@)
176 NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr)
178 NET_API_STATUS ret;
179 BOOL local = NETAPI_IsLocalComputer( servername );
181 TRACE("%s %ld %p\n", debugstr_w( servername ), level, bufptr );
183 if (!local)
185 if (samba_init())
187 ULONG size = 1024;
188 struct server_getinfo_params params = { servername, level, NULL, &size };
190 for (;;)
192 if (!(params.buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
193 ret = SAMBA_CALL( server_getinfo, &params );
194 if (!ret) *bufptr = params.buffer;
195 else free( params.buffer );
196 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
199 FIXME( "remote computers not supported\n" );
200 return ERROR_INVALID_LEVEL;
202 if (!bufptr) return ERROR_INVALID_PARAMETER;
204 switch (level)
206 case 100:
207 case 101:
209 DWORD computerNameLen, size;
210 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
212 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
213 GetComputerNameW(computerName, &computerNameLen);
214 computerNameLen++; /* include NULL terminator */
216 /* Plus 1 for empty comment */
217 size = sizeof(SERVER_INFO_101) + (computerNameLen + 1) * sizeof(WCHAR);
218 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
219 if (ret == NERR_Success)
221 /* INFO_100 structure is a subset of INFO_101 */
222 PSERVER_INFO_101 info = (PSERVER_INFO_101)*bufptr;
223 OSVERSIONINFOW verInfo;
225 info->sv101_platform_id = PLATFORM_ID_NT;
226 info->sv101_name = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101));
227 memcpy(info->sv101_name, computerName,
228 computerNameLen * sizeof(WCHAR));
229 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
230 GetVersionExW(&verInfo);
231 info->sv101_version_major = verInfo.dwMajorVersion;
232 info->sv101_version_minor = verInfo.dwMinorVersion;
233 /* Use generic type as no wine equivalent of DC / Server */
234 info->sv101_type = SV_TYPE_NT;
235 info->sv101_comment = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101)
236 + computerNameLen * sizeof(WCHAR));
237 info->sv101_comment[0] = '\0';
239 break;
242 default:
243 FIXME("level %ld unimplemented\n", level);
244 ret = ERROR_INVALID_LEVEL;
246 return ret;
250 /************************************************************
251 * NetStatisticsGet (NETAPI32.@)
253 NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
254 DWORD level, DWORD options,
255 LPBYTE *bufptr)
257 int res;
258 union
260 STAT_WORKSTATION_0 workst;
261 STAT_SERVER_0 server;
262 } *stat;
263 void *dataptr;
265 TRACE("(server %s, service %s, level %ld, options %ld, buffer %p): stub\n",
266 debugstr_w(server), debugstr_w(service), level, options, bufptr);
268 res = NetApiBufferAllocate(sizeof(*stat), &dataptr);
269 if (res != NERR_Success) return res;
271 res = NERR_InternalError;
272 stat = dataptr;
273 switch (level)
275 case 0:
276 if (!wcscmp( service, L"Lanman Workstation" ))
278 /* Fill the struct STAT_WORKSTATION_0 properly */
279 memset(&stat->workst, 0, sizeof(stat->workst));
280 res = NERR_Success;
282 else if (!wcscmp( service, L"Lanman Server" ))
284 /* Fill the struct STAT_SERVER_0 properly */
285 memset(&stat->server, 0, sizeof(stat->server));
286 res = NERR_Success;
288 break;
290 if (res != NERR_Success)
291 NetApiBufferFree(dataptr);
292 else
293 *bufptr = dataptr;
295 return res;
298 NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize,
299 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle)
301 FIXME("stub (%p, %ld, %p, %ld, %p, %p, %p)\n", server, level, bufptr, prefmaxsize,
302 entriesread, totalentries, resumehandle);
303 return ERROR_NOT_SUPPORTED;
306 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
308 TRACE("(%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
309 return NetrJobAdd(server, (AT_INFO *)bufptr, jobid);
312 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
314 TRACE("(%s, %lu, %lu)\n", debugstr_w(server), minjobid, maxjobid);
315 return NetrJobDel(server, minjobid, maxjobid);
318 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
319 LPDWORD totalentries, LPDWORD resumehandle)
321 AT_ENUM_CONTAINER container;
322 NET_API_STATUS ret;
324 TRACE("(%s, %p, %lu, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
326 container.EntriesRead = 0;
327 container.Buffer = NULL;
328 ret = NetrJobEnum(server, &container, prefmaxsize, totalentries, resumehandle);
329 if (ret == ERROR_SUCCESS)
331 *bufptr = (LPBYTE)container.Buffer;
332 *entriesread = container.EntriesRead;
334 return ret;
337 NET_API_STATUS WINAPI NetScheduleJobGetInfo(LPCWSTR server, DWORD jobid, LPBYTE *bufptr)
339 TRACE("(%s, %lu, %p)\n", debugstr_w(server), jobid, bufptr);
340 return NetrJobGetInfo(server, jobid, (LPAT_INFO *)bufptr);
343 NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
345 FIXME("stub (%p, %p, %ld, %p)\n", server, name, level, bufptr);
346 return ERROR_NOT_SUPPORTED;
350 /************************************************************
351 * NetApiBufferAllocate (NETAPI32.@)
353 NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
355 TRACE("(%ld, %p)\n", ByteCount, Buffer);
357 if (Buffer == NULL) return ERROR_INVALID_PARAMETER;
358 *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
359 if (*Buffer)
360 return NERR_Success;
361 else
362 return GetLastError();
365 /************************************************************
366 * NetApiBufferFree (NETAPI32.@)
368 NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
370 TRACE("(%p)\n", Buffer);
371 MIDL_user_free(Buffer);
372 return NERR_Success;
375 /************************************************************
376 * NetApiBufferReallocate (NETAPI32.@)
378 NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
379 LPVOID* NewBuffer)
381 TRACE("(%p, %ld, %p)\n", OldBuffer, NewByteCount, NewBuffer);
382 if (NewByteCount)
384 if (OldBuffer)
385 *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
386 else
387 *NewBuffer = HeapAlloc(GetProcessHeap(), 0, NewByteCount);
388 return *NewBuffer ? NERR_Success : GetLastError();
390 else
392 if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
393 *NewBuffer = 0;
394 return NERR_Success;
398 /************************************************************
399 * NetApiBufferSize (NETAPI32.@)
401 NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
403 DWORD dw;
405 TRACE("(%p, %p)\n", Buffer, ByteCount);
406 if (Buffer == NULL)
407 return ERROR_INVALID_PARAMETER;
408 dw = HeapSize(GetProcessHeap(), 0, Buffer);
409 TRACE("size: %ld\n", dw);
410 if (dw != 0xFFFFFFFF)
411 *ByteCount = dw;
412 else
413 *ByteCount = 0;
415 return NERR_Success;
418 /************************************************************
419 * NetSessionEnum (NETAPI32.@)
421 * PARAMS
422 * servername [I] Pointer to a string with the name of the server
423 * UncClientName [I] Pointer to a string with the name of the session
424 * username [I] Pointer to a string with the name of the user
425 * level [I] Data information level
426 * bufptr [O] Buffer to the data
427 * prefmaxlen [I] Preferred maximum length of the data
428 * entriesread [O] Pointer to the number of entries enumerated
429 * totalentries [O] Pointer to the possible number of entries
430 * resume_handle [I/O] Pointer to a handle for subsequent searches
432 * RETURNS
433 * If successful, the function returns NERR_Success
434 * On failure it returns:
435 * ERROR_ACCESS_DENIED User has no access to the requested information
436 * ERROR_INVALID_LEVEL Value of 'level' is not correct
437 * ERROR_INVALID_PARAMETER Wrong parameter
438 * ERROR_MORE_DATA Need a larger buffer
439 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
440 * NERR_ClientNameNotFound A session does not exist on a given computer
441 * NERR_InvalidComputer Invalid computer name
442 * NERR_UserNotFound User name could not be found.
444 NET_API_STATUS WINAPI NetSessionEnum(LMSTR servername, LMSTR UncClientName,
445 LMSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread,
446 LPDWORD totalentries, LPDWORD resume_handle)
448 FIXME("Stub (%s %s %s %ld %p %ld %p %p %p)\n", debugstr_w(servername),
449 debugstr_w(UncClientName), debugstr_w(username),
450 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
452 return NERR_Success;
455 /************************************************************
456 * NetShareEnum (NETAPI32.@)
458 * PARAMS
459 * servername [I] Pointer to a string with the name of the server
460 * level [I] Data information level
461 * bufptr [O] Buffer to the data
462 * prefmaxlen [I] Preferred maximum length of the data
463 * entriesread [O] Pointer to the number of entries enumerated
464 * totalentries [O] Pointer to the possible number of entries
465 * resume_handle [I/O] Pointer to a handle for subsequent searches
467 * RETURNS
468 * If successful, the function returns NERR_Success
469 * On failure it returns a system error code (FIXME: find out which)
472 NET_API_STATUS WINAPI NetShareEnum( LMSTR servername, DWORD level, LPBYTE* bufptr,
473 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
475 FIXME("Stub (%s %ld %p %ld %p %p %p)\n", debugstr_w(servername), level, bufptr,
476 prefmaxlen, entriesread, totalentries, resume_handle);
478 return ERROR_NOT_SUPPORTED;
481 /************************************************************
482 * NetShareDel (NETAPI32.@)
484 NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserved)
486 BOOL local = NETAPI_IsLocalComputer( servername );
488 TRACE("%s %s %ld\n", debugstr_w(servername), debugstr_w(netname), reserved);
490 if (!local)
492 if (samba_init())
494 struct share_del_params params = { servername, netname, reserved };
495 return SAMBA_CALL( share_del, &params );
497 FIXME( "remote computers not supported\n" );
500 FIXME("%s %s %ld\n", debugstr_w(servername), debugstr_w(netname), reserved);
501 return NERR_Success;
504 /************************************************************
505 * NetShareGetInfo (NETAPI32.@)
507 NET_API_STATUS WINAPI NetShareGetInfo(LMSTR servername, LMSTR netname,
508 DWORD level, LPBYTE *bufptr)
510 FIXME("Stub (%s %s %ld %p)\n", debugstr_w(servername),
511 debugstr_w(netname),level, bufptr);
512 return NERR_NetNameNotFound;
515 /************************************************************
516 * NetShareAdd (NETAPI32.@)
518 NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
519 DWORD level, LPBYTE buf, LPDWORD parm_err)
521 BOOL local = NETAPI_IsLocalComputer( servername );
523 TRACE("%s %ld %p %p\n", debugstr_w(servername), level, buf, parm_err);
525 if (!local)
527 if (samba_init())
529 struct share_add_params params = { servername, level, buf, parm_err };
530 return SAMBA_CALL( share_add, &params );
532 FIXME( "remote computers not supported\n" );
535 FIXME("%s %ld %p %p\n", debugstr_w(servername), level, buf, parm_err);
536 return ERROR_NOT_SUPPORTED;
539 /************************************************************
540 * NetFileEnum (NETAPI32.@)
542 NET_API_STATUS WINAPI NetFileEnum(
543 LPWSTR ServerName, LPWSTR BasePath, LPWSTR UserName,
544 DWORD Level, LPBYTE* BufPtr, DWORD PrefMaxLen,
545 LPDWORD EntriesRead, LPDWORD TotalEntries, PDWORD_PTR ResumeHandle)
547 FIXME("(%s, %s, %s, %lu): stub\n", debugstr_w(ServerName), debugstr_w(BasePath),
548 debugstr_w(UserName), Level);
549 return ERROR_NOT_SUPPORTED;
552 static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)
554 int i;
555 unsigned char val;
557 if (!buffer)
558 return;
559 if (len < 1)
560 return;
561 if (!ifRow)
563 *buffer = '\0';
564 return;
567 for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
569 val = ifRow->bPhysAddr[i];
570 if ((val >>4) >9)
571 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
572 else
573 buffer[2*i] = (WCHAR)((val >>4) + '0');
574 if ((val & 0xf ) >9)
575 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
576 else
577 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
579 buffer[2*i]=0;
582 /* Theoretically this could be too short, except that MS defines
583 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
584 * represent a count of WCHARs, so even with an extraordinarily long header
585 * this will be plenty
587 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
588 #define MAX_TRANSPORT_ADDR 13
590 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
591 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
593 static void wprint_name(WCHAR *buffer, int len, ULONG transport,
594 PMIB_IFROW ifRow)
596 WCHAR *ptr1, *ptr2;
597 const char *name;
599 if (!buffer)
600 return;
601 if (!ifRow)
603 *buffer = '\0';
604 return;
607 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
608 name = NBT_TRANSPORT_NAME_HEADER;
609 else
610 name = UNKNOWN_TRANSPORT_NAME_HEADER;
612 for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
613 *ptr1 = *name;
614 for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
615 *ptr1 = *ptr2;
616 *ptr1 = '\0';
619 /***********************************************************************
620 * NetWkstaTransportEnum (NETAPI32.@)
623 struct WkstaTransportEnumData
625 UCHAR n_adapt;
626 UCHAR n_read;
627 DWORD prefmaxlen;
628 LPBYTE *pbuf;
629 NET_API_STATUS ret;
632 /**********************************************************************/
634 static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
635 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
637 BOOL ret;
638 struct WkstaTransportEnumData *enumData = closure;
640 if (enumData && enumData->pbuf)
642 if (lanaIndex == 0)
644 DWORD toAllocate;
646 enumData->n_adapt = totalLANAs;
647 enumData->n_read = 0;
649 toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
650 + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
651 MAX_TRANSPORT_ADDR * sizeof(WCHAR));
652 if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
653 toAllocate = enumData->prefmaxlen;
654 NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
656 if (*(enumData->pbuf))
658 UCHAR spaceFor;
660 if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
661 spaceFor = totalLANAs;
662 else
663 spaceFor = enumData->prefmaxlen /
664 (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
665 MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
666 if (enumData->n_read < spaceFor)
668 PWKSTA_TRANSPORT_INFO_0 ti;
669 LMSTR transport_name, transport_addr;
670 MIB_IFROW ifRow;
672 ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
673 enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
674 transport_name = (LMSTR)(*(enumData->pbuf) +
675 totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
676 enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
677 transport_addr = (LMSTR)(*(enumData->pbuf) +
678 totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
679 MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
680 enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
682 ifRow.dwIndex = data->ifIndex;
683 GetIfEntry(&ifRow);
684 ti->wkti0_quality_of_service = 0;
685 ti->wkti0_number_of_vcs = 0;
686 ti->wkti0_transport_name = transport_name;
687 wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
688 transport, &ifRow);
689 ti->wkti0_transport_address = transport_addr;
690 wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
691 &ifRow);
692 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
693 ti->wkti0_wan_ish = TRUE;
694 else
695 ti->wkti0_wan_ish = FALSE;
696 TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
697 TRACE("transport_name at %p %s\n",
698 ti->wkti0_transport_name,
699 debugstr_w(ti->wkti0_transport_name));
700 TRACE("transport_address at %p %s\n",
701 ti->wkti0_transport_address,
702 debugstr_w(ti->wkti0_transport_address));
703 enumData->n_read++;
704 enumData->ret = NERR_Success;
705 ret = TRUE;
707 else
709 enumData->ret = ERROR_MORE_DATA;
710 ret = FALSE;
713 else
715 enumData->ret = ERROR_OUTOFMEMORY;
716 ret = FALSE;
719 else
720 ret = FALSE;
721 return ret;
724 /**********************************************************************/
726 NET_API_STATUS WINAPI
727 NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
728 DWORD prefmaxlen, LPDWORD read_entries,
729 PDWORD total_entries, PDWORD hresume)
731 NET_API_STATUS ret;
733 TRACE(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName),
734 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
735 if (!NETAPI_IsLocalComputer(ServerName))
737 FIXME(":not implemented for non-local computers\n");
738 ret = ERROR_INVALID_LEVEL;
740 else
742 if (hresume && *hresume)
744 FIXME(":resume handle not implemented\n");
745 return ERROR_INVALID_LEVEL;
748 switch (level)
750 case 0: /* transport info */
752 ULONG allTransports;
753 struct WkstaTransportEnumData enumData;
755 if (NetBIOSNumAdapters() == 0)
756 return ERROR_NETWORK_UNREACHABLE;
757 if (!read_entries)
758 return STATUS_ACCESS_VIOLATION;
759 if (!total_entries || !pbuf)
760 return RPC_X_NULL_REF_POINTER;
762 enumData.prefmaxlen = prefmaxlen;
763 enumData.pbuf = pbuf;
764 memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
765 NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
766 &enumData);
767 *read_entries = enumData.n_read;
768 *total_entries = enumData.n_adapt;
769 if (hresume) *hresume= 0;
770 ret = enumData.ret;
771 break;
773 default:
774 TRACE("Invalid level %ld is specified\n", level);
775 ret = ERROR_INVALID_LEVEL;
778 return ret;
781 /************************************************************
782 * NetWkstaUserGetInfo (NETAPI32.@)
784 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
785 PBYTE* bufptr)
787 NET_API_STATUS nastatus;
789 TRACE("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr);
790 switch (level)
792 case 0:
794 PWKSTA_USER_INFO_0 ui;
795 DWORD dwSize = UNLEN + 1;
797 /* set up buffer */
798 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
799 (LPVOID *) bufptr);
800 if (nastatus != NERR_Success)
801 return ERROR_NOT_ENOUGH_MEMORY;
803 ui = (PWKSTA_USER_INFO_0) *bufptr;
804 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
806 /* get data */
807 if (!GetUserNameW(ui->wkui0_username, &dwSize))
809 NetApiBufferFree(ui);
810 return ERROR_NOT_ENOUGH_MEMORY;
812 else {
813 nastatus = NetApiBufferReallocate(
814 *bufptr, sizeof(WKSTA_USER_INFO_0) +
815 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
816 (LPVOID *) bufptr);
817 if (nastatus != NERR_Success)
819 NetApiBufferFree(ui);
820 return nastatus;
822 ui = (PWKSTA_USER_INFO_0) *bufptr;
823 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
825 break;
828 case 1:
830 PWKSTA_USER_INFO_1 ui;
831 PWKSTA_USER_INFO_0 ui0;
832 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
833 LSA_HANDLE PolicyHandle;
834 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
835 NTSTATUS NtStatus;
837 /* sizes of the field buffers in WCHARS */
838 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
840 FIXME("Level 1 processing is partially implemented\n");
841 oth_domains_sz = 1;
842 logon_server_sz = 1;
844 /* get some information first to estimate size of the buffer */
845 ui0 = NULL;
846 nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
847 if (nastatus != NERR_Success)
848 return nastatus;
849 username_sz = lstrlenW(ui0->wkui0_username) + 1;
851 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
852 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
853 POLICY_VIEW_LOCAL_INFORMATION,
854 &PolicyHandle);
855 if (NtStatus != STATUS_SUCCESS)
857 TRACE("LsaOpenPolicyFailed with NT status %lx\n",
858 LsaNtStatusToWinError(NtStatus));
859 NetApiBufferFree(ui0);
860 return ERROR_NOT_ENOUGH_MEMORY;
862 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
863 (PVOID*) &DomainInfo);
864 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
865 LsaClose(PolicyHandle);
867 /* set up buffer */
868 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
869 (username_sz + logon_domain_sz +
870 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
871 (LPVOID *) bufptr);
872 if (nastatus != NERR_Success) {
873 NetApiBufferFree(ui0);
874 return nastatus;
876 ui = (WKSTA_USER_INFO_1 *) *bufptr;
877 ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
878 ui->wkui1_logon_domain = (LMSTR) (
879 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
880 ui->wkui1_oth_domains = (LMSTR) (
881 ((PBYTE) ui->wkui1_logon_domain) +
882 logon_domain_sz * sizeof(WCHAR));
883 ui->wkui1_logon_server = (LMSTR) (
884 ((PBYTE) ui->wkui1_oth_domains) +
885 oth_domains_sz * sizeof(WCHAR));
887 /* get data */
888 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
889 NetApiBufferFree(ui0);
891 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
892 logon_domain_sz);
893 LsaFreeMemory(DomainInfo);
895 /* FIXME. Not implemented. Populated with empty strings */
896 ui->wkui1_oth_domains[0] = 0;
897 ui->wkui1_logon_server[0] = 0;
898 break;
900 case 1101:
902 PWKSTA_USER_INFO_1101 ui;
903 DWORD dwSize = 1;
905 FIXME("Stub. Level 1101 processing is not implemented\n");
906 /* FIXME see also wkui1_oth_domains for level 1 */
908 /* set up buffer */
909 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
910 (LPVOID *) bufptr);
911 if (nastatus != NERR_Success)
912 return nastatus;
913 ui = (PWKSTA_USER_INFO_1101) *bufptr;
914 ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
916 /* get data */
917 ui->wkui1101_oth_domains[0] = 0;
918 break;
920 default:
921 TRACE("Invalid level %ld is specified\n", level);
922 return ERROR_INVALID_LEVEL;
924 return NERR_Success;
927 /************************************************************
928 * NetWkstaUserEnum (NETAPI32.@)
930 NET_API_STATUS WINAPI
931 NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr,
932 DWORD prefmaxlen, LPDWORD entriesread,
933 LPDWORD totalentries, LPDWORD resumehandle)
935 FIXME("(%s, %ld, %p, %ld, %p, %p, %p): stub!\n", debugstr_w(servername),
936 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
937 return ERROR_INVALID_PARAMETER;
940 /************************************************************
941 * NetpGetComputerName (NETAPI32.@)
943 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
945 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
947 TRACE("(%p)\n", Buffer);
948 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
949 if (GetComputerNameW(*Buffer, &dwSize))
951 return NetApiBufferReallocate(
952 *Buffer, (dwSize + 1) * sizeof(WCHAR),
953 (LPVOID *) Buffer);
955 else
957 NetApiBufferFree(*Buffer);
958 return ERROR_NOT_ENOUGH_MEMORY;
962 NET_API_STATUS WINAPI I_NetNameCompare(LPVOID p1, LPWSTR wkgrp, LPWSTR comp,
963 LPVOID p4, LPVOID p5)
965 FIXME("(%p %s %s %p %p): stub\n", p1, debugstr_w(wkgrp), debugstr_w(comp),
966 p4, p5);
967 return ERROR_INVALID_PARAMETER;
970 NET_API_STATUS WINAPI I_NetNameValidate(LPVOID p1, LPWSTR wkgrp, LPVOID p3,
971 LPVOID p4)
973 FIXME("(%p %s %p %p): stub\n", p1, debugstr_w(wkgrp), p3, p4);
974 return ERROR_INVALID_PARAMETER;
977 NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
978 LPBYTE* bufptr)
980 NET_API_STATUS ret;
981 BOOL local = NETAPI_IsLocalComputer( servername );
983 TRACE("%s %ld %p\n", debugstr_w( servername ), level, bufptr );
985 if (!local)
987 if (samba_init())
989 ULONG size = 1024;
990 struct wksta_getinfo_params params = { servername, level, NULL, &size };
992 for (;;)
994 if (!(params.buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
995 ret = SAMBA_CALL( wksta_getinfo, &params );
996 if (!ret) *bufptr = params.buffer;
997 else free( params.buffer );
998 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
1001 FIXME( "remote computers not supported\n" );
1002 return ERROR_INVALID_LEVEL;
1004 if (!bufptr) return ERROR_INVALID_PARAMETER;
1006 switch (level)
1008 case 100:
1009 case 101:
1010 case 102:
1012 static const WCHAR lanroot[] = L"c:\\lanman"; /* FIXME */
1013 DWORD computerNameLen, domainNameLen, size;
1014 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1015 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1016 LSA_HANDLE PolicyHandle;
1017 NTSTATUS NtStatus;
1019 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1020 GetComputerNameW(computerName, &computerNameLen);
1021 computerNameLen++; /* include NULL terminator */
1023 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1024 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1025 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
1026 if (NtStatus != STATUS_SUCCESS)
1027 ret = LsaNtStatusToWinError(NtStatus);
1028 else
1030 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1032 LsaQueryInformationPolicy(PolicyHandle,
1033 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
1034 domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1035 size = sizeof(WKSTA_INFO_102) + computerNameLen * sizeof(WCHAR)
1036 + domainNameLen * sizeof(WCHAR) + sizeof(lanroot);
1037 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1038 if (ret == NERR_Success)
1040 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1041 PWKSTA_INFO_102 info = (PWKSTA_INFO_102)*bufptr;
1042 OSVERSIONINFOW verInfo;
1044 info->wki102_platform_id = PLATFORM_ID_NT;
1045 info->wki102_computername = (LMSTR)(*bufptr +
1046 sizeof(WKSTA_INFO_102));
1047 memcpy(info->wki102_computername, computerName,
1048 computerNameLen * sizeof(WCHAR));
1049 info->wki102_langroup = info->wki102_computername + computerNameLen;
1050 memcpy(info->wki102_langroup, DomainInfo->DomainName.Buffer,
1051 domainNameLen * sizeof(WCHAR));
1052 info->wki102_lanroot = info->wki102_langroup + domainNameLen;
1053 memcpy(info->wki102_lanroot, lanroot, sizeof(lanroot));
1054 memset(&verInfo, 0, sizeof(verInfo));
1055 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1056 GetVersionExW(&verInfo);
1057 info->wki102_ver_major = verInfo.dwMajorVersion;
1058 info->wki102_ver_minor = verInfo.dwMinorVersion;
1059 info->wki102_logged_on_users = 1;
1061 LsaFreeMemory(DomainInfo);
1062 LsaClose(PolicyHandle);
1064 break;
1067 default:
1068 FIXME("level %ld unimplemented\n", level);
1069 ret = ERROR_INVALID_LEVEL;
1071 return ret;
1074 /************************************************************
1075 * NetGetJoinInformation (NETAPI32.@)
1077 NET_API_STATUS NET_API_FUNCTION NetGetJoinInformation(
1078 LPCWSTR Server,
1079 LPWSTR *Name,
1080 PNETSETUP_JOIN_STATUS type)
1082 static const WCHAR workgroupW[] = L"Workgroup";
1084 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server), Name, type);
1086 if (!Name || !type)
1087 return ERROR_INVALID_PARAMETER;
1089 NetApiBufferAllocate(sizeof(workgroupW), (LPVOID *)Name);
1090 lstrcpyW(*Name, workgroupW);
1091 *type = NetSetupWorkgroupName;
1093 return NERR_Success;
1096 /************************************************************
1097 * NetUserGetGroups (NETAPI32.@)
1099 NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
1100 LPCWSTR servername,
1101 LPCWSTR username,
1102 DWORD level,
1103 LPBYTE *bufptr,
1104 DWORD prefixmaxlen,
1105 LPDWORD entriesread,
1106 LPDWORD totalentries)
1108 FIXME("%s %s %ld %p %ld %p %p stub\n", debugstr_w(servername),
1109 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
1110 totalentries);
1112 *bufptr = NULL;
1113 *entriesread = 0;
1114 *totalentries = 0;
1116 return ERROR_INVALID_LEVEL;
1119 struct sam_user
1121 struct list entry;
1122 WCHAR user_name[LM20_UNLEN+1];
1123 WCHAR user_password[PWLEN + 1];
1124 DWORD sec_since_passwd_change;
1125 DWORD user_priv;
1126 LPWSTR home_dir;
1127 LPWSTR user_comment;
1128 DWORD user_flags;
1129 LPWSTR user_logon_script_path;
1132 static struct list user_list = LIST_INIT( user_list );
1134 /************************************************************
1135 * NETAPI_ValidateServername
1137 * Validates server name
1139 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
1141 if (ServerName)
1143 if (ServerName[0] == 0)
1144 return ERROR_BAD_NETPATH;
1145 else if (
1146 ((ServerName[0] == '\\') &&
1147 (ServerName[1] != '\\'))
1149 ((ServerName[0] == '\\') &&
1150 (ServerName[1] == '\\') &&
1151 (ServerName[2] == 0))
1153 return ERROR_INVALID_NAME;
1155 return NERR_Success;
1158 /************************************************************
1159 * NETAPI_FindUser
1161 * Looks for a user in the user database.
1162 * Returns a pointer to the entry in the user list when the user
1163 * is found, NULL otherwise.
1165 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
1167 struct sam_user *user;
1169 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
1171 if(wcscmp(user->user_name, UserName) == 0)
1172 return user;
1174 return NULL;
1177 static BOOL NETAPI_IsCurrentUser(LPCWSTR username)
1179 LPWSTR curr_user = NULL;
1180 DWORD dwSize;
1181 BOOL ret = FALSE;
1183 dwSize = LM20_UNLEN+1;
1184 curr_user = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
1185 if(!curr_user)
1187 ERR("Failed to allocate memory for user name.\n");
1188 goto end;
1190 if(!GetUserNameW(curr_user, &dwSize))
1192 ERR("Failed to get current user's user name.\n");
1193 goto end;
1195 if (!wcscmp(curr_user, username))
1197 ret = TRUE;
1200 end:
1201 HeapFree(GetProcessHeap(), 0, curr_user);
1202 return ret;
1205 /************************************************************
1206 * NetUserAdd (NETAPI32.@)
1208 NET_API_STATUS WINAPI NetUserAdd(LPCWSTR servername,
1209 DWORD level, LPBYTE bufptr, LPDWORD parm_err)
1211 NET_API_STATUS status;
1212 struct sam_user * su = NULL;
1214 FIXME("(%s, %ld, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err);
1216 if((status = NETAPI_ValidateServername(servername)) != NERR_Success)
1217 return status;
1219 switch(level)
1221 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
1222 case 4:
1223 case 3:
1224 FIXME("Level 3 and 4 not implemented.\n");
1225 /* Fall through */
1226 case 2:
1227 FIXME("Level 2 not implemented.\n");
1228 /* Fall through */
1229 case 1:
1231 PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
1232 su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
1233 if(!su)
1235 status = NERR_InternalError;
1236 break;
1239 if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
1241 status = NERR_BadUsername;
1242 break;
1245 /*FIXME: do other checks for a valid username */
1246 lstrcpyW(su->user_name, ui->usri1_name);
1248 if(lstrlenW(ui->usri1_password) > PWLEN)
1250 /* Always return PasswordTooShort on invalid passwords. */
1251 status = NERR_PasswordTooShort;
1252 break;
1254 lstrcpyW(su->user_password, ui->usri1_password);
1256 su->sec_since_passwd_change = ui->usri1_password_age;
1257 su->user_priv = ui->usri1_priv;
1258 su->user_flags = ui->usri1_flags;
1260 /*FIXME: set the other LPWSTRs to NULL for now */
1261 su->home_dir = NULL;
1262 su->user_comment = NULL;
1263 su->user_logon_script_path = NULL;
1265 list_add_head(&user_list, &su->entry);
1266 return NERR_Success;
1268 default:
1269 TRACE("Invalid level %ld specified.\n", level);
1270 status = ERROR_INVALID_LEVEL;
1271 break;
1274 HeapFree(GetProcessHeap(), 0, su);
1276 return status;
1279 /************************************************************
1280 * NetUserDel (NETAPI32.@)
1282 NET_API_STATUS WINAPI NetUserDel(LPCWSTR servername, LPCWSTR username)
1284 NET_API_STATUS status;
1285 struct sam_user *user;
1287 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
1289 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
1290 return status;
1292 if ((user = NETAPI_FindUser(username)) == NULL)
1293 return NERR_UserNotFound;
1295 list_remove(&user->entry);
1297 HeapFree(GetProcessHeap(), 0, user->home_dir);
1298 HeapFree(GetProcessHeap(), 0, user->user_comment);
1299 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
1300 HeapFree(GetProcessHeap(), 0, user);
1302 return NERR_Success;
1305 /************************************************************
1306 * NetUserGetInfo (NETAPI32.@)
1308 NET_API_STATUS WINAPI
1309 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
1310 LPBYTE* bufptr)
1312 NET_API_STATUS status;
1313 TRACE("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username),
1314 level, bufptr);
1315 status = NETAPI_ValidateServername(servername);
1316 if (status != NERR_Success)
1317 return status;
1319 if(!NETAPI_IsLocalComputer(servername))
1321 FIXME("Only implemented for local computer, but remote server"
1322 "%s was requested.\n", debugstr_w(servername));
1323 return NERR_InvalidComputer;
1326 if(!NETAPI_FindUser(username) && !NETAPI_IsCurrentUser(username))
1328 TRACE("User %s is unknown.\n", debugstr_w(username));
1329 return NERR_UserNotFound;
1332 switch (level)
1334 case 0:
1336 PUSER_INFO_0 ui;
1337 int name_sz;
1339 name_sz = lstrlenW(username) + 1;
1341 /* set up buffer */
1342 NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
1343 (LPVOID *) bufptr);
1345 ui = (PUSER_INFO_0) *bufptr;
1346 ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
1348 /* get data */
1349 lstrcpyW(ui->usri0_name, username);
1350 break;
1353 case 10:
1355 PUSER_INFO_10 ui;
1356 PUSER_INFO_0 ui0;
1357 /* sizes of the field buffers in WCHARS */
1358 int name_sz, comment_sz, usr_comment_sz, full_name_sz;
1360 comment_sz = 1;
1361 usr_comment_sz = 1;
1362 full_name_sz = 1;
1364 /* get data */
1365 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1366 if (status != NERR_Success)
1368 NetApiBufferFree(ui0);
1369 return status;
1371 name_sz = lstrlenW(ui0->usri0_name) + 1;
1373 /* set up buffer */
1374 NetApiBufferAllocate(sizeof(USER_INFO_10) +
1375 (name_sz + comment_sz + usr_comment_sz +
1376 full_name_sz) * sizeof(WCHAR),
1377 (LPVOID *) bufptr);
1378 ui = (PUSER_INFO_10) *bufptr;
1379 ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
1380 ui->usri10_comment = (LPWSTR) (
1381 ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
1382 ui->usri10_usr_comment = (LPWSTR) (
1383 ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
1384 ui->usri10_full_name = (LPWSTR) (
1385 ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
1387 /* set data */
1388 lstrcpyW(ui->usri10_name, ui0->usri0_name);
1389 NetApiBufferFree(ui0);
1390 ui->usri10_comment[0] = 0;
1391 ui->usri10_usr_comment[0] = 0;
1392 ui->usri10_full_name[0] = 0;
1393 break;
1396 case 1:
1398 PUSER_INFO_1 ui;
1399 PUSER_INFO_0 ui0;
1400 /* sizes of the field buffers in WCHARS */
1401 int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
1403 password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
1404 comment_sz = 1;
1405 script_path_sz = 1;
1407 /* get data */
1408 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1409 if (status != NERR_Success)
1411 NetApiBufferFree(ui0);
1412 return status;
1414 name_sz = lstrlenW(ui0->usri0_name) + 1;
1415 home_dir_sz = GetEnvironmentVariableW(L"HOME", NULL,0);
1416 /* set up buffer */
1417 NetApiBufferAllocate(sizeof(USER_INFO_1) +
1418 (name_sz + password_sz + home_dir_sz +
1419 comment_sz + script_path_sz) * sizeof(WCHAR),
1420 (LPVOID *) bufptr);
1422 ui = (PUSER_INFO_1) *bufptr;
1423 ui->usri1_name = (LPWSTR) (ui + 1);
1424 ui->usri1_password = ui->usri1_name + name_sz;
1425 ui->usri1_home_dir = ui->usri1_password + password_sz;
1426 ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
1427 ui->usri1_script_path = ui->usri1_comment + comment_sz;
1428 /* set data */
1429 lstrcpyW(ui->usri1_name, ui0->usri0_name);
1430 NetApiBufferFree(ui0);
1431 ui->usri1_password[0] = 0;
1432 ui->usri1_password_age = 0;
1433 ui->usri1_priv = 0;
1434 GetEnvironmentVariableW(L"HOME", ui->usri1_home_dir,home_dir_sz);
1435 ui->usri1_comment[0] = 0;
1436 ui->usri1_flags = 0;
1437 ui->usri1_script_path[0] = 0;
1438 break;
1440 case 2:
1441 case 3:
1442 case 4:
1443 case 11:
1444 case 20:
1445 case 23:
1446 case 1003:
1447 case 1005:
1448 case 1006:
1449 case 1007:
1450 case 1008:
1451 case 1009:
1452 case 1010:
1453 case 1011:
1454 case 1012:
1455 case 1013:
1456 case 1014:
1457 case 1017:
1458 case 1018:
1459 case 1020:
1460 case 1023:
1461 case 1024:
1462 case 1025:
1463 case 1051:
1464 case 1052:
1465 case 1053:
1467 FIXME("Level %ld is not implemented\n", level);
1468 return NERR_InternalError;
1470 default:
1471 TRACE("Invalid level %ld is specified\n", level);
1472 return ERROR_INVALID_LEVEL;
1474 return NERR_Success;
1477 /************************************************************
1478 * NetUserGetLocalGroups (NETAPI32.@)
1480 NET_API_STATUS WINAPI
1481 NetUserGetLocalGroups(LPCWSTR servername, LPCWSTR username, DWORD level,
1482 DWORD flags, LPBYTE* bufptr, DWORD prefmaxlen,
1483 LPDWORD entriesread, LPDWORD totalentries)
1485 static const WCHAR admins[] = L"Administrators";
1486 NET_API_STATUS status;
1487 LPWSTR currentuser;
1488 LOCALGROUP_USERS_INFO_0* info;
1489 DWORD size;
1491 FIXME("(%s, %s, %ld, %08lx, %p %ld, %p, %p) stub!\n",
1492 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
1493 prefmaxlen, entriesread, totalentries);
1495 status = NETAPI_ValidateServername(servername);
1496 if (status != NERR_Success)
1497 return status;
1499 size = UNLEN + 1;
1500 NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)&currentuser);
1501 if (!GetUserNameW(currentuser, &size)) {
1502 NetApiBufferFree(currentuser);
1503 return ERROR_NOT_ENOUGH_MEMORY;
1506 if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
1508 NetApiBufferFree(currentuser);
1509 return NERR_UserNotFound;
1512 NetApiBufferFree(currentuser);
1513 *totalentries = 1;
1514 size = sizeof(*info) + sizeof(admins);
1516 if(prefmaxlen < size)
1517 status = ERROR_MORE_DATA;
1518 else
1519 status = NetApiBufferAllocate(size, (LPVOID*)&info);
1521 if(status != NERR_Success)
1523 *bufptr = NULL;
1524 *entriesread = 0;
1525 return status;
1528 info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
1529 lstrcpyW(info->lgrui0_name, admins);
1531 *bufptr = (LPBYTE)info;
1532 *entriesread = 1;
1534 return NERR_Success;
1537 /************************************************************
1538 * NetUserEnum (NETAPI32.@)
1540 NET_API_STATUS WINAPI
1541 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
1542 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
1543 LPDWORD resume_handle)
1545 NET_API_STATUS status;
1546 WCHAR user[UNLEN + 1];
1547 DWORD size, len = ARRAY_SIZE(user);
1549 TRACE("(%s, %lu, 0x%lx, %p, %lu, %p, %p, %p)\n", debugstr_w(servername), level,
1550 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1552 status = NETAPI_ValidateServername(servername);
1553 if (status != NERR_Success)
1554 return status;
1556 if (!NETAPI_IsLocalComputer(servername))
1558 FIXME("Only implemented for local computer, but remote server"
1559 "%s was requested.\n", debugstr_w(servername));
1560 return NERR_InvalidComputer;
1563 if (!GetUserNameW(user, &len)) return GetLastError();
1565 switch (level)
1567 case 0:
1569 USER_INFO_0 *info;
1571 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1573 if (prefmaxlen < size)
1574 status = ERROR_MORE_DATA;
1575 else
1576 status = NetApiBufferAllocate(size, (void **)&info);
1578 if (status != NERR_Success)
1579 return status;
1581 info->usri0_name = (WCHAR *)((char *)info + sizeof(*info));
1582 wcscpy(info->usri0_name, user);
1584 *bufptr = (BYTE *)info;
1585 *entriesread = *totalentries = 1;
1586 break;
1588 case 20:
1590 USER_INFO_20 *info;
1591 SID *sid;
1592 UCHAR *count;
1593 DWORD *rid;
1594 SID_NAME_USE use;
1596 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1598 if (prefmaxlen < size)
1599 status = ERROR_MORE_DATA;
1600 else
1601 status = NetApiBufferAllocate(size, (void **)&info);
1603 if (status != NERR_Success)
1604 return status;
1606 size = len = 0;
1607 LookupAccountNameW(NULL, user, NULL, &size, NULL, &len, &use);
1608 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1609 return GetLastError();
1611 status = NetApiBufferAllocate(size, (void **)&sid);
1612 if (status != NERR_Success)
1613 return status;
1615 if (!LookupAccountNameW(NULL, user, sid, &size, NULL, &len, &use))
1616 return GetLastError();
1618 count = GetSidSubAuthorityCount(sid);
1619 rid = GetSidSubAuthority(sid, *count - 1);
1621 info->usri20_name = (WCHAR *)((char *)info + sizeof(*info));
1622 wcscpy(info->usri20_name, user);
1623 info->usri20_full_name = NULL;
1624 info->usri20_comment = NULL;
1625 info->usri20_flags = UF_NORMAL_ACCOUNT;
1626 info->usri20_user_id = *rid;
1628 *bufptr = (BYTE *)info;
1629 *entriesread = *totalentries = 1;
1631 NetApiBufferFree(sid);
1632 break;
1634 default:
1635 FIXME("level %lu not supported\n", level);
1636 return ERROR_INVALID_LEVEL;
1638 return NERR_Success;
1641 /************************************************************
1642 * ACCESS_QueryAdminDisplayInformation
1644 * Creates a buffer with information for the Admin User
1646 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1648 static const WCHAR sAdminUserName[] = L"Administrator";
1650 /* sizes of the field buffers in WCHARS */
1651 int name_sz, comment_sz, full_name_sz;
1652 PNET_DISPLAY_USER usr;
1654 /* set up buffer */
1655 name_sz = lstrlenW(sAdminUserName) + 1;
1656 comment_sz = 1;
1657 full_name_sz = 1;
1659 *pdwSize = sizeof(NET_DISPLAY_USER);
1660 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1661 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1663 usr = *buf;
1664 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1665 usr->usri1_comment = (LPWSTR) (
1666 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1667 usr->usri1_full_name = (LPWSTR) (
1668 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1670 /* set data */
1671 lstrcpyW(usr->usri1_name, sAdminUserName);
1672 usr->usri1_comment[0] = 0;
1673 usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1674 usr->usri1_full_name[0] = 0;
1675 usr->usri1_user_id = DOMAIN_USER_RID_ADMIN;
1676 usr->usri1_next_index = 0;
1679 /************************************************************
1680 * ACCESS_QueryGuestDisplayInformation
1682 * Creates a buffer with information for the Guest User
1684 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1686 static const WCHAR sGuestUserName[] = L"Guest";
1688 /* sizes of the field buffers in WCHARS */
1689 int name_sz, comment_sz, full_name_sz;
1690 PNET_DISPLAY_USER usr;
1692 /* set up buffer */
1693 name_sz = lstrlenW(sGuestUserName) + 1;
1694 comment_sz = 1;
1695 full_name_sz = 1;
1697 *pdwSize = sizeof(NET_DISPLAY_USER);
1698 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1699 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1701 usr = *buf;
1702 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1703 usr->usri1_comment = (LPWSTR) (
1704 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1705 usr->usri1_full_name = (LPWSTR) (
1706 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1708 /* set data */
1709 lstrcpyW(usr->usri1_name, sGuestUserName);
1710 usr->usri1_comment[0] = 0;
1711 usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
1712 UF_DONT_EXPIRE_PASSWD;
1713 usr->usri1_full_name[0] = 0;
1714 usr->usri1_user_id = DOMAIN_USER_RID_GUEST;
1715 usr->usri1_next_index = 0;
1718 /************************************************************
1719 * Copies NET_DISPLAY_USER record.
1721 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER *dest, LPWSTR *dest_buf,
1722 PNET_DISPLAY_USER src)
1724 LPWSTR str = *dest_buf;
1726 src->usri1_name = str;
1727 lstrcpyW(src->usri1_name, dest->usri1_name);
1728 str = (LPWSTR) (
1729 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1731 src->usri1_comment = str;
1732 lstrcpyW(src->usri1_comment, dest->usri1_comment);
1733 str = (LPWSTR) (
1734 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1736 src->usri1_flags = dest->usri1_flags;
1738 src->usri1_full_name = str;
1739 lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
1740 str = (LPWSTR) (
1741 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1743 src->usri1_user_id = dest->usri1_user_id;
1744 src->usri1_next_index = dest->usri1_next_index;
1745 *dest_buf = str;
1748 /************************************************************
1749 * NetQueryDisplayInformation (NETAPI32.@)
1751 * The buffer structure:
1752 * - array of fixed size record of the level type
1753 * - strings, referenced by the record of the level type
1755 NET_API_STATUS WINAPI
1756 NetQueryDisplayInformation(
1757 LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
1758 DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
1759 PVOID *SortedBuffer)
1761 TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName),
1762 Level, Index, EntriesRequested, PreferredMaximumLength,
1763 ReturnedEntryCount, SortedBuffer);
1765 if(!NETAPI_IsLocalComputer(ServerName))
1767 FIXME("Only implemented on local computer, but requested for "
1768 "remote server %s\n", debugstr_w(ServerName));
1769 return ERROR_ACCESS_DENIED;
1772 switch (Level)
1774 case 1:
1776 /* current record */
1777 PNET_DISPLAY_USER inf;
1778 /* current available strings buffer */
1779 LPWSTR str;
1780 PNET_DISPLAY_USER admin, guest;
1781 DWORD admin_size, guest_size;
1782 LPWSTR name = NULL;
1783 DWORD dwSize;
1785 /* sizes of the field buffers in WCHARS */
1786 int name_sz, comment_sz, full_name_sz;
1788 /* number of the records, returned in SortedBuffer
1789 3 - for current user, Administrator and Guest users
1791 int records = 3;
1793 FIXME("Level %ld partially implemented\n", Level);
1794 *ReturnedEntryCount = records;
1795 comment_sz = 1;
1796 full_name_sz = 1;
1798 /* get data */
1799 dwSize = UNLEN + 1;
1800 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &name);
1801 if (!GetUserNameW(name, &dwSize))
1803 NetApiBufferFree(name);
1804 return ERROR_ACCESS_DENIED;
1806 name_sz = dwSize;
1807 ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
1808 ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
1810 /* set up buffer */
1811 dwSize = sizeof(NET_DISPLAY_USER) * records;
1812 dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1814 NetApiBufferAllocate(dwSize +
1815 admin_size - sizeof(NET_DISPLAY_USER) +
1816 guest_size - sizeof(NET_DISPLAY_USER),
1817 SortedBuffer);
1818 inf = *SortedBuffer;
1819 str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
1820 inf->usri1_name = str;
1821 str = (LPWSTR) (
1822 ((PBYTE) str) + name_sz * sizeof(WCHAR));
1823 inf->usri1_comment = str;
1824 str = (LPWSTR) (
1825 ((PBYTE) str) + comment_sz * sizeof(WCHAR));
1826 inf->usri1_full_name = str;
1827 str = (LPWSTR) (
1828 ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
1830 /* set data */
1831 lstrcpyW(inf->usri1_name, name);
1832 NetApiBufferFree(name);
1833 inf->usri1_comment[0] = 0;
1834 inf->usri1_flags =
1835 UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1836 inf->usri1_full_name[0] = 0;
1837 inf->usri1_user_id = 0;
1838 inf->usri1_next_index = 0;
1840 inf++;
1841 ACCESS_CopyDisplayUser(admin, &str, inf);
1842 NetApiBufferFree(admin);
1844 inf++;
1845 ACCESS_CopyDisplayUser(guest, &str, inf);
1846 NetApiBufferFree(guest);
1847 break;
1850 case 2:
1851 case 3:
1853 FIXME("Level %ld is not implemented\n", Level);
1854 break;
1857 default:
1858 TRACE("Invalid level %ld is specified\n", Level);
1859 return ERROR_INVALID_LEVEL;
1861 return NERR_Success;
1864 /************************************************************
1865 * NetGetDCName (NETAPI32.@)
1867 * Return the name of the primary domain controller (PDC)
1870 NET_API_STATUS WINAPI
1871 NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1873 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1874 debugstr_w(domainname), bufptr);
1875 return NERR_DCNotFound; /* say we can't find a domain controller */
1878 /************************************************************
1879 * NetGetAnyDCName (NETAPI32.@)
1881 * Return the name of any domain controller (DC) for a
1882 * domain that is directly trusted by the specified server
1885 NET_API_STATUS WINAPI NetGetAnyDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1887 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1888 debugstr_w(domainname), bufptr);
1889 return ERROR_NO_SUCH_DOMAIN;
1892 /************************************************************
1893 * NetGroupAddUser (NETAPI32.@)
1895 NET_API_STATUS WINAPI
1896 NetGroupAddUser(LPCWSTR servername, LPCWSTR groupname, LPCWSTR username)
1898 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername),
1899 debugstr_w(groupname), debugstr_w(username));
1900 return NERR_Success;
1903 /************************************************************
1904 * NetGroupEnum (NETAPI32.@)
1907 NET_API_STATUS WINAPI
1908 NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen,
1909 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
1911 FIXME("(%s, %ld, %p, %ld, %p, %p, %p) stub!\n", debugstr_w(servername),
1912 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1913 return ERROR_ACCESS_DENIED;
1916 /************************************************************
1917 * NetGroupGetInfo (NETAPI32.@)
1920 NET_API_STATUS WINAPI NetGroupGetInfo(LPCWSTR servername, LPCWSTR groupname, DWORD level, LPBYTE *bufptr)
1922 FIXME("(%s, %s, %ld, %p) stub!\n", debugstr_w(servername), debugstr_w(groupname), level, bufptr);
1923 return ERROR_ACCESS_DENIED;
1926 /******************************************************************************
1927 * NetUserModalsGet (NETAPI32.@)
1929 * Retrieves global information for all users and global groups in the security
1930 * database.
1932 * PARAMS
1933 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
1934 * on which the function is to execute.
1935 * level [I] Information level of the data.
1936 * 0 Return global passwords parameters. bufptr points to a
1937 * USER_MODALS_INFO_0 struct.
1938 * 1 Return logon server and domain controller information. bufptr
1939 * points to a USER_MODALS_INFO_1 struct.
1940 * 2 Return domain name and identifier. bufptr points to a
1941 * USER_MODALS_INFO_2 struct.
1942 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
1943 * struct.
1944 * pbuffer [I] Buffer that receives the data.
1946 * RETURNS
1947 * Success: NERR_Success.
1948 * Failure:
1949 * ERROR_ACCESS_DENIED - the user does not have access to the info.
1950 * NERR_InvalidComputer - computer name is invalid.
1952 NET_API_STATUS WINAPI NetUserModalsGet(
1953 LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
1955 TRACE("(%s %ld %p)\n", debugstr_w(szServer), level, pbuffer);
1957 switch (level)
1959 case 0:
1960 /* return global passwords parameters */
1961 FIXME("level 0 not implemented!\n");
1962 *pbuffer = NULL;
1963 return NERR_InternalError;
1964 case 1:
1965 /* return logon server and domain controller info */
1966 FIXME("level 1 not implemented!\n");
1967 *pbuffer = NULL;
1968 return NERR_InternalError;
1969 case 2:
1971 /* return domain name and identifier */
1972 PUSER_MODALS_INFO_2 umi;
1973 LSA_HANDLE policyHandle;
1974 LSA_OBJECT_ATTRIBUTES objectAttributes;
1975 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo;
1976 NTSTATUS ntStatus;
1977 PSID domainIdentifier = NULL;
1978 int domainNameLen;
1980 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
1981 objectAttributes.Length = sizeof(objectAttributes);
1983 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
1984 POLICY_VIEW_LOCAL_INFORMATION,
1985 &policyHandle);
1986 if (ntStatus != STATUS_SUCCESS)
1988 WARN("LsaOpenPolicy failed with NT status %lx\n",
1989 LsaNtStatusToWinError(ntStatus));
1990 return ntStatus;
1993 ntStatus = LsaQueryInformationPolicy(policyHandle,
1994 PolicyAccountDomainInformation,
1995 (PVOID *)&domainInfo);
1996 if (ntStatus != STATUS_SUCCESS)
1998 WARN("LsaQueryInformationPolicy failed with NT status %lx\n",
1999 LsaNtStatusToWinError(ntStatus));
2000 LsaClose(policyHandle);
2001 return ntStatus;
2004 domainIdentifier = domainInfo->DomainSid;
2005 domainNameLen = lstrlenW(domainInfo->DomainName.Buffer) + 1;
2006 LsaClose(policyHandle);
2008 ntStatus = NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2) +
2009 GetLengthSid(domainIdentifier) +
2010 domainNameLen * sizeof(WCHAR),
2011 (LPVOID *)pbuffer);
2013 if (ntStatus != NERR_Success)
2015 WARN("NetApiBufferAllocate() failed\n");
2016 LsaFreeMemory(domainInfo);
2017 return ntStatus;
2020 umi = (USER_MODALS_INFO_2 *) *pbuffer;
2021 umi->usrmod2_domain_id = *pbuffer + sizeof(USER_MODALS_INFO_2);
2022 umi->usrmod2_domain_name = (LPWSTR)(*pbuffer +
2023 sizeof(USER_MODALS_INFO_2) + GetLengthSid(domainIdentifier));
2025 lstrcpynW(umi->usrmod2_domain_name,
2026 domainInfo->DomainName.Buffer,
2027 domainNameLen);
2028 CopySid(GetLengthSid(domainIdentifier), umi->usrmod2_domain_id,
2029 domainIdentifier);
2031 LsaFreeMemory(domainInfo);
2033 break;
2035 case 3:
2036 /* return lockout information */
2037 FIXME("level 3 not implemented!\n");
2038 *pbuffer = NULL;
2039 return NERR_InternalError;
2040 default:
2041 TRACE("Invalid level %ld is specified\n", level);
2042 *pbuffer = NULL;
2043 return ERROR_INVALID_LEVEL;
2046 return NERR_Success;
2049 /******************************************************************************
2050 * NetUserChangePassword (NETAPI32.@)
2051 * PARAMS
2052 * domainname [I] Optional. Domain on which the user resides or the logon
2053 * domain of the current user if NULL.
2054 * username [I] Optional. Username to change the password for or the name
2055 * of the current user if NULL.
2056 * oldpassword [I] The user's current password.
2057 * newpassword [I] The password that the user will be changed to using.
2059 * RETURNS
2060 * Success: NERR_Success.
2061 * Failure: NERR_* failure code or win error code.
2064 NET_API_STATUS WINAPI NetUserChangePassword(LPCWSTR domainname, LPCWSTR username,
2065 LPCWSTR oldpassword, LPCWSTR newpassword)
2067 struct sam_user *user;
2068 struct change_password_params params = { domainname, username, oldpassword, newpassword };
2070 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2072 if (samba_init() && !SAMBA_CALL( change_password, &params ))
2073 return NERR_Success;
2075 if(domainname)
2076 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
2078 if((user = NETAPI_FindUser(username)) == NULL)
2079 return NERR_UserNotFound;
2081 if(wcscmp(user->user_password, oldpassword) != 0)
2082 return ERROR_INVALID_PASSWORD;
2084 if(lstrlenW(newpassword) > PWLEN)
2085 return ERROR_PASSWORD_RESTRICTION;
2087 lstrcpyW(user->user_password, newpassword);
2089 return NERR_Success;
2092 NET_API_STATUS WINAPI NetUseAdd(LMSTR servername, DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2094 FIXME("%s %ld %p %p stub\n", debugstr_w(servername), level, bufptr, parm_err);
2095 return NERR_Success;
2098 NET_API_STATUS WINAPI NetUseDel(LMSTR servername, LMSTR usename, DWORD forcecond)
2100 FIXME("%s %s %ld stub\n", debugstr_w(servername), debugstr_w(usename), forcecond);
2101 return NERR_Success;
2104 /************************************************************
2105 * I_BrowserSetNetlogonState (NETAPI32.@)
2107 NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
2108 LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
2109 DWORD Role)
2111 return ERROR_NOT_SUPPORTED;
2114 /************************************************************
2115 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
2117 NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
2118 LPWSTR ServerName, PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
2119 LPDWORD EntriesRead)
2121 return ERROR_NOT_SUPPORTED;
2124 #define NS_MAXDNAME 1025
2126 static DWORD get_dc_info(const WCHAR *domain, WCHAR *dc, WCHAR *ip)
2128 WCHAR name[NS_MAXDNAME];
2129 DWORD ret, size;
2130 DNS_RECORDW *rec;
2132 wcscpy( name, L"_ldap._tcp.dc._msdcs." );
2133 wcscat( name, domain );
2135 ret = DnsQuery_W(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2136 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(domain), ret);
2137 if (ret == ERROR_SUCCESS)
2139 TRACE("target %s, port %d\n", wine_dbgstr_w(rec->Data.Srv.pNameTarget), rec->Data.Srv.wPort);
2141 lstrcpynW(dc, rec->Data.Srv.pNameTarget, NS_MAXDNAME);
2142 DnsRecordListFree(rec, DnsFreeRecordList);
2144 /* IPv4 */
2145 ret = DnsQuery_W(dc, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2146 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(dc), ret);
2147 if (ret == ERROR_SUCCESS)
2149 SOCKADDR_IN addr;
2151 addr.sin_family = AF_INET;
2152 addr.sin_port = 0;
2153 addr.sin_addr.s_addr = rec->Data.A.IpAddress;
2154 size = IP6_ADDRESS_STRING_LENGTH;
2155 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2156 if (!ret)
2157 TRACE("WSAAddressToStringW => %ld, %s\n", ret, wine_dbgstr_w(ip));
2159 DnsRecordListFree(rec, DnsFreeRecordList);
2161 return ret;
2164 /* IPv6 */
2165 ret = DnsQuery_W(dc, DNS_TYPE_AAAA, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2166 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(dc), ret);
2167 if (ret == ERROR_SUCCESS)
2169 SOCKADDR_IN6 addr;
2171 addr.sin6_family = AF_INET6;
2172 addr.sin6_port = 0;
2173 addr.sin6_scope_id = 0;
2174 memcpy(addr.sin6_addr.s6_addr, &rec->Data.AAAA.Ip6Address, sizeof(rec->Data.AAAA.Ip6Address));
2175 size = IP6_ADDRESS_STRING_LENGTH;
2176 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2177 if (!ret)
2178 TRACE("WSAAddressToStringW => %ld, %s\n", ret, wine_dbgstr_w(ip));
2180 DnsRecordListFree(rec, DnsFreeRecordList);
2184 return ret;
2187 DWORD WINAPI DsGetDcNameW(LPCWSTR computer, LPCWSTR domain, GUID *domain_guid,
2188 LPCWSTR site, ULONG flags, PDOMAIN_CONTROLLER_INFOW *dc_info)
2190 static const WCHAR pfxW[] = {'\\','\\'};
2191 static const WCHAR default_site_nameW[] = L"Default-First-Site-Name";
2192 NTSTATUS status;
2193 POLICY_DNS_DOMAIN_INFO *dns_domain_info = NULL;
2194 DOMAIN_CONTROLLER_INFOW *info;
2195 WCHAR dc[NS_MAXDNAME], ip[IP6_ADDRESS_STRING_LENGTH];
2196 DWORD size;
2198 FIXME("(%s, %s, %s, %s, %08lx, %p): semi-stub\n", debugstr_w(computer),
2199 debugstr_w(domain), debugstr_guid(domain_guid), debugstr_w(site), flags, dc_info);
2201 if (!dc_info) return ERROR_INVALID_PARAMETER;
2203 if (!domain)
2205 LSA_OBJECT_ATTRIBUTES attrs;
2206 LSA_HANDLE lsa;
2208 memset(&attrs, 0, sizeof(attrs));
2209 attrs.Length = sizeof(attrs);
2210 status = LsaOpenPolicy(NULL, &attrs, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
2211 if (status)
2212 return LsaNtStatusToWinError(status);
2214 status = LsaQueryInformationPolicy(lsa, PolicyDnsDomainInformation, (void **)&dns_domain_info);
2215 LsaClose(lsa);
2216 if (status)
2217 return LsaNtStatusToWinError(status);
2219 domain = dns_domain_info->DnsDomainName.Buffer;
2222 status = get_dc_info(domain, dc, ip);
2223 if (status) return status;
2225 size = sizeof(DOMAIN_CONTROLLER_INFOW) + lstrlenW(domain) * sizeof(WCHAR) +
2226 sizeof(pfxW) * 2 + (lstrlenW(dc) + 1 + lstrlenW(ip) + 1) * sizeof(WCHAR) +
2227 lstrlenW(domain) * sizeof(WCHAR) /* assume forest == domain */ +
2228 sizeof(default_site_nameW) * 2;
2229 status = NetApiBufferAllocate(size, (void **)&info);
2230 if (status != NERR_Success)
2232 LsaFreeMemory(dns_domain_info);
2233 return ERROR_NOT_ENOUGH_MEMORY;
2236 info->DomainControllerName = (WCHAR *)(info + 1);
2237 memcpy(info->DomainControllerName, pfxW, sizeof(pfxW));
2238 lstrcpyW(info->DomainControllerName + 2, dc);
2239 info->DomainControllerAddress = (WCHAR *)((char *)info->DomainControllerName + (wcslen(info->DomainControllerName) + 1) * sizeof(WCHAR));
2240 memcpy(info->DomainControllerAddress, pfxW, sizeof(pfxW));
2241 lstrcpyW(info->DomainControllerAddress + 2, ip);
2242 info->DomainControllerAddressType = DS_INET_ADDRESS;
2243 info->DomainGuid = dns_domain_info ? dns_domain_info->DomainGuid : GUID_NULL /* FIXME */;
2244 info->DomainName = (WCHAR *)((char *)info->DomainControllerAddress + (wcslen(info->DomainControllerAddress) + 1) * sizeof(WCHAR));
2245 lstrcpyW(info->DomainName, domain);
2246 info->DnsForestName = (WCHAR *)((char *)info->DomainName + (lstrlenW(info->DomainName) + 1) * sizeof(WCHAR));
2247 lstrcpyW(info->DnsForestName, domain);
2248 info->DcSiteName = (WCHAR *)((char *)info->DnsForestName + (lstrlenW(info->DnsForestName) + 1) * sizeof(WCHAR));
2249 lstrcpyW(info->DcSiteName, default_site_nameW);
2250 info->ClientSiteName = (WCHAR *)((char *)info->DcSiteName + sizeof(default_site_nameW));
2251 lstrcpyW(info->ClientSiteName, default_site_nameW);
2252 info->Flags = DS_DNS_DOMAIN_FLAG | DS_DNS_FOREST_FLAG;
2254 LsaFreeMemory(dns_domain_info);
2256 *dc_info = info;
2258 return ERROR_SUCCESS;
2261 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
2262 GUID* DomainGuid, LPCSTR SiteName, ULONG Flags,
2263 PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo)
2265 FIXME("(%s, %s, %s, %s, %08lx, %p): stub\n", debugstr_a(ComputerName),
2266 debugstr_a(AvoidDCName), debugstr_guid(DomainGuid),
2267 debugstr_a(SiteName), Flags, DomainControllerInfo);
2268 return ERROR_CALL_NOT_IMPLEMENTED;
2271 DWORD WINAPI DsGetSiteNameW(LPCWSTR ComputerName, LPWSTR *SiteName)
2273 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName), SiteName);
2274 return ERROR_CALL_NOT_IMPLEMENTED;
2277 DWORD WINAPI DsGetSiteNameA(LPCSTR ComputerName, LPSTR *SiteName)
2279 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName), SiteName);
2280 return ERROR_CALL_NOT_IMPLEMENTED;
2283 /************************************************************
2284 * DsRoleFreeMemory (NETAPI32.@)
2286 * PARAMS
2287 * Buffer [I] Pointer to the to-be-freed buffer.
2289 * RETURNS
2290 * Nothing
2292 VOID WINAPI DsRoleFreeMemory(PVOID Buffer)
2294 TRACE("(%p)\n", Buffer);
2295 HeapFree(GetProcessHeap(), 0, Buffer);
2298 /************************************************************
2299 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
2301 * PARAMS
2302 * lpServer [I] Pointer to UNICODE string with ComputerName
2303 * InfoLevel [I] Type of data to retrieve
2304 * Buffer [O] Pointer to to the requested data
2306 * RETURNS
2308 * NOTES
2309 * When lpServer is NULL, use the local computer
2311 DWORD WINAPI DsRoleGetPrimaryDomainInformation(
2312 LPCWSTR lpServer, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
2313 PBYTE* Buffer)
2315 DWORD ret;
2317 FIXME("(%p, %d, %p) stub\n", lpServer, InfoLevel, Buffer);
2319 /* Check some input parameters */
2321 if (!Buffer) return ERROR_INVALID_PARAMETER;
2322 if ((InfoLevel < DsRolePrimaryDomainInfoBasic) || (InfoLevel > DsRoleOperationState)) return ERROR_INVALID_PARAMETER;
2324 *Buffer = NULL;
2325 switch (InfoLevel)
2327 case DsRolePrimaryDomainInfoBasic:
2329 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
2330 LSA_HANDLE PolicyHandle;
2331 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
2332 NTSTATUS NtStatus;
2333 int logon_domain_sz;
2334 DWORD size;
2335 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic;
2337 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
2338 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
2339 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
2340 if (NtStatus != STATUS_SUCCESS)
2342 TRACE("LsaOpenPolicyFailed with NT status %lx\n",
2343 LsaNtStatusToWinError(NtStatus));
2344 return ERROR_OUTOFMEMORY;
2346 LsaQueryInformationPolicy(PolicyHandle,
2347 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
2348 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
2349 LsaClose(PolicyHandle);
2351 size = sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC) +
2352 logon_domain_sz * sizeof(WCHAR);
2353 basic = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2354 if (basic)
2356 basic->MachineRole = DsRole_RoleStandaloneWorkstation;
2357 basic->DomainNameFlat = (LPWSTR)((LPBYTE)basic +
2358 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
2359 lstrcpyW(basic->DomainNameFlat, DomainInfo->DomainName.Buffer);
2360 ret = ERROR_SUCCESS;
2362 else
2363 ret = ERROR_OUTOFMEMORY;
2364 *Buffer = (PBYTE)basic;
2365 LsaFreeMemory(DomainInfo);
2367 break;
2368 default:
2369 ret = ERROR_CALL_NOT_IMPLEMENTED;
2371 return ret;
2374 /************************************************************
2375 * NetLocalGroupAdd (NETAPI32.@)
2377 NET_API_STATUS WINAPI NetLocalGroupAdd(
2378 LPCWSTR servername,
2379 DWORD level,
2380 LPBYTE buf,
2381 LPDWORD parm_err)
2383 FIXME("(%s %ld %p %p) stub!\n", debugstr_w(servername), level, buf,
2384 parm_err);
2385 return NERR_Success;
2388 /************************************************************
2389 * NetLocalGroupAddMember (NETAPI32.@)
2391 NET_API_STATUS WINAPI NetLocalGroupAddMember(
2392 LPCWSTR servername,
2393 LPCWSTR groupname,
2394 PSID membersid)
2396 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2397 debugstr_w(groupname), membersid);
2398 return NERR_Success;
2401 /************************************************************
2402 * NetLocalGroupAddMembers (NETAPI32.@)
2404 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
2405 LPCWSTR servername,
2406 LPCWSTR groupname,
2407 DWORD level,
2408 LPBYTE buf,
2409 DWORD totalentries)
2411 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2412 debugstr_w(groupname), level, buf, totalentries);
2413 return NERR_Success;
2416 /************************************************************
2417 * NetLocalGroupDel (NETAPI32.@)
2419 NET_API_STATUS WINAPI NetLocalGroupDel(
2420 LPCWSTR servername,
2421 LPCWSTR groupname)
2423 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
2424 return NERR_Success;
2427 /************************************************************
2428 * NetLocalGroupDelMember (NETAPI32.@)
2430 NET_API_STATUS WINAPI NetLocalGroupDelMember(
2431 LPCWSTR servername,
2432 LPCWSTR groupname,
2433 PSID membersid)
2435 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2436 debugstr_w(groupname), membersid);
2437 return NERR_Success;
2440 /************************************************************
2441 * NetLocalGroupDelMembers (NETAPI32.@)
2443 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
2444 LPCWSTR servername,
2445 LPCWSTR groupname,
2446 DWORD level,
2447 LPBYTE buf,
2448 DWORD totalentries)
2450 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2451 debugstr_w(groupname), level, buf, totalentries);
2452 return NERR_Success;
2455 /************************************************************
2456 * NetLocalGroupEnum (NETAPI32.@)
2458 NET_API_STATUS WINAPI NetLocalGroupEnum(
2459 LPCWSTR servername,
2460 DWORD level,
2461 LPBYTE* bufptr,
2462 DWORD prefmaxlen,
2463 LPDWORD entriesread,
2464 LPDWORD totalentries,
2465 PDWORD_PTR resumehandle)
2467 FIXME("(%s %ld %p %ld %p %p %p) stub!\n", debugstr_w(servername),
2468 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
2469 *entriesread = 0;
2470 *totalentries = 0;
2471 return NERR_Success;
2474 /************************************************************
2475 * NetLocalGroupGetInfo (NETAPI32.@)
2477 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
2478 LPCWSTR servername,
2479 LPCWSTR groupname,
2480 DWORD level,
2481 LPBYTE* bufptr)
2483 static const WCHAR commentW[] = L"No comment";
2484 LOCALGROUP_INFO_1* info;
2485 DWORD size;
2487 FIXME("(%s %s %ld %p) semi-stub!\n", debugstr_w(servername),
2488 debugstr_w(groupname), level, bufptr);
2490 size = sizeof(*info) + sizeof(WCHAR) * (lstrlenW(groupname)+1) + sizeof(commentW);
2491 NetApiBufferAllocate(size, (LPVOID*)&info);
2493 info->lgrpi1_name = (LPWSTR)(info + 1);
2494 lstrcpyW(info->lgrpi1_name, groupname);
2496 info->lgrpi1_comment = info->lgrpi1_name + lstrlenW(groupname) + 1;
2497 lstrcpyW(info->lgrpi1_comment, commentW);
2499 *bufptr = (LPBYTE)info;
2501 return NERR_Success;
2504 /************************************************************
2505 * NetLocalGroupGetMembers (NETAPI32.@)
2507 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
2508 LPCWSTR servername,
2509 LPCWSTR localgroupname,
2510 DWORD level,
2511 LPBYTE* bufptr,
2512 DWORD prefmaxlen,
2513 LPDWORD entriesread,
2514 LPDWORD totalentries,
2515 PDWORD_PTR resumehandle)
2517 FIXME("(%s %s %ld %p %ld, %p %p %p) stub!\n", debugstr_w(servername),
2518 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
2519 totalentries, resumehandle);
2521 if (level == 3)
2523 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
2524 DWORD userNameLen;
2525 DWORD len,needlen;
2526 PLOCALGROUP_MEMBERS_INFO_3 ptr;
2528 /* still a stub, current user is belonging to all groups */
2530 *totalentries = 1;
2531 *entriesread = 0;
2533 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
2534 if (!GetUserNameW(userName,&userNameLen))
2535 return ERROR_NOT_ENOUGH_MEMORY;
2537 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
2538 (userNameLen+2) * sizeof(WCHAR);
2539 if (prefmaxlen != MAX_PREFERRED_LENGTH)
2540 len = min(prefmaxlen,needlen);
2541 else
2542 len = needlen;
2544 NetApiBufferAllocate(len, (LPVOID *) bufptr);
2545 if (len < needlen)
2546 return ERROR_MORE_DATA;
2548 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
2549 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
2550 lstrcpyW(ptr->lgrmi3_domainandname,userName);
2552 *entriesread = 1;
2555 return NERR_Success;
2558 /************************************************************
2559 * NetLocalGroupSetInfo (NETAPI32.@)
2561 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
2562 LPCWSTR servername,
2563 LPCWSTR groupname,
2564 DWORD level,
2565 LPBYTE buf,
2566 LPDWORD parm_err)
2568 FIXME("(%s %s %ld %p %p) stub!\n", debugstr_w(servername),
2569 debugstr_w(groupname), level, buf, parm_err);
2570 return NERR_Success;
2573 /************************************************************
2574 * NetLocalGroupSetMember (NETAPI32.@)
2576 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
2577 LPCWSTR servername,
2578 LPCWSTR groupname,
2579 DWORD level,
2580 LPBYTE buf,
2581 DWORD totalentries)
2583 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2584 debugstr_w(groupname), level, buf, totalentries);
2585 return NERR_Success;
2588 /************************************************************
2589 * NetRemoteTOD (NETAPI32.@)
2591 NET_API_STATUS NET_API_FUNCTION NetRemoteTOD(
2592 LPCWSTR servername,
2593 LPBYTE *buf)
2595 FIXME("(%s %p) stub!\n", debugstr_w(servername), buf);
2596 return ERROR_NO_BROWSER_SERVERS_FOUND;
2599 /************************************************************
2600 * DavGetHTTPFromUNCPath (NETAPI32.@)
2602 DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buflen)
2604 static const WCHAR httpW[] = L"http://";
2605 static const WCHAR httpsW[] = L"https://";
2606 const WCHAR *p = unc_path, *q, *server, *path, *scheme = httpW;
2607 UINT i, len_server, len_path = 0, len_port = 0, len, port = 0;
2608 WCHAR *end, portbuf[12];
2610 TRACE("(%s %p %p)\n", debugstr_w(unc_path), buf, buflen);
2612 if (p[0] != '\\' || p[1] != '\\' || !p[2]) return ERROR_INVALID_PARAMETER;
2613 q = p += 2;
2614 while (*q && *q != '\\' && *q != '/' && *q != '@') q++;
2615 server = p;
2616 len_server = q - p;
2617 if (*q == '@')
2619 p = ++q;
2620 while (*p && (*p != '\\' && *p != '/' && *p != '@')) p++;
2621 if (p - q == 3 && !wcsnicmp( q, L"SSL", 3 ))
2623 scheme = httpsW;
2624 q = p;
2626 else if ((port = wcstol( q, &end, 10 ))) q = end;
2627 else return ERROR_INVALID_PARAMETER;
2629 if (*q == '@')
2631 if (!(port = wcstol( ++q, &end, 10 ))) return ERROR_INVALID_PARAMETER;
2632 q = end;
2634 if (*q == '\\' || *q == '/') q++;
2635 path = q;
2636 while (*q++) len_path++;
2637 if (len_path && (path[len_path - 1] == '\\' || path[len_path - 1] == '/'))
2638 len_path--; /* remove trailing slash */
2640 swprintf( portbuf, ARRAY_SIZE(portbuf), L":%u", port );
2641 if (scheme == httpsW)
2643 len = wcslen( httpsW );
2644 if (port && port != 443) len_port = wcslen( portbuf );
2646 else
2648 len = wcslen( httpW );
2649 if (port && port != 80) len_port = wcslen( portbuf );
2651 len += len_server;
2652 len += len_port;
2653 if (len_path) len += len_path + 1; /* leading '/' */
2654 len++; /* nul */
2656 if (*buflen < len)
2658 *buflen = len;
2659 return ERROR_INSUFFICIENT_BUFFER;
2662 memcpy( buf, scheme, wcslen(scheme) * sizeof(WCHAR) );
2663 buf += wcslen( scheme );
2664 memcpy( buf, server, len_server * sizeof(WCHAR) );
2665 buf += len_server;
2666 if (len_port)
2668 memcpy( buf, portbuf, len_port * sizeof(WCHAR) );
2669 buf += len_port;
2671 if (len_path)
2673 *buf++ = '/';
2674 for (i = 0; i < len_path; i++)
2676 if (path[i] == '\\') *buf++ = '/';
2677 else *buf++ = path[i];
2680 *buf = 0;
2681 *buflen = len;
2683 return ERROR_SUCCESS;
2686 /************************************************************
2687 * DavGetUNCFromHTTPPath (NETAPI32.@)
2689 DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen)
2691 static const WCHAR httpW[] = {'h','t','t','p'};
2692 static const WCHAR httpsW[] = {'h','t','t','p','s'};
2693 static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
2694 static const WCHAR sslW[] = {'@','S','S','L'};
2695 static const WCHAR port80W[] = {'8','0'};
2696 static const WCHAR port443W[] = {'4','4','3'};
2697 const WCHAR *p = http_path, *server, *port = NULL, *path = NULL;
2698 DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0;
2699 BOOL ssl;
2701 TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen);
2703 while (*p && *p != ':') { p++; len++; };
2704 if (len == ARRAY_SIZE(httpW) && !wcsnicmp( http_path, httpW, len )) ssl = FALSE;
2705 else if (len == ARRAY_SIZE(httpsW) && !wcsnicmp( http_path, httpsW, len )) ssl = TRUE;
2706 else return ERROR_INVALID_PARAMETER;
2708 if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER;
2709 server = p += 3;
2711 while (*p && *p != ':' && *p != '/') { p++; len_server++; };
2712 if (!len_server) return ERROR_BAD_NET_NAME;
2713 if (*p == ':')
2715 port = ++p;
2716 while (*p >= '0' && *p <= '9') { p++; len_port++; };
2717 if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL;
2718 else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL;
2719 path = p;
2721 else if (*p == '/') path = p;
2723 while (*p)
2725 if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME;
2726 p++; len_path++;
2728 if (len_path && path[len_path - 1] == '/') len_path--;
2730 len = len_server + 2; /* \\ */
2731 if (ssl) len += 4; /* @SSL */
2732 if (port) len += len_port + 1 /* @ */;
2733 len += ARRAY_SIZE(davrootW);
2734 len += len_path + 1; /* nul */
2736 if (*buflen < len)
2738 *buflen = len;
2739 return ERROR_INSUFFICIENT_BUFFER;
2742 buf[0] = buf[1] = '\\';
2743 buf += 2;
2744 memcpy( buf, server, len_server * sizeof(WCHAR) );
2745 buf += len_server;
2746 if (ssl)
2748 memcpy( buf, sslW, sizeof(sslW) );
2749 buf += 4;
2751 if (port)
2753 *buf++ = '@';
2754 memcpy( buf, port, len_port * sizeof(WCHAR) );
2755 buf += len_port;
2757 memcpy( buf, davrootW, sizeof(davrootW) );
2758 buf += ARRAY_SIZE(davrootW);
2759 for (i = 0; i < len_path; i++)
2761 if (path[i] == '/') *buf++ = '\\';
2762 else *buf++ = path[i];
2765 *buf = 0;
2766 *buflen = len;
2768 return ERROR_SUCCESS;
2771 /************************************************************
2772 * DsEnumerateDomainTrustsA (NETAPI32.@)
2774 DWORD WINAPI DsEnumerateDomainTrustsA(LPSTR server, ULONG flags, PDS_DOMAIN_TRUSTSA* domains, PULONG count)
2776 FIXME("(%s, 0x%04lx, %p, %p): stub\n", debugstr_a(server), flags, domains, count);
2777 return ERROR_NO_LOGON_SERVERS;
2780 /************************************************************
2781 * DsEnumerateDomainTrustsW (NETAPI32.@)
2783 DWORD WINAPI DsEnumerateDomainTrustsW(LPWSTR server, ULONG flags, PDS_DOMAIN_TRUSTSW* domains, PULONG count)
2785 FIXME("(%s, 0x%04lx, %p, %p): stub\n", debugstr_w(server), flags, domains, count);
2786 return ERROR_NO_LOGON_SERVERS;
2789 void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
2791 return HeapAlloc(GetProcessHeap(), 0, n);
2794 void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
2796 HeapFree(GetProcessHeap(), 0, p);
2799 handle_t __RPC_USER ATSVC_HANDLE_bind(ATSVC_HANDLE str)
2801 static unsigned char ncalrpc[] = "ncalrpc";
2802 unsigned char *binding_str;
2803 handle_t rpc_handle = 0;
2805 if (RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str) == RPC_S_OK)
2807 RpcBindingFromStringBindingA(binding_str, &rpc_handle);
2808 RpcStringFreeA(&binding_str);
2810 return rpc_handle;
2813 void __RPC_USER ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, handle_t rpc_handle)
2815 RpcBindingFree(&rpc_handle);
2818 /************************************************************
2819 * NetGetAadJoinInformation (NETAPI32.@)
2821 HRESULT WINAPI NetGetAadJoinInformation(LPCWSTR tenant_id, PDSREG_JOIN_INFO *join_info)
2823 FIXME("(%s, %p): stub\n", debugstr_w(tenant_id), join_info);
2824 return ERROR_CALL_NOT_IMPLEMENTED;