cmd: DIR command outputs free space for the path.
[wine.git] / dlls / netapi32 / netapi32.c
blobd9694cc38e3fa3e23414c84558ff0cb74908e312
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 #define SAMBA_CALL(func, args) WINE_UNIX_CALL( unix_ ## func, args )
60 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
62 static BOOL WINAPI load_samba( INIT_ONCE *once, void *param, void **context )
64 SAMBA_CALL( netapi_init, NULL );
65 return TRUE;
68 static BOOL samba_init(void)
70 return __wine_unixlib_handle && InitOnceExecuteOnce( &init_once, load_samba, NULL, NULL );
73 /************************************************************
74 * NETAPI_IsLocalComputer
76 * Checks whether the server name indicates local machine.
78 static BOOL NETAPI_IsLocalComputer( LMCSTR name )
80 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
81 DWORD size = ARRAY_SIZE(buf);
82 BOOL ret;
84 if (!name || !name[0]) return TRUE;
86 ret = GetComputerNameW( buf, &size );
87 if (ret && name[0] == '\\' && name[1] == '\\') name += 2;
88 return ret && !wcsicmp( name, buf );
91 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
93 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
95 switch (fdwReason) {
96 case DLL_PROCESS_ATTACH:
97 __wine_init_unix_call();
98 DisableThreadLibraryCalls(hinstDLL);
99 NetBIOSInit();
100 NetBTInit();
101 break;
102 case DLL_PROCESS_DETACH:
103 if (lpvReserved) break;
104 NetBIOSShutdown();
105 break;
108 return TRUE;
111 /************************************************************
112 * NetServerEnum (NETAPI32.@)
114 NET_API_STATUS WINAPI NetServerEnum(
115 LMCSTR servername,
116 DWORD level,
117 LPBYTE* bufptr,
118 DWORD prefmaxlen,
119 LPDWORD entriesread,
120 LPDWORD totalentries,
121 DWORD servertype,
122 LMCSTR domain,
123 LPDWORD resume_handle
126 FIXME("Stub (%s %ld %p %ld %p %p %ld %s %p)\n", debugstr_w(servername),
127 level, bufptr, prefmaxlen, entriesread, totalentries, servertype,
128 debugstr_w(domain), resume_handle);
130 return ERROR_NO_BROWSER_SERVERS_FOUND;
133 /************************************************************
134 * NetServerEnumEx (NETAPI32.@)
136 NET_API_STATUS WINAPI NetServerEnumEx(
137 LMCSTR ServerName,
138 DWORD Level,
139 LPBYTE *Bufptr,
140 DWORD PrefMaxlen,
141 LPDWORD EntriesRead,
142 LPDWORD totalentries,
143 DWORD servertype,
144 LMCSTR domain,
145 LMCSTR FirstNameToReturn)
147 FIXME("Stub (%s %ld %p %ld %p %p %ld %s %s)\n",
148 debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
149 servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
151 return ERROR_NO_BROWSER_SERVERS_FOUND;
154 /************************************************************
155 * NetServerDiskEnum (NETAPI32.@)
157 NET_API_STATUS WINAPI NetServerDiskEnum(
158 LMCSTR ServerName,
159 DWORD Level,
160 LPBYTE *Bufptr,
161 DWORD PrefMaxlen,
162 LPDWORD EntriesRead,
163 LPDWORD totalentries,
164 LPDWORD Resume_Handle)
166 FIXME("Stub (%s %ld %p %ld %p %p %p)\n", debugstr_w(ServerName),
167 Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
169 return ERROR_NO_BROWSER_SERVERS_FOUND;
172 /************************************************************
173 * NetServerGetInfo (NETAPI32.@)
175 NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr)
177 NET_API_STATUS ret;
178 BOOL local = NETAPI_IsLocalComputer( servername );
180 TRACE("%s %ld %p\n", debugstr_w( servername ), level, bufptr );
182 if (!local)
184 if (samba_init())
186 ULONG size = 1024;
187 struct server_getinfo_params params = { servername, level, NULL, &size };
189 for (;;)
191 if (!(params.buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
192 ret = SAMBA_CALL( server_getinfo, &params );
193 if (!ret) *bufptr = params.buffer;
194 else free( params.buffer );
195 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
198 FIXME( "remote computers not supported\n" );
199 return ERROR_INVALID_LEVEL;
201 if (!bufptr) return ERROR_INVALID_PARAMETER;
203 switch (level)
205 case 100:
206 case 101:
208 DWORD computerNameLen, size;
209 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
211 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
212 GetComputerNameW(computerName, &computerNameLen);
213 computerNameLen++; /* include NULL terminator */
215 /* Plus 1 for empty comment */
216 size = sizeof(SERVER_INFO_101) + (computerNameLen + 1) * sizeof(WCHAR);
217 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
218 if (ret == NERR_Success)
220 /* INFO_100 structure is a subset of INFO_101 */
221 PSERVER_INFO_101 info = (PSERVER_INFO_101)*bufptr;
222 OSVERSIONINFOW verInfo;
224 info->sv101_platform_id = PLATFORM_ID_NT;
225 info->sv101_name = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101));
226 memcpy(info->sv101_name, computerName,
227 computerNameLen * sizeof(WCHAR));
228 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
229 GetVersionExW(&verInfo);
230 info->sv101_version_major = verInfo.dwMajorVersion;
231 info->sv101_version_minor = verInfo.dwMinorVersion;
232 /* Use generic type as no wine equivalent of DC / Server */
233 info->sv101_type = SV_TYPE_NT;
234 info->sv101_comment = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101)
235 + computerNameLen * sizeof(WCHAR));
236 info->sv101_comment[0] = '\0';
238 break;
241 default:
242 FIXME("level %ld unimplemented\n", level);
243 ret = ERROR_INVALID_LEVEL;
245 return ret;
249 /************************************************************
250 * NetStatisticsGet (NETAPI32.@)
252 NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
253 DWORD level, DWORD options,
254 LPBYTE *bufptr)
256 int res;
257 union
259 STAT_WORKSTATION_0 workst;
260 STAT_SERVER_0 server;
261 } *stat;
262 void *dataptr;
264 TRACE("(server %s, service %s, level %ld, options %ld, buffer %p): stub\n",
265 debugstr_w(server), debugstr_w(service), level, options, bufptr);
267 res = NetApiBufferAllocate(sizeof(*stat), &dataptr);
268 if (res != NERR_Success) return res;
270 res = NERR_InternalError;
271 stat = dataptr;
272 switch (level)
274 case 0:
275 if (!wcscmp( service, L"Lanman Workstation" ))
277 /* Fill the struct STAT_WORKSTATION_0 properly */
278 memset(&stat->workst, 0, sizeof(stat->workst));
279 res = NERR_Success;
281 else if (!wcscmp( service, L"Lanman Server" ))
283 /* Fill the struct STAT_SERVER_0 properly */
284 memset(&stat->server, 0, sizeof(stat->server));
285 res = NERR_Success;
287 break;
289 if (res != NERR_Success)
290 NetApiBufferFree(dataptr);
291 else
292 *bufptr = dataptr;
294 return res;
297 NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize,
298 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle)
300 FIXME("stub (%p, %ld, %p, %ld, %p, %p, %p)\n", server, level, bufptr, prefmaxsize,
301 entriesread, totalentries, resumehandle);
302 return ERROR_NOT_SUPPORTED;
305 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
307 TRACE("(%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
308 return NetrJobAdd(server, (AT_INFO *)bufptr, jobid);
311 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
313 TRACE("(%s, %lu, %lu)\n", debugstr_w(server), minjobid, maxjobid);
314 return NetrJobDel(server, minjobid, maxjobid);
317 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
318 LPDWORD totalentries, LPDWORD resumehandle)
320 AT_ENUM_CONTAINER container;
321 NET_API_STATUS ret;
323 TRACE("(%s, %p, %lu, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
325 container.EntriesRead = 0;
326 container.Buffer = NULL;
327 ret = NetrJobEnum(server, &container, prefmaxsize, totalentries, resumehandle);
328 if (ret == ERROR_SUCCESS)
330 *bufptr = (LPBYTE)container.Buffer;
331 *entriesread = container.EntriesRead;
333 return ret;
336 NET_API_STATUS WINAPI NetScheduleJobGetInfo(LPCWSTR server, DWORD jobid, LPBYTE *bufptr)
338 TRACE("(%s, %lu, %p)\n", debugstr_w(server), jobid, bufptr);
339 return NetrJobGetInfo(server, jobid, (LPAT_INFO *)bufptr);
342 NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
344 FIXME("stub (%p, %p, %ld, %p)\n", server, name, level, bufptr);
345 return ERROR_NOT_SUPPORTED;
349 /************************************************************
350 * NetApiBufferAllocate (NETAPI32.@)
352 NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
354 TRACE("(%ld, %p)\n", ByteCount, Buffer);
356 if (Buffer == NULL) return ERROR_INVALID_PARAMETER;
357 *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
358 if (*Buffer)
359 return NERR_Success;
360 else
361 return GetLastError();
364 /************************************************************
365 * NetApiBufferFree (NETAPI32.@)
367 NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
369 TRACE("(%p)\n", Buffer);
370 MIDL_user_free(Buffer);
371 return NERR_Success;
374 /************************************************************
375 * NetApiBufferReallocate (NETAPI32.@)
377 NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
378 LPVOID* NewBuffer)
380 TRACE("(%p, %ld, %p)\n", OldBuffer, NewByteCount, NewBuffer);
381 if (NewByteCount)
383 if (OldBuffer)
384 *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
385 else
386 *NewBuffer = HeapAlloc(GetProcessHeap(), 0, NewByteCount);
387 return *NewBuffer ? NERR_Success : GetLastError();
389 else
391 if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
392 *NewBuffer = 0;
393 return NERR_Success;
397 /************************************************************
398 * NetApiBufferSize (NETAPI32.@)
400 NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
402 DWORD dw;
404 TRACE("(%p, %p)\n", Buffer, ByteCount);
405 if (Buffer == NULL)
406 return ERROR_INVALID_PARAMETER;
407 dw = HeapSize(GetProcessHeap(), 0, Buffer);
408 TRACE("size: %ld\n", dw);
409 if (dw != 0xFFFFFFFF)
410 *ByteCount = dw;
411 else
412 *ByteCount = 0;
414 return NERR_Success;
417 /************************************************************
418 * NetSessionEnum (NETAPI32.@)
420 * PARAMS
421 * servername [I] Pointer to a string with the name of the server
422 * UncClientName [I] Pointer to a string with the name of the session
423 * username [I] Pointer to a string with the name of the user
424 * level [I] Data information level
425 * bufptr [O] Buffer to the data
426 * prefmaxlen [I] Preferred maximum length of the data
427 * entriesread [O] Pointer to the number of entries enumerated
428 * totalentries [O] Pointer to the possible number of entries
429 * resume_handle [I/O] Pointer to a handle for subsequent searches
431 * RETURNS
432 * If successful, the function returns NERR_Success
433 * On failure it returns:
434 * ERROR_ACCESS_DENIED User has no access to the requested information
435 * ERROR_INVALID_LEVEL Value of 'level' is not correct
436 * ERROR_INVALID_PARAMETER Wrong parameter
437 * ERROR_MORE_DATA Need a larger buffer
438 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
439 * NERR_ClientNameNotFound A session does not exist on a given computer
440 * NERR_InvalidComputer Invalid computer name
441 * NERR_UserNotFound User name could not be found.
443 NET_API_STATUS WINAPI NetSessionEnum(LMSTR servername, LMSTR UncClientName,
444 LMSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread,
445 LPDWORD totalentries, LPDWORD resume_handle)
447 FIXME("Stub (%s %s %s %ld %p %ld %p %p %p)\n", debugstr_w(servername),
448 debugstr_w(UncClientName), debugstr_w(username),
449 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
451 return NERR_Success;
454 /************************************************************
455 * NetShareEnum (NETAPI32.@)
457 * PARAMS
458 * servername [I] Pointer to a string with the name of the server
459 * level [I] Data information level
460 * bufptr [O] Buffer to the data
461 * prefmaxlen [I] Preferred maximum length of the data
462 * entriesread [O] Pointer to the number of entries enumerated
463 * totalentries [O] Pointer to the possible number of entries
464 * resume_handle [I/O] Pointer to a handle for subsequent searches
466 * RETURNS
467 * If successful, the function returns NERR_Success
468 * On failure it returns a system error code (FIXME: find out which)
471 NET_API_STATUS WINAPI NetShareEnum( LMSTR servername, DWORD level, LPBYTE* bufptr,
472 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
474 FIXME("Stub (%s %ld %p %ld %p %p %p)\n", debugstr_w(servername), level, bufptr,
475 prefmaxlen, entriesread, totalentries, resume_handle);
477 return ERROR_NOT_SUPPORTED;
480 /************************************************************
481 * NetShareDel (NETAPI32.@)
483 NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserved)
485 BOOL local = NETAPI_IsLocalComputer( servername );
487 TRACE("%s %s %ld\n", debugstr_w(servername), debugstr_w(netname), reserved);
489 if (!local)
491 if (samba_init())
493 struct share_del_params params = { servername, netname, reserved };
494 return SAMBA_CALL( share_del, &params );
496 FIXME( "remote computers not supported\n" );
499 FIXME("%s %s %ld\n", debugstr_w(servername), debugstr_w(netname), reserved);
500 return NERR_Success;
503 /************************************************************
504 * NetShareGetInfo (NETAPI32.@)
506 NET_API_STATUS WINAPI NetShareGetInfo(LMSTR servername, LMSTR netname,
507 DWORD level, LPBYTE *bufptr)
509 FIXME("Stub (%s %s %ld %p)\n", debugstr_w(servername),
510 debugstr_w(netname),level, bufptr);
511 return NERR_NetNameNotFound;
514 /************************************************************
515 * NetShareAdd (NETAPI32.@)
517 NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
518 DWORD level, LPBYTE buf, LPDWORD parm_err)
520 BOOL local = NETAPI_IsLocalComputer( servername );
522 TRACE("%s %ld %p %p\n", debugstr_w(servername), level, buf, parm_err);
524 if (!local)
526 if (samba_init())
528 struct share_add_params params = { servername, level, buf, parm_err };
529 return SAMBA_CALL( share_add, &params );
531 FIXME( "remote computers not supported\n" );
534 FIXME("%s %ld %p %p\n", debugstr_w(servername), level, buf, parm_err);
535 return ERROR_NOT_SUPPORTED;
538 /************************************************************
539 * NetFileEnum (NETAPI32.@)
541 NET_API_STATUS WINAPI NetFileEnum(
542 LPWSTR ServerName, LPWSTR BasePath, LPWSTR UserName,
543 DWORD Level, LPBYTE* BufPtr, DWORD PrefMaxLen,
544 LPDWORD EntriesRead, LPDWORD TotalEntries, PDWORD_PTR ResumeHandle)
546 FIXME("(%s, %s, %s, %lu): stub\n", debugstr_w(ServerName), debugstr_w(BasePath),
547 debugstr_w(UserName), Level);
548 return ERROR_NOT_SUPPORTED;
551 static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)
553 int i;
554 unsigned char val;
556 if (!buffer)
557 return;
558 if (len < 1)
559 return;
560 if (!ifRow)
562 *buffer = '\0';
563 return;
566 for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
568 val = ifRow->bPhysAddr[i];
569 if ((val >>4) >9)
570 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
571 else
572 buffer[2*i] = (WCHAR)((val >>4) + '0');
573 if ((val & 0xf ) >9)
574 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
575 else
576 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
578 buffer[2*i]=0;
581 /* Theoretically this could be too short, except that MS defines
582 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
583 * represent a count of WCHARs, so even with an extraordinarily long header
584 * this will be plenty
586 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
587 #define MAX_TRANSPORT_ADDR 13
589 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
590 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
592 static void wprint_name(WCHAR *buffer, int len, ULONG transport,
593 PMIB_IFROW ifRow)
595 WCHAR *ptr1, *ptr2;
596 const char *name;
598 if (!buffer)
599 return;
600 if (!ifRow)
602 *buffer = '\0';
603 return;
606 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
607 name = NBT_TRANSPORT_NAME_HEADER;
608 else
609 name = UNKNOWN_TRANSPORT_NAME_HEADER;
611 for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
612 *ptr1 = *name;
613 for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
614 *ptr1 = *ptr2;
615 *ptr1 = '\0';
618 /***********************************************************************
619 * NetWkstaTransportEnum (NETAPI32.@)
622 struct WkstaTransportEnumData
624 UCHAR n_adapt;
625 UCHAR n_read;
626 DWORD prefmaxlen;
627 LPBYTE *pbuf;
628 NET_API_STATUS ret;
631 /**********************************************************************/
633 static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
634 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
636 BOOL ret;
637 struct WkstaTransportEnumData *enumData = closure;
639 if (enumData && enumData->pbuf)
641 if (lanaIndex == 0)
643 DWORD toAllocate;
645 enumData->n_adapt = totalLANAs;
646 enumData->n_read = 0;
648 toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
649 + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
650 MAX_TRANSPORT_ADDR * sizeof(WCHAR));
651 if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
652 toAllocate = enumData->prefmaxlen;
653 NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
655 if (*(enumData->pbuf))
657 UCHAR spaceFor;
659 if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
660 spaceFor = totalLANAs;
661 else
662 spaceFor = enumData->prefmaxlen /
663 (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
664 MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
665 if (enumData->n_read < spaceFor)
667 PWKSTA_TRANSPORT_INFO_0 ti;
668 LMSTR transport_name, transport_addr;
669 MIB_IFROW ifRow;
671 ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
672 enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
673 transport_name = (LMSTR)(*(enumData->pbuf) +
674 totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
675 enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
676 transport_addr = (LMSTR)(*(enumData->pbuf) +
677 totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
678 MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
679 enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
681 ifRow.dwIndex = data->ifIndex;
682 GetIfEntry(&ifRow);
683 ti->wkti0_quality_of_service = 0;
684 ti->wkti0_number_of_vcs = 0;
685 ti->wkti0_transport_name = transport_name;
686 wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
687 transport, &ifRow);
688 ti->wkti0_transport_address = transport_addr;
689 wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
690 &ifRow);
691 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
692 ti->wkti0_wan_ish = TRUE;
693 else
694 ti->wkti0_wan_ish = FALSE;
695 TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
696 TRACE("transport_name at %p %s\n",
697 ti->wkti0_transport_name,
698 debugstr_w(ti->wkti0_transport_name));
699 TRACE("transport_address at %p %s\n",
700 ti->wkti0_transport_address,
701 debugstr_w(ti->wkti0_transport_address));
702 enumData->n_read++;
703 enumData->ret = NERR_Success;
704 ret = TRUE;
706 else
708 enumData->ret = ERROR_MORE_DATA;
709 ret = FALSE;
712 else
714 enumData->ret = ERROR_OUTOFMEMORY;
715 ret = FALSE;
718 else
719 ret = FALSE;
720 return ret;
723 /**********************************************************************/
725 NET_API_STATUS WINAPI
726 NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
727 DWORD prefmaxlen, LPDWORD read_entries,
728 PDWORD total_entries, PDWORD hresume)
730 NET_API_STATUS ret;
732 TRACE(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName),
733 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
734 if (!NETAPI_IsLocalComputer(ServerName))
736 FIXME(":not implemented for non-local computers\n");
737 ret = ERROR_INVALID_LEVEL;
739 else
741 if (hresume && *hresume)
743 FIXME(":resume handle not implemented\n");
744 return ERROR_INVALID_LEVEL;
747 switch (level)
749 case 0: /* transport info */
751 ULONG allTransports;
752 struct WkstaTransportEnumData enumData;
754 if (NetBIOSNumAdapters() == 0)
755 return ERROR_NETWORK_UNREACHABLE;
756 if (!read_entries)
757 return STATUS_ACCESS_VIOLATION;
758 if (!total_entries || !pbuf)
759 return RPC_X_NULL_REF_POINTER;
761 enumData.prefmaxlen = prefmaxlen;
762 enumData.pbuf = pbuf;
763 memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
764 NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
765 &enumData);
766 *read_entries = enumData.n_read;
767 *total_entries = enumData.n_adapt;
768 if (hresume) *hresume= 0;
769 ret = enumData.ret;
770 break;
772 default:
773 TRACE("Invalid level %ld is specified\n", level);
774 ret = ERROR_INVALID_LEVEL;
777 return ret;
780 /************************************************************
781 * NetWkstaUserGetInfo (NETAPI32.@)
783 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
784 PBYTE* bufptr)
786 NET_API_STATUS nastatus;
788 TRACE("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr);
789 switch (level)
791 case 0:
793 PWKSTA_USER_INFO_0 ui;
794 DWORD dwSize = UNLEN + 1;
796 /* set up buffer */
797 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
798 (LPVOID *) bufptr);
799 if (nastatus != NERR_Success)
800 return ERROR_NOT_ENOUGH_MEMORY;
802 ui = (PWKSTA_USER_INFO_0) *bufptr;
803 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
805 /* get data */
806 if (!GetUserNameW(ui->wkui0_username, &dwSize))
808 NetApiBufferFree(ui);
809 return ERROR_NOT_ENOUGH_MEMORY;
811 else {
812 nastatus = NetApiBufferReallocate(
813 *bufptr, sizeof(WKSTA_USER_INFO_0) +
814 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
815 (LPVOID *) bufptr);
816 if (nastatus != NERR_Success)
818 NetApiBufferFree(ui);
819 return nastatus;
821 ui = (PWKSTA_USER_INFO_0) *bufptr;
822 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
824 break;
827 case 1:
829 PWKSTA_USER_INFO_1 ui;
830 PWKSTA_USER_INFO_0 ui0;
831 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
832 LSA_HANDLE PolicyHandle;
833 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
834 NTSTATUS NtStatus;
836 /* sizes of the field buffers in WCHARS */
837 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
839 FIXME("Level 1 processing is partially implemented\n");
840 oth_domains_sz = 1;
841 logon_server_sz = 1;
843 /* get some information first to estimate size of the buffer */
844 ui0 = NULL;
845 nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
846 if (nastatus != NERR_Success)
847 return nastatus;
848 username_sz = lstrlenW(ui0->wkui0_username) + 1;
850 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
851 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
852 POLICY_VIEW_LOCAL_INFORMATION,
853 &PolicyHandle);
854 if (NtStatus != STATUS_SUCCESS)
856 TRACE("LsaOpenPolicyFailed with NT status %lx\n",
857 LsaNtStatusToWinError(NtStatus));
858 NetApiBufferFree(ui0);
859 return ERROR_NOT_ENOUGH_MEMORY;
861 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
862 (PVOID*) &DomainInfo);
863 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
864 LsaClose(PolicyHandle);
866 /* set up buffer */
867 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
868 (username_sz + logon_domain_sz +
869 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
870 (LPVOID *) bufptr);
871 if (nastatus != NERR_Success) {
872 NetApiBufferFree(ui0);
873 return nastatus;
875 ui = (WKSTA_USER_INFO_1 *) *bufptr;
876 ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
877 ui->wkui1_logon_domain = (LMSTR) (
878 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
879 ui->wkui1_oth_domains = (LMSTR) (
880 ((PBYTE) ui->wkui1_logon_domain) +
881 logon_domain_sz * sizeof(WCHAR));
882 ui->wkui1_logon_server = (LMSTR) (
883 ((PBYTE) ui->wkui1_oth_domains) +
884 oth_domains_sz * sizeof(WCHAR));
886 /* get data */
887 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
888 NetApiBufferFree(ui0);
890 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
891 logon_domain_sz);
892 LsaFreeMemory(DomainInfo);
894 /* FIXME. Not implemented. Populated with empty strings */
895 ui->wkui1_oth_domains[0] = 0;
896 ui->wkui1_logon_server[0] = 0;
897 break;
899 case 1101:
901 PWKSTA_USER_INFO_1101 ui;
902 DWORD dwSize = 1;
904 FIXME("Stub. Level 1101 processing is not implemented\n");
905 /* FIXME see also wkui1_oth_domains for level 1 */
907 /* set up buffer */
908 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
909 (LPVOID *) bufptr);
910 if (nastatus != NERR_Success)
911 return nastatus;
912 ui = (PWKSTA_USER_INFO_1101) *bufptr;
913 ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
915 /* get data */
916 ui->wkui1101_oth_domains[0] = 0;
917 break;
919 default:
920 TRACE("Invalid level %ld is specified\n", level);
921 return ERROR_INVALID_LEVEL;
923 return NERR_Success;
926 /************************************************************
927 * NetWkstaUserEnum (NETAPI32.@)
929 NET_API_STATUS WINAPI
930 NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr,
931 DWORD prefmaxlen, LPDWORD entriesread,
932 LPDWORD totalentries, LPDWORD resumehandle)
934 FIXME("(%s, %ld, %p, %ld, %p, %p, %p): stub!\n", debugstr_w(servername),
935 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
936 return ERROR_INVALID_PARAMETER;
939 /************************************************************
940 * NetpGetComputerName (NETAPI32.@)
942 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
944 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
946 TRACE("(%p)\n", Buffer);
947 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
948 if (GetComputerNameW(*Buffer, &dwSize))
950 return NetApiBufferReallocate(
951 *Buffer, (dwSize + 1) * sizeof(WCHAR),
952 (LPVOID *) Buffer);
954 else
956 NetApiBufferFree(*Buffer);
957 return ERROR_NOT_ENOUGH_MEMORY;
961 NET_API_STATUS WINAPI I_NetNameCompare(LPVOID p1, LPWSTR wkgrp, LPWSTR comp,
962 LPVOID p4, LPVOID p5)
964 FIXME("(%p %s %s %p %p): stub\n", p1, debugstr_w(wkgrp), debugstr_w(comp),
965 p4, p5);
966 return ERROR_INVALID_PARAMETER;
969 NET_API_STATUS WINAPI I_NetNameValidate(LPVOID p1, LPWSTR wkgrp, LPVOID p3,
970 LPVOID p4)
972 FIXME("(%p %s %p %p): stub\n", p1, debugstr_w(wkgrp), p3, p4);
973 return ERROR_INVALID_PARAMETER;
976 NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
977 LPBYTE* bufptr)
979 NET_API_STATUS ret;
980 BOOL local = NETAPI_IsLocalComputer( servername );
982 TRACE("%s %ld %p\n", debugstr_w( servername ), level, bufptr );
984 if (!local)
986 if (samba_init())
988 ULONG size = 1024;
989 struct wksta_getinfo_params params = { servername, level, NULL, &size };
991 for (;;)
993 if (!(params.buffer = malloc( size ))) return ERROR_OUTOFMEMORY;
994 ret = SAMBA_CALL( wksta_getinfo, &params );
995 if (!ret) *bufptr = params.buffer;
996 else free( params.buffer );
997 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
1000 FIXME( "remote computers not supported\n" );
1001 return ERROR_INVALID_LEVEL;
1003 if (!bufptr) return ERROR_INVALID_PARAMETER;
1005 switch (level)
1007 case 100:
1008 case 101:
1009 case 102:
1011 static const WCHAR lanroot[] = L"c:\\lanman"; /* FIXME */
1012 DWORD computerNameLen, domainNameLen, size;
1013 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1014 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1015 LSA_HANDLE PolicyHandle;
1016 NTSTATUS NtStatus;
1018 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1019 GetComputerNameW(computerName, &computerNameLen);
1020 computerNameLen++; /* include NULL terminator */
1022 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1023 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1024 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
1025 if (NtStatus != STATUS_SUCCESS)
1026 ret = LsaNtStatusToWinError(NtStatus);
1027 else
1029 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1031 LsaQueryInformationPolicy(PolicyHandle,
1032 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
1033 domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1034 size = sizeof(WKSTA_INFO_102) + computerNameLen * sizeof(WCHAR)
1035 + domainNameLen * sizeof(WCHAR) + sizeof(lanroot);
1036 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1037 if (ret == NERR_Success)
1039 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1040 PWKSTA_INFO_102 info = (PWKSTA_INFO_102)*bufptr;
1041 OSVERSIONINFOW verInfo;
1043 info->wki102_platform_id = PLATFORM_ID_NT;
1044 info->wki102_computername = (LMSTR)(*bufptr +
1045 sizeof(WKSTA_INFO_102));
1046 memcpy(info->wki102_computername, computerName,
1047 computerNameLen * sizeof(WCHAR));
1048 info->wki102_langroup = info->wki102_computername + computerNameLen;
1049 memcpy(info->wki102_langroup, DomainInfo->DomainName.Buffer,
1050 domainNameLen * sizeof(WCHAR));
1051 info->wki102_lanroot = info->wki102_langroup + domainNameLen;
1052 memcpy(info->wki102_lanroot, lanroot, sizeof(lanroot));
1053 memset(&verInfo, 0, sizeof(verInfo));
1054 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1055 GetVersionExW(&verInfo);
1056 info->wki102_ver_major = verInfo.dwMajorVersion;
1057 info->wki102_ver_minor = verInfo.dwMinorVersion;
1058 info->wki102_logged_on_users = 1;
1060 LsaFreeMemory(DomainInfo);
1061 LsaClose(PolicyHandle);
1063 break;
1066 default:
1067 FIXME("level %ld unimplemented\n", level);
1068 ret = ERROR_INVALID_LEVEL;
1070 return ret;
1073 /************************************************************
1074 * NetGetJoinInformation (NETAPI32.@)
1076 NET_API_STATUS NET_API_FUNCTION NetGetJoinInformation(
1077 LPCWSTR Server,
1078 LPWSTR *Name,
1079 PNETSETUP_JOIN_STATUS type)
1081 static const WCHAR workgroupW[] = L"Workgroup";
1083 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server), Name, type);
1085 if (!Name || !type)
1086 return ERROR_INVALID_PARAMETER;
1088 NetApiBufferAllocate(sizeof(workgroupW), (LPVOID *)Name);
1089 lstrcpyW(*Name, workgroupW);
1090 *type = NetSetupWorkgroupName;
1092 return NERR_Success;
1095 /************************************************************
1096 * NetUserGetGroups (NETAPI32.@)
1098 NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
1099 LPCWSTR servername,
1100 LPCWSTR username,
1101 DWORD level,
1102 LPBYTE *bufptr,
1103 DWORD prefixmaxlen,
1104 LPDWORD entriesread,
1105 LPDWORD totalentries)
1107 FIXME("%s %s %ld %p %ld %p %p stub\n", debugstr_w(servername),
1108 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
1109 totalentries);
1111 *bufptr = NULL;
1112 *entriesread = 0;
1113 *totalentries = 0;
1115 return ERROR_INVALID_LEVEL;
1118 struct sam_user
1120 struct list entry;
1121 WCHAR user_name[LM20_UNLEN+1];
1122 WCHAR user_password[PWLEN + 1];
1123 DWORD sec_since_passwd_change;
1124 DWORD user_priv;
1125 LPWSTR home_dir;
1126 LPWSTR user_comment;
1127 DWORD user_flags;
1128 LPWSTR user_logon_script_path;
1131 static struct list user_list = LIST_INIT( user_list );
1133 /************************************************************
1134 * NETAPI_ValidateServername
1136 * Validates server name
1138 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
1140 if (ServerName)
1142 if (ServerName[0] == 0)
1143 return ERROR_BAD_NETPATH;
1144 else if (
1145 ((ServerName[0] == '\\') &&
1146 (ServerName[1] != '\\'))
1148 ((ServerName[0] == '\\') &&
1149 (ServerName[1] == '\\') &&
1150 (ServerName[2] == 0))
1152 return ERROR_INVALID_NAME;
1154 return NERR_Success;
1157 /************************************************************
1158 * NETAPI_FindUser
1160 * Looks for a user in the user database.
1161 * Returns a pointer to the entry in the user list when the user
1162 * is found, NULL otherwise.
1164 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
1166 struct sam_user *user;
1168 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
1170 if(wcscmp(user->user_name, UserName) == 0)
1171 return user;
1173 return NULL;
1176 static BOOL NETAPI_IsCurrentUser(LPCWSTR username)
1178 LPWSTR curr_user = NULL;
1179 DWORD dwSize;
1180 BOOL ret = FALSE;
1182 dwSize = LM20_UNLEN+1;
1183 curr_user = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
1184 if(!curr_user)
1186 ERR("Failed to allocate memory for user name.\n");
1187 goto end;
1189 if(!GetUserNameW(curr_user, &dwSize))
1191 ERR("Failed to get current user's user name.\n");
1192 goto end;
1194 if (!wcscmp(curr_user, username))
1196 ret = TRUE;
1199 end:
1200 HeapFree(GetProcessHeap(), 0, curr_user);
1201 return ret;
1204 /************************************************************
1205 * NetUserAdd (NETAPI32.@)
1207 NET_API_STATUS WINAPI NetUserAdd(LPCWSTR servername,
1208 DWORD level, LPBYTE bufptr, LPDWORD parm_err)
1210 NET_API_STATUS status;
1211 struct sam_user * su = NULL;
1213 FIXME("(%s, %ld, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err);
1215 if((status = NETAPI_ValidateServername(servername)) != NERR_Success)
1216 return status;
1218 switch(level)
1220 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
1221 case 4:
1222 case 3:
1223 FIXME("Level 3 and 4 not implemented.\n");
1224 /* Fall through */
1225 case 2:
1226 FIXME("Level 2 not implemented.\n");
1227 /* Fall through */
1228 case 1:
1230 PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
1231 su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
1232 if(!su)
1234 status = NERR_InternalError;
1235 break;
1238 if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
1240 status = NERR_BadUsername;
1241 break;
1244 /*FIXME: do other checks for a valid username */
1245 lstrcpyW(su->user_name, ui->usri1_name);
1247 if(lstrlenW(ui->usri1_password) > PWLEN)
1249 /* Always return PasswordTooShort on invalid passwords. */
1250 status = NERR_PasswordTooShort;
1251 break;
1253 lstrcpyW(su->user_password, ui->usri1_password);
1255 su->sec_since_passwd_change = ui->usri1_password_age;
1256 su->user_priv = ui->usri1_priv;
1257 su->user_flags = ui->usri1_flags;
1259 /*FIXME: set the other LPWSTRs to NULL for now */
1260 su->home_dir = NULL;
1261 su->user_comment = NULL;
1262 su->user_logon_script_path = NULL;
1264 list_add_head(&user_list, &su->entry);
1265 return NERR_Success;
1267 default:
1268 TRACE("Invalid level %ld specified.\n", level);
1269 status = ERROR_INVALID_LEVEL;
1270 break;
1273 HeapFree(GetProcessHeap(), 0, su);
1275 return status;
1278 /************************************************************
1279 * NetUserDel (NETAPI32.@)
1281 NET_API_STATUS WINAPI NetUserDel(LPCWSTR servername, LPCWSTR username)
1283 NET_API_STATUS status;
1284 struct sam_user *user;
1286 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
1288 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
1289 return status;
1291 if ((user = NETAPI_FindUser(username)) == NULL)
1292 return NERR_UserNotFound;
1294 list_remove(&user->entry);
1296 HeapFree(GetProcessHeap(), 0, user->home_dir);
1297 HeapFree(GetProcessHeap(), 0, user->user_comment);
1298 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
1299 HeapFree(GetProcessHeap(), 0, user);
1301 return NERR_Success;
1304 /************************************************************
1305 * NetUserGetInfo (NETAPI32.@)
1307 NET_API_STATUS WINAPI
1308 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
1309 LPBYTE* bufptr)
1311 NET_API_STATUS status;
1312 TRACE("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username),
1313 level, bufptr);
1314 status = NETAPI_ValidateServername(servername);
1315 if (status != NERR_Success)
1316 return status;
1318 if(!NETAPI_IsLocalComputer(servername))
1320 FIXME("Only implemented for local computer, but remote server"
1321 "%s was requested.\n", debugstr_w(servername));
1322 return NERR_InvalidComputer;
1325 if(!NETAPI_FindUser(username) && !NETAPI_IsCurrentUser(username))
1327 TRACE("User %s is unknown.\n", debugstr_w(username));
1328 return NERR_UserNotFound;
1331 switch (level)
1333 case 0:
1335 PUSER_INFO_0 ui;
1336 int name_sz;
1338 name_sz = lstrlenW(username) + 1;
1340 /* set up buffer */
1341 NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
1342 (LPVOID *) bufptr);
1344 ui = (PUSER_INFO_0) *bufptr;
1345 ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
1347 /* get data */
1348 lstrcpyW(ui->usri0_name, username);
1349 break;
1352 case 10:
1354 PUSER_INFO_10 ui;
1355 PUSER_INFO_0 ui0;
1356 /* sizes of the field buffers in WCHARS */
1357 int name_sz, comment_sz, usr_comment_sz, full_name_sz;
1359 comment_sz = 1;
1360 usr_comment_sz = 1;
1361 full_name_sz = 1;
1363 /* get data */
1364 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1365 if (status != NERR_Success)
1367 NetApiBufferFree(ui0);
1368 return status;
1370 name_sz = lstrlenW(ui0->usri0_name) + 1;
1372 /* set up buffer */
1373 NetApiBufferAllocate(sizeof(USER_INFO_10) +
1374 (name_sz + comment_sz + usr_comment_sz +
1375 full_name_sz) * sizeof(WCHAR),
1376 (LPVOID *) bufptr);
1377 ui = (PUSER_INFO_10) *bufptr;
1378 ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
1379 ui->usri10_comment = (LPWSTR) (
1380 ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
1381 ui->usri10_usr_comment = (LPWSTR) (
1382 ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
1383 ui->usri10_full_name = (LPWSTR) (
1384 ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
1386 /* set data */
1387 lstrcpyW(ui->usri10_name, ui0->usri0_name);
1388 NetApiBufferFree(ui0);
1389 ui->usri10_comment[0] = 0;
1390 ui->usri10_usr_comment[0] = 0;
1391 ui->usri10_full_name[0] = 0;
1392 break;
1395 case 1:
1397 PUSER_INFO_1 ui;
1398 PUSER_INFO_0 ui0;
1399 /* sizes of the field buffers in WCHARS */
1400 int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
1402 password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
1403 comment_sz = 1;
1404 script_path_sz = 1;
1406 /* get data */
1407 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
1408 if (status != NERR_Success)
1410 NetApiBufferFree(ui0);
1411 return status;
1413 name_sz = lstrlenW(ui0->usri0_name) + 1;
1414 home_dir_sz = GetEnvironmentVariableW(L"HOME", NULL,0);
1415 /* set up buffer */
1416 NetApiBufferAllocate(sizeof(USER_INFO_1) +
1417 (name_sz + password_sz + home_dir_sz +
1418 comment_sz + script_path_sz) * sizeof(WCHAR),
1419 (LPVOID *) bufptr);
1421 ui = (PUSER_INFO_1) *bufptr;
1422 ui->usri1_name = (LPWSTR) (ui + 1);
1423 ui->usri1_password = ui->usri1_name + name_sz;
1424 ui->usri1_home_dir = ui->usri1_password + password_sz;
1425 ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
1426 ui->usri1_script_path = ui->usri1_comment + comment_sz;
1427 /* set data */
1428 lstrcpyW(ui->usri1_name, ui0->usri0_name);
1429 NetApiBufferFree(ui0);
1430 ui->usri1_password[0] = 0;
1431 ui->usri1_password_age = 0;
1432 ui->usri1_priv = 0;
1433 GetEnvironmentVariableW(L"HOME", ui->usri1_home_dir,home_dir_sz);
1434 ui->usri1_comment[0] = 0;
1435 ui->usri1_flags = 0;
1436 ui->usri1_script_path[0] = 0;
1437 break;
1439 case 2:
1440 case 3:
1441 case 4:
1442 case 11:
1443 case 20:
1444 case 23:
1445 case 1003:
1446 case 1005:
1447 case 1006:
1448 case 1007:
1449 case 1008:
1450 case 1009:
1451 case 1010:
1452 case 1011:
1453 case 1012:
1454 case 1013:
1455 case 1014:
1456 case 1017:
1457 case 1018:
1458 case 1020:
1459 case 1023:
1460 case 1024:
1461 case 1025:
1462 case 1051:
1463 case 1052:
1464 case 1053:
1466 FIXME("Level %ld is not implemented\n", level);
1467 return NERR_InternalError;
1469 default:
1470 TRACE("Invalid level %ld is specified\n", level);
1471 return ERROR_INVALID_LEVEL;
1473 return NERR_Success;
1476 /************************************************************
1477 * NetUserGetLocalGroups (NETAPI32.@)
1479 NET_API_STATUS WINAPI
1480 NetUserGetLocalGroups(LPCWSTR servername, LPCWSTR username, DWORD level,
1481 DWORD flags, LPBYTE* bufptr, DWORD prefmaxlen,
1482 LPDWORD entriesread, LPDWORD totalentries)
1484 static const WCHAR admins[] = L"Administrators";
1485 NET_API_STATUS status;
1486 LPWSTR currentuser;
1487 LOCALGROUP_USERS_INFO_0* info;
1488 DWORD size;
1490 FIXME("(%s, %s, %ld, %08lx, %p %ld, %p, %p) stub!\n",
1491 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
1492 prefmaxlen, entriesread, totalentries);
1494 status = NETAPI_ValidateServername(servername);
1495 if (status != NERR_Success)
1496 return status;
1498 size = UNLEN + 1;
1499 NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)&currentuser);
1500 if (!GetUserNameW(currentuser, &size)) {
1501 NetApiBufferFree(currentuser);
1502 return ERROR_NOT_ENOUGH_MEMORY;
1505 if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
1507 NetApiBufferFree(currentuser);
1508 return NERR_UserNotFound;
1511 NetApiBufferFree(currentuser);
1512 *totalentries = 1;
1513 size = sizeof(*info) + sizeof(admins);
1515 if(prefmaxlen < size)
1516 status = ERROR_MORE_DATA;
1517 else
1518 status = NetApiBufferAllocate(size, (LPVOID*)&info);
1520 if(status != NERR_Success)
1522 *bufptr = NULL;
1523 *entriesread = 0;
1524 return status;
1527 info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
1528 lstrcpyW(info->lgrui0_name, admins);
1530 *bufptr = (LPBYTE)info;
1531 *entriesread = 1;
1533 return NERR_Success;
1536 /************************************************************
1537 * NetUserEnum (NETAPI32.@)
1539 NET_API_STATUS WINAPI
1540 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
1541 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
1542 LPDWORD resume_handle)
1544 NET_API_STATUS status;
1545 WCHAR user[UNLEN + 1];
1546 DWORD size, len = ARRAY_SIZE(user);
1548 TRACE("(%s, %lu, 0x%lx, %p, %lu, %p, %p, %p)\n", debugstr_w(servername), level,
1549 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1551 status = NETAPI_ValidateServername(servername);
1552 if (status != NERR_Success)
1553 return status;
1555 if (!NETAPI_IsLocalComputer(servername))
1557 FIXME("Only implemented for local computer, but remote server"
1558 "%s was requested.\n", debugstr_w(servername));
1559 return NERR_InvalidComputer;
1562 if (!GetUserNameW(user, &len)) return GetLastError();
1564 switch (level)
1566 case 0:
1568 USER_INFO_0 *info;
1570 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1572 if (prefmaxlen < size)
1573 status = ERROR_MORE_DATA;
1574 else
1575 status = NetApiBufferAllocate(size, (void **)&info);
1577 if (status != NERR_Success)
1578 return status;
1580 info->usri0_name = (WCHAR *)((char *)info + sizeof(*info));
1581 wcscpy(info->usri0_name, user);
1583 *bufptr = (BYTE *)info;
1584 *entriesread = *totalentries = 1;
1585 break;
1587 case 20:
1589 USER_INFO_20 *info;
1590 SID *sid;
1591 UCHAR *count;
1592 DWORD *rid;
1593 SID_NAME_USE use;
1595 size = sizeof(*info) + (wcslen(user) + 1) * sizeof(WCHAR);
1597 if (prefmaxlen < size)
1598 status = ERROR_MORE_DATA;
1599 else
1600 status = NetApiBufferAllocate(size, (void **)&info);
1602 if (status != NERR_Success)
1603 return status;
1605 size = len = 0;
1606 LookupAccountNameW(NULL, user, NULL, &size, NULL, &len, &use);
1607 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1608 return GetLastError();
1610 status = NetApiBufferAllocate(size, (void **)&sid);
1611 if (status != NERR_Success)
1612 return status;
1614 if (!LookupAccountNameW(NULL, user, sid, &size, NULL, &len, &use))
1615 return GetLastError();
1617 count = GetSidSubAuthorityCount(sid);
1618 rid = GetSidSubAuthority(sid, *count - 1);
1620 info->usri20_name = (WCHAR *)((char *)info + sizeof(*info));
1621 wcscpy(info->usri20_name, user);
1622 info->usri20_full_name = NULL;
1623 info->usri20_comment = NULL;
1624 info->usri20_flags = UF_NORMAL_ACCOUNT;
1625 info->usri20_user_id = *rid;
1627 *bufptr = (BYTE *)info;
1628 *entriesread = *totalentries = 1;
1630 NetApiBufferFree(sid);
1631 break;
1633 default:
1634 FIXME("level %lu not supported\n", level);
1635 return ERROR_INVALID_LEVEL;
1637 return NERR_Success;
1640 /************************************************************
1641 * ACCESS_QueryAdminDisplayInformation
1643 * Creates a buffer with information for the Admin User
1645 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1647 static const WCHAR sAdminUserName[] = L"Administrator";
1649 /* sizes of the field buffers in WCHARS */
1650 int name_sz, comment_sz, full_name_sz;
1651 PNET_DISPLAY_USER usr;
1653 /* set up buffer */
1654 name_sz = lstrlenW(sAdminUserName) + 1;
1655 comment_sz = 1;
1656 full_name_sz = 1;
1658 *pdwSize = sizeof(NET_DISPLAY_USER);
1659 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1660 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1662 usr = *buf;
1663 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1664 usr->usri1_comment = (LPWSTR) (
1665 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1666 usr->usri1_full_name = (LPWSTR) (
1667 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1669 /* set data */
1670 lstrcpyW(usr->usri1_name, sAdminUserName);
1671 usr->usri1_comment[0] = 0;
1672 usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1673 usr->usri1_full_name[0] = 0;
1674 usr->usri1_user_id = DOMAIN_USER_RID_ADMIN;
1675 usr->usri1_next_index = 0;
1678 /************************************************************
1679 * ACCESS_QueryGuestDisplayInformation
1681 * Creates a buffer with information for the Guest User
1683 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
1685 static const WCHAR sGuestUserName[] = L"Guest";
1687 /* sizes of the field buffers in WCHARS */
1688 int name_sz, comment_sz, full_name_sz;
1689 PNET_DISPLAY_USER usr;
1691 /* set up buffer */
1692 name_sz = lstrlenW(sGuestUserName) + 1;
1693 comment_sz = 1;
1694 full_name_sz = 1;
1696 *pdwSize = sizeof(NET_DISPLAY_USER);
1697 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1698 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
1700 usr = *buf;
1701 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
1702 usr->usri1_comment = (LPWSTR) (
1703 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
1704 usr->usri1_full_name = (LPWSTR) (
1705 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
1707 /* set data */
1708 lstrcpyW(usr->usri1_name, sGuestUserName);
1709 usr->usri1_comment[0] = 0;
1710 usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
1711 UF_DONT_EXPIRE_PASSWD;
1712 usr->usri1_full_name[0] = 0;
1713 usr->usri1_user_id = DOMAIN_USER_RID_GUEST;
1714 usr->usri1_next_index = 0;
1717 /************************************************************
1718 * Copies NET_DISPLAY_USER record.
1720 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER *dest, LPWSTR *dest_buf,
1721 PNET_DISPLAY_USER src)
1723 LPWSTR str = *dest_buf;
1725 src->usri1_name = str;
1726 lstrcpyW(src->usri1_name, dest->usri1_name);
1727 str = (LPWSTR) (
1728 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1730 src->usri1_comment = str;
1731 lstrcpyW(src->usri1_comment, dest->usri1_comment);
1732 str = (LPWSTR) (
1733 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1735 src->usri1_flags = dest->usri1_flags;
1737 src->usri1_full_name = str;
1738 lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
1739 str = (LPWSTR) (
1740 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
1742 src->usri1_user_id = dest->usri1_user_id;
1743 src->usri1_next_index = dest->usri1_next_index;
1744 *dest_buf = str;
1747 /************************************************************
1748 * NetQueryDisplayInformation (NETAPI32.@)
1750 * The buffer structure:
1751 * - array of fixed size record of the level type
1752 * - strings, referenced by the record of the level type
1754 NET_API_STATUS WINAPI
1755 NetQueryDisplayInformation(
1756 LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
1757 DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
1758 PVOID *SortedBuffer)
1760 TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName),
1761 Level, Index, EntriesRequested, PreferredMaximumLength,
1762 ReturnedEntryCount, SortedBuffer);
1764 if(!NETAPI_IsLocalComputer(ServerName))
1766 FIXME("Only implemented on local computer, but requested for "
1767 "remote server %s\n", debugstr_w(ServerName));
1768 return ERROR_ACCESS_DENIED;
1771 switch (Level)
1773 case 1:
1775 /* current record */
1776 PNET_DISPLAY_USER inf;
1777 /* current available strings buffer */
1778 LPWSTR str;
1779 PNET_DISPLAY_USER admin, guest;
1780 DWORD admin_size, guest_size;
1781 LPWSTR name = NULL;
1782 DWORD dwSize;
1784 /* sizes of the field buffers in WCHARS */
1785 int name_sz, comment_sz, full_name_sz;
1787 /* number of the records, returned in SortedBuffer
1788 3 - for current user, Administrator and Guest users
1790 int records = 3;
1792 FIXME("Level %ld partially implemented\n", Level);
1793 *ReturnedEntryCount = records;
1794 comment_sz = 1;
1795 full_name_sz = 1;
1797 /* get data */
1798 dwSize = UNLEN + 1;
1799 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &name);
1800 if (!GetUserNameW(name, &dwSize))
1802 NetApiBufferFree(name);
1803 return ERROR_ACCESS_DENIED;
1805 name_sz = dwSize;
1806 ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
1807 ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
1809 /* set up buffer */
1810 dwSize = sizeof(NET_DISPLAY_USER) * records;
1811 dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
1813 NetApiBufferAllocate(dwSize +
1814 admin_size - sizeof(NET_DISPLAY_USER) +
1815 guest_size - sizeof(NET_DISPLAY_USER),
1816 SortedBuffer);
1817 inf = *SortedBuffer;
1818 str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
1819 inf->usri1_name = str;
1820 str = (LPWSTR) (
1821 ((PBYTE) str) + name_sz * sizeof(WCHAR));
1822 inf->usri1_comment = str;
1823 str = (LPWSTR) (
1824 ((PBYTE) str) + comment_sz * sizeof(WCHAR));
1825 inf->usri1_full_name = str;
1826 str = (LPWSTR) (
1827 ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
1829 /* set data */
1830 lstrcpyW(inf->usri1_name, name);
1831 NetApiBufferFree(name);
1832 inf->usri1_comment[0] = 0;
1833 inf->usri1_flags =
1834 UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
1835 inf->usri1_full_name[0] = 0;
1836 inf->usri1_user_id = 0;
1837 inf->usri1_next_index = 0;
1839 inf++;
1840 ACCESS_CopyDisplayUser(admin, &str, inf);
1841 NetApiBufferFree(admin);
1843 inf++;
1844 ACCESS_CopyDisplayUser(guest, &str, inf);
1845 NetApiBufferFree(guest);
1846 break;
1849 case 2:
1850 case 3:
1852 FIXME("Level %ld is not implemented\n", Level);
1853 break;
1856 default:
1857 TRACE("Invalid level %ld is specified\n", Level);
1858 return ERROR_INVALID_LEVEL;
1860 return NERR_Success;
1863 /************************************************************
1864 * NetGetDCName (NETAPI32.@)
1866 * Return the name of the primary domain controller (PDC)
1869 NET_API_STATUS WINAPI
1870 NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1872 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1873 debugstr_w(domainname), bufptr);
1874 return NERR_DCNotFound; /* say we can't find a domain controller */
1877 /************************************************************
1878 * NetGetAnyDCName (NETAPI32.@)
1880 * Return the name of any domain controller (DC) for a
1881 * domain that is directly trusted by the specified server
1884 NET_API_STATUS WINAPI NetGetAnyDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
1886 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
1887 debugstr_w(domainname), bufptr);
1888 return ERROR_NO_SUCH_DOMAIN;
1891 /************************************************************
1892 * NetGroupAddUser (NETAPI32.@)
1894 NET_API_STATUS WINAPI
1895 NetGroupAddUser(LPCWSTR servername, LPCWSTR groupname, LPCWSTR username)
1897 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername),
1898 debugstr_w(groupname), debugstr_w(username));
1899 return NERR_Success;
1902 /************************************************************
1903 * NetGroupEnum (NETAPI32.@)
1906 NET_API_STATUS WINAPI
1907 NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen,
1908 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
1910 FIXME("(%s, %ld, %p, %ld, %p, %p, %p) stub!\n", debugstr_w(servername),
1911 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1912 return ERROR_ACCESS_DENIED;
1915 /************************************************************
1916 * NetGroupGetInfo (NETAPI32.@)
1919 NET_API_STATUS WINAPI NetGroupGetInfo(LPCWSTR servername, LPCWSTR groupname, DWORD level, LPBYTE *bufptr)
1921 FIXME("(%s, %s, %ld, %p) stub!\n", debugstr_w(servername), debugstr_w(groupname), level, bufptr);
1922 return ERROR_ACCESS_DENIED;
1925 /******************************************************************************
1926 * NetUserModalsGet (NETAPI32.@)
1928 * Retrieves global information for all users and global groups in the security
1929 * database.
1931 * PARAMS
1932 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
1933 * on which the function is to execute.
1934 * level [I] Information level of the data.
1935 * 0 Return global passwords parameters. bufptr points to a
1936 * USER_MODALS_INFO_0 struct.
1937 * 1 Return logon server and domain controller information. bufptr
1938 * points to a USER_MODALS_INFO_1 struct.
1939 * 2 Return domain name and identifier. bufptr points to a
1940 * USER_MODALS_INFO_2 struct.
1941 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
1942 * struct.
1943 * pbuffer [I] Buffer that receives the data.
1945 * RETURNS
1946 * Success: NERR_Success.
1947 * Failure:
1948 * ERROR_ACCESS_DENIED - the user does not have access to the info.
1949 * NERR_InvalidComputer - computer name is invalid.
1951 NET_API_STATUS WINAPI NetUserModalsGet(
1952 LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
1954 TRACE("(%s %ld %p)\n", debugstr_w(szServer), level, pbuffer);
1956 switch (level)
1958 case 0:
1959 /* return global passwords parameters */
1960 FIXME("level 0 not implemented!\n");
1961 *pbuffer = NULL;
1962 return NERR_InternalError;
1963 case 1:
1964 /* return logon server and domain controller info */
1965 FIXME("level 1 not implemented!\n");
1966 *pbuffer = NULL;
1967 return NERR_InternalError;
1968 case 2:
1970 /* return domain name and identifier */
1971 PUSER_MODALS_INFO_2 umi;
1972 LSA_HANDLE policyHandle;
1973 LSA_OBJECT_ATTRIBUTES objectAttributes;
1974 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo;
1975 NTSTATUS ntStatus;
1976 PSID domainIdentifier = NULL;
1977 int domainNameLen;
1979 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
1980 objectAttributes.Length = sizeof(objectAttributes);
1982 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
1983 POLICY_VIEW_LOCAL_INFORMATION,
1984 &policyHandle);
1985 if (ntStatus != STATUS_SUCCESS)
1987 WARN("LsaOpenPolicy failed with NT status %lx\n",
1988 LsaNtStatusToWinError(ntStatus));
1989 return ntStatus;
1992 ntStatus = LsaQueryInformationPolicy(policyHandle,
1993 PolicyAccountDomainInformation,
1994 (PVOID *)&domainInfo);
1995 if (ntStatus != STATUS_SUCCESS)
1997 WARN("LsaQueryInformationPolicy failed with NT status %lx\n",
1998 LsaNtStatusToWinError(ntStatus));
1999 LsaClose(policyHandle);
2000 return ntStatus;
2003 domainIdentifier = domainInfo->DomainSid;
2004 domainNameLen = lstrlenW(domainInfo->DomainName.Buffer) + 1;
2005 LsaClose(policyHandle);
2007 ntStatus = NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2) +
2008 GetLengthSid(domainIdentifier) +
2009 domainNameLen * sizeof(WCHAR),
2010 (LPVOID *)pbuffer);
2012 if (ntStatus != NERR_Success)
2014 WARN("NetApiBufferAllocate() failed\n");
2015 LsaFreeMemory(domainInfo);
2016 return ntStatus;
2019 umi = (USER_MODALS_INFO_2 *) *pbuffer;
2020 umi->usrmod2_domain_id = *pbuffer + sizeof(USER_MODALS_INFO_2);
2021 umi->usrmod2_domain_name = (LPWSTR)(*pbuffer +
2022 sizeof(USER_MODALS_INFO_2) + GetLengthSid(domainIdentifier));
2024 lstrcpynW(umi->usrmod2_domain_name,
2025 domainInfo->DomainName.Buffer,
2026 domainNameLen);
2027 CopySid(GetLengthSid(domainIdentifier), umi->usrmod2_domain_id,
2028 domainIdentifier);
2030 LsaFreeMemory(domainInfo);
2032 break;
2034 case 3:
2035 /* return lockout information */
2036 FIXME("level 3 not implemented!\n");
2037 *pbuffer = NULL;
2038 return NERR_InternalError;
2039 default:
2040 TRACE("Invalid level %ld is specified\n", level);
2041 *pbuffer = NULL;
2042 return ERROR_INVALID_LEVEL;
2045 return NERR_Success;
2048 /******************************************************************************
2049 * NetUserChangePassword (NETAPI32.@)
2050 * PARAMS
2051 * domainname [I] Optional. Domain on which the user resides or the logon
2052 * domain of the current user if NULL.
2053 * username [I] Optional. Username to change the password for or the name
2054 * of the current user if NULL.
2055 * oldpassword [I] The user's current password.
2056 * newpassword [I] The password that the user will be changed to using.
2058 * RETURNS
2059 * Success: NERR_Success.
2060 * Failure: NERR_* failure code or win error code.
2063 NET_API_STATUS WINAPI NetUserChangePassword(LPCWSTR domainname, LPCWSTR username,
2064 LPCWSTR oldpassword, LPCWSTR newpassword)
2066 struct sam_user *user;
2067 struct change_password_params params = { domainname, username, oldpassword, newpassword };
2069 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2071 if (samba_init() && !SAMBA_CALL( change_password, &params ))
2072 return NERR_Success;
2074 if(domainname)
2075 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
2077 if((user = NETAPI_FindUser(username)) == NULL)
2078 return NERR_UserNotFound;
2080 if(wcscmp(user->user_password, oldpassword) != 0)
2081 return ERROR_INVALID_PASSWORD;
2083 if(lstrlenW(newpassword) > PWLEN)
2084 return ERROR_PASSWORD_RESTRICTION;
2086 lstrcpyW(user->user_password, newpassword);
2088 return NERR_Success;
2091 NET_API_STATUS WINAPI NetUseAdd(LMSTR servername, DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2093 FIXME("%s %ld %p %p stub\n", debugstr_w(servername), level, bufptr, parm_err);
2094 return NERR_Success;
2097 NET_API_STATUS WINAPI NetUseDel(LMSTR servername, LMSTR usename, DWORD forcecond)
2099 FIXME("%s %s %ld stub\n", debugstr_w(servername), debugstr_w(usename), forcecond);
2100 return NERR_Success;
2103 /************************************************************
2104 * I_BrowserSetNetlogonState (NETAPI32.@)
2106 NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
2107 LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
2108 DWORD Role)
2110 return ERROR_NOT_SUPPORTED;
2113 /************************************************************
2114 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
2116 NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
2117 LPWSTR ServerName, PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
2118 LPDWORD EntriesRead)
2120 return ERROR_NOT_SUPPORTED;
2123 #define NS_MAXDNAME 1025
2125 static DWORD get_dc_info(const WCHAR *domain, WCHAR *dc, WCHAR *ip)
2127 WCHAR name[NS_MAXDNAME];
2128 DWORD ret, size;
2129 DNS_RECORDW *rec;
2131 wcscpy( name, L"_ldap._tcp.dc._msdcs." );
2132 wcscat( name, domain );
2134 ret = DnsQuery_W(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2135 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(domain), ret);
2136 if (ret == ERROR_SUCCESS)
2138 TRACE("target %s, port %d\n", wine_dbgstr_w(rec->Data.Srv.pNameTarget), rec->Data.Srv.wPort);
2140 lstrcpynW(dc, rec->Data.Srv.pNameTarget, NS_MAXDNAME);
2141 DnsRecordListFree(rec, DnsFreeRecordList);
2143 /* IPv4 */
2144 ret = DnsQuery_W(dc, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2145 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(dc), ret);
2146 if (ret == ERROR_SUCCESS)
2148 SOCKADDR_IN addr;
2150 addr.sin_family = AF_INET;
2151 addr.sin_port = 0;
2152 addr.sin_addr.s_addr = rec->Data.A.IpAddress;
2153 size = IP6_ADDRESS_STRING_LENGTH;
2154 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2155 if (!ret)
2156 TRACE("WSAAddressToStringW => %ld, %s\n", ret, wine_dbgstr_w(ip));
2158 DnsRecordListFree(rec, DnsFreeRecordList);
2160 return ret;
2163 /* IPv6 */
2164 ret = DnsQuery_W(dc, DNS_TYPE_AAAA, DNS_QUERY_STANDARD, NULL, &rec, NULL);
2165 TRACE("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(dc), ret);
2166 if (ret == ERROR_SUCCESS)
2168 SOCKADDR_IN6 addr;
2170 addr.sin6_family = AF_INET6;
2171 addr.sin6_port = 0;
2172 addr.sin6_scope_id = 0;
2173 memcpy(addr.sin6_addr.s6_addr, &rec->Data.AAAA.Ip6Address, sizeof(rec->Data.AAAA.Ip6Address));
2174 size = IP6_ADDRESS_STRING_LENGTH;
2175 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
2176 if (!ret)
2177 TRACE("WSAAddressToStringW => %ld, %s\n", ret, wine_dbgstr_w(ip));
2179 DnsRecordListFree(rec, DnsFreeRecordList);
2183 return ret;
2186 DWORD WINAPI DsGetDcNameW(LPCWSTR computer, LPCWSTR domain, GUID *domain_guid,
2187 LPCWSTR site, ULONG flags, PDOMAIN_CONTROLLER_INFOW *dc_info)
2189 static const WCHAR pfxW[] = {'\\','\\'};
2190 static const WCHAR default_site_nameW[] = L"Default-First-Site-Name";
2191 NTSTATUS status;
2192 POLICY_DNS_DOMAIN_INFO *dns_domain_info = NULL;
2193 DOMAIN_CONTROLLER_INFOW *info;
2194 WCHAR dc[NS_MAXDNAME], ip[IP6_ADDRESS_STRING_LENGTH];
2195 DWORD size;
2197 FIXME("(%s, %s, %s, %s, %08lx, %p): semi-stub\n", debugstr_w(computer),
2198 debugstr_w(domain), debugstr_guid(domain_guid), debugstr_w(site), flags, dc_info);
2200 if (!dc_info) return ERROR_INVALID_PARAMETER;
2202 if (!domain)
2204 LSA_OBJECT_ATTRIBUTES attrs;
2205 LSA_HANDLE lsa;
2207 memset(&attrs, 0, sizeof(attrs));
2208 attrs.Length = sizeof(attrs);
2209 status = LsaOpenPolicy(NULL, &attrs, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
2210 if (status)
2211 return LsaNtStatusToWinError(status);
2213 status = LsaQueryInformationPolicy(lsa, PolicyDnsDomainInformation, (void **)&dns_domain_info);
2214 LsaClose(lsa);
2215 if (status)
2216 return LsaNtStatusToWinError(status);
2218 domain = dns_domain_info->DnsDomainName.Buffer;
2221 status = get_dc_info(domain, dc, ip);
2222 if (status) return status;
2224 size = sizeof(DOMAIN_CONTROLLER_INFOW) + lstrlenW(domain) * sizeof(WCHAR) +
2225 sizeof(pfxW) * 2 + (lstrlenW(dc) + 1 + lstrlenW(ip) + 1) * sizeof(WCHAR) +
2226 lstrlenW(domain) * sizeof(WCHAR) /* assume forest == domain */ +
2227 sizeof(default_site_nameW) * 2;
2228 status = NetApiBufferAllocate(size, (void **)&info);
2229 if (status != NERR_Success)
2231 LsaFreeMemory(dns_domain_info);
2232 return ERROR_NOT_ENOUGH_MEMORY;
2235 info->DomainControllerName = (WCHAR *)(info + 1);
2236 memcpy(info->DomainControllerName, pfxW, sizeof(pfxW));
2237 lstrcpyW(info->DomainControllerName + 2, dc);
2238 info->DomainControllerAddress = (WCHAR *)((char *)info->DomainControllerName + (wcslen(info->DomainControllerName) + 1) * sizeof(WCHAR));
2239 memcpy(info->DomainControllerAddress, pfxW, sizeof(pfxW));
2240 lstrcpyW(info->DomainControllerAddress + 2, ip);
2241 info->DomainControllerAddressType = DS_INET_ADDRESS;
2242 info->DomainGuid = dns_domain_info ? dns_domain_info->DomainGuid : GUID_NULL /* FIXME */;
2243 info->DomainName = (WCHAR *)((char *)info->DomainControllerAddress + (wcslen(info->DomainControllerAddress) + 1) * sizeof(WCHAR));
2244 lstrcpyW(info->DomainName, domain);
2245 info->DnsForestName = (WCHAR *)((char *)info->DomainName + (lstrlenW(info->DomainName) + 1) * sizeof(WCHAR));
2246 lstrcpyW(info->DnsForestName, domain);
2247 info->DcSiteName = (WCHAR *)((char *)info->DnsForestName + (lstrlenW(info->DnsForestName) + 1) * sizeof(WCHAR));
2248 lstrcpyW(info->DcSiteName, default_site_nameW);
2249 info->ClientSiteName = (WCHAR *)((char *)info->DcSiteName + sizeof(default_site_nameW));
2250 lstrcpyW(info->ClientSiteName, default_site_nameW);
2251 info->Flags = DS_DNS_DOMAIN_FLAG | DS_DNS_FOREST_FLAG;
2253 LsaFreeMemory(dns_domain_info);
2255 *dc_info = info;
2257 return ERROR_SUCCESS;
2260 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
2261 GUID* DomainGuid, LPCSTR SiteName, ULONG Flags,
2262 PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo)
2264 FIXME("(%s, %s, %s, %s, %08lx, %p): stub\n", debugstr_a(ComputerName),
2265 debugstr_a(AvoidDCName), debugstr_guid(DomainGuid),
2266 debugstr_a(SiteName), Flags, DomainControllerInfo);
2267 return ERROR_CALL_NOT_IMPLEMENTED;
2270 DWORD WINAPI DsGetSiteNameW(LPCWSTR ComputerName, LPWSTR *SiteName)
2272 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName), SiteName);
2273 return ERROR_CALL_NOT_IMPLEMENTED;
2276 DWORD WINAPI DsGetSiteNameA(LPCSTR ComputerName, LPSTR *SiteName)
2278 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName), SiteName);
2279 return ERROR_CALL_NOT_IMPLEMENTED;
2282 /************************************************************
2283 * DsRoleFreeMemory (NETAPI32.@)
2285 * PARAMS
2286 * Buffer [I] Pointer to the to-be-freed buffer.
2288 * RETURNS
2289 * Nothing
2291 VOID WINAPI DsRoleFreeMemory(PVOID Buffer)
2293 TRACE("(%p)\n", Buffer);
2294 HeapFree(GetProcessHeap(), 0, Buffer);
2297 /************************************************************
2298 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
2300 * PARAMS
2301 * lpServer [I] Pointer to UNICODE string with ComputerName
2302 * InfoLevel [I] Type of data to retrieve
2303 * Buffer [O] Pointer to to the requested data
2305 * RETURNS
2307 * NOTES
2308 * When lpServer is NULL, use the local computer
2310 DWORD WINAPI DsRoleGetPrimaryDomainInformation(
2311 LPCWSTR lpServer, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
2312 PBYTE* Buffer)
2314 DWORD ret;
2316 FIXME("(%p, %d, %p) stub\n", lpServer, InfoLevel, Buffer);
2318 /* Check some input parameters */
2320 if (!Buffer) return ERROR_INVALID_PARAMETER;
2321 if ((InfoLevel < DsRolePrimaryDomainInfoBasic) || (InfoLevel > DsRoleOperationState)) return ERROR_INVALID_PARAMETER;
2323 *Buffer = NULL;
2324 switch (InfoLevel)
2326 case DsRolePrimaryDomainInfoBasic:
2328 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
2329 LSA_HANDLE PolicyHandle;
2330 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
2331 NTSTATUS NtStatus;
2332 int logon_domain_sz;
2333 DWORD size;
2334 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic;
2336 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
2337 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
2338 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
2339 if (NtStatus != STATUS_SUCCESS)
2341 TRACE("LsaOpenPolicyFailed with NT status %lx\n",
2342 LsaNtStatusToWinError(NtStatus));
2343 return ERROR_OUTOFMEMORY;
2345 LsaQueryInformationPolicy(PolicyHandle,
2346 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
2347 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
2348 LsaClose(PolicyHandle);
2350 size = sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC) +
2351 logon_domain_sz * sizeof(WCHAR);
2352 basic = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2353 if (basic)
2355 basic->MachineRole = DsRole_RoleStandaloneWorkstation;
2356 basic->DomainNameFlat = (LPWSTR)((LPBYTE)basic +
2357 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
2358 lstrcpyW(basic->DomainNameFlat, DomainInfo->DomainName.Buffer);
2359 ret = ERROR_SUCCESS;
2361 else
2362 ret = ERROR_OUTOFMEMORY;
2363 *Buffer = (PBYTE)basic;
2364 LsaFreeMemory(DomainInfo);
2366 break;
2367 default:
2368 ret = ERROR_CALL_NOT_IMPLEMENTED;
2370 return ret;
2373 /************************************************************
2374 * NetLocalGroupAdd (NETAPI32.@)
2376 NET_API_STATUS WINAPI NetLocalGroupAdd(
2377 LPCWSTR servername,
2378 DWORD level,
2379 LPBYTE buf,
2380 LPDWORD parm_err)
2382 FIXME("(%s %ld %p %p) stub!\n", debugstr_w(servername), level, buf,
2383 parm_err);
2384 return NERR_Success;
2387 /************************************************************
2388 * NetLocalGroupAddMember (NETAPI32.@)
2390 NET_API_STATUS WINAPI NetLocalGroupAddMember(
2391 LPCWSTR servername,
2392 LPCWSTR groupname,
2393 PSID membersid)
2395 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2396 debugstr_w(groupname), membersid);
2397 return NERR_Success;
2400 /************************************************************
2401 * NetLocalGroupAddMembers (NETAPI32.@)
2403 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
2404 LPCWSTR servername,
2405 LPCWSTR groupname,
2406 DWORD level,
2407 LPBYTE buf,
2408 DWORD totalentries)
2410 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2411 debugstr_w(groupname), level, buf, totalentries);
2412 return NERR_Success;
2415 /************************************************************
2416 * NetLocalGroupDel (NETAPI32.@)
2418 NET_API_STATUS WINAPI NetLocalGroupDel(
2419 LPCWSTR servername,
2420 LPCWSTR groupname)
2422 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
2423 return NERR_Success;
2426 /************************************************************
2427 * NetLocalGroupDelMember (NETAPI32.@)
2429 NET_API_STATUS WINAPI NetLocalGroupDelMember(
2430 LPCWSTR servername,
2431 LPCWSTR groupname,
2432 PSID membersid)
2434 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
2435 debugstr_w(groupname), membersid);
2436 return NERR_Success;
2439 /************************************************************
2440 * NetLocalGroupDelMembers (NETAPI32.@)
2442 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
2443 LPCWSTR servername,
2444 LPCWSTR groupname,
2445 DWORD level,
2446 LPBYTE buf,
2447 DWORD totalentries)
2449 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2450 debugstr_w(groupname), level, buf, totalentries);
2451 return NERR_Success;
2454 /************************************************************
2455 * NetLocalGroupEnum (NETAPI32.@)
2457 NET_API_STATUS WINAPI NetLocalGroupEnum(
2458 LPCWSTR servername,
2459 DWORD level,
2460 LPBYTE* bufptr,
2461 DWORD prefmaxlen,
2462 LPDWORD entriesread,
2463 LPDWORD totalentries,
2464 PDWORD_PTR resumehandle)
2466 FIXME("(%s %ld %p %ld %p %p %p) stub!\n", debugstr_w(servername),
2467 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
2468 *entriesread = 0;
2469 *totalentries = 0;
2470 return NERR_Success;
2473 /************************************************************
2474 * NetLocalGroupGetInfo (NETAPI32.@)
2476 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
2477 LPCWSTR servername,
2478 LPCWSTR groupname,
2479 DWORD level,
2480 LPBYTE* bufptr)
2482 static const WCHAR commentW[] = L"No comment";
2483 LOCALGROUP_INFO_1* info;
2484 DWORD size;
2486 FIXME("(%s %s %ld %p) semi-stub!\n", debugstr_w(servername),
2487 debugstr_w(groupname), level, bufptr);
2489 size = sizeof(*info) + sizeof(WCHAR) * (lstrlenW(groupname)+1) + sizeof(commentW);
2490 NetApiBufferAllocate(size, (LPVOID*)&info);
2492 info->lgrpi1_name = (LPWSTR)(info + 1);
2493 lstrcpyW(info->lgrpi1_name, groupname);
2495 info->lgrpi1_comment = info->lgrpi1_name + lstrlenW(groupname) + 1;
2496 lstrcpyW(info->lgrpi1_comment, commentW);
2498 *bufptr = (LPBYTE)info;
2500 return NERR_Success;
2503 /************************************************************
2504 * NetLocalGroupGetMembers (NETAPI32.@)
2506 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
2507 LPCWSTR servername,
2508 LPCWSTR localgroupname,
2509 DWORD level,
2510 LPBYTE* bufptr,
2511 DWORD prefmaxlen,
2512 LPDWORD entriesread,
2513 LPDWORD totalentries,
2514 PDWORD_PTR resumehandle)
2516 FIXME("(%s %s %ld %p %ld, %p %p %p) stub!\n", debugstr_w(servername),
2517 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
2518 totalentries, resumehandle);
2520 if (level == 3)
2522 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
2523 DWORD userNameLen;
2524 DWORD len,needlen;
2525 PLOCALGROUP_MEMBERS_INFO_3 ptr;
2527 /* still a stub, current user is belonging to all groups */
2529 *totalentries = 1;
2530 *entriesread = 0;
2532 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
2533 if (!GetUserNameW(userName,&userNameLen))
2534 return ERROR_NOT_ENOUGH_MEMORY;
2536 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
2537 (userNameLen+2) * sizeof(WCHAR);
2538 if (prefmaxlen != MAX_PREFERRED_LENGTH)
2539 len = min(prefmaxlen,needlen);
2540 else
2541 len = needlen;
2543 NetApiBufferAllocate(len, (LPVOID *) bufptr);
2544 if (len < needlen)
2545 return ERROR_MORE_DATA;
2547 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
2548 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
2549 lstrcpyW(ptr->lgrmi3_domainandname,userName);
2551 *entriesread = 1;
2554 return NERR_Success;
2557 /************************************************************
2558 * NetLocalGroupSetInfo (NETAPI32.@)
2560 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
2561 LPCWSTR servername,
2562 LPCWSTR groupname,
2563 DWORD level,
2564 LPBYTE buf,
2565 LPDWORD parm_err)
2567 FIXME("(%s %s %ld %p %p) stub!\n", debugstr_w(servername),
2568 debugstr_w(groupname), level, buf, parm_err);
2569 return NERR_Success;
2572 /************************************************************
2573 * NetLocalGroupSetMember (NETAPI32.@)
2575 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
2576 LPCWSTR servername,
2577 LPCWSTR groupname,
2578 DWORD level,
2579 LPBYTE buf,
2580 DWORD totalentries)
2582 FIXME("(%s %s %ld %p %ld) stub!\n", debugstr_w(servername),
2583 debugstr_w(groupname), level, buf, totalentries);
2584 return NERR_Success;
2587 /************************************************************
2588 * DavGetHTTPFromUNCPath (NETAPI32.@)
2590 DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buflen)
2592 static const WCHAR httpW[] = L"http://";
2593 static const WCHAR httpsW[] = L"https://";
2594 const WCHAR *p = unc_path, *q, *server, *path, *scheme = httpW;
2595 UINT i, len_server, len_path = 0, len_port = 0, len, port = 0;
2596 WCHAR *end, portbuf[12];
2598 TRACE("(%s %p %p)\n", debugstr_w(unc_path), buf, buflen);
2600 if (p[0] != '\\' || p[1] != '\\' || !p[2]) return ERROR_INVALID_PARAMETER;
2601 q = p += 2;
2602 while (*q && *q != '\\' && *q != '/' && *q != '@') q++;
2603 server = p;
2604 len_server = q - p;
2605 if (*q == '@')
2607 p = ++q;
2608 while (*p && (*p != '\\' && *p != '/' && *p != '@')) p++;
2609 if (p - q == 3 && !wcsnicmp( q, L"SSL", 3 ))
2611 scheme = httpsW;
2612 q = p;
2614 else if ((port = wcstol( q, &end, 10 ))) q = end;
2615 else return ERROR_INVALID_PARAMETER;
2617 if (*q == '@')
2619 if (!(port = wcstol( ++q, &end, 10 ))) return ERROR_INVALID_PARAMETER;
2620 q = end;
2622 if (*q == '\\' || *q == '/') q++;
2623 path = q;
2624 while (*q++) len_path++;
2625 if (len_path && (path[len_path - 1] == '\\' || path[len_path - 1] == '/'))
2626 len_path--; /* remove trailing slash */
2628 swprintf( portbuf, ARRAY_SIZE(portbuf), L":%u", port );
2629 if (scheme == httpsW)
2631 len = wcslen( httpsW );
2632 if (port && port != 443) len_port = wcslen( portbuf );
2634 else
2636 len = wcslen( httpW );
2637 if (port && port != 80) len_port = wcslen( portbuf );
2639 len += len_server;
2640 len += len_port;
2641 if (len_path) len += len_path + 1; /* leading '/' */
2642 len++; /* nul */
2644 if (*buflen < len)
2646 *buflen = len;
2647 return ERROR_INSUFFICIENT_BUFFER;
2650 memcpy( buf, scheme, wcslen(scheme) * sizeof(WCHAR) );
2651 buf += wcslen( scheme );
2652 memcpy( buf, server, len_server * sizeof(WCHAR) );
2653 buf += len_server;
2654 if (len_port)
2656 memcpy( buf, portbuf, len_port * sizeof(WCHAR) );
2657 buf += len_port;
2659 if (len_path)
2661 *buf++ = '/';
2662 for (i = 0; i < len_path; i++)
2664 if (path[i] == '\\') *buf++ = '/';
2665 else *buf++ = path[i];
2668 *buf = 0;
2669 *buflen = len;
2671 return ERROR_SUCCESS;
2674 /************************************************************
2675 * DavGetUNCFromHTTPPath (NETAPI32.@)
2677 DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen)
2679 static const WCHAR httpW[] = {'h','t','t','p'};
2680 static const WCHAR httpsW[] = {'h','t','t','p','s'};
2681 static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
2682 static const WCHAR sslW[] = {'@','S','S','L'};
2683 static const WCHAR port80W[] = {'8','0'};
2684 static const WCHAR port443W[] = {'4','4','3'};
2685 const WCHAR *p = http_path, *server, *port = NULL, *path = NULL;
2686 DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0;
2687 BOOL ssl;
2689 TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen);
2691 while (*p && *p != ':') { p++; len++; };
2692 if (len == ARRAY_SIZE(httpW) && !wcsnicmp( http_path, httpW, len )) ssl = FALSE;
2693 else if (len == ARRAY_SIZE(httpsW) && !wcsnicmp( http_path, httpsW, len )) ssl = TRUE;
2694 else return ERROR_INVALID_PARAMETER;
2696 if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER;
2697 server = p += 3;
2699 while (*p && *p != ':' && *p != '/') { p++; len_server++; };
2700 if (!len_server) return ERROR_BAD_NET_NAME;
2701 if (*p == ':')
2703 port = ++p;
2704 while (*p >= '0' && *p <= '9') { p++; len_port++; };
2705 if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL;
2706 else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL;
2707 path = p;
2709 else if (*p == '/') path = p;
2711 while (*p)
2713 if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME;
2714 p++; len_path++;
2716 if (len_path && path[len_path - 1] == '/') len_path--;
2718 len = len_server + 2; /* \\ */
2719 if (ssl) len += 4; /* @SSL */
2720 if (port) len += len_port + 1 /* @ */;
2721 len += ARRAY_SIZE(davrootW);
2722 len += len_path + 1; /* nul */
2724 if (*buflen < len)
2726 *buflen = len;
2727 return ERROR_INSUFFICIENT_BUFFER;
2730 buf[0] = buf[1] = '\\';
2731 buf += 2;
2732 memcpy( buf, server, len_server * sizeof(WCHAR) );
2733 buf += len_server;
2734 if (ssl)
2736 memcpy( buf, sslW, sizeof(sslW) );
2737 buf += 4;
2739 if (port)
2741 *buf++ = '@';
2742 memcpy( buf, port, len_port * sizeof(WCHAR) );
2743 buf += len_port;
2745 memcpy( buf, davrootW, sizeof(davrootW) );
2746 buf += ARRAY_SIZE(davrootW);
2747 for (i = 0; i < len_path; i++)
2749 if (path[i] == '/') *buf++ = '\\';
2750 else *buf++ = path[i];
2753 *buf = 0;
2754 *buflen = len;
2756 return ERROR_SUCCESS;
2759 /************************************************************
2760 * DsEnumerateDomainTrustsA (NETAPI32.@)
2762 DWORD WINAPI DsEnumerateDomainTrustsA(LPSTR server, ULONG flags, PDS_DOMAIN_TRUSTSA* domains, PULONG count)
2764 FIXME("(%s, 0x%04lx, %p, %p): stub\n", debugstr_a(server), flags, domains, count);
2765 return ERROR_NO_LOGON_SERVERS;
2768 /************************************************************
2769 * DsEnumerateDomainTrustsW (NETAPI32.@)
2771 DWORD WINAPI DsEnumerateDomainTrustsW(LPWSTR server, ULONG flags, PDS_DOMAIN_TRUSTSW* domains, PULONG count)
2773 FIXME("(%s, 0x%04lx, %p, %p): stub\n", debugstr_w(server), flags, domains, count);
2774 return ERROR_NO_LOGON_SERVERS;
2777 DECLSPEC_HIDDEN void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
2779 return HeapAlloc(GetProcessHeap(), 0, n);
2782 DECLSPEC_HIDDEN void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
2784 HeapFree(GetProcessHeap(), 0, p);
2787 DECLSPEC_HIDDEN handle_t __RPC_USER ATSVC_HANDLE_bind(ATSVC_HANDLE str)
2789 static unsigned char ncalrpc[] = "ncalrpc";
2790 unsigned char *binding_str;
2791 handle_t rpc_handle = 0;
2793 if (RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str) == RPC_S_OK)
2795 RpcBindingFromStringBindingA(binding_str, &rpc_handle);
2796 RpcStringFreeA(&binding_str);
2798 return rpc_handle;
2801 DECLSPEC_HIDDEN void __RPC_USER ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, handle_t rpc_handle)
2803 RpcBindingFree(&rpc_handle);