ws2_32: Return a valid value for WSAIoctl SIO_IDEAL_SEND_BACKLOG_QUERY.
[wine.git] / dlls / netapi32 / netapi32.c
blobe1c465c2243cc2712c11e078842ce4083f5efc4e
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 unixlib_handle_t samba_handle;
60 #define SAMBA_CALL(func, args) __wine_unix_call( samba_handle, unix_ ## func, args )
62 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
64 static BOOL WINAPI load_samba( INIT_ONCE *once, void *param, void **context )
66 SAMBA_CALL( netapi_init, NULL );
67 return TRUE;
70 static BOOL samba_init(void)
72 return samba_handle && InitOnceExecuteOnce( &init_once, load_samba, NULL, NULL );
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,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
97 switch (fdwReason) {
98 case DLL_PROCESS_ATTACH:
99 NtQueryVirtualMemory( GetCurrentProcess(), hinstDLL, MemoryWineUnixFuncs,
100 &samba_handle, sizeof(samba_handle), NULL );
101 DisableThreadLibraryCalls(hinstDLL);
102 NetBIOSInit();
103 NetBTInit();
104 break;
105 case DLL_PROCESS_DETACH:
106 if (lpvReserved) break;
107 NetBIOSShutdown();
108 break;
111 return TRUE;
114 /************************************************************
115 * NetServerEnum (NETAPI32.@)
117 NET_API_STATUS WINAPI NetServerEnum(
118 LMCSTR servername,
119 DWORD level,
120 LPBYTE* bufptr,
121 DWORD prefmaxlen,
122 LPDWORD entriesread,
123 LPDWORD totalentries,
124 DWORD servertype,
125 LMCSTR domain,
126 LPDWORD resume_handle
129 FIXME("Stub (%s %ld %p %ld %p %p %ld %s %p)\n", debugstr_w(servername),
130 level, bufptr, prefmaxlen, entriesread, totalentries, servertype,
131 debugstr_w(domain), resume_handle);
133 return ERROR_NO_BROWSER_SERVERS_FOUND;
136 /************************************************************
137 * NetServerEnumEx (NETAPI32.@)
139 NET_API_STATUS WINAPI NetServerEnumEx(
140 LMCSTR ServerName,
141 DWORD Level,
142 LPBYTE *Bufptr,
143 DWORD PrefMaxlen,
144 LPDWORD EntriesRead,
145 LPDWORD totalentries,
146 DWORD servertype,
147 LMCSTR domain,
148 LMCSTR FirstNameToReturn)
150 FIXME("Stub (%s %ld %p %ld %p %p %ld %s %s)\n",
151 debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
152 servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
154 return ERROR_NO_BROWSER_SERVERS_FOUND;
157 /************************************************************
158 * NetServerDiskEnum (NETAPI32.@)
160 NET_API_STATUS WINAPI NetServerDiskEnum(
161 LMCSTR ServerName,
162 DWORD Level,
163 LPBYTE *Bufptr,
164 DWORD PrefMaxlen,
165 LPDWORD EntriesRead,
166 LPDWORD totalentries,
167 LPDWORD Resume_Handle)
169 FIXME("Stub (%s %ld %p %ld %p %p %p)\n", debugstr_w(ServerName),
170 Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
172 return ERROR_NO_BROWSER_SERVERS_FOUND;
175 /************************************************************
176 * NetServerGetInfo (NETAPI32.@)
178 NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr)
180 NET_API_STATUS ret;
181 BOOL local = NETAPI_IsLocalComputer( servername );
183 TRACE("%s %ld %p\n", debugstr_w( servername ), level, bufptr );
185 if (!local)
187 if (samba_init())
189 ULONG size = 1024;
190 struct server_getinfo_params params = { servername, level, NULL, &size };
192 for (;;)
194 if (!(params.buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
195 ret = SAMBA_CALL( server_getinfo, &params );
196 if (!ret) *bufptr = params.buffer;
197 else free( params.buffer );
198 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
201 FIXME( "remote computers not supported\n" );
202 return ERROR_INVALID_LEVEL;
204 if (!bufptr) return ERROR_INVALID_PARAMETER;
206 switch (level)
208 case 100:
209 case 101:
211 DWORD computerNameLen, size;
212 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
214 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
215 GetComputerNameW(computerName, &computerNameLen);
216 computerNameLen++; /* include NULL terminator */
218 /* Plus 1 for empty comment */
219 size = sizeof(SERVER_INFO_101) + (computerNameLen + 1) * sizeof(WCHAR);
220 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
221 if (ret == NERR_Success)
223 /* INFO_100 structure is a subset of INFO_101 */
224 PSERVER_INFO_101 info = (PSERVER_INFO_101)*bufptr;
225 OSVERSIONINFOW verInfo;
227 info->sv101_platform_id = PLATFORM_ID_NT;
228 info->sv101_name = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101));
229 memcpy(info->sv101_name, computerName,
230 computerNameLen * sizeof(WCHAR));
231 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
232 GetVersionExW(&verInfo);
233 info->sv101_version_major = verInfo.dwMajorVersion;
234 info->sv101_version_minor = verInfo.dwMinorVersion;
235 /* Use generic type as no wine equivalent of DC / Server */
236 info->sv101_type = SV_TYPE_NT;
237 info->sv101_comment = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101)
238 + computerNameLen * sizeof(WCHAR));
239 info->sv101_comment[0] = '\0';
241 break;
244 default:
245 FIXME("level %ld unimplemented\n", level);
246 ret = ERROR_INVALID_LEVEL;
248 return ret;
252 /************************************************************
253 * NetStatisticsGet (NETAPI32.@)
255 NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
256 DWORD level, DWORD options,
257 LPBYTE *bufptr)
259 int res;
260 union
262 STAT_WORKSTATION_0 workst;
263 STAT_SERVER_0 server;
264 } *stat;
265 void *dataptr;
267 TRACE("(server %s, service %s, level %ld, options %ld, buffer %p): stub\n",
268 debugstr_w(server), debugstr_w(service), level, options, bufptr);
270 res = NetApiBufferAllocate(sizeof(*stat), &dataptr);
271 if (res != NERR_Success) return res;
273 res = NERR_InternalError;
274 stat = dataptr;
275 switch (level)
277 case 0:
278 if (!wcscmp( service, L"Lanman Workstation" ))
280 /* Fill the struct STAT_WORKSTATION_0 properly */
281 memset(&stat->workst, 0, sizeof(stat->workst));
282 res = NERR_Success;
284 else if (!wcscmp( service, L"Lanman Server" ))
286 /* Fill the struct STAT_SERVER_0 properly */
287 memset(&stat->server, 0, sizeof(stat->server));
288 res = NERR_Success;
290 break;
292 if (res != NERR_Success)
293 NetApiBufferFree(dataptr);
294 else
295 *bufptr = dataptr;
297 return res;
300 NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize,
301 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle)
303 FIXME("stub (%p, %ld, %p, %ld, %p, %p, %p)\n", server, level, bufptr, prefmaxsize,
304 entriesread, totalentries, resumehandle);
305 return ERROR_NOT_SUPPORTED;
308 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
310 TRACE("(%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
311 return NetrJobAdd(server, (AT_INFO *)bufptr, jobid);
314 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
316 TRACE("(%s, %lu, %lu)\n", debugstr_w(server), minjobid, maxjobid);
317 return NetrJobDel(server, minjobid, maxjobid);
320 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
321 LPDWORD totalentries, LPDWORD resumehandle)
323 AT_ENUM_CONTAINER container;
324 NET_API_STATUS ret;
326 TRACE("(%s, %p, %lu, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
328 container.EntriesRead = 0;
329 container.Buffer = NULL;
330 ret = NetrJobEnum(server, &container, prefmaxsize, totalentries, resumehandle);
331 if (ret == ERROR_SUCCESS)
333 *bufptr = (LPBYTE)container.Buffer;
334 *entriesread = container.EntriesRead;
336 return ret;
339 NET_API_STATUS WINAPI NetScheduleJobGetInfo(LPCWSTR server, DWORD jobid, LPBYTE *bufptr)
341 TRACE("(%s, %lu, %p)\n", debugstr_w(server), jobid, bufptr);
342 return NetrJobGetInfo(server, jobid, (LPAT_INFO *)bufptr);
345 NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
347 FIXME("stub (%p, %p, %ld, %p)\n", server, name, level, bufptr);
348 return ERROR_NOT_SUPPORTED;
352 /************************************************************
353 * NetApiBufferAllocate (NETAPI32.@)
355 NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
357 TRACE("(%ld, %p)\n", ByteCount, Buffer);
359 if (Buffer == NULL) return ERROR_INVALID_PARAMETER;
360 *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
361 if (*Buffer)
362 return NERR_Success;
363 else
364 return GetLastError();
367 /************************************************************
368 * NetApiBufferFree (NETAPI32.@)
370 NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
372 TRACE("(%p)\n", Buffer);
373 MIDL_user_free(Buffer);
374 return NERR_Success;
377 /************************************************************
378 * NetApiBufferReallocate (NETAPI32.@)
380 NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
381 LPVOID* NewBuffer)
383 TRACE("(%p, %ld, %p)\n", OldBuffer, NewByteCount, NewBuffer);
384 if (NewByteCount)
386 if (OldBuffer)
387 *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
388 else
389 *NewBuffer = HeapAlloc(GetProcessHeap(), 0, NewByteCount);
390 return *NewBuffer ? NERR_Success : GetLastError();
392 else
394 if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
395 *NewBuffer = 0;
396 return NERR_Success;
400 /************************************************************
401 * NetApiBufferSize (NETAPI32.@)
403 NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
405 DWORD dw;
407 TRACE("(%p, %p)\n", Buffer, ByteCount);
408 if (Buffer == NULL)
409 return ERROR_INVALID_PARAMETER;
410 dw = HeapSize(GetProcessHeap(), 0, Buffer);
411 TRACE("size: %ld\n", dw);
412 if (dw != 0xFFFFFFFF)
413 *ByteCount = dw;
414 else
415 *ByteCount = 0;
417 return NERR_Success;
420 /************************************************************
421 * NetSessionEnum (NETAPI32.@)
423 * PARAMS
424 * servername [I] Pointer to a string with the name of the server
425 * UncClientName [I] Pointer to a string with the name of the session
426 * username [I] Pointer to a string with the name of the user
427 * level [I] Data information level
428 * bufptr [O] Buffer to the data
429 * prefmaxlen [I] Preferred maximum length of the data
430 * entriesread [O] Pointer to the number of entries enumerated
431 * totalentries [O] Pointer to the possible number of entries
432 * resume_handle [I/O] Pointer to a handle for subsequent searches
434 * RETURNS
435 * If successful, the function returns NERR_Success
436 * On failure it returns:
437 * ERROR_ACCESS_DENIED User has no access to the requested information
438 * ERROR_INVALID_LEVEL Value of 'level' is not correct
439 * ERROR_INVALID_PARAMETER Wrong parameter
440 * ERROR_MORE_DATA Need a larger buffer
441 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
442 * NERR_ClientNameNotFound A session does not exist on a given computer
443 * NERR_InvalidComputer Invalid computer name
444 * NERR_UserNotFound User name could not be found.
446 NET_API_STATUS WINAPI NetSessionEnum(LMSTR servername, LMSTR UncClientName,
447 LMSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread,
448 LPDWORD totalentries, LPDWORD resume_handle)
450 FIXME("Stub (%s %s %s %ld %p %ld %p %p %p)\n", debugstr_w(servername),
451 debugstr_w(UncClientName), debugstr_w(username),
452 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
454 return NERR_Success;
457 /************************************************************
458 * NetShareEnum (NETAPI32.@)
460 * PARAMS
461 * servername [I] Pointer to a string with the name of the server
462 * level [I] Data information level
463 * bufptr [O] Buffer to the data
464 * prefmaxlen [I] Preferred maximum length of the data
465 * entriesread [O] Pointer to the number of entries enumerated
466 * totalentries [O] Pointer to the possible number of entries
467 * resume_handle [I/O] Pointer to a handle for subsequent searches
469 * RETURNS
470 * If successful, the function returns NERR_Success
471 * On failure it returns a system error code (FIXME: find out which)
474 NET_API_STATUS WINAPI NetShareEnum( LMSTR servername, DWORD level, LPBYTE* bufptr,
475 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
477 FIXME("Stub (%s %ld %p %ld %p %p %p)\n", debugstr_w(servername), level, bufptr,
478 prefmaxlen, entriesread, totalentries, resume_handle);
480 return ERROR_NOT_SUPPORTED;
483 /************************************************************
484 * NetShareDel (NETAPI32.@)
486 NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserved)
488 BOOL local = NETAPI_IsLocalComputer( servername );
490 TRACE("%s %s %ld\n", debugstr_w(servername), debugstr_w(netname), reserved);
492 if (!local)
494 if (samba_init())
496 struct share_del_params params = { servername, netname, reserved };
497 return SAMBA_CALL( share_del, &params );
499 FIXME( "remote computers not supported\n" );
502 FIXME("%s %s %ld\n", debugstr_w(servername), debugstr_w(netname), reserved);
503 return NERR_Success;
506 /************************************************************
507 * NetShareGetInfo (NETAPI32.@)
509 NET_API_STATUS WINAPI NetShareGetInfo(LMSTR servername, LMSTR netname,
510 DWORD level, LPBYTE *bufptr)
512 FIXME("Stub (%s %s %ld %p)\n", debugstr_w(servername),
513 debugstr_w(netname),level, bufptr);
514 return NERR_NetNameNotFound;
517 /************************************************************
518 * NetShareAdd (NETAPI32.@)
520 NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
521 DWORD level, LPBYTE buf, LPDWORD parm_err)
523 BOOL local = NETAPI_IsLocalComputer( servername );
525 TRACE("%s %ld %p %p\n", debugstr_w(servername), level, buf, parm_err);
527 if (!local)
529 if (samba_init())
531 struct share_add_params params = { servername, level, buf, parm_err };
532 return SAMBA_CALL( share_add, &params );
534 FIXME( "remote computers not supported\n" );
537 FIXME("%s %ld %p %p\n", debugstr_w(servername), level, buf, parm_err);
538 return ERROR_NOT_SUPPORTED;
541 /************************************************************
542 * NetFileEnum (NETAPI32.@)
544 NET_API_STATUS WINAPI NetFileEnum(
545 LPWSTR ServerName, LPWSTR BasePath, LPWSTR UserName,
546 DWORD Level, LPBYTE* BufPtr, DWORD PrefMaxLen,
547 LPDWORD EntriesRead, LPDWORD TotalEntries, PDWORD_PTR ResumeHandle)
549 FIXME("(%s, %s, %s, %lu): stub\n", debugstr_w(ServerName), debugstr_w(BasePath),
550 debugstr_w(UserName), Level);
551 return ERROR_NOT_SUPPORTED;
554 static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)
556 int i;
557 unsigned char val;
559 if (!buffer)
560 return;
561 if (len < 1)
562 return;
563 if (!ifRow)
565 *buffer = '\0';
566 return;
569 for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
571 val = ifRow->bPhysAddr[i];
572 if ((val >>4) >9)
573 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
574 else
575 buffer[2*i] = (WCHAR)((val >>4) + '0');
576 if ((val & 0xf ) >9)
577 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
578 else
579 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
581 buffer[2*i]=0;
584 /* Theoretically this could be too short, except that MS defines
585 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
586 * represent a count of WCHARs, so even with an extraordinarily long header
587 * this will be plenty
589 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
590 #define MAX_TRANSPORT_ADDR 13
592 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
593 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
595 static void wprint_name(WCHAR *buffer, int len, ULONG transport,
596 PMIB_IFROW ifRow)
598 WCHAR *ptr1, *ptr2;
599 const char *name;
601 if (!buffer)
602 return;
603 if (!ifRow)
605 *buffer = '\0';
606 return;
609 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
610 name = NBT_TRANSPORT_NAME_HEADER;
611 else
612 name = UNKNOWN_TRANSPORT_NAME_HEADER;
614 for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
615 *ptr1 = *name;
616 for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
617 *ptr1 = *ptr2;
618 *ptr1 = '\0';
621 /***********************************************************************
622 * NetWkstaTransportEnum (NETAPI32.@)
625 struct WkstaTransportEnumData
627 UCHAR n_adapt;
628 UCHAR n_read;
629 DWORD prefmaxlen;
630 LPBYTE *pbuf;
631 NET_API_STATUS ret;
634 /**********************************************************************/
636 static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
637 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
639 BOOL ret;
640 struct WkstaTransportEnumData *enumData = closure;
642 if (enumData && enumData->pbuf)
644 if (lanaIndex == 0)
646 DWORD toAllocate;
648 enumData->n_adapt = totalLANAs;
649 enumData->n_read = 0;
651 toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
652 + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
653 MAX_TRANSPORT_ADDR * sizeof(WCHAR));
654 if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
655 toAllocate = enumData->prefmaxlen;
656 NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
658 if (*(enumData->pbuf))
660 UCHAR spaceFor;
662 if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
663 spaceFor = totalLANAs;
664 else
665 spaceFor = enumData->prefmaxlen /
666 (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
667 MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
668 if (enumData->n_read < spaceFor)
670 PWKSTA_TRANSPORT_INFO_0 ti;
671 LMSTR transport_name, transport_addr;
672 MIB_IFROW ifRow;
674 ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
675 enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
676 transport_name = (LMSTR)(*(enumData->pbuf) +
677 totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
678 enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
679 transport_addr = (LMSTR)(*(enumData->pbuf) +
680 totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
681 MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
682 enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
684 ifRow.dwIndex = data->ifIndex;
685 GetIfEntry(&ifRow);
686 ti->wkti0_quality_of_service = 0;
687 ti->wkti0_number_of_vcs = 0;
688 ti->wkti0_transport_name = transport_name;
689 wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
690 transport, &ifRow);
691 ti->wkti0_transport_address = transport_addr;
692 wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
693 &ifRow);
694 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
695 ti->wkti0_wan_ish = TRUE;
696 else
697 ti->wkti0_wan_ish = FALSE;
698 TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
699 TRACE("transport_name at %p %s\n",
700 ti->wkti0_transport_name,
701 debugstr_w(ti->wkti0_transport_name));
702 TRACE("transport_address at %p %s\n",
703 ti->wkti0_transport_address,
704 debugstr_w(ti->wkti0_transport_address));
705 enumData->n_read++;
706 enumData->ret = NERR_Success;
707 ret = TRUE;
709 else
711 enumData->ret = ERROR_MORE_DATA;
712 ret = FALSE;
715 else
717 enumData->ret = ERROR_OUTOFMEMORY;
718 ret = FALSE;
721 else
722 ret = FALSE;
723 return ret;
726 /**********************************************************************/
728 NET_API_STATUS WINAPI
729 NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
730 DWORD prefmaxlen, LPDWORD read_entries,
731 PDWORD total_entries, PDWORD hresume)
733 NET_API_STATUS ret;
735 TRACE(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName),
736 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
737 if (!NETAPI_IsLocalComputer(ServerName))
739 FIXME(":not implemented for non-local computers\n");
740 ret = ERROR_INVALID_LEVEL;
742 else
744 if (hresume && *hresume)
746 FIXME(":resume handle not implemented\n");
747 return ERROR_INVALID_LEVEL;
750 switch (level)
752 case 0: /* transport info */
754 ULONG allTransports;
755 struct WkstaTransportEnumData enumData;
757 if (NetBIOSNumAdapters() == 0)
758 return ERROR_NETWORK_UNREACHABLE;
759 if (!read_entries)
760 return STATUS_ACCESS_VIOLATION;
761 if (!total_entries || !pbuf)
762 return RPC_X_NULL_REF_POINTER;
764 enumData.prefmaxlen = prefmaxlen;
765 enumData.pbuf = pbuf;
766 memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
767 NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
768 &enumData);
769 *read_entries = enumData.n_read;
770 *total_entries = enumData.n_adapt;
771 if (hresume) *hresume= 0;
772 ret = enumData.ret;
773 break;
775 default:
776 TRACE("Invalid level %ld is specified\n", level);
777 ret = ERROR_INVALID_LEVEL;
780 return ret;
783 /************************************************************
784 * NetWkstaUserGetInfo (NETAPI32.@)
786 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
787 PBYTE* bufptr)
789 NET_API_STATUS nastatus;
791 TRACE("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr);
792 switch (level)
794 case 0:
796 PWKSTA_USER_INFO_0 ui;
797 DWORD dwSize = UNLEN + 1;
799 /* set up buffer */
800 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
801 (LPVOID *) bufptr);
802 if (nastatus != NERR_Success)
803 return ERROR_NOT_ENOUGH_MEMORY;
805 ui = (PWKSTA_USER_INFO_0) *bufptr;
806 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
808 /* get data */
809 if (!GetUserNameW(ui->wkui0_username, &dwSize))
811 NetApiBufferFree(ui);
812 return ERROR_NOT_ENOUGH_MEMORY;
814 else {
815 nastatus = NetApiBufferReallocate(
816 *bufptr, sizeof(WKSTA_USER_INFO_0) +
817 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
818 (LPVOID *) bufptr);
819 if (nastatus != NERR_Success)
821 NetApiBufferFree(ui);
822 return nastatus;
824 ui = (PWKSTA_USER_INFO_0) *bufptr;
825 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
827 break;
830 case 1:
832 PWKSTA_USER_INFO_1 ui;
833 PWKSTA_USER_INFO_0 ui0;
834 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
835 LSA_HANDLE PolicyHandle;
836 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
837 NTSTATUS NtStatus;
839 /* sizes of the field buffers in WCHARS */
840 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
842 FIXME("Level 1 processing is partially implemented\n");
843 oth_domains_sz = 1;
844 logon_server_sz = 1;
846 /* get some information first to estimate size of the buffer */
847 ui0 = NULL;
848 nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
849 if (nastatus != NERR_Success)
850 return nastatus;
851 username_sz = lstrlenW(ui0->wkui0_username) + 1;
853 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
854 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
855 POLICY_VIEW_LOCAL_INFORMATION,
856 &PolicyHandle);
857 if (NtStatus != STATUS_SUCCESS)
859 TRACE("LsaOpenPolicyFailed with NT status %lx\n",
860 LsaNtStatusToWinError(NtStatus));
861 NetApiBufferFree(ui0);
862 return ERROR_NOT_ENOUGH_MEMORY;
864 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
865 (PVOID*) &DomainInfo);
866 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
867 LsaClose(PolicyHandle);
869 /* set up buffer */
870 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
871 (username_sz + logon_domain_sz +
872 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
873 (LPVOID *) bufptr);
874 if (nastatus != NERR_Success) {
875 NetApiBufferFree(ui0);
876 return nastatus;
878 ui = (WKSTA_USER_INFO_1 *) *bufptr;
879 ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
880 ui->wkui1_logon_domain = (LMSTR) (
881 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
882 ui->wkui1_oth_domains = (LMSTR) (
883 ((PBYTE) ui->wkui1_logon_domain) +
884 logon_domain_sz * sizeof(WCHAR));
885 ui->wkui1_logon_server = (LMSTR) (
886 ((PBYTE) ui->wkui1_oth_domains) +
887 oth_domains_sz * sizeof(WCHAR));
889 /* get data */
890 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
891 NetApiBufferFree(ui0);
893 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
894 logon_domain_sz);
895 LsaFreeMemory(DomainInfo);
897 /* FIXME. Not implemented. Populated with empty strings */
898 ui->wkui1_oth_domains[0] = 0;
899 ui->wkui1_logon_server[0] = 0;
900 break;
902 case 1101:
904 PWKSTA_USER_INFO_1101 ui;
905 DWORD dwSize = 1;
907 FIXME("Stub. Level 1101 processing is not implemented\n");
908 /* FIXME see also wkui1_oth_domains for level 1 */
910 /* set up buffer */
911 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
912 (LPVOID *) bufptr);
913 if (nastatus != NERR_Success)
914 return nastatus;
915 ui = (PWKSTA_USER_INFO_1101) *bufptr;
916 ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
918 /* get data */
919 ui->wkui1101_oth_domains[0] = 0;
920 break;
922 default:
923 TRACE("Invalid level %ld is specified\n", level);
924 return ERROR_INVALID_LEVEL;
926 return NERR_Success;
929 /************************************************************
930 * NetWkstaUserEnum (NETAPI32.@)
932 NET_API_STATUS WINAPI
933 NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr,
934 DWORD prefmaxlen, LPDWORD entriesread,
935 LPDWORD totalentries, LPDWORD resumehandle)
937 FIXME("(%s, %ld, %p, %ld, %p, %p, %p): stub!\n", debugstr_w(servername),
938 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
939 return ERROR_INVALID_PARAMETER;
942 /************************************************************
943 * NetpGetComputerName (NETAPI32.@)
945 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
947 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
949 TRACE("(%p)\n", Buffer);
950 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
951 if (GetComputerNameW(*Buffer, &dwSize))
953 return NetApiBufferReallocate(
954 *Buffer, (dwSize + 1) * sizeof(WCHAR),
955 (LPVOID *) Buffer);
957 else
959 NetApiBufferFree(*Buffer);
960 return ERROR_NOT_ENOUGH_MEMORY;
964 NET_API_STATUS WINAPI I_NetNameCompare(LPVOID p1, LPWSTR wkgrp, LPWSTR comp,
965 LPVOID p4, LPVOID p5)
967 FIXME("(%p %s %s %p %p): stub\n", p1, debugstr_w(wkgrp), debugstr_w(comp),
968 p4, p5);
969 return ERROR_INVALID_PARAMETER;
972 NET_API_STATUS WINAPI I_NetNameValidate(LPVOID p1, LPWSTR wkgrp, LPVOID p3,
973 LPVOID p4)
975 FIXME("(%p %s %p %p): stub\n", p1, debugstr_w(wkgrp), p3, p4);
976 return ERROR_INVALID_PARAMETER;
979 NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
980 LPBYTE* bufptr)
982 NET_API_STATUS ret;
983 BOOL local = NETAPI_IsLocalComputer( servername );
985 TRACE("%s %ld %p\n", debugstr_w( servername ), level, bufptr );
987 if (!local)
989 if (samba_init())
991 ULONG size = 1024;
992 struct wksta_getinfo_params params = { servername, level, NULL, &size };
994 for (;;)
996 if (!(params.buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
997 ret = SAMBA_CALL( wksta_getinfo, &params );
998 if (!ret) *bufptr = params.buffer;
999 else free( params.buffer );
1000 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
1003 FIXME( "remote computers not supported\n" );
1004 return ERROR_INVALID_LEVEL;
1006 if (!bufptr) return ERROR_INVALID_PARAMETER;
1008 switch (level)
1010 case 100:
1011 case 101:
1012 case 102:
1014 static const WCHAR lanroot[] = L"c:\\lanman"; /* FIXME */
1015 DWORD computerNameLen, domainNameLen, size;
1016 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1017 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1018 LSA_HANDLE PolicyHandle;
1019 NTSTATUS NtStatus;
1021 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1022 GetComputerNameW(computerName, &computerNameLen);
1023 computerNameLen++; /* include NULL terminator */
1025 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1026 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1027 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
1028 if (NtStatus != STATUS_SUCCESS)
1029 ret = LsaNtStatusToWinError(NtStatus);
1030 else
1032 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1034 LsaQueryInformationPolicy(PolicyHandle,
1035 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
1036 domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1037 size = sizeof(WKSTA_INFO_102) + computerNameLen * sizeof(WCHAR)
1038 + domainNameLen * sizeof(WCHAR) + sizeof(lanroot);
1039 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1040 if (ret == NERR_Success)
1042 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1043 PWKSTA_INFO_102 info = (PWKSTA_INFO_102)*bufptr;
1044 OSVERSIONINFOW verInfo;
1046 info->wki102_platform_id = PLATFORM_ID_NT;
1047 info->wki102_computername = (LMSTR)(*bufptr +
1048 sizeof(WKSTA_INFO_102));
1049 memcpy(info->wki102_computername, computerName,
1050 computerNameLen * sizeof(WCHAR));
1051 info->wki102_langroup = info->wki102_computername + computerNameLen;
1052 memcpy(info->wki102_langroup, DomainInfo->DomainName.Buffer,
1053 domainNameLen * sizeof(WCHAR));
1054 info->wki102_lanroot = info->wki102_langroup + domainNameLen;
1055 memcpy(info->wki102_lanroot, lanroot, sizeof(lanroot));
1056 memset(&verInfo, 0, sizeof(verInfo));
1057 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1058 GetVersionExW(&verInfo);
1059 info->wki102_ver_major = verInfo.dwMajorVersion;
1060 info->wki102_ver_minor = verInfo.dwMinorVersion;
1061 info->wki102_logged_on_users = 1;
1063 LsaFreeMemory(DomainInfo);
1064 LsaClose(PolicyHandle);
1066 break;
1069 default:
1070 FIXME("level %ld unimplemented\n", level);
1071 ret = ERROR_INVALID_LEVEL;
1073 return ret;
1076 /************************************************************
1077 * NetGetJoinInformation (NETAPI32.@)
1079 NET_API_STATUS NET_API_FUNCTION NetGetJoinInformation(
1080 LPCWSTR Server,
1081 LPWSTR *Name,
1082 PNETSETUP_JOIN_STATUS type)
1084 static const WCHAR workgroupW[] = L"Workgroup";
1086 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server), Name, type);
1088 if (!Name || !type)
1089 return ERROR_INVALID_PARAMETER;
1091 NetApiBufferAllocate(sizeof(workgroupW), (LPVOID *)Name);
1092 lstrcpyW(*Name, workgroupW);
1093 *type = NetSetupWorkgroupName;
1095 return NERR_Success;
1098 /************************************************************
1099 * NetUserGetGroups (NETAPI32.@)
1101 NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
1102 LPCWSTR servername,
1103 LPCWSTR username,
1104 DWORD level,
1105 LPBYTE *bufptr,
1106 DWORD prefixmaxlen,
1107 LPDWORD entriesread,
1108 LPDWORD totalentries)
1110 FIXME("%s %s %ld %p %ld %p %p stub\n", debugstr_w(servername),
1111 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
1112 totalentries);
1114 *bufptr = NULL;
1115 *entriesread = 0;
1116 *totalentries = 0;
1118 return ERROR_INVALID_LEVEL;
1121 struct sam_user
1123 struct list entry;
1124 WCHAR user_name[LM20_UNLEN+1];
1125 WCHAR user_password[PWLEN + 1];
1126 DWORD sec_since_passwd_change;
1127 DWORD user_priv;
1128 LPWSTR home_dir;
1129 LPWSTR user_comment;
1130 DWORD user_flags;
1131 LPWSTR user_logon_script_path;
1134 static struct list user_list = LIST_INIT( user_list );
1136 /************************************************************
1137 * NETAPI_ValidateServername
1139 * Validates server name
1141 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
1143 if (ServerName)
1145 if (ServerName[0] == 0)
1146 return ERROR_BAD_NETPATH;
1147 else if (
1148 ((ServerName[0] == '\\') &&
1149 (ServerName[1] != '\\'))
1151 ((ServerName[0] == '\\') &&
1152 (ServerName[1] == '\\') &&
1153 (ServerName[2] == 0))
1155 return ERROR_INVALID_NAME;
1157 return NERR_Success;
1160 /************************************************************
1161 * NETAPI_FindUser
1163 * Looks for a user in the user database.
1164 * Returns a pointer to the entry in the user list when the user
1165 * is found, NULL otherwise.
1167 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
1169 struct sam_user *user;
1171 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
1173 if(wcscmp(user->user_name, UserName) == 0)
1174 return user;
1176 return NULL;
1179 static BOOL NETAPI_IsCurrentUser(LPCWSTR username)
1181 LPWSTR curr_user = NULL;
1182 DWORD dwSize;
1183 BOOL ret = FALSE;
1185 dwSize = LM20_UNLEN+1;
1186 curr_user = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
1187 if(!curr_user)
1189 ERR("Failed to allocate memory for user name.\n");
1190 goto end;
1192 if(!GetUserNameW(curr_user, &dwSize))
1194 ERR("Failed to get current user's user name.\n");
1195 goto end;
1197 if (!wcscmp(curr_user, username))
1199 ret = TRUE;
1202 end:
1203 HeapFree(GetProcessHeap(), 0, curr_user);
1204 return ret;
1207 /************************************************************
1208 * NetUserAdd (NETAPI32.@)
1210 NET_API_STATUS WINAPI NetUserAdd(LPCWSTR servername,
1211 DWORD level, LPBYTE bufptr, LPDWORD parm_err)
1213 NET_API_STATUS status;
1214 struct sam_user * su = NULL;
1216 FIXME("(%s, %ld, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err);
1218 if((status = NETAPI_ValidateServername(servername)) != NERR_Success)
1219 return status;
1221 switch(level)
1223 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
1224 case 4:
1225 case 3:
1226 FIXME("Level 3 and 4 not implemented.\n");
1227 /* Fall through */
1228 case 2:
1229 FIXME("Level 2 not implemented.\n");
1230 /* Fall through */
1231 case 1:
1233 PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
1234 su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
1235 if(!su)
1237 status = NERR_InternalError;
1238 break;
1241 if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
1243 status = NERR_BadUsername;
1244 break;
1247 /*FIXME: do other checks for a valid username */
1248 lstrcpyW(su->user_name, ui->usri1_name);
1250 if(lstrlenW(ui->usri1_password) > PWLEN)
1252 /* Always return PasswordTooShort on invalid passwords. */
1253 status = NERR_PasswordTooShort;
1254 break;
1256 lstrcpyW(su->user_password, ui->usri1_password);
1258 su->sec_since_passwd_change = ui->usri1_password_age;
1259 su->user_priv = ui->usri1_priv;
1260 su->user_flags = ui->usri1_flags;
1262 /*FIXME: set the other LPWSTRs to NULL for now */
1263 su->home_dir = NULL;
1264 su->user_comment = NULL;
1265 su->user_logon_script_path = NULL;
1267 list_add_head(&user_list, &su->entry);
1268 return NERR_Success;
1270 default:
1271 TRACE("Invalid level %ld specified.\n", level);
1272 status = ERROR_INVALID_LEVEL;
1273 break;
1276 HeapFree(GetProcessHeap(), 0, su);
1278 return status;
1281 /************************************************************
1282 * NetUserDel (NETAPI32.@)
1284 NET_API_STATUS WINAPI NetUserDel(LPCWSTR servername, LPCWSTR username)
1286 NET_API_STATUS status;
1287 struct sam_user *user;
1289 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
1291 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
1292 return status;
1294 if ((user = NETAPI_FindUser(username)) == NULL)
1295 return NERR_UserNotFound;
1297 list_remove(&user->entry);
1299 HeapFree(GetProcessHeap(), 0, user->home_dir);
1300 HeapFree(GetProcessHeap(), 0, user->user_comment);
1301 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
1302 HeapFree(GetProcessHeap(), 0, user);
1304 return NERR_Success;
1307 /************************************************************
1308 * NetUserGetInfo (NETAPI32.@)
1310 NET_API_STATUS WINAPI
1311 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
1312 LPBYTE* bufptr)
1314 NET_API_STATUS status;
1315 TRACE("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username),
1316 level, bufptr);
1317 status = NETAPI_ValidateServername(servername);
1318 if (status != NERR_Success)
1319 return status;
1321 if(!NETAPI_IsLocalComputer(servername))
1323 FIXME("Only implemented for local computer, but remote server"
1324 "%s was requested.\n", debugstr_w(servername));
1325 return NERR_InvalidComputer;
1328 if(!NETAPI_FindUser(username) && !NETAPI_IsCurrentUser(username))
1330 TRACE("User %s is unknown.\n", debugstr_w(username));
1331 return NERR_UserNotFound;
1334 switch (level)
1336 case 0:
1338 PUSER_INFO_0 ui;
1339 int name_sz;
1341 name_sz = lstrlenW(username) + 1;
1343 /* set up buffer */
1344 NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
1345 (LPVOID *) bufptr);
1347 ui = (PUSER_INFO_0) *bufptr;
1348 ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
1350 /* get data */
1351 lstrcpyW(ui->usri0_name, username);
1352 break;
1355 case 10:
1357 PUSER_INFO_10 ui;
1358 PUSER_INFO_0 ui0;
1359 /* sizes of the field buffers in WCHARS */
1360 int name_sz, comment_sz, usr_comment_sz, full_name_sz;
1362 comment_sz = 1;
1363 usr_comment_sz = 1;
1364 full_name_sz = 1;
1366 /* get data */
1367 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1368 if (status != NERR_Success)
1370 NetApiBufferFree(ui0);
1371 return status;
1373 name_sz = lstrlenW(ui0->usri0_name) + 1;
1375 /* set up buffer */
1376 NetApiBufferAllocate(sizeof(USER_INFO_10) +
1377 (name_sz + comment_sz + usr_comment_sz +
1378 full_name_sz) * sizeof(WCHAR),
1379 (LPVOID *) bufptr);
1380 ui = (PUSER_INFO_10) *bufptr;
1381 ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
1382 ui->usri10_comment = (LPWSTR) (
1383 ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
1384 ui->usri10_usr_comment = (LPWSTR) (
1385 ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
1386 ui->usri10_full_name = (LPWSTR) (
1387 ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
1389 /* set data */
1390 lstrcpyW(ui->usri10_name, ui0->usri0_name);
1391 NetApiBufferFree(ui0);
1392 ui->usri10_comment[0] = 0;
1393 ui->usri10_usr_comment[0] = 0;
1394 ui->usri10_full_name[0] = 0;
1395 break;
1398 case 1:
1400 PUSER_INFO_1 ui;
1401 PUSER_INFO_0 ui0;
1402 /* sizes of the field buffers in WCHARS */
1403 int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
1405 password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
1406 comment_sz = 1;
1407 script_path_sz = 1;
1409 /* get data */
1410 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1411 if (status != NERR_Success)
1413 NetApiBufferFree(ui0);
1414 return status;
1416 name_sz = lstrlenW(ui0->usri0_name) + 1;
1417 home_dir_sz = GetEnvironmentVariableW(L"HOME", NULL,0);
1418 /* set up buffer */
1419 NetApiBufferAllocate(sizeof(USER_INFO_1) +
1420 (name_sz + password_sz + home_dir_sz +
1421 comment_sz + script_path_sz) * sizeof(WCHAR),
1422 (LPVOID *) bufptr);
1424 ui = (PUSER_INFO_1) *bufptr;
1425 ui->usri1_name = (LPWSTR) (ui + 1);
1426 ui->usri1_password = ui->usri1_name + name_sz;
1427 ui->usri1_home_dir = ui->usri1_password + password_sz;
1428 ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
1429 ui->usri1_script_path = ui->usri1_comment + comment_sz;
1430 /* set data */
1431 lstrcpyW(ui->usri1_name, ui0->usri0_name);
1432 NetApiBufferFree(ui0);
1433 ui->usri1_password[0] = 0;
1434 ui->usri1_password_age = 0;
1435 ui->usri1_priv = 0;
1436 GetEnvironmentVariableW(L"HOME", ui->usri1_home_dir,home_dir_sz);
1437 ui->usri1_comment[0] = 0;
1438 ui->usri1_flags = 0;
1439 ui->usri1_script_path[0] = 0;
1440 break;
1442 case 2:
1443 case 3:
1444 case 4:
1445 case 11:
1446 case 20:
1447 case 23:
1448 case 1003:
1449 case 1005:
1450 case 1006:
1451 case 1007:
1452 case 1008:
1453 case 1009:
1454 case 1010:
1455 case 1011:
1456 case 1012:
1457 case 1013:
1458 case 1014:
1459 case 1017:
1460 case 1018:
1461 case 1020:
1462 case 1023:
1463 case 1024:
1464 case 1025:
1465 case 1051:
1466 case 1052:
1467 case 1053:
1469 FIXME("Level %ld is not implemented\n", level);
1470 return NERR_InternalError;
1472 default:
1473 TRACE("Invalid level %ld is specified\n", level);
1474 return ERROR_INVALID_LEVEL;
1476 return NERR_Success;
1479 /************************************************************
1480 * NetUserGetLocalGroups (NETAPI32.@)
1482 NET_API_STATUS WINAPI
1483 NetUserGetLocalGroups(LPCWSTR servername, LPCWSTR username, DWORD level,
1484 DWORD flags, LPBYTE* bufptr, DWORD prefmaxlen,
1485 LPDWORD entriesread, LPDWORD totalentries)
1487 static const WCHAR admins[] = L"Administrators";
1488 NET_API_STATUS status;
1489 LPWSTR currentuser;
1490 LOCALGROUP_USERS_INFO_0* info;
1491 DWORD size;
1493 FIXME("(%s, %s, %ld, %08lx, %p %ld, %p, %p) stub!\n",
1494 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
1495 prefmaxlen, entriesread, totalentries);
1497 status = NETAPI_ValidateServername(servername);
1498 if (status != NERR_Success)
1499 return status;
1501 size = UNLEN + 1;
1502 NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)&currentuser);
1503 if (!GetUserNameW(currentuser, &size)) {
1504 NetApiBufferFree(currentuser);
1505 return ERROR_NOT_ENOUGH_MEMORY;
1508 if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
1510 NetApiBufferFree(currentuser);
1511 return NERR_UserNotFound;
1514 NetApiBufferFree(currentuser);
1515 *totalentries = 1;
1516 size = sizeof(*info) + sizeof(admins);
1518 if(prefmaxlen < size)
1519 status = ERROR_MORE_DATA;
1520 else
1521 status = NetApiBufferAllocate(size, (LPVOID*)&info);
1523 if(status != NERR_Success)
1525 *bufptr = NULL;
1526 *entriesread = 0;
1527 return status;
1530 info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
1531 lstrcpyW(info->lgrui0_name, admins);
1533 *bufptr = (LPBYTE)info;
1534 *entriesread = 1;
1536 return NERR_Success;
1539 /************************************************************
1540 * NetUserEnum (NETAPI32.@)
1542 NET_API_STATUS WINAPI
1543 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
1544 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
1545 LPDWORD resume_handle)
1547 NET_API_STATUS status;
1548 WCHAR user[UNLEN + 1];
1549 DWORD size, len = ARRAY_SIZE(user);
1551 TRACE("(%s, %lu, 0x%lx, %p, %lu, %p, %p, %p)\n", debugstr_w(servername), level,
1552 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1554 status = NETAPI_ValidateServername(servername);
1555 if (status != NERR_Success)
1556 return status;
1558 if (!NETAPI_IsLocalComputer(servername))
1560 FIXME("Only implemented for local computer, but remote server"
1561 "%s was requested.\n", debugstr_w(servername));
1562 return NERR_InvalidComputer;
1565 if (!GetUserNameW(user, &len)) return GetLastError();
1567 switch (level)
1569 case 0:
1571 USER_INFO_0 *info;
1573 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1575 if (prefmaxlen < size)
1576 status = ERROR_MORE_DATA;
1577 else
1578 status = NetApiBufferAllocate(size, (void **)&info);
1580 if (status != NERR_Success)
1581 return status;
1583 info->usri0_name = (WCHAR *)((char *)info + sizeof(*info));
1584 wcscpy(info->usri0_name, user);
1586 *bufptr = (BYTE *)info;
1587 *entriesread = *totalentries = 1;
1588 break;
1590 case 20:
1592 USER_INFO_20 *info;
1593 SID *sid;
1594 UCHAR *count;
1595 DWORD *rid;
1596 SID_NAME_USE use;
1598 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1600 if (prefmaxlen < size)
1601 status = ERROR_MORE_DATA;
1602 else
1603 status = NetApiBufferAllocate(size, (void **)&info);
1605 if (status != NERR_Success)
1606 return status;
1608 size = len = 0;
1609 LookupAccountNameW(NULL, user, NULL, &size, NULL, &len, &use);
1610 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1611 return GetLastError();
1613 status = NetApiBufferAllocate(size, (void **)&sid);
1614 if (status != NERR_Success)
1615 return status;
1617 if (!LookupAccountNameW(NULL, user, sid, &size, NULL, &len, &use))
1618 return GetLastError();
1620 count = GetSidSubAuthorityCount(sid);
1621 rid = GetSidSubAuthority(sid, *count - 1);
1623 info->usri20_name = (WCHAR *)((char *)info + sizeof(*info));
1624 wcscpy(info->usri20_name, user);
1625 info->usri20_full_name = NULL;
1626 info->usri20_comment = NULL;
1627 info->usri20_flags = UF_NORMAL_ACCOUNT;
1628 info->usri20_user_id = *rid;
1630 *bufptr = (BYTE *)info;
1631 *entriesread = *totalentries = 1;
1633 NetApiBufferFree(sid);
1634 break;
1636 default:
1637 FIXME("level %lu not supported\n", level);
1638 return ERROR_INVALID_LEVEL;
1640 return NERR_Success;
1643 /************************************************************
1644 * ACCESS_QueryAdminDisplayInformation
1646 * Creates a buffer with information for the Admin User
1648 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1650 static const WCHAR sAdminUserName[] = L"Administrator";
1652 /* sizes of the field buffers in WCHARS */
1653 int name_sz, comment_sz, full_name_sz;
1654 PNET_DISPLAY_USER usr;
1656 /* set up buffer */
1657 name_sz = lstrlenW(sAdminUserName) + 1;
1658 comment_sz = 1;
1659 full_name_sz = 1;
1661 *pdwSize = sizeof(NET_DISPLAY_USER);
1662 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1663 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1665 usr = *buf;
1666 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1667 usr->usri1_comment = (LPWSTR) (
1668 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1669 usr->usri1_full_name = (LPWSTR) (
1670 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1672 /* set data */
1673 lstrcpyW(usr->usri1_name, sAdminUserName);
1674 usr->usri1_comment[0] = 0;
1675 usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1676 usr->usri1_full_name[0] = 0;
1677 usr->usri1_user_id = DOMAIN_USER_RID_ADMIN;
1678 usr->usri1_next_index = 0;
1681 /************************************************************
1682 * ACCESS_QueryGuestDisplayInformation
1684 * Creates a buffer with information for the Guest User
1686 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1688 static const WCHAR sGuestUserName[] = L"Guest";
1690 /* sizes of the field buffers in WCHARS */
1691 int name_sz, comment_sz, full_name_sz;
1692 PNET_DISPLAY_USER usr;
1694 /* set up buffer */
1695 name_sz = lstrlenW(sGuestUserName) + 1;
1696 comment_sz = 1;
1697 full_name_sz = 1;
1699 *pdwSize = sizeof(NET_DISPLAY_USER);
1700 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1701 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1703 usr = *buf;
1704 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1705 usr->usri1_comment = (LPWSTR) (
1706 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1707 usr->usri1_full_name = (LPWSTR) (
1708 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1710 /* set data */
1711 lstrcpyW(usr->usri1_name, sGuestUserName);
1712 usr->usri1_comment[0] = 0;
1713 usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
1714 UF_DONT_EXPIRE_PASSWD;
1715 usr->usri1_full_name[0] = 0;
1716 usr->usri1_user_id = DOMAIN_USER_RID_GUEST;
1717 usr->usri1_next_index = 0;
1720 /************************************************************
1721 * Copies NET_DISPLAY_USER record.
1723 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER *dest, LPWSTR *dest_buf,
1724 PNET_DISPLAY_USER src)
1726 LPWSTR str = *dest_buf;
1728 src->usri1_name = str;
1729 lstrcpyW(src->usri1_name, dest->usri1_name);
1730 str = (LPWSTR) (
1731 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1733 src->usri1_comment = str;
1734 lstrcpyW(src->usri1_comment, dest->usri1_comment);
1735 str = (LPWSTR) (
1736 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1738 src->usri1_flags = dest->usri1_flags;
1740 src->usri1_full_name = str;
1741 lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
1742 str = (LPWSTR) (
1743 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1745 src->usri1_user_id = dest->usri1_user_id;
1746 src->usri1_next_index = dest->usri1_next_index;
1747 *dest_buf = str;
1750 /************************************************************
1751 * NetQueryDisplayInformation (NETAPI32.@)
1753 * The buffer structure:
1754 * - array of fixed size record of the level type
1755 * - strings, referenced by the record of the level type
1757 NET_API_STATUS WINAPI
1758 NetQueryDisplayInformation(
1759 LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
1760 DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
1761 PVOID *SortedBuffer)
1763 TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName),
1764 Level, Index, EntriesRequested, PreferredMaximumLength,
1765 ReturnedEntryCount, SortedBuffer);
1767 if(!NETAPI_IsLocalComputer(ServerName))
1769 FIXME("Only implemented on local computer, but requested for "
1770 "remote server %s\n", debugstr_w(ServerName));
1771 return ERROR_ACCESS_DENIED;
1774 switch (Level)
1776 case 1:
1778 /* current record */
1779 PNET_DISPLAY_USER inf;
1780 /* current available strings buffer */
1781 LPWSTR str;
1782 PNET_DISPLAY_USER admin, guest;
1783 DWORD admin_size, guest_size;
1784 LPWSTR name = NULL;
1785 DWORD dwSize;
1787 /* sizes of the field buffers in WCHARS */
1788 int name_sz, comment_sz, full_name_sz;
1790 /* number of the records, returned in SortedBuffer
1791 3 - for current user, Administrator and Guest users
1793 int records = 3;
1795 FIXME("Level %ld partially implemented\n", Level);
1796 *ReturnedEntryCount = records;
1797 comment_sz = 1;
1798 full_name_sz = 1;
1800 /* get data */
1801 dwSize = UNLEN + 1;
1802 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &name);
1803 if (!GetUserNameW(name, &dwSize))
1805 NetApiBufferFree(name);
1806 return ERROR_ACCESS_DENIED;
1808 name_sz = dwSize;
1809 ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
1810 ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
1812 /* set up buffer */
1813 dwSize = sizeof(NET_DISPLAY_USER) * records;
1814 dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1816 NetApiBufferAllocate(dwSize +
1817 admin_size - sizeof(NET_DISPLAY_USER) +
1818 guest_size - sizeof(NET_DISPLAY_USER),
1819 SortedBuffer);
1820 inf = *SortedBuffer;
1821 str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
1822 inf->usri1_name = str;
1823 str = (LPWSTR) (
1824 ((PBYTE) str) + name_sz * sizeof(WCHAR));
1825 inf->usri1_comment = str;
1826 str = (LPWSTR) (
1827 ((PBYTE) str) + comment_sz * sizeof(WCHAR));
1828 inf->usri1_full_name = str;
1829 str = (LPWSTR) (
1830 ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
1832 /* set data */
1833 lstrcpyW(inf->usri1_name, name);
1834 NetApiBufferFree(name);
1835 inf->usri1_comment[0] = 0;
1836 inf->usri1_flags =
1837 UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1838 inf->usri1_full_name[0] = 0;
1839 inf->usri1_user_id = 0;
1840 inf->usri1_next_index = 0;
1842 inf++;
1843 ACCESS_CopyDisplayUser(admin, &str, inf);
1844 NetApiBufferFree(admin);
1846 inf++;
1847 ACCESS_CopyDisplayUser(guest, &str, inf);
1848 NetApiBufferFree(guest);
1849 break;
1852 case 2:
1853 case 3:
1855 FIXME("Level %ld is not implemented\n", Level);
1856 break;
1859 default:
1860 TRACE("Invalid level %ld is specified\n", Level);
1861 return ERROR_INVALID_LEVEL;
1863 return NERR_Success;
1866 /************************************************************
1867 * NetGetDCName (NETAPI32.@)
1869 * Return the name of the primary domain controller (PDC)
1872 NET_API_STATUS WINAPI
1873 NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1875 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1876 debugstr_w(domainname), bufptr);
1877 return NERR_DCNotFound; /* say we can't find a domain controller */
1880 /************************************************************
1881 * NetGetAnyDCName (NETAPI32.@)
1883 * Return the name of any domain controller (DC) for a
1884 * domain that is directly trusted by the specified server
1887 NET_API_STATUS WINAPI NetGetAnyDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1889 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1890 debugstr_w(domainname), bufptr);
1891 return ERROR_NO_SUCH_DOMAIN;
1894 /************************************************************
1895 * NetGroupAddUser (NETAPI32.@)
1897 NET_API_STATUS WINAPI
1898 NetGroupAddUser(LPCWSTR servername, LPCWSTR groupname, LPCWSTR username)
1900 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername),
1901 debugstr_w(groupname), debugstr_w(username));
1902 return NERR_Success;
1905 /************************************************************
1906 * NetGroupEnum (NETAPI32.@)
1909 NET_API_STATUS WINAPI
1910 NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen,
1911 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
1913 FIXME("(%s, %ld, %p, %ld, %p, %p, %p) stub!\n", debugstr_w(servername),
1914 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1915 return ERROR_ACCESS_DENIED;
1918 /************************************************************
1919 * NetGroupGetInfo (NETAPI32.@)
1922 NET_API_STATUS WINAPI NetGroupGetInfo(LPCWSTR servername, LPCWSTR groupname, DWORD level, LPBYTE *bufptr)
1924 FIXME("(%s, %s, %ld, %p) stub!\n", debugstr_w(servername), debugstr_w(groupname), level, bufptr);
1925 return ERROR_ACCESS_DENIED;
1928 /******************************************************************************
1929 * NetUserModalsGet (NETAPI32.@)
1931 * Retrieves global information for all users and global groups in the security
1932 * database.
1934 * PARAMS
1935 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
1936 * on which the function is to execute.
1937 * level [I] Information level of the data.
1938 * 0 Return global passwords parameters. bufptr points to a
1939 * USER_MODALS_INFO_0 struct.
1940 * 1 Return logon server and domain controller information. bufptr
1941 * points to a USER_MODALS_INFO_1 struct.
1942 * 2 Return domain name and identifier. bufptr points to a
1943 * USER_MODALS_INFO_2 struct.
1944 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
1945 * struct.
1946 * pbuffer [I] Buffer that receives the data.
1948 * RETURNS
1949 * Success: NERR_Success.
1950 * Failure:
1951 * ERROR_ACCESS_DENIED - the user does not have access to the info.
1952 * NERR_InvalidComputer - computer name is invalid.
1954 NET_API_STATUS WINAPI NetUserModalsGet(
1955 LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
1957 TRACE("(%s %ld %p)\n", debugstr_w(szServer), level, pbuffer);
1959 switch (level)
1961 case 0:
1962 /* return global passwords parameters */
1963 FIXME("level 0 not implemented!\n");
1964 *pbuffer = NULL;
1965 return NERR_InternalError;
1966 case 1:
1967 /* return logon server and domain controller info */
1968 FIXME("level 1 not implemented!\n");
1969 *pbuffer = NULL;
1970 return NERR_InternalError;
1971 case 2:
1973 /* return domain name and identifier */
1974 PUSER_MODALS_INFO_2 umi;
1975 LSA_HANDLE policyHandle;
1976 LSA_OBJECT_ATTRIBUTES objectAttributes;
1977 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo;
1978 NTSTATUS ntStatus;
1979 PSID domainIdentifier = NULL;
1980 int domainNameLen;
1982 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
1983 objectAttributes.Length = sizeof(objectAttributes);
1985 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
1986 POLICY_VIEW_LOCAL_INFORMATION,
1987 &policyHandle);
1988 if (ntStatus != STATUS_SUCCESS)
1990 WARN("LsaOpenPolicy failed with NT status %lx\n",
1991 LsaNtStatusToWinError(ntStatus));
1992 return ntStatus;
1995 ntStatus = LsaQueryInformationPolicy(policyHandle,
1996 PolicyAccountDomainInformation,
1997 (PVOID *)&domainInfo);
1998 if (ntStatus != STATUS_SUCCESS)
2000 WARN("LsaQueryInformationPolicy failed with NT status %lx\n",
2001 LsaNtStatusToWinError(ntStatus));
2002 LsaClose(policyHandle);
2003 return ntStatus;
2006 domainIdentifier = domainInfo->DomainSid;
2007 domainNameLen = lstrlenW(domainInfo->DomainName.Buffer) + 1;
2008 LsaClose(policyHandle);
2010 ntStatus = NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2) +
2011 GetLengthSid(domainIdentifier) +
2012 domainNameLen * sizeof(WCHAR),
2013 (LPVOID *)pbuffer);
2015 if (ntStatus != NERR_Success)
2017 WARN("NetApiBufferAllocate() failed\n");
2018 LsaFreeMemory(domainInfo);
2019 return ntStatus;
2022 umi = (USER_MODALS_INFO_2 *) *pbuffer;
2023 umi->usrmod2_domain_id = *pbuffer + sizeof(USER_MODALS_INFO_2);
2024 umi->usrmod2_domain_name = (LPWSTR)(*pbuffer +
2025 sizeof(USER_MODALS_INFO_2) + GetLengthSid(domainIdentifier));
2027 lstrcpynW(umi->usrmod2_domain_name,
2028 domainInfo->DomainName.Buffer,
2029 domainNameLen);
2030 CopySid(GetLengthSid(domainIdentifier), umi->usrmod2_domain_id,
2031 domainIdentifier);
2033 LsaFreeMemory(domainInfo);
2035 break;
2037 case 3:
2038 /* return lockout information */
2039 FIXME("level 3 not implemented!\n");
2040 *pbuffer = NULL;
2041 return NERR_InternalError;
2042 default:
2043 TRACE("Invalid level %ld is specified\n", level);
2044 *pbuffer = NULL;
2045 return ERROR_INVALID_LEVEL;
2048 return NERR_Success;
2051 /******************************************************************************
2052 * NetUserChangePassword (NETAPI32.@)
2053 * PARAMS
2054 * domainname [I] Optional. Domain on which the user resides or the logon
2055 * domain of the current user if NULL.
2056 * username [I] Optional. Username to change the password for or the name
2057 * of the current user if NULL.
2058 * oldpassword [I] The user's current password.
2059 * newpassword [I] The password that the user will be changed to using.
2061 * RETURNS
2062 * Success: NERR_Success.
2063 * Failure: NERR_* failure code or win error code.
2066 NET_API_STATUS WINAPI NetUserChangePassword(LPCWSTR domainname, LPCWSTR username,
2067 LPCWSTR oldpassword, LPCWSTR newpassword)
2069 struct sam_user *user;
2070 struct change_password_params params = { domainname, username, oldpassword, newpassword };
2072 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2074 if (samba_init() && !SAMBA_CALL( change_password, &params ))
2075 return NERR_Success;
2077 if(domainname)
2078 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
2080 if((user = NETAPI_FindUser(username)) == NULL)
2081 return NERR_UserNotFound;
2083 if(wcscmp(user->user_password, oldpassword) != 0)
2084 return ERROR_INVALID_PASSWORD;
2086 if(lstrlenW(newpassword) > PWLEN)
2087 return ERROR_PASSWORD_RESTRICTION;
2089 lstrcpyW(user->user_password, newpassword);
2091 return NERR_Success;
2094 NET_API_STATUS WINAPI NetUseAdd(LMSTR servername, DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2096 FIXME("%s %ld %p %p stub\n", debugstr_w(servername), level, bufptr, parm_err);
2097 return NERR_Success;
2100 NET_API_STATUS WINAPI NetUseDel(LMSTR servername, LMSTR usename, DWORD forcecond)
2102 FIXME("%s %s %ld stub\n", debugstr_w(servername), debugstr_w(usename), forcecond);
2103 return NERR_Success;
2106 /************************************************************
2107 * I_BrowserSetNetlogonState (NETAPI32.@)
2109 NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
2110 LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
2111 DWORD Role)
2113 return ERROR_NOT_SUPPORTED;
2116 /************************************************************
2117 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
2119 NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
2120 LPWSTR ServerName, PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
2121 LPDWORD EntriesRead)
2123 return ERROR_NOT_SUPPORTED;
2126 #define NS_MAXDNAME 1025
2128 static DWORD get_dc_info(const WCHAR *domain, WCHAR *dc, WCHAR *ip)
2130 WCHAR name[NS_MAXDNAME];
2131 DWORD ret, size;
2132 DNS_RECORDW *rec;
2134 wcscpy( name, L"_ldap._tcp.dc._msdcs." );
2135 wcscat( name, domain );
2137 ret = DnsQuery_W(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2138 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(domain), ret);
2139 if (ret == ERROR_SUCCESS)
2141 TRACE("target %s, port %d\n", wine_dbgstr_w(rec->Data.Srv.pNameTarget), rec->Data.Srv.wPort);
2143 lstrcpynW(dc, rec->Data.Srv.pNameTarget, NS_MAXDNAME);
2144 DnsRecordListFree(rec, DnsFreeRecordList);
2146 /* IPv4 */
2147 ret = DnsQuery_W(dc, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2148 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(dc), ret);
2149 if (ret == ERROR_SUCCESS)
2151 SOCKADDR_IN addr;
2153 addr.sin_family = AF_INET;
2154 addr.sin_port = 0;
2155 addr.sin_addr.s_addr = rec->Data.A.IpAddress;
2156 size = IP6_ADDRESS_STRING_LENGTH;
2157 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2158 if (!ret)
2159 TRACE("WSAAddressToStringW => %ld, %s\n", ret, wine_dbgstr_w(ip));
2161 DnsRecordListFree(rec, DnsFreeRecordList);
2163 return ret;
2166 /* IPv6 */
2167 ret = DnsQuery_W(dc, DNS_TYPE_AAAA, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2168 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(dc), ret);
2169 if (ret == ERROR_SUCCESS)
2171 SOCKADDR_IN6 addr;
2173 addr.sin6_family = AF_INET6;
2174 addr.sin6_port = 0;
2175 addr.sin6_scope_id = 0;
2176 memcpy(addr.sin6_addr.s6_addr, &rec->Data.AAAA.Ip6Address, sizeof(rec->Data.AAAA.Ip6Address));
2177 size = IP6_ADDRESS_STRING_LENGTH;
2178 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2179 if (!ret)
2180 TRACE("WSAAddressToStringW => %ld, %s\n", ret, wine_dbgstr_w(ip));
2182 DnsRecordListFree(rec, DnsFreeRecordList);
2186 return ret;
2189 DWORD WINAPI DsGetDcNameW(LPCWSTR computer, LPCWSTR domain, GUID *domain_guid,
2190 LPCWSTR site, ULONG flags, PDOMAIN_CONTROLLER_INFOW *dc_info)
2192 static const WCHAR pfxW[] = {'\\','\\'};
2193 static const WCHAR default_site_nameW[] = L"Default-First-Site-Name";
2194 NTSTATUS status;
2195 POLICY_DNS_DOMAIN_INFO *dns_domain_info = NULL;
2196 DOMAIN_CONTROLLER_INFOW *info;
2197 WCHAR dc[NS_MAXDNAME], ip[IP6_ADDRESS_STRING_LENGTH];
2198 DWORD size;
2200 FIXME("(%s, %s, %s, %s, %08lx, %p): semi-stub\n", debugstr_w(computer),
2201 debugstr_w(domain), debugstr_guid(domain_guid), debugstr_w(site), flags, dc_info);
2203 if (!dc_info) return ERROR_INVALID_PARAMETER;
2205 if (!domain)
2207 LSA_OBJECT_ATTRIBUTES attrs;
2208 LSA_HANDLE lsa;
2210 memset(&attrs, 0, sizeof(attrs));
2211 attrs.Length = sizeof(attrs);
2212 status = LsaOpenPolicy(NULL, &attrs, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
2213 if (status)
2214 return LsaNtStatusToWinError(status);
2216 status = LsaQueryInformationPolicy(lsa, PolicyDnsDomainInformation, (void **)&dns_domain_info);
2217 LsaClose(lsa);
2218 if (status)
2219 return LsaNtStatusToWinError(status);
2221 domain = dns_domain_info->DnsDomainName.Buffer;
2224 status = get_dc_info(domain, dc, ip);
2225 if (status) return status;
2227 size = sizeof(DOMAIN_CONTROLLER_INFOW) + lstrlenW(domain) * sizeof(WCHAR) +
2228 sizeof(pfxW) * 2 + (lstrlenW(dc) + 1 + lstrlenW(ip) + 1) * sizeof(WCHAR) +
2229 lstrlenW(domain) * sizeof(WCHAR) /* assume forest == domain */ +
2230 sizeof(default_site_nameW) * 2;
2231 status = NetApiBufferAllocate(size, (void **)&info);
2232 if (status != NERR_Success)
2234 LsaFreeMemory(dns_domain_info);
2235 return ERROR_NOT_ENOUGH_MEMORY;
2238 info->DomainControllerName = (WCHAR *)(info + 1);
2239 memcpy(info->DomainControllerName, pfxW, sizeof(pfxW));
2240 lstrcpyW(info->DomainControllerName + 2, dc);
2241 info->DomainControllerAddress = (WCHAR *)((char *)info->DomainControllerName + (wcslen(info->DomainControllerName) + 1) * sizeof(WCHAR));
2242 memcpy(info->DomainControllerAddress, pfxW, sizeof(pfxW));
2243 lstrcpyW(info->DomainControllerAddress + 2, ip);
2244 info->DomainControllerAddressType = DS_INET_ADDRESS;
2245 info->DomainGuid = dns_domain_info ? dns_domain_info->DomainGuid : GUID_NULL /* FIXME */;
2246 info->DomainName = (WCHAR *)((char *)info->DomainControllerAddress + (wcslen(info->DomainControllerAddress) + 1) * sizeof(WCHAR));
2247 lstrcpyW(info->DomainName, domain);
2248 info->DnsForestName = (WCHAR *)((char *)info->DomainName + (lstrlenW(info->DomainName) + 1) * sizeof(WCHAR));
2249 lstrcpyW(info->DnsForestName, domain);
2250 info->DcSiteName = (WCHAR *)((char *)info->DnsForestName + (lstrlenW(info->DnsForestName) + 1) * sizeof(WCHAR));
2251 lstrcpyW(info->DcSiteName, default_site_nameW);
2252 info->ClientSiteName = (WCHAR *)((char *)info->DcSiteName + sizeof(default_site_nameW));
2253 lstrcpyW(info->ClientSiteName, default_site_nameW);
2254 info->Flags = DS_DNS_DOMAIN_FLAG | DS_DNS_FOREST_FLAG;
2256 LsaFreeMemory(dns_domain_info);
2258 *dc_info = info;
2260 return ERROR_SUCCESS;
2263 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
2264 GUID* DomainGuid, LPCSTR SiteName, ULONG Flags,
2265 PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo)
2267 FIXME("(%s, %s, %s, %s, %08lx, %p): stub\n", debugstr_a(ComputerName),
2268 debugstr_a(AvoidDCName), debugstr_guid(DomainGuid),
2269 debugstr_a(SiteName), Flags, DomainControllerInfo);
2270 return ERROR_CALL_NOT_IMPLEMENTED;
2273 DWORD WINAPI DsGetSiteNameW(LPCWSTR ComputerName, LPWSTR *SiteName)
2275 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName), SiteName);
2276 return ERROR_CALL_NOT_IMPLEMENTED;
2279 DWORD WINAPI DsGetSiteNameA(LPCSTR ComputerName, LPSTR *SiteName)
2281 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName), SiteName);
2282 return ERROR_CALL_NOT_IMPLEMENTED;
2285 /************************************************************
2286 * DsRoleFreeMemory (NETAPI32.@)
2288 * PARAMS
2289 * Buffer [I] Pointer to the to-be-freed buffer.
2291 * RETURNS
2292 * Nothing
2294 VOID WINAPI DsRoleFreeMemory(PVOID Buffer)
2296 TRACE("(%p)\n", Buffer);
2297 HeapFree(GetProcessHeap(), 0, Buffer);
2300 /************************************************************
2301 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
2303 * PARAMS
2304 * lpServer [I] Pointer to UNICODE string with ComputerName
2305 * InfoLevel [I] Type of data to retrieve
2306 * Buffer [O] Pointer to to the requested data
2308 * RETURNS
2310 * NOTES
2311 * When lpServer is NULL, use the local computer
2313 DWORD WINAPI DsRoleGetPrimaryDomainInformation(
2314 LPCWSTR lpServer, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
2315 PBYTE* Buffer)
2317 DWORD ret;
2319 FIXME("(%p, %d, %p) stub\n", lpServer, InfoLevel, Buffer);
2321 /* Check some input parameters */
2323 if (!Buffer) return ERROR_INVALID_PARAMETER;
2324 if ((InfoLevel < DsRolePrimaryDomainInfoBasic) || (InfoLevel > DsRoleOperationState)) return ERROR_INVALID_PARAMETER;
2326 *Buffer = NULL;
2327 switch (InfoLevel)
2329 case DsRolePrimaryDomainInfoBasic:
2331 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
2332 LSA_HANDLE PolicyHandle;
2333 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
2334 NTSTATUS NtStatus;
2335 int logon_domain_sz;
2336 DWORD size;
2337 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic;
2339 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
2340 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
2341 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
2342 if (NtStatus != STATUS_SUCCESS)
2344 TRACE("LsaOpenPolicyFailed with NT status %lx\n",
2345 LsaNtStatusToWinError(NtStatus));
2346 return ERROR_OUTOFMEMORY;
2348 LsaQueryInformationPolicy(PolicyHandle,
2349 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
2350 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
2351 LsaClose(PolicyHandle);
2353 size = sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC) +
2354 logon_domain_sz * sizeof(WCHAR);
2355 basic = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2356 if (basic)
2358 basic->MachineRole = DsRole_RoleStandaloneWorkstation;
2359 basic->DomainNameFlat = (LPWSTR)((LPBYTE)basic +
2360 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
2361 lstrcpyW(basic->DomainNameFlat, DomainInfo->DomainName.Buffer);
2362 ret = ERROR_SUCCESS;
2364 else
2365 ret = ERROR_OUTOFMEMORY;
2366 *Buffer = (PBYTE)basic;
2367 LsaFreeMemory(DomainInfo);
2369 break;
2370 default:
2371 ret = ERROR_CALL_NOT_IMPLEMENTED;
2373 return ret;
2376 /************************************************************
2377 * NetLocalGroupAdd (NETAPI32.@)
2379 NET_API_STATUS WINAPI NetLocalGroupAdd(
2380 LPCWSTR servername,
2381 DWORD level,
2382 LPBYTE buf,
2383 LPDWORD parm_err)
2385 FIXME("(%s %ld %p %p) stub!\n", debugstr_w(servername), level, buf,
2386 parm_err);
2387 return NERR_Success;
2390 /************************************************************
2391 * NetLocalGroupAddMember (NETAPI32.@)
2393 NET_API_STATUS WINAPI NetLocalGroupAddMember(
2394 LPCWSTR servername,
2395 LPCWSTR groupname,
2396 PSID membersid)
2398 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2399 debugstr_w(groupname), membersid);
2400 return NERR_Success;
2403 /************************************************************
2404 * NetLocalGroupAddMembers (NETAPI32.@)
2406 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
2407 LPCWSTR servername,
2408 LPCWSTR groupname,
2409 DWORD level,
2410 LPBYTE buf,
2411 DWORD totalentries)
2413 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2414 debugstr_w(groupname), level, buf, totalentries);
2415 return NERR_Success;
2418 /************************************************************
2419 * NetLocalGroupDel (NETAPI32.@)
2421 NET_API_STATUS WINAPI NetLocalGroupDel(
2422 LPCWSTR servername,
2423 LPCWSTR groupname)
2425 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
2426 return NERR_Success;
2429 /************************************************************
2430 * NetLocalGroupDelMember (NETAPI32.@)
2432 NET_API_STATUS WINAPI NetLocalGroupDelMember(
2433 LPCWSTR servername,
2434 LPCWSTR groupname,
2435 PSID membersid)
2437 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2438 debugstr_w(groupname), membersid);
2439 return NERR_Success;
2442 /************************************************************
2443 * NetLocalGroupDelMembers (NETAPI32.@)
2445 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
2446 LPCWSTR servername,
2447 LPCWSTR groupname,
2448 DWORD level,
2449 LPBYTE buf,
2450 DWORD totalentries)
2452 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2453 debugstr_w(groupname), level, buf, totalentries);
2454 return NERR_Success;
2457 /************************************************************
2458 * NetLocalGroupEnum (NETAPI32.@)
2460 NET_API_STATUS WINAPI NetLocalGroupEnum(
2461 LPCWSTR servername,
2462 DWORD level,
2463 LPBYTE* bufptr,
2464 DWORD prefmaxlen,
2465 LPDWORD entriesread,
2466 LPDWORD totalentries,
2467 PDWORD_PTR resumehandle)
2469 FIXME("(%s %ld %p %ld %p %p %p) stub!\n", debugstr_w(servername),
2470 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
2471 *entriesread = 0;
2472 *totalentries = 0;
2473 return NERR_Success;
2476 /************************************************************
2477 * NetLocalGroupGetInfo (NETAPI32.@)
2479 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
2480 LPCWSTR servername,
2481 LPCWSTR groupname,
2482 DWORD level,
2483 LPBYTE* bufptr)
2485 static const WCHAR commentW[] = L"No comment";
2486 LOCALGROUP_INFO_1* info;
2487 DWORD size;
2489 FIXME("(%s %s %ld %p) semi-stub!\n", debugstr_w(servername),
2490 debugstr_w(groupname), level, bufptr);
2492 size = sizeof(*info) + sizeof(WCHAR) * (lstrlenW(groupname)+1) + sizeof(commentW);
2493 NetApiBufferAllocate(size, (LPVOID*)&info);
2495 info->lgrpi1_name = (LPWSTR)(info + 1);
2496 lstrcpyW(info->lgrpi1_name, groupname);
2498 info->lgrpi1_comment = info->lgrpi1_name + lstrlenW(groupname) + 1;
2499 lstrcpyW(info->lgrpi1_comment, commentW);
2501 *bufptr = (LPBYTE)info;
2503 return NERR_Success;
2506 /************************************************************
2507 * NetLocalGroupGetMembers (NETAPI32.@)
2509 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
2510 LPCWSTR servername,
2511 LPCWSTR localgroupname,
2512 DWORD level,
2513 LPBYTE* bufptr,
2514 DWORD prefmaxlen,
2515 LPDWORD entriesread,
2516 LPDWORD totalentries,
2517 PDWORD_PTR resumehandle)
2519 FIXME("(%s %s %ld %p %ld, %p %p %p) stub!\n", debugstr_w(servername),
2520 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
2521 totalentries, resumehandle);
2523 if (level == 3)
2525 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
2526 DWORD userNameLen;
2527 DWORD len,needlen;
2528 PLOCALGROUP_MEMBERS_INFO_3 ptr;
2530 /* still a stub, current user is belonging to all groups */
2532 *totalentries = 1;
2533 *entriesread = 0;
2535 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
2536 if (!GetUserNameW(userName,&userNameLen))
2537 return ERROR_NOT_ENOUGH_MEMORY;
2539 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
2540 (userNameLen+2) * sizeof(WCHAR);
2541 if (prefmaxlen != MAX_PREFERRED_LENGTH)
2542 len = min(prefmaxlen,needlen);
2543 else
2544 len = needlen;
2546 NetApiBufferAllocate(len, (LPVOID *) bufptr);
2547 if (len < needlen)
2548 return ERROR_MORE_DATA;
2550 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
2551 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
2552 lstrcpyW(ptr->lgrmi3_domainandname,userName);
2554 *entriesread = 1;
2557 return NERR_Success;
2560 /************************************************************
2561 * NetLocalGroupSetInfo (NETAPI32.@)
2563 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
2564 LPCWSTR servername,
2565 LPCWSTR groupname,
2566 DWORD level,
2567 LPBYTE buf,
2568 LPDWORD parm_err)
2570 FIXME("(%s %s %ld %p %p) stub!\n", debugstr_w(servername),
2571 debugstr_w(groupname), level, buf, parm_err);
2572 return NERR_Success;
2575 /************************************************************
2576 * NetLocalGroupSetMember (NETAPI32.@)
2578 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
2579 LPCWSTR servername,
2580 LPCWSTR groupname,
2581 DWORD level,
2582 LPBYTE buf,
2583 DWORD totalentries)
2585 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2586 debugstr_w(groupname), level, buf, totalentries);
2587 return NERR_Success;
2590 /************************************************************
2591 * DavGetHTTPFromUNCPath (NETAPI32.@)
2593 DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buflen)
2595 static const WCHAR httpW[] = L"http://";
2596 static const WCHAR httpsW[] = L"https://";
2597 const WCHAR *p = unc_path, *q, *server, *path, *scheme = httpW;
2598 UINT i, len_server, len_path = 0, len_port = 0, len, port = 0;
2599 WCHAR *end, portbuf[12];
2601 TRACE("(%s %p %p)\n", debugstr_w(unc_path), buf, buflen);
2603 if (p[0] != '\\' || p[1] != '\\' || !p[2]) return ERROR_INVALID_PARAMETER;
2604 q = p += 2;
2605 while (*q && *q != '\\' && *q != '/' && *q != '@') q++;
2606 server = p;
2607 len_server = q - p;
2608 if (*q == '@')
2610 p = ++q;
2611 while (*p && (*p != '\\' && *p != '/' && *p != '@')) p++;
2612 if (p - q == 3 && !wcsnicmp( q, L"SSL", 3 ))
2614 scheme = httpsW;
2615 q = p;
2617 else if ((port = wcstol( q, &end, 10 ))) q = end;
2618 else return ERROR_INVALID_PARAMETER;
2620 if (*q == '@')
2622 if (!(port = wcstol( ++q, &end, 10 ))) return ERROR_INVALID_PARAMETER;
2623 q = end;
2625 if (*q == '\\' || *q == '/') q++;
2626 path = q;
2627 while (*q++) len_path++;
2628 if (len_path && (path[len_path - 1] == '\\' || path[len_path - 1] == '/'))
2629 len_path--; /* remove trailing slash */
2631 swprintf( portbuf, ARRAY_SIZE(portbuf), L":%u", port );
2632 if (scheme == httpsW)
2634 len = wcslen( httpsW );
2635 if (port && port != 443) len_port = wcslen( portbuf );
2637 else
2639 len = wcslen( httpW );
2640 if (port && port != 80) len_port = wcslen( portbuf );
2642 len += len_server;
2643 len += len_port;
2644 if (len_path) len += len_path + 1; /* leading '/' */
2645 len++; /* nul */
2647 if (*buflen < len)
2649 *buflen = len;
2650 return ERROR_INSUFFICIENT_BUFFER;
2653 memcpy( buf, scheme, wcslen(scheme) * sizeof(WCHAR) );
2654 buf += wcslen( scheme );
2655 memcpy( buf, server, len_server * sizeof(WCHAR) );
2656 buf += len_server;
2657 if (len_port)
2659 memcpy( buf, portbuf, len_port * sizeof(WCHAR) );
2660 buf += len_port;
2662 if (len_path)
2664 *buf++ = '/';
2665 for (i = 0; i < len_path; i++)
2667 if (path[i] == '\\') *buf++ = '/';
2668 else *buf++ = path[i];
2671 *buf = 0;
2672 *buflen = len;
2674 return ERROR_SUCCESS;
2677 /************************************************************
2678 * DavGetUNCFromHTTPPath (NETAPI32.@)
2680 DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen)
2682 static const WCHAR httpW[] = {'h','t','t','p'};
2683 static const WCHAR httpsW[] = {'h','t','t','p','s'};
2684 static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
2685 static const WCHAR sslW[] = {'@','S','S','L'};
2686 static const WCHAR port80W[] = {'8','0'};
2687 static const WCHAR port443W[] = {'4','4','3'};
2688 const WCHAR *p = http_path, *server, *port = NULL, *path = NULL;
2689 DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0;
2690 BOOL ssl;
2692 TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen);
2694 while (*p && *p != ':') { p++; len++; };
2695 if (len == ARRAY_SIZE(httpW) && !wcsnicmp( http_path, httpW, len )) ssl = FALSE;
2696 else if (len == ARRAY_SIZE(httpsW) && !wcsnicmp( http_path, httpsW, len )) ssl = TRUE;
2697 else return ERROR_INVALID_PARAMETER;
2699 if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER;
2700 server = p += 3;
2702 while (*p && *p != ':' && *p != '/') { p++; len_server++; };
2703 if (!len_server) return ERROR_BAD_NET_NAME;
2704 if (*p == ':')
2706 port = ++p;
2707 while (*p >= '0' && *p <= '9') { p++; len_port++; };
2708 if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL;
2709 else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL;
2710 path = p;
2712 else if (*p == '/') path = p;
2714 while (*p)
2716 if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME;
2717 p++; len_path++;
2719 if (len_path && path[len_path - 1] == '/') len_path--;
2721 len = len_server + 2; /* \\ */
2722 if (ssl) len += 4; /* @SSL */
2723 if (port) len += len_port + 1 /* @ */;
2724 len += ARRAY_SIZE(davrootW);
2725 len += len_path + 1; /* nul */
2727 if (*buflen < len)
2729 *buflen = len;
2730 return ERROR_INSUFFICIENT_BUFFER;
2733 buf[0] = buf[1] = '\\';
2734 buf += 2;
2735 memcpy( buf, server, len_server * sizeof(WCHAR) );
2736 buf += len_server;
2737 if (ssl)
2739 memcpy( buf, sslW, sizeof(sslW) );
2740 buf += 4;
2742 if (port)
2744 *buf++ = '@';
2745 memcpy( buf, port, len_port * sizeof(WCHAR) );
2746 buf += len_port;
2748 memcpy( buf, davrootW, sizeof(davrootW) );
2749 buf += ARRAY_SIZE(davrootW);
2750 for (i = 0; i < len_path; i++)
2752 if (path[i] == '/') *buf++ = '\\';
2753 else *buf++ = path[i];
2756 *buf = 0;
2757 *buflen = len;
2759 return ERROR_SUCCESS;
2762 /************************************************************
2763 * DsEnumerateDomainTrustsA (NETAPI32.@)
2765 DWORD WINAPI DsEnumerateDomainTrustsA(LPSTR server, ULONG flags, PDS_DOMAIN_TRUSTSA* domains, PULONG count)
2767 FIXME("(%s, 0x%04lx, %p, %p): stub\n", debugstr_a(server), flags, domains, count);
2768 return ERROR_NO_LOGON_SERVERS;
2771 /************************************************************
2772 * DsEnumerateDomainTrustsW (NETAPI32.@)
2774 DWORD WINAPI DsEnumerateDomainTrustsW(LPWSTR server, ULONG flags, PDS_DOMAIN_TRUSTSW* domains, PULONG count)
2776 FIXME("(%s, 0x%04lx, %p, %p): stub\n", debugstr_w(server), flags, domains, count);
2777 return ERROR_NO_LOGON_SERVERS;
2780 DECLSPEC_HIDDEN void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
2782 return HeapAlloc(GetProcessHeap(), 0, n);
2785 DECLSPEC_HIDDEN void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
2787 HeapFree(GetProcessHeap(), 0, p);
2790 DECLSPEC_HIDDEN handle_t __RPC_USER ATSVC_HANDLE_bind(ATSVC_HANDLE str)
2792 static unsigned char ncalrpc[] = "ncalrpc";
2793 unsigned char *binding_str;
2794 handle_t rpc_handle = 0;
2796 if (RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str) == RPC_S_OK)
2798 RpcBindingFromStringBindingA(binding_str, &rpc_handle);
2799 RpcStringFreeA(&binding_str);
2801 return rpc_handle;
2804 DECLSPEC_HIDDEN void __RPC_USER ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, handle_t rpc_handle)
2806 RpcBindingFree(&rpc_handle);