msvcrt: _Gettnames() should respect user overrides.
[wine.git] / dlls / netapi32 / netapi32.c
blob278d4528b014aa98da4ba10e722e58a40086c4eb
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
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #ifdef HAVE_SYS_WAIT_H
30 #include <sys/wait.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
36 #include "ntstatus.h"
37 #define WIN32_NO_STATUS
38 #include "windef.h"
39 #include "winbase.h"
40 #include "lm.h"
41 #include "lmaccess.h"
42 #include "lmat.h"
43 #include "lmapibuf.h"
44 #include "lmbrowsr.h"
45 #include "lmshare.h"
46 #include "lmwksta.h"
47 #include "netbios.h"
48 #include "ifmib.h"
49 #include "iphlpapi.h"
50 #include "ntsecapi.h"
51 #include "winnls.h"
52 #include "dsrole.h"
53 #include "dsgetdc.h"
54 #include "davclnt.h"
55 #include "wine/debug.h"
56 #include "wine/library.h"
57 #include "wine/list.h"
58 #include "wine/unicode.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
62 static char *strdup_unixcp( const WCHAR *str )
64 char *ret;
65 int len = WideCharToMultiByte( CP_UNIXCP, 0, str, -1, NULL, 0, NULL, NULL );
66 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
67 WideCharToMultiByte( CP_UNIXCP, 0, str, -1, ret, len, NULL, NULL );
68 return ret;
71 #ifdef SONAME_LIBNETAPI
73 static void *libnetapi_handle;
74 static void *libnetapi_ctx;
76 static DWORD (*plibnetapi_init)(void **);
77 static DWORD (*plibnetapi_free)(void *);
78 static DWORD (*plibnetapi_set_debuglevel)(void *, const char *);
79 static DWORD (*plibnetapi_set_username)(void *, const char *);
80 static DWORD (*plibnetapi_set_password)(void *, const char *);
82 static NET_API_STATUS (*pNetApiBufferAllocate)(unsigned int, void **);
83 static NET_API_STATUS (*pNetApiBufferFree)(void *);
84 static NET_API_STATUS (*pNetServerGetInfo)(const char *, unsigned int, unsigned char **);
85 static NET_API_STATUS (*pNetShareAdd)(const char *, unsigned int, unsigned char *, unsigned int *);
86 static NET_API_STATUS (*pNetShareDel)(const char *, const char *, unsigned int);
87 static NET_API_STATUS (*pNetWkstaGetInfo)(const char *, unsigned int, unsigned char **);
89 static void destroy_context(void)
91 TRACE( "destroying %p\n", libnetapi_ctx );
92 plibnetapi_free( libnetapi_ctx );
93 libnetapi_ctx = NULL;
96 static BOOL init_context(void)
98 DWORD status;
100 if ((status = plibnetapi_init( &libnetapi_ctx )))
102 ERR( "Failed to initialize context %u\n", status );
103 return FALSE;
105 if (TRACE_ON( netapi32 ) && (status = plibnetapi_set_debuglevel( libnetapi_ctx, "10" )))
107 ERR( "Failed to set debug level %u\n", status );
108 destroy_context();
109 return FALSE;
111 /* perform an anonymous login by default (avoids a password prompt) */
112 if ((status = plibnetapi_set_username( libnetapi_ctx, "Guest" )))
114 ERR( "Failed to set username %u\n", status );
115 destroy_context();
116 return FALSE;
118 if ((status = plibnetapi_set_password( libnetapi_ctx, "" )))
120 ERR( "Failed to set password %u\n", status );
121 destroy_context();
122 return FALSE;
124 TRACE( "using %p\n", libnetapi_ctx );
125 return TRUE;
128 static BOOL libnetapi_init(void)
130 char buf[200];
132 if (libnetapi_handle) return TRUE;
133 if (!(libnetapi_handle = wine_dlopen( SONAME_LIBNETAPI, RTLD_NOW, buf, sizeof(buf) )))
135 WARN( "Failed to load libnetapi: %s\n", buf );
136 return FALSE;
139 #define LOAD_FUNCPTR(f) \
140 if (!(p##f = wine_dlsym( libnetapi_handle, #f, buf, sizeof(buf) ))) \
142 ERR( "Failed to load %s: %s\n", #f, buf ); \
143 goto error; \
146 LOAD_FUNCPTR(libnetapi_init)
147 LOAD_FUNCPTR(libnetapi_free)
148 LOAD_FUNCPTR(libnetapi_set_debuglevel)
149 LOAD_FUNCPTR(libnetapi_set_username)
150 LOAD_FUNCPTR(libnetapi_set_password)
152 LOAD_FUNCPTR(NetApiBufferAllocate)
153 LOAD_FUNCPTR(NetApiBufferFree)
154 LOAD_FUNCPTR(NetServerGetInfo)
155 LOAD_FUNCPTR(NetShareAdd)
156 LOAD_FUNCPTR(NetShareDel)
157 LOAD_FUNCPTR(NetWkstaGetInfo)
158 #undef LOAD_FUNCPTR
160 if (init_context()) return TRUE;
162 error:
163 wine_dlclose( libnetapi_handle, NULL, 0 );
164 libnetapi_handle = NULL;
165 return FALSE;
168 struct server_info_101
170 unsigned int sv101_platform_id;
171 const char *sv101_name;
172 unsigned int sv101_version_major;
173 unsigned int sv101_version_minor;
174 unsigned int sv101_type;
175 const char *sv101_comment;
178 static NET_API_STATUS server_info_101_from_samba( const unsigned char *buf, BYTE **bufptr )
180 SERVER_INFO_101 *ret;
181 struct server_info_101 *info = (struct server_info_101 *)buf;
182 DWORD len = 0;
183 WCHAR *ptr;
185 if (info->sv101_name) len += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_name, -1, NULL, 0 );
186 if (info->sv101_comment) len += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_comment, -1, NULL, 0 );
187 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
188 return ERROR_OUTOFMEMORY;
190 ptr = (WCHAR *)(ret + 1);
191 ret->sv101_platform_id = info->sv101_platform_id;
192 if (!info->sv101_name) ret->sv101_name = NULL;
193 else
195 ret->sv101_name = ptr;
196 ptr += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_name, -1, ptr, len );
198 ret->sv101_version_major = info->sv101_version_major;
199 ret->sv101_version_minor = info->sv101_version_minor;
200 ret->sv101_type = info->sv101_type;
201 if (!info->sv101_comment) ret->sv101_comment = NULL;
202 else
204 ret->sv101_comment = ptr;
205 MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_comment, -1, ptr, len );
207 *bufptr = (BYTE *)ret;
208 return NERR_Success;
211 static NET_API_STATUS server_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
213 switch (level)
215 case 101: return server_info_101_from_samba( buf, bufptr );
216 default:
217 FIXME( "level %u not supported\n", level );
218 return ERROR_NOT_SUPPORTED;
222 static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
224 NET_API_STATUS status;
225 char *server = NULL;
226 unsigned char *buf = NULL;
228 if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
229 status = pNetServerGetInfo( server, level, &buf );
230 HeapFree( GetProcessHeap(), 0, server );
231 if (!status)
233 status = server_info_from_samba( level, buf, bufptr );
234 pNetApiBufferFree( buf );
236 return status;
239 struct share_info_2
241 const char *shi2_netname;
242 unsigned int shi2_type;
243 const char *shi2_remark;
244 unsigned int shi2_permissions;
245 unsigned int shi2_max_uses;
246 unsigned int shi2_current_uses;
247 const char *shi2_path;
248 const char *shi2_passwd;
251 static NET_API_STATUS share_info_2_to_samba( const BYTE *buf, unsigned char **bufptr )
253 struct share_info_2 *ret;
254 SHARE_INFO_2 *info = (SHARE_INFO_2 *)buf;
255 DWORD len = 0;
256 char *ptr;
258 if (info->shi2_netname)
259 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_netname, -1, NULL, 0, NULL, NULL );
260 if (info->shi2_remark)
261 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_remark, -1, NULL, 0, NULL, NULL );
262 if (info->shi2_path)
263 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_path, -1, NULL, 0, NULL, NULL );
264 if (info->shi2_passwd)
265 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_passwd, -1, NULL, 0, NULL, NULL );
266 if (!(ret = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) + len )))
267 return ERROR_OUTOFMEMORY;
269 ptr = (char *)(ret + 1);
270 if (!info->shi2_netname) ret->shi2_netname = NULL;
271 else
273 ret->shi2_netname = ptr;
274 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_netname, -1, ptr, len, NULL, NULL );
276 ret->shi2_type = info->shi2_type;
277 if (!info->shi2_remark) ret->shi2_remark = NULL;
278 else
280 ret->shi2_remark = ptr;
281 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_remark, -1, ptr, len, NULL, NULL );
283 ret->shi2_permissions = info->shi2_permissions;
284 ret->shi2_max_uses = info->shi2_max_uses;
285 ret->shi2_current_uses = info->shi2_current_uses;
286 if (!info->shi2_path) ret->shi2_path = NULL;
287 else
289 ret->shi2_path = ptr;
290 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_path, -1, ptr, len, NULL, NULL );
292 if (!info->shi2_passwd) ret->shi2_passwd = NULL;
293 else
295 ret->shi2_passwd = ptr;
296 WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_passwd, -1, ptr, len, NULL, NULL );
298 *bufptr = (unsigned char *)ret;
299 return NERR_Success;
302 struct sid
304 unsigned char sid_rev_num;
305 unsigned char num_auths;
306 unsigned char id_auth[6];
307 unsigned int sub_auths[15];
310 enum ace_type
312 ACE_TYPE_ACCESS_ALLOWED,
313 ACE_TYPE_ACCESS_DENIED,
314 ACE_TYPE_SYSTEM_AUDIT,
315 ACE_TYPE_SYSTEM_ALARM,
316 ACE_TYPE_ALLOWED_COMPOUND,
317 ACE_TYPE_ACCESS_ALLOWED_OBJECT,
318 ACE_TYPE_ACCESS_DENIED_OBJECT,
319 ACE_TYPE_SYSTEM_AUDIT_OBJECT,
320 ACE_TYPE_SYSTEM_ALARM_OBJECT
323 #define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
324 #define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
325 #define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
326 #define SEC_ACE_FLAG_INHERIT_ONLY 0x08
327 #define SEC_ACE_FLAG_INHERITED_ACE 0x10
328 #define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
329 #define SEC_ACE_FLAG_FAILED_ACCESS 0x80
331 struct guid
333 unsigned int time_low;
334 unsigned short time_mid;
335 unsigned short time_hi_and_version;
336 unsigned char clock_seq[2];
337 unsigned char node[6];
340 union ace_object_type
342 struct guid type;
345 union ace_object_inherited_type
347 struct guid inherited_type;
350 struct ace_object
352 unsigned int flags;
353 union ace_object_type type;
354 union ace_object_inherited_type inherited_type;
357 union ace_object_ctr
359 struct ace_object object;
362 struct ace
364 enum ace_type type;
365 unsigned char flags;
366 unsigned short size;
367 unsigned int access_mask;
368 union ace_object_ctr object;
369 struct sid trustee;
372 enum acl_revision
374 ACL_REVISION_NT4 = 2,
375 ACL_REVISION_ADS = 4
378 struct acl
380 enum acl_revision revision;
381 unsigned short size;
382 unsigned int num_aces;
383 struct ace *aces;
386 enum security_descriptor_revision
388 SECURITY_DESCRIPTOR_REVISION_1 = 1
391 #define SEC_DESC_OWNER_DEFAULTED 0x0001
392 #define SEC_DESC_GROUP_DEFAULTED 0x0002
393 #define SEC_DESC_DACL_PRESENT 0x0004
394 #define SEC_DESC_DACL_DEFAULTED 0x0008
395 #define SEC_DESC_SACL_PRESENT 0x0010
396 #define SEC_DESC_SACL_DEFAULTED 0x0020
397 #define SEC_DESC_DACL_TRUSTED 0x0040
398 #define SEC_DESC_SERVER_SECURITY 0x0080
399 #define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
400 #define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
401 #define SEC_DESC_DACL_AUTO_INHERITED 0x0400
402 #define SEC_DESC_SACL_AUTO_INHERITED 0x0800
403 #define SEC_DESC_DACL_PROTECTED 0x1000
404 #define SEC_DESC_SACL_PROTECTED 0x2000
405 #define SEC_DESC_RM_CONTROL_VALID 0x4000
406 #define SEC_DESC_SELF_RELATIVE 0x8000
408 struct security_descriptor
410 enum security_descriptor_revision revision;
411 unsigned short type;
412 struct sid *owner_sid;
413 struct sid *group_sid;
414 struct acl *sacl;
415 struct acl *dacl;
418 struct share_info_502
420 const char *shi502_netname;
421 unsigned int shi502_type;
422 const char *shi502_remark;
423 unsigned int shi502_permissions;
424 unsigned int shi502_max_uses;
425 unsigned int shi502_current_uses;
426 const char *shi502_path;
427 const char *shi502_passwd;
428 unsigned int shi502_reserved;
429 struct security_descriptor *shi502_security_descriptor;
432 static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control )
434 unsigned short ret = 0;
436 if (control & SE_OWNER_DEFAULTED) ret |= SEC_DESC_OWNER_DEFAULTED;
437 if (control & SE_GROUP_DEFAULTED) ret |= SEC_DESC_GROUP_DEFAULTED;
438 if (control & SE_DACL_PRESENT) ret |= SEC_DESC_DACL_PRESENT;
439 if (control & SE_DACL_DEFAULTED) ret |= SEC_DESC_DACL_DEFAULTED;
440 if (control & SE_SACL_PRESENT) ret |= SEC_DESC_SACL_PRESENT;
441 if (control & SE_SACL_DEFAULTED) ret |= SEC_DESC_SACL_DEFAULTED;
442 if (control & SE_DACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_DACL_AUTO_INHERIT_REQ;
443 if (control & SE_SACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_SACL_AUTO_INHERIT_REQ;
444 if (control & SE_DACL_AUTO_INHERITED) ret |= SEC_DESC_DACL_AUTO_INHERITED;
445 if (control & SE_SACL_AUTO_INHERITED) ret |= SEC_DESC_SACL_AUTO_INHERITED;
446 if (control & SE_DACL_PROTECTED) ret |= SEC_DESC_DACL_PROTECTED;
447 if (control & SE_SACL_PROTECTED) ret |= SEC_DESC_SACL_PROTECTED;
448 if (control & SE_RM_CONTROL_VALID) ret |= SEC_DESC_RM_CONTROL_VALID;
449 return ret;
452 static NET_API_STATUS sid_to_samba( const SID *src, struct sid *dst )
454 unsigned int i;
456 if (src->Revision != 1)
458 ERR( "unknown revision %u\n", src->Revision );
459 return ERROR_UNKNOWN_REVISION;
461 if (src->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
463 WARN( "invalid subauthority count %u\n", src->SubAuthorityCount );
464 return ERROR_INVALID_PARAMETER;
466 dst->sid_rev_num = SECURITY_DESCRIPTOR_REVISION_1;
467 dst->num_auths = src->SubAuthorityCount;
468 for (i = 0; i < 6; i++) dst->id_auth[i] = src->IdentifierAuthority.Value[i];
469 for (i = 0; i < dst->num_auths; i++) dst->sub_auths[i] = src->SubAuthority[i];
470 return NERR_Success;
473 static enum ace_type ace_type_to_samba( BYTE type )
475 switch (type)
477 case ACCESS_ALLOWED_ACE_TYPE: return ACE_TYPE_ACCESS_ALLOWED;
478 case ACCESS_DENIED_ACE_TYPE: return ACE_TYPE_ACCESS_DENIED;
479 case SYSTEM_AUDIT_ACE_TYPE: return ACE_TYPE_SYSTEM_AUDIT;
480 case SYSTEM_ALARM_ACE_TYPE: return ACE_TYPE_SYSTEM_ALARM;
481 default:
482 ERR( "unhandled type %u\n", type );
483 return 0;
487 static unsigned char ace_flags_to_samba( BYTE flags )
489 static const BYTE known_flags =
490 OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | NO_PROPAGATE_INHERIT_ACE |
491 INHERIT_ONLY_ACE | INHERITED_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
492 unsigned char ret = 0;
494 if (flags & ~known_flags)
496 ERR( "unknown flags %x\n", flags & ~known_flags );
497 return 0;
499 if (flags & OBJECT_INHERIT_ACE) ret |= SEC_ACE_FLAG_OBJECT_INHERIT;
500 if (flags & CONTAINER_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
501 if (flags & NO_PROPAGATE_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
502 if (flags & INHERIT_ONLY_ACE) ret |= SEC_ACE_FLAG_INHERIT_ONLY;
503 if (flags & INHERITED_ACE) ret |= SEC_ACE_FLAG_INHERITED_ACE;
504 if (flags & SUCCESSFUL_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_SUCCESSFUL_ACCESS;
505 if (flags & FAILED_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_FAILED_ACCESS;
506 return ret;
509 #define GENERIC_ALL_ACCESS (1u << 28)
510 #define GENERIC_EXECUTE_ACCESS (1u << 29)
511 #define GENERIC_WRITE_ACCESS (1u << 30)
512 #define GENERIC_READ_ACCESS (1u << 31)
514 static unsigned int access_mask_to_samba( DWORD mask )
516 static const DWORD known_rights =
517 GENERIC_ALL | GENERIC_EXECUTE | GENERIC_WRITE | GENERIC_READ;
518 unsigned int ret = 0;
520 if (mask & ~known_rights)
522 ERR( "unknown rights %x\n", mask & ~known_rights );
523 return 0;
525 if (mask & GENERIC_ALL) ret |= GENERIC_ALL_ACCESS;
526 if (mask & GENERIC_EXECUTE) ret |= GENERIC_EXECUTE_ACCESS;
527 if (mask & GENERIC_WRITE) ret |= GENERIC_WRITE_ACCESS;
528 if (mask & GENERIC_READ) ret |= GENERIC_READ_ACCESS;
529 return ret;
532 static NET_API_STATUS ace_to_samba( const ACE_HEADER *src, struct ace *dst )
534 dst->type = ace_type_to_samba( src->AceType );
535 dst->flags = ace_flags_to_samba( src->AceFlags );
536 dst->size = sizeof(*dst);
537 switch (src->AceType)
539 case ACCESS_ALLOWED_ACE_TYPE:
541 ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *)src;
542 dst->access_mask = access_mask_to_samba( ace->Mask );
543 memset( &dst->object, 0, sizeof(dst->object) );
544 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
545 break;
547 case ACCESS_DENIED_ACE_TYPE:
549 ACCESS_DENIED_ACE *ace = (ACCESS_DENIED_ACE *)src;
550 dst->access_mask = access_mask_to_samba( ace->Mask );
551 memset( &dst->object, 0, sizeof(dst->object) );
552 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
553 break;
555 case SYSTEM_AUDIT_ACE_TYPE:
557 SYSTEM_AUDIT_ACE *ace = (SYSTEM_AUDIT_ACE *)src;
558 dst->access_mask = access_mask_to_samba( ace->Mask );
559 memset( &dst->object, 0, sizeof(dst->object) );
560 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
561 break;
563 case SYSTEM_ALARM_ACE_TYPE:
565 SYSTEM_ALARM_ACE *ace = (SYSTEM_ALARM_ACE *)src;
566 dst->access_mask = access_mask_to_samba( ace->Mask );
567 memset( &dst->object, 0, sizeof(dst->object) );
568 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
569 break;
571 default:
572 ERR( "unhandled type %u\n", src->AceType );
573 return ERROR_INVALID_PARAMETER;
575 return NERR_Success;
578 static NET_API_STATUS acl_to_samba( const ACL *src, struct acl *dst )
580 NET_API_STATUS status;
581 ACE_HEADER *src_ace;
582 unsigned int i;
584 switch (src->AclRevision)
586 case ACL_REVISION4:
587 dst->revision = ACL_REVISION_ADS;
588 break;
589 default:
590 ERR( "unkhandled revision %u\n", src->AclRevision );
591 return ERROR_UNKNOWN_REVISION;
593 dst->size = sizeof(*dst);
594 src_ace = (ACE_HEADER *)(src + 1);
595 dst->aces = (struct ace *)(dst + 1);
596 for (i = 0; i < src->AceCount; i++)
598 if ((status = ace_to_samba( src_ace, &dst->aces[i] ))) return status;
599 src_ace = (ACE_HEADER *)((char *)src_ace + src_ace->AceSize);
600 dst->size += dst->aces[i].size;
602 return NERR_Success;
605 #define SELF_RELATIVE_FIELD(sd,field)\
606 ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
608 static NET_API_STATUS sd_to_samba( const SECURITY_DESCRIPTOR *src, struct security_descriptor *dst )
610 NET_API_STATUS status;
611 const SID *owner, *group;
612 const ACL *dacl, *sacl;
613 unsigned int offset = sizeof(*dst);
615 if (src->Revision != SECURITY_DESCRIPTOR_REVISION1)
616 return ERROR_UNKNOWN_REVISION;
618 dst->revision = SECURITY_DESCRIPTOR_REVISION_1;
619 dst->type = sd_control_to_samba( src->Control );
621 if (src->Control & SE_SELF_RELATIVE)
623 if (!src->Owner) dst->owner_sid = NULL;
624 else
626 dst->owner_sid = (struct sid *)((char *)dst + offset);
627 owner = (const SID *)SELF_RELATIVE_FIELD( src, Owner );
628 if ((status = sid_to_samba( owner, dst->owner_sid ))) return status;
629 offset += sizeof(struct sid);
631 if (!src->Group) dst->group_sid = NULL;
632 else
634 dst->group_sid = (struct sid *)((char *)dst + offset);
635 group = (const SID *)SELF_RELATIVE_FIELD( src, Group );
636 if ((status = sid_to_samba( group, dst->group_sid ))) return status;
637 offset += sizeof(struct sid);
639 if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
640 else
642 dst->sacl = (struct acl *)((char *)dst + offset);
643 sacl = (const ACL *)SELF_RELATIVE_FIELD( src, Sacl );
644 if ((status = acl_to_samba( sacl, dst->sacl ))) return status;
645 offset += dst->sacl->size;
647 if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
648 else
650 dst->dacl = (struct acl *)((char *)dst + offset);
651 dacl = (const ACL *)SELF_RELATIVE_FIELD( src, Dacl );
652 if ((status = acl_to_samba( dacl, dst->dacl ))) return status;
655 else
657 if (!src->Owner) dst->owner_sid = NULL;
658 else
660 dst->owner_sid = (struct sid *)((char *)dst + offset);
661 if ((status = sid_to_samba( src->Owner, dst->owner_sid ))) return status;
662 offset += sizeof(struct sid);
664 if (!src->Group) dst->group_sid = NULL;
665 else
667 dst->group_sid = (struct sid *)((char *)dst + offset);
668 if ((status = sid_to_samba( src->Group, dst->group_sid ))) return status;
669 offset += sizeof(struct sid);
671 if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
672 else
674 dst->sacl = (struct acl *)((char *)dst + offset);
675 if ((status = acl_to_samba( src->Sacl, dst->sacl ))) return status;
676 offset += dst->sacl->size;
678 if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
679 else
681 dst->dacl = (struct acl *)((char *)dst + offset);
682 if ((status = acl_to_samba( src->Dacl, dst->dacl ))) return status;
685 return NERR_Success;
688 static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR *sd )
690 unsigned int ret = sizeof(struct security_descriptor);
692 if (sd->Owner) ret += sizeof(struct sid);
693 if (sd->Group) ret += sizeof(struct sid);
694 if (sd->Control & SE_SACL_PRESENT)
695 ret += sizeof(struct acl) + sd->Sacl->AceCount * sizeof(struct ace);
696 if (sd->Control & SE_DACL_PRESENT)
697 ret += sizeof(struct acl) + sd->Dacl->AceCount * sizeof(struct ace);
698 return ret;
701 static NET_API_STATUS share_info_502_to_samba( const BYTE *buf, unsigned char **bufptr )
703 NET_API_STATUS status;
704 struct share_info_502 *ret;
705 SHARE_INFO_502 *info = (SHARE_INFO_502 *)buf;
706 DWORD len = 0, size = 0;
707 char *ptr;
709 *bufptr = NULL;
710 if (info->shi502_netname)
711 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_netname, -1, NULL, 0, NULL, NULL );
712 if (info->shi502_remark)
713 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_remark, -1, NULL, 0, NULL, NULL );
714 if (info->shi502_path)
715 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_path, -1, NULL, 0, NULL, NULL );
716 if (info->shi502_passwd)
717 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_passwd, -1, NULL, 0, NULL, NULL );
718 if (info->shi502_security_descriptor)
719 size = sd_to_samba_size( info->shi502_security_descriptor );
720 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR)) + size )))
721 return ERROR_OUTOFMEMORY;
723 ptr = (char *)(ret + 1);
724 if (!info->shi502_netname) ret->shi502_netname = NULL;
725 else
727 ret->shi502_netname = ptr;
728 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_netname, -1, ptr, len, NULL, NULL );
730 ret->shi502_type = info->shi502_type;
731 if (!info->shi502_remark) ret->shi502_remark = NULL;
732 else
734 ret->shi502_remark = ptr;
735 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_remark, -1, ptr, len, NULL, NULL );
737 ret->shi502_permissions = info->shi502_permissions;
738 ret->shi502_max_uses = info->shi502_max_uses;
739 ret->shi502_current_uses = info->shi502_current_uses;
740 if (!info->shi502_path) ret->shi502_path = NULL;
741 else
743 ret->shi502_path = ptr;
744 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_path, -1, ptr, len, NULL, NULL );
746 if (!info->shi502_passwd) ret->shi502_passwd = NULL;
747 else
749 ret->shi502_passwd = ptr;
750 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_passwd, -1, ptr, len, NULL, NULL );
752 ret->shi502_reserved = info->shi502_reserved;
753 if (!info->shi502_security_descriptor) ret->shi502_security_descriptor = NULL;
754 else
756 status = sd_to_samba( info->shi502_security_descriptor, (struct security_descriptor *)ptr );
757 if (status)
759 HeapFree( GetProcessHeap(), 0, ret );
760 return status;
762 ret->shi502_security_descriptor = (struct security_descriptor *)ptr;
764 *bufptr = (unsigned char *)ret;
765 return NERR_Success;
768 static NET_API_STATUS share_info_to_samba( DWORD level, const BYTE *buf, unsigned char **bufptr )
770 switch (level)
772 case 2: return share_info_2_to_samba( buf, bufptr );
773 case 502: return share_info_502_to_samba( buf, bufptr );
774 default:
775 FIXME( "level %u not supported\n", level );
776 return ERROR_NOT_SUPPORTED;
780 static NET_API_STATUS share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
782 char *server = NULL;
783 unsigned char *info;
784 NET_API_STATUS status;
786 if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
787 status = share_info_to_samba( level, buf, &info );
788 if (!status)
790 unsigned int err;
792 status = pNetShareAdd( server, level, info, &err );
793 HeapFree( GetProcessHeap(), 0, info );
794 if (parm_err) *parm_err = err;
796 HeapFree( GetProcessHeap(), 0, server );
797 return status;
800 static NET_API_STATUS share_del( LMSTR servername, LMSTR netname, DWORD reserved )
802 char *server = NULL, *share;
803 NET_API_STATUS status;
805 if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
806 if (!(share = strdup_unixcp( netname )))
808 HeapFree( GetProcessHeap(), 0, server );
809 return ERROR_OUTOFMEMORY;
811 status = pNetShareDel( server, share, reserved );
812 HeapFree( GetProcessHeap(), 0, server );
813 HeapFree( GetProcessHeap(), 0, share );
814 return status;
817 struct wksta_info_100
819 unsigned int wki100_platform_id;
820 const char *wki100_computername;
821 const char *wki100_langroup;
822 unsigned int wki100_ver_major;
823 unsigned int wki100_ver_minor;
826 static NET_API_STATUS wksta_info_100_from_samba( const unsigned char *buf, BYTE **bufptr )
828 WKSTA_INFO_100 *ret;
829 struct wksta_info_100 *info = (struct wksta_info_100 *)buf;
830 DWORD len = 0;
831 WCHAR *ptr;
833 if (info->wki100_computername)
834 len += MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_computername, -1, NULL, 0 );
835 if (info->wki100_langroup)
836 len += MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_langroup, -1, NULL, 0 );
837 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
838 return ERROR_OUTOFMEMORY;
840 ptr = (WCHAR *)(ret + 1);
841 ret->wki100_platform_id = info->wki100_platform_id;
842 if (!info->wki100_computername) ret->wki100_computername = NULL;
843 else
845 ret->wki100_computername = ptr;
846 ptr += MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_computername, -1, ptr, len );
848 if (!info->wki100_langroup) ret->wki100_langroup = NULL;
849 else
851 ret->wki100_langroup = ptr;
852 MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_langroup, -1, ptr, len );
854 ret->wki100_ver_major = info->wki100_ver_major;
855 ret->wki100_ver_minor = info->wki100_ver_minor;
856 *bufptr = (BYTE *)ret;
857 return NERR_Success;
860 static NET_API_STATUS wksta_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
862 switch (level)
864 case 100: return wksta_info_100_from_samba( buf, bufptr );
865 default:
866 FIXME( "level %u not supported\n", level );
867 return ERROR_NOT_SUPPORTED;
871 static NET_API_STATUS wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
873 NET_API_STATUS status;
874 char *wksta = NULL;
875 unsigned char *buf = NULL;
877 if (servername && !(wksta = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
878 status = pNetWkstaGetInfo( wksta, level, &buf );
879 HeapFree( GetProcessHeap(), 0, wksta );
880 if (!status)
882 status = wksta_info_from_samba( level, buf, bufptr );
883 pNetApiBufferFree( buf );
885 return status;
888 #else
890 static BOOL libnetapi_init(void)
892 return FALSE;
895 static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
897 ERR( "\n" );
898 return ERROR_NOT_SUPPORTED;
900 static NET_API_STATUS share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
902 ERR( "\n" );
903 return ERROR_NOT_SUPPORTED;
905 static NET_API_STATUS share_del( LMSTR servername, LMSTR netname, DWORD reserved )
907 ERR( "\n" );
908 return ERROR_NOT_SUPPORTED;
910 static NET_API_STATUS wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
912 ERR( "\n" );
913 return ERROR_NOT_SUPPORTED;
916 #endif /* SONAME_LIBNETAPI */
918 /************************************************************
919 * NETAPI_IsLocalComputer
921 * Checks whether the server name indicates local machine.
923 static BOOL NETAPI_IsLocalComputer( LMCSTR name )
925 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
926 DWORD size = sizeof(buf) / sizeof(buf[0]);
927 BOOL ret;
929 if (!name || !name[0]) return TRUE;
931 ret = GetComputerNameW( buf, &size );
932 if (ret && name[0] == '\\' && name[1] == '\\') name += 2;
933 return ret && !strcmpiW( name, buf );
936 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
938 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
940 switch (fdwReason) {
941 case DLL_PROCESS_ATTACH:
942 DisableThreadLibraryCalls(hinstDLL);
943 NetBIOSInit();
944 NetBTInit();
945 break;
946 case DLL_PROCESS_DETACH:
947 if (lpvReserved) break;
948 NetBIOSShutdown();
949 break;
952 return TRUE;
955 /************************************************************
956 * NetServerEnum (NETAPI32.@)
958 NET_API_STATUS WINAPI NetServerEnum(
959 LMCSTR servername,
960 DWORD level,
961 LPBYTE* bufptr,
962 DWORD prefmaxlen,
963 LPDWORD entriesread,
964 LPDWORD totalentries,
965 DWORD servertype,
966 LMCSTR domain,
967 LPDWORD resume_handle
970 FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(servername),
971 level, bufptr, prefmaxlen, entriesread, totalentries, servertype,
972 debugstr_w(domain), resume_handle);
974 return ERROR_NO_BROWSER_SERVERS_FOUND;
977 /************************************************************
978 * NetServerEnumEx (NETAPI32.@)
980 NET_API_STATUS WINAPI NetServerEnumEx(
981 LMCSTR ServerName,
982 DWORD Level,
983 LPBYTE *Bufptr,
984 DWORD PrefMaxlen,
985 LPDWORD EntriesRead,
986 LPDWORD totalentries,
987 DWORD servertype,
988 LMCSTR domain,
989 LMCSTR FirstNameToReturn)
991 FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
992 debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
993 servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
995 return ERROR_NO_BROWSER_SERVERS_FOUND;
998 /************************************************************
999 * NetServerDiskEnum (NETAPI32.@)
1001 NET_API_STATUS WINAPI NetServerDiskEnum(
1002 LMCSTR ServerName,
1003 DWORD Level,
1004 LPBYTE *Bufptr,
1005 DWORD PrefMaxlen,
1006 LPDWORD EntriesRead,
1007 LPDWORD totalentries,
1008 LPDWORD Resume_Handle)
1010 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName),
1011 Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
1013 return ERROR_NO_BROWSER_SERVERS_FOUND;
1016 /************************************************************
1017 * NetServerGetInfo (NETAPI32.@)
1019 NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr)
1021 NET_API_STATUS ret;
1022 BOOL local = NETAPI_IsLocalComputer( servername );
1024 TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr );
1026 if (!local)
1028 if (libnetapi_init()) return server_getinfo( servername, level, bufptr );
1029 FIXME( "remote computers not supported\n" );
1030 return ERROR_INVALID_LEVEL;
1032 if (!bufptr) return ERROR_INVALID_PARAMETER;
1034 switch (level)
1036 case 100:
1037 case 101:
1039 DWORD computerNameLen, size;
1040 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1042 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1043 GetComputerNameW(computerName, &computerNameLen);
1044 computerNameLen++; /* include NULL terminator */
1046 /* Plus 1 for empty comment */
1047 size = sizeof(SERVER_INFO_101) + (computerNameLen + 1) * sizeof(WCHAR);
1048 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1049 if (ret == NERR_Success)
1051 /* INFO_100 structure is a subset of INFO_101 */
1052 PSERVER_INFO_101 info = (PSERVER_INFO_101)*bufptr;
1053 OSVERSIONINFOW verInfo;
1055 info->sv101_platform_id = PLATFORM_ID_NT;
1056 info->sv101_name = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101));
1057 memcpy(info->sv101_name, computerName,
1058 computerNameLen * sizeof(WCHAR));
1059 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1060 GetVersionExW(&verInfo);
1061 info->sv101_version_major = verInfo.dwMajorVersion;
1062 info->sv101_version_minor = verInfo.dwMinorVersion;
1063 /* Use generic type as no wine equivalent of DC / Server */
1064 info->sv101_type = SV_TYPE_NT;
1065 info->sv101_comment = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101)
1066 + computerNameLen * sizeof(WCHAR));
1067 info->sv101_comment[0] = '\0';
1069 break;
1072 default:
1073 FIXME("level %d unimplemented\n", level);
1074 ret = ERROR_INVALID_LEVEL;
1076 return ret;
1080 /************************************************************
1081 * NetStatisticsGet (NETAPI32.@)
1083 NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
1084 DWORD level, DWORD options,
1085 LPBYTE *bufptr)
1087 int res;
1088 static const WCHAR SERVICE_WORKSTATION[] = {
1089 'L', 'a', 'n', 'm', 'a', 'n',
1090 'W', 'o', 'r', 'k', 's', 't', 'a', 't', 'i', 'o', 'n', '\0'};
1091 static const WCHAR SERVICE_SERVER[] = {
1092 'L', 'a', 'n', 'm', 'a', 'n',
1093 'S', 'e', 'r', 'v', 'e', 'r', '\0'};
1094 union
1096 STAT_WORKSTATION_0 workst;
1097 STAT_SERVER_0 server;
1098 } *stat;
1099 void *dataptr;
1101 TRACE("(server %s, service %s, level %d, options %d, buffer %p): stub\n",
1102 debugstr_w(server), debugstr_w(service), level, options, bufptr);
1104 res = NetApiBufferAllocate(sizeof(*stat), &dataptr);
1105 if (res != NERR_Success) return res;
1107 res = NERR_InternalError;
1108 stat = dataptr;
1109 switch (level)
1111 case 0:
1112 if (!lstrcmpW(service, SERVICE_WORKSTATION))
1114 /* Fill the struct STAT_WORKSTATION_0 properly */
1115 memset(&stat->workst, 0, sizeof(stat->workst));
1116 res = NERR_Success;
1118 else if (!lstrcmpW(service, SERVICE_SERVER))
1120 /* Fill the struct STAT_SERVER_0 properly */
1121 memset(&stat->server, 0, sizeof(stat->server));
1122 res = NERR_Success;
1124 break;
1126 if (res != NERR_Success)
1127 NetApiBufferFree(dataptr);
1128 else
1129 *bufptr = dataptr;
1131 return res;
1134 NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize,
1135 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle)
1137 FIXME("stub (%p, %d, %p, %d, %p, %p, %p)\n", server, level, bufptr, prefmaxsize,
1138 entriesread, totalentries, resumehandle);
1139 return ERROR_NOT_SUPPORTED;
1142 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
1144 FIXME("stub (%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
1145 return NERR_Success;
1148 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
1150 FIXME("stub (%s, %d, %d)\n", debugstr_w(server), minjobid, maxjobid);
1151 return NERR_Success;
1154 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
1155 LPDWORD totalentries, LPDWORD resumehandle)
1157 FIXME("stub (%s, %p, %d, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
1158 *entriesread = 0;
1159 *totalentries = 0;
1160 return NERR_Success;
1163 NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
1165 FIXME("stub (%p, %p, %d, %p)\n", server, name, level, bufptr);
1166 return ERROR_NOT_SUPPORTED;
1170 /************************************************************
1171 * NetApiBufferAllocate (NETAPI32.@)
1173 NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
1175 TRACE("(%d, %p)\n", ByteCount, Buffer);
1177 if (Buffer == NULL) return ERROR_INVALID_PARAMETER;
1178 *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
1179 if (*Buffer)
1180 return NERR_Success;
1181 else
1182 return GetLastError();
1185 /************************************************************
1186 * NetApiBufferFree (NETAPI32.@)
1188 NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
1190 TRACE("(%p)\n", Buffer);
1191 HeapFree(GetProcessHeap(), 0, Buffer);
1192 return NERR_Success;
1195 /************************************************************
1196 * NetApiBufferReallocate (NETAPI32.@)
1198 NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
1199 LPVOID* NewBuffer)
1201 TRACE("(%p, %d, %p)\n", OldBuffer, NewByteCount, NewBuffer);
1202 if (NewByteCount)
1204 if (OldBuffer)
1205 *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
1206 else
1207 *NewBuffer = HeapAlloc(GetProcessHeap(), 0, NewByteCount);
1208 return *NewBuffer ? NERR_Success : GetLastError();
1210 else
1212 if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
1213 *NewBuffer = 0;
1214 return NERR_Success;
1218 /************************************************************
1219 * NetApiBufferSize (NETAPI32.@)
1221 NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
1223 DWORD dw;
1225 TRACE("(%p, %p)\n", Buffer, ByteCount);
1226 if (Buffer == NULL)
1227 return ERROR_INVALID_PARAMETER;
1228 dw = HeapSize(GetProcessHeap(), 0, Buffer);
1229 TRACE("size: %d\n", dw);
1230 if (dw != 0xFFFFFFFF)
1231 *ByteCount = dw;
1232 else
1233 *ByteCount = 0;
1235 return NERR_Success;
1238 /************************************************************
1239 * NetSessionEnum (NETAPI32.@)
1241 * PARAMS
1242 * servername [I] Pointer to a string with the name of the server
1243 * UncClientName [I] Pointer to a string with the name of the session
1244 * username [I] Pointer to a string with the name of the user
1245 * level [I] Data information level
1246 * bufptr [O] Buffer to the data
1247 * prefmaxlen [I] Preferred maximum length of the data
1248 * entriesread [O] Pointer to the number of entries enumerated
1249 * totalentries [O] Pointer to the possible number of entries
1250 * resume_handle [I/O] Pointer to a handle for subsequent searches
1252 * RETURNS
1253 * If successful, the function returns NERR_Success
1254 * On failure it returns:
1255 * ERROR_ACCESS_DENIED User has no access to the requested information
1256 * ERROR_INVALID_LEVEL Value of 'level' is not correct
1257 * ERROR_INVALID_PARAMETER Wrong parameter
1258 * ERROR_MORE_DATA Need a larger buffer
1259 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
1260 * NERR_ClientNameNotFound A session does not exist on a given computer
1261 * NERR_InvalidComputer Invalid computer name
1262 * NERR_UserNotFound User name could not be found.
1264 NET_API_STATUS WINAPI NetSessionEnum(LMSTR servername, LMSTR UncClientName,
1265 LMSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread,
1266 LPDWORD totalentries, LPDWORD resume_handle)
1268 FIXME("Stub (%s %s %s %d %p %d %p %p %p)\n", debugstr_w(servername),
1269 debugstr_w(UncClientName), debugstr_w(username),
1270 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1272 return NERR_Success;
1275 /************************************************************
1276 * NetShareEnum (NETAPI32.@)
1278 * PARAMS
1279 * servername [I] Pointer to a string with the name of the server
1280 * level [I] Data information level
1281 * bufptr [O] Buffer to the data
1282 * prefmaxlen [I] Preferred maximum length of the data
1283 * entriesread [O] Pointer to the number of entries enumerated
1284 * totalentries [O] Pointer to the possible number of entries
1285 * resume_handle [I/O] Pointer to a handle for subsequent searches
1287 * RETURNS
1288 * If successful, the function returns NERR_Success
1289 * On failure it returns a system error code (FIXME: find out which)
1292 NET_API_STATUS WINAPI NetShareEnum( LMSTR servername, DWORD level, LPBYTE* bufptr,
1293 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
1295 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(servername), level, bufptr,
1296 prefmaxlen, entriesread, totalentries, resume_handle);
1298 return ERROR_NOT_SUPPORTED;
1301 /************************************************************
1302 * NetShareDel (NETAPI32.@)
1304 NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserved)
1306 BOOL local = NETAPI_IsLocalComputer( servername );
1308 TRACE("%s %s %d\n", debugstr_w(servername), debugstr_w(netname), reserved);
1310 if (!local)
1312 if (libnetapi_init()) return share_del( servername, netname, reserved );
1313 FIXME( "remote computers not supported\n" );
1316 FIXME("%s %s %d\n", debugstr_w(servername), debugstr_w(netname), reserved);
1317 return NERR_Success;
1320 /************************************************************
1321 * NetShareGetInfo (NETAPI32.@)
1323 NET_API_STATUS WINAPI NetShareGetInfo(LMSTR servername, LMSTR netname,
1324 DWORD level, LPBYTE *bufptr)
1326 FIXME("Stub (%s %s %d %p)\n", debugstr_w(servername),
1327 debugstr_w(netname),level, bufptr);
1328 return NERR_NetNameNotFound;
1331 /************************************************************
1332 * NetShareAdd (NETAPI32.@)
1334 NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
1335 DWORD level, LPBYTE buf, LPDWORD parm_err)
1337 BOOL local = NETAPI_IsLocalComputer( servername );
1339 TRACE("%s %d %p %p\n", debugstr_w(servername), level, buf, parm_err);
1341 if (!local)
1343 if (libnetapi_init()) return share_add( servername, level, buf, parm_err );
1344 FIXME( "remote computers not supported\n" );
1347 FIXME("%s %d %p %p\n", debugstr_w(servername), level, buf, parm_err);
1348 return ERROR_NOT_SUPPORTED;
1351 /************************************************************
1352 * NetFileEnum (NETAPI32.@)
1354 NET_API_STATUS WINAPI NetFileEnum(
1355 LPWSTR ServerName, LPWSTR BasePath, LPWSTR UserName,
1356 DWORD Level, LPBYTE* BufPtr, DWORD PrefMaxLen,
1357 LPDWORD EntriesRead, LPDWORD TotalEntries, PDWORD_PTR ResumeHandle)
1359 FIXME("(%s, %s, %s, %u): stub\n", debugstr_w(ServerName), debugstr_w(BasePath),
1360 debugstr_w(UserName), Level);
1361 return ERROR_NOT_SUPPORTED;
1364 static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)
1366 int i;
1367 unsigned char val;
1369 if (!buffer)
1370 return;
1371 if (len < 1)
1372 return;
1373 if (!ifRow)
1375 *buffer = '\0';
1376 return;
1379 for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
1381 val = ifRow->bPhysAddr[i];
1382 if ((val >>4) >9)
1383 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
1384 else
1385 buffer[2*i] = (WCHAR)((val >>4) + '0');
1386 if ((val & 0xf ) >9)
1387 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
1388 else
1389 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
1391 buffer[2*i]=0;
1394 /* Theoretically this could be too short, except that MS defines
1395 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
1396 * represent a count of WCHARs, so even with an extraordinarily long header
1397 * this will be plenty
1399 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
1400 #define MAX_TRANSPORT_ADDR 13
1402 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
1403 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
1405 static void wprint_name(WCHAR *buffer, int len, ULONG transport,
1406 PMIB_IFROW ifRow)
1408 WCHAR *ptr1, *ptr2;
1409 const char *name;
1411 if (!buffer)
1412 return;
1413 if (!ifRow)
1415 *buffer = '\0';
1416 return;
1419 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
1420 name = NBT_TRANSPORT_NAME_HEADER;
1421 else
1422 name = UNKNOWN_TRANSPORT_NAME_HEADER;
1424 for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
1425 *ptr1 = *name;
1426 for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
1427 *ptr1 = *ptr2;
1428 *ptr1 = '\0';
1431 /***********************************************************************
1432 * NetWkstaTransportEnum (NETAPI32.@)
1435 struct WkstaTransportEnumData
1437 UCHAR n_adapt;
1438 UCHAR n_read;
1439 DWORD prefmaxlen;
1440 LPBYTE *pbuf;
1441 NET_API_STATUS ret;
1444 /**********************************************************************/
1446 static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
1447 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
1449 BOOL ret;
1450 struct WkstaTransportEnumData *enumData = closure;
1452 if (enumData && enumData->pbuf)
1454 if (lanaIndex == 0)
1456 DWORD toAllocate;
1458 enumData->n_adapt = totalLANAs;
1459 enumData->n_read = 0;
1461 toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
1462 + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
1463 MAX_TRANSPORT_ADDR * sizeof(WCHAR));
1464 if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
1465 toAllocate = enumData->prefmaxlen;
1466 NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
1468 if (*(enumData->pbuf))
1470 UCHAR spaceFor;
1472 if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
1473 spaceFor = totalLANAs;
1474 else
1475 spaceFor = enumData->prefmaxlen /
1476 (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
1477 MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
1478 if (enumData->n_read < spaceFor)
1480 PWKSTA_TRANSPORT_INFO_0 ti;
1481 LMSTR transport_name, transport_addr;
1482 MIB_IFROW ifRow;
1484 ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
1485 enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
1486 transport_name = (LMSTR)(*(enumData->pbuf) +
1487 totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
1488 enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
1489 transport_addr = (LMSTR)(*(enumData->pbuf) +
1490 totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
1491 MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
1492 enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
1494 ifRow.dwIndex = data->ifIndex;
1495 GetIfEntry(&ifRow);
1496 ti->wkti0_quality_of_service = 0;
1497 ti->wkti0_number_of_vcs = 0;
1498 ti->wkti0_transport_name = transport_name;
1499 wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
1500 transport, &ifRow);
1501 ti->wkti0_transport_address = transport_addr;
1502 wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
1503 &ifRow);
1504 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
1505 ti->wkti0_wan_ish = TRUE;
1506 else
1507 ti->wkti0_wan_ish = FALSE;
1508 TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
1509 TRACE("transport_name at %p %s\n",
1510 ti->wkti0_transport_name,
1511 debugstr_w(ti->wkti0_transport_name));
1512 TRACE("transport_address at %p %s\n",
1513 ti->wkti0_transport_address,
1514 debugstr_w(ti->wkti0_transport_address));
1515 enumData->n_read++;
1516 enumData->ret = NERR_Success;
1517 ret = TRUE;
1519 else
1521 enumData->ret = ERROR_MORE_DATA;
1522 ret = FALSE;
1525 else
1527 enumData->ret = ERROR_OUTOFMEMORY;
1528 ret = FALSE;
1531 else
1532 ret = FALSE;
1533 return ret;
1536 /**********************************************************************/
1538 NET_API_STATUS WINAPI
1539 NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
1540 DWORD prefmaxlen, LPDWORD read_entries,
1541 PDWORD total_entries, PDWORD hresume)
1543 NET_API_STATUS ret;
1545 TRACE(":%s, 0x%08x, %p, 0x%08x, %p, %p, %p\n", debugstr_w(ServerName),
1546 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
1547 if (!NETAPI_IsLocalComputer(ServerName))
1549 FIXME(":not implemented for non-local computers\n");
1550 ret = ERROR_INVALID_LEVEL;
1552 else
1554 if (hresume && *hresume)
1556 FIXME(":resume handle not implemented\n");
1557 return ERROR_INVALID_LEVEL;
1560 switch (level)
1562 case 0: /* transport info */
1564 ULONG allTransports;
1565 struct WkstaTransportEnumData enumData;
1567 if (NetBIOSNumAdapters() == 0)
1568 return ERROR_NETWORK_UNREACHABLE;
1569 if (!read_entries)
1570 return STATUS_ACCESS_VIOLATION;
1571 if (!total_entries || !pbuf)
1572 return RPC_X_NULL_REF_POINTER;
1574 enumData.prefmaxlen = prefmaxlen;
1575 enumData.pbuf = pbuf;
1576 memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
1577 NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
1578 &enumData);
1579 *read_entries = enumData.n_read;
1580 *total_entries = enumData.n_adapt;
1581 if (hresume) *hresume= 0;
1582 ret = enumData.ret;
1583 break;
1585 default:
1586 TRACE("Invalid level %d is specified\n", level);
1587 ret = ERROR_INVALID_LEVEL;
1590 return ret;
1593 /************************************************************
1594 * NetWkstaUserGetInfo (NETAPI32.@)
1596 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
1597 PBYTE* bufptr)
1599 NET_API_STATUS nastatus;
1601 TRACE("(%s, %d, %p)\n", debugstr_w(reserved), level, bufptr);
1602 switch (level)
1604 case 0:
1606 PWKSTA_USER_INFO_0 ui;
1607 DWORD dwSize = UNLEN + 1;
1609 /* set up buffer */
1610 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
1611 (LPVOID *) bufptr);
1612 if (nastatus != NERR_Success)
1613 return ERROR_NOT_ENOUGH_MEMORY;
1615 ui = (PWKSTA_USER_INFO_0) *bufptr;
1616 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
1618 /* get data */
1619 if (!GetUserNameW(ui->wkui0_username, &dwSize))
1621 NetApiBufferFree(ui);
1622 return ERROR_NOT_ENOUGH_MEMORY;
1624 else {
1625 nastatus = NetApiBufferReallocate(
1626 *bufptr, sizeof(WKSTA_USER_INFO_0) +
1627 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
1628 (LPVOID *) bufptr);
1629 if (nastatus != NERR_Success)
1631 NetApiBufferFree(ui);
1632 return nastatus;
1634 ui = (PWKSTA_USER_INFO_0) *bufptr;
1635 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
1637 break;
1640 case 1:
1642 PWKSTA_USER_INFO_1 ui;
1643 PWKSTA_USER_INFO_0 ui0;
1644 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1645 LSA_HANDLE PolicyHandle;
1646 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1647 NTSTATUS NtStatus;
1649 /* sizes of the field buffers in WCHARS */
1650 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
1652 FIXME("Level 1 processing is partially implemented\n");
1653 oth_domains_sz = 1;
1654 logon_server_sz = 1;
1656 /* get some information first to estimate size of the buffer */
1657 ui0 = NULL;
1658 nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
1659 if (nastatus != NERR_Success)
1660 return nastatus;
1661 username_sz = lstrlenW(ui0->wkui0_username) + 1;
1663 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1664 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1665 POLICY_VIEW_LOCAL_INFORMATION,
1666 &PolicyHandle);
1667 if (NtStatus != STATUS_SUCCESS)
1669 TRACE("LsaOpenPolicyFailed with NT status %x\n",
1670 LsaNtStatusToWinError(NtStatus));
1671 NetApiBufferFree(ui0);
1672 return ERROR_NOT_ENOUGH_MEMORY;
1674 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
1675 (PVOID*) &DomainInfo);
1676 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1677 LsaClose(PolicyHandle);
1679 /* set up buffer */
1680 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
1681 (username_sz + logon_domain_sz +
1682 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
1683 (LPVOID *) bufptr);
1684 if (nastatus != NERR_Success) {
1685 NetApiBufferFree(ui0);
1686 return nastatus;
1688 ui = (WKSTA_USER_INFO_1 *) *bufptr;
1689 ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
1690 ui->wkui1_logon_domain = (LMSTR) (
1691 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
1692 ui->wkui1_oth_domains = (LMSTR) (
1693 ((PBYTE) ui->wkui1_logon_domain) +
1694 logon_domain_sz * sizeof(WCHAR));
1695 ui->wkui1_logon_server = (LMSTR) (
1696 ((PBYTE) ui->wkui1_oth_domains) +
1697 oth_domains_sz * sizeof(WCHAR));
1699 /* get data */
1700 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
1701 NetApiBufferFree(ui0);
1703 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
1704 logon_domain_sz);
1705 LsaFreeMemory(DomainInfo);
1707 /* FIXME. Not implemented. Populated with empty strings */
1708 ui->wkui1_oth_domains[0] = 0;
1709 ui->wkui1_logon_server[0] = 0;
1710 break;
1712 case 1101:
1714 PWKSTA_USER_INFO_1101 ui;
1715 DWORD dwSize = 1;
1717 FIXME("Stub. Level 1101 processing is not implemented\n");
1718 /* FIXME see also wkui1_oth_domains for level 1 */
1720 /* set up buffer */
1721 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
1722 (LPVOID *) bufptr);
1723 if (nastatus != NERR_Success)
1724 return nastatus;
1725 ui = (PWKSTA_USER_INFO_1101) *bufptr;
1726 ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
1728 /* get data */
1729 ui->wkui1101_oth_domains[0] = 0;
1730 break;
1732 default:
1733 TRACE("Invalid level %d is specified\n", level);
1734 return ERROR_INVALID_LEVEL;
1736 return NERR_Success;
1739 /************************************************************
1740 * NetWkstaUserEnum (NETAPI32.@)
1742 NET_API_STATUS WINAPI
1743 NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr,
1744 DWORD prefmaxlen, LPDWORD entriesread,
1745 LPDWORD totalentries, LPDWORD resumehandle)
1747 FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername),
1748 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
1749 return ERROR_INVALID_PARAMETER;
1752 /************************************************************
1753 * NetpGetComputerName (NETAPI32.@)
1755 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
1757 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
1759 TRACE("(%p)\n", Buffer);
1760 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
1761 if (GetComputerNameW(*Buffer, &dwSize))
1763 return NetApiBufferReallocate(
1764 *Buffer, (dwSize + 1) * sizeof(WCHAR),
1765 (LPVOID *) Buffer);
1767 else
1769 NetApiBufferFree(*Buffer);
1770 return ERROR_NOT_ENOUGH_MEMORY;
1774 NET_API_STATUS WINAPI I_NetNameCompare(LPVOID p1, LPWSTR wkgrp, LPWSTR comp,
1775 LPVOID p4, LPVOID p5)
1777 FIXME("(%p %s %s %p %p): stub\n", p1, debugstr_w(wkgrp), debugstr_w(comp),
1778 p4, p5);
1779 return ERROR_INVALID_PARAMETER;
1782 NET_API_STATUS WINAPI I_NetNameValidate(LPVOID p1, LPWSTR wkgrp, LPVOID p3,
1783 LPVOID p4)
1785 FIXME("(%p %s %p %p): stub\n", p1, debugstr_w(wkgrp), p3, p4);
1786 return ERROR_INVALID_PARAMETER;
1789 NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
1790 LPBYTE* bufptr)
1792 NET_API_STATUS ret;
1793 BOOL local = NETAPI_IsLocalComputer( servername );
1795 TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr );
1797 if (!local)
1799 if (libnetapi_init()) return wksta_getinfo( servername, level, bufptr );
1800 FIXME( "remote computers not supported\n" );
1801 return ERROR_INVALID_LEVEL;
1803 if (!bufptr) return ERROR_INVALID_PARAMETER;
1805 switch (level)
1807 case 100:
1808 case 101:
1809 case 102:
1811 static const WCHAR lanroot[] = {'c',':','\\','l','a','n','m','a','n',0}; /* FIXME */
1812 DWORD computerNameLen, domainNameLen, size;
1813 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1814 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1815 LSA_HANDLE PolicyHandle;
1816 NTSTATUS NtStatus;
1818 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1819 GetComputerNameW(computerName, &computerNameLen);
1820 computerNameLen++; /* include NULL terminator */
1822 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1823 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1824 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
1825 if (NtStatus != STATUS_SUCCESS)
1826 ret = LsaNtStatusToWinError(NtStatus);
1827 else
1829 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1831 LsaQueryInformationPolicy(PolicyHandle,
1832 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
1833 domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1834 size = sizeof(WKSTA_INFO_102) + computerNameLen * sizeof(WCHAR)
1835 + domainNameLen * sizeof(WCHAR) + sizeof(lanroot);
1836 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1837 if (ret == NERR_Success)
1839 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1840 PWKSTA_INFO_102 info = (PWKSTA_INFO_102)*bufptr;
1841 OSVERSIONINFOW verInfo;
1843 info->wki102_platform_id = PLATFORM_ID_NT;
1844 info->wki102_computername = (LMSTR)(*bufptr +
1845 sizeof(WKSTA_INFO_102));
1846 memcpy(info->wki102_computername, computerName,
1847 computerNameLen * sizeof(WCHAR));
1848 info->wki102_langroup = info->wki102_computername + computerNameLen;
1849 memcpy(info->wki102_langroup, DomainInfo->DomainName.Buffer,
1850 domainNameLen * sizeof(WCHAR));
1851 info->wki102_lanroot = info->wki102_langroup + domainNameLen;
1852 memcpy(info->wki102_lanroot, lanroot, sizeof(lanroot));
1853 memset(&verInfo, 0, sizeof(verInfo));
1854 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1855 GetVersionExW(&verInfo);
1856 info->wki102_ver_major = verInfo.dwMajorVersion;
1857 info->wki102_ver_minor = verInfo.dwMinorVersion;
1858 info->wki102_logged_on_users = 1;
1860 LsaFreeMemory(DomainInfo);
1861 LsaClose(PolicyHandle);
1863 break;
1866 default:
1867 FIXME("level %d unimplemented\n", level);
1868 ret = ERROR_INVALID_LEVEL;
1870 return ret;
1873 /************************************************************
1874 * NetGetJoinInformation (NETAPI32.@)
1876 NET_API_STATUS NET_API_FUNCTION NetGetJoinInformation(
1877 LPCWSTR Server,
1878 LPWSTR *Name,
1879 PNETSETUP_JOIN_STATUS type)
1881 static const WCHAR workgroupW[] = {'W','o','r','k','g','r','o','u','p',0};
1883 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server), Name, type);
1885 if (!Name || !type)
1886 return ERROR_INVALID_PARAMETER;
1888 NetApiBufferAllocate(sizeof(workgroupW), (LPVOID *)Name);
1889 lstrcpyW(*Name, workgroupW);
1890 *type = NetSetupWorkgroupName;
1892 return NERR_Success;
1895 /************************************************************
1896 * NetUserGetGroups (NETAPI32.@)
1898 NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
1899 LPCWSTR servername,
1900 LPCWSTR username,
1901 DWORD level,
1902 LPBYTE *bufptr,
1903 DWORD prefixmaxlen,
1904 LPDWORD entriesread,
1905 LPDWORD totalentries)
1907 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
1908 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
1909 totalentries);
1911 *bufptr = NULL;
1912 *entriesread = 0;
1913 *totalentries = 0;
1915 return ERROR_INVALID_LEVEL;
1918 struct sam_user
1920 struct list entry;
1921 WCHAR user_name[LM20_UNLEN+1];
1922 WCHAR user_password[PWLEN + 1];
1923 DWORD sec_since_passwd_change;
1924 DWORD user_priv;
1925 LPWSTR home_dir;
1926 LPWSTR user_comment;
1927 DWORD user_flags;
1928 LPWSTR user_logon_script_path;
1931 static struct list user_list = LIST_INIT( user_list );
1933 /************************************************************
1934 * NETAPI_ValidateServername
1936 * Validates server name
1938 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
1940 if (ServerName)
1942 if (ServerName[0] == 0)
1943 return ERROR_BAD_NETPATH;
1944 else if (
1945 ((ServerName[0] == '\\') &&
1946 (ServerName[1] != '\\'))
1948 ((ServerName[0] == '\\') &&
1949 (ServerName[1] == '\\') &&
1950 (ServerName[2] == 0))
1952 return ERROR_INVALID_NAME;
1954 return NERR_Success;
1957 /************************************************************
1958 * NETAPI_FindUser
1960 * Looks for a user in the user database.
1961 * Returns a pointer to the entry in the user list when the user
1962 * is found, NULL otherwise.
1964 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
1966 struct sam_user *user;
1968 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
1970 if(lstrcmpW(user->user_name, UserName) == 0)
1971 return user;
1973 return NULL;
1976 static BOOL NETAPI_IsCurrentUser(LPCWSTR username)
1978 LPWSTR curr_user = NULL;
1979 DWORD dwSize;
1980 BOOL ret = FALSE;
1982 dwSize = LM20_UNLEN+1;
1983 curr_user = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
1984 if(!curr_user)
1986 ERR("Failed to allocate memory for user name.\n");
1987 goto end;
1989 if(!GetUserNameW(curr_user, &dwSize))
1991 ERR("Failed to get current user's user name.\n");
1992 goto end;
1994 if (!lstrcmpW(curr_user, username))
1996 ret = TRUE;
1999 end:
2000 HeapFree(GetProcessHeap(), 0, curr_user);
2001 return ret;
2004 /************************************************************
2005 * NetUserAdd (NETAPI32.@)
2007 NET_API_STATUS WINAPI NetUserAdd(LPCWSTR servername,
2008 DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2010 NET_API_STATUS status;
2011 struct sam_user * su = NULL;
2013 FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err);
2015 if((status = NETAPI_ValidateServername(servername)) != NERR_Success)
2016 return status;
2018 switch(level)
2020 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
2021 case 4:
2022 case 3:
2023 FIXME("Level 3 and 4 not implemented.\n");
2024 /* Fall through */
2025 case 2:
2026 FIXME("Level 2 not implemented.\n");
2027 /* Fall through */
2028 case 1:
2030 PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
2031 su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
2032 if(!su)
2034 status = NERR_InternalError;
2035 break;
2038 if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
2040 status = NERR_BadUsername;
2041 break;
2044 /*FIXME: do other checks for a valid username */
2045 lstrcpyW(su->user_name, ui->usri1_name);
2047 if(lstrlenW(ui->usri1_password) > PWLEN)
2049 /* Always return PasswordTooShort on invalid passwords. */
2050 status = NERR_PasswordTooShort;
2051 break;
2053 lstrcpyW(su->user_password, ui->usri1_password);
2055 su->sec_since_passwd_change = ui->usri1_password_age;
2056 su->user_priv = ui->usri1_priv;
2057 su->user_flags = ui->usri1_flags;
2059 /*FIXME: set the other LPWSTRs to NULL for now */
2060 su->home_dir = NULL;
2061 su->user_comment = NULL;
2062 su->user_logon_script_path = NULL;
2064 list_add_head(&user_list, &su->entry);
2065 return NERR_Success;
2067 default:
2068 TRACE("Invalid level %d specified.\n", level);
2069 status = ERROR_INVALID_LEVEL;
2070 break;
2073 HeapFree(GetProcessHeap(), 0, su);
2075 return status;
2078 /************************************************************
2079 * NetUserDel (NETAPI32.@)
2081 NET_API_STATUS WINAPI NetUserDel(LPCWSTR servername, LPCWSTR username)
2083 NET_API_STATUS status;
2084 struct sam_user *user;
2086 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
2088 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
2089 return status;
2091 if ((user = NETAPI_FindUser(username)) == NULL)
2092 return NERR_UserNotFound;
2094 list_remove(&user->entry);
2096 HeapFree(GetProcessHeap(), 0, user->home_dir);
2097 HeapFree(GetProcessHeap(), 0, user->user_comment);
2098 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
2099 HeapFree(GetProcessHeap(), 0, user);
2101 return NERR_Success;
2104 /************************************************************
2105 * NetUserGetInfo (NETAPI32.@)
2107 NET_API_STATUS WINAPI
2108 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
2109 LPBYTE* bufptr)
2111 NET_API_STATUS status;
2112 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername), debugstr_w(username),
2113 level, bufptr);
2114 status = NETAPI_ValidateServername(servername);
2115 if (status != NERR_Success)
2116 return status;
2118 if(!NETAPI_IsLocalComputer(servername))
2120 FIXME("Only implemented for local computer, but remote server"
2121 "%s was requested.\n", debugstr_w(servername));
2122 return NERR_InvalidComputer;
2125 if(!NETAPI_FindUser(username) && !NETAPI_IsCurrentUser(username))
2127 TRACE("User %s is unknown.\n", debugstr_w(username));
2128 return NERR_UserNotFound;
2131 switch (level)
2133 case 0:
2135 PUSER_INFO_0 ui;
2136 int name_sz;
2138 name_sz = lstrlenW(username) + 1;
2140 /* set up buffer */
2141 NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
2142 (LPVOID *) bufptr);
2144 ui = (PUSER_INFO_0) *bufptr;
2145 ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
2147 /* get data */
2148 lstrcpyW(ui->usri0_name, username);
2149 break;
2152 case 10:
2154 PUSER_INFO_10 ui;
2155 PUSER_INFO_0 ui0;
2156 /* sizes of the field buffers in WCHARS */
2157 int name_sz, comment_sz, usr_comment_sz, full_name_sz;
2159 comment_sz = 1;
2160 usr_comment_sz = 1;
2161 full_name_sz = 1;
2163 /* get data */
2164 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
2165 if (status != NERR_Success)
2167 NetApiBufferFree(ui0);
2168 return status;
2170 name_sz = lstrlenW(ui0->usri0_name) + 1;
2172 /* set up buffer */
2173 NetApiBufferAllocate(sizeof(USER_INFO_10) +
2174 (name_sz + comment_sz + usr_comment_sz +
2175 full_name_sz) * sizeof(WCHAR),
2176 (LPVOID *) bufptr);
2177 ui = (PUSER_INFO_10) *bufptr;
2178 ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
2179 ui->usri10_comment = (LPWSTR) (
2180 ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
2181 ui->usri10_usr_comment = (LPWSTR) (
2182 ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
2183 ui->usri10_full_name = (LPWSTR) (
2184 ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
2186 /* set data */
2187 lstrcpyW(ui->usri10_name, ui0->usri0_name);
2188 NetApiBufferFree(ui0);
2189 ui->usri10_comment[0] = 0;
2190 ui->usri10_usr_comment[0] = 0;
2191 ui->usri10_full_name[0] = 0;
2192 break;
2195 case 1:
2197 static const WCHAR homedirW[] = {'H','O','M','E',0};
2198 PUSER_INFO_1 ui;
2199 PUSER_INFO_0 ui0;
2200 /* sizes of the field buffers in WCHARS */
2201 int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
2203 password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
2204 comment_sz = 1;
2205 script_path_sz = 1;
2207 /* get data */
2208 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
2209 if (status != NERR_Success)
2211 NetApiBufferFree(ui0);
2212 return status;
2214 name_sz = lstrlenW(ui0->usri0_name) + 1;
2215 home_dir_sz = GetEnvironmentVariableW(homedirW, NULL,0);
2216 /* set up buffer */
2217 NetApiBufferAllocate(sizeof(USER_INFO_1) +
2218 (name_sz + password_sz + home_dir_sz +
2219 comment_sz + script_path_sz) * sizeof(WCHAR),
2220 (LPVOID *) bufptr);
2222 ui = (PUSER_INFO_1) *bufptr;
2223 ui->usri1_name = (LPWSTR) (ui + 1);
2224 ui->usri1_password = ui->usri1_name + name_sz;
2225 ui->usri1_home_dir = ui->usri1_password + password_sz;
2226 ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
2227 ui->usri1_script_path = ui->usri1_comment + comment_sz;
2228 /* set data */
2229 lstrcpyW(ui->usri1_name, ui0->usri0_name);
2230 NetApiBufferFree(ui0);
2231 ui->usri1_password[0] = 0;
2232 ui->usri1_password_age = 0;
2233 ui->usri1_priv = 0;
2234 GetEnvironmentVariableW(homedirW, ui->usri1_home_dir,home_dir_sz);
2235 ui->usri1_comment[0] = 0;
2236 ui->usri1_flags = 0;
2237 ui->usri1_script_path[0] = 0;
2238 break;
2240 case 2:
2241 case 3:
2242 case 4:
2243 case 11:
2244 case 20:
2245 case 23:
2246 case 1003:
2247 case 1005:
2248 case 1006:
2249 case 1007:
2250 case 1008:
2251 case 1009:
2252 case 1010:
2253 case 1011:
2254 case 1012:
2255 case 1013:
2256 case 1014:
2257 case 1017:
2258 case 1018:
2259 case 1020:
2260 case 1023:
2261 case 1024:
2262 case 1025:
2263 case 1051:
2264 case 1052:
2265 case 1053:
2267 FIXME("Level %d is not implemented\n", level);
2268 return NERR_InternalError;
2270 default:
2271 TRACE("Invalid level %d is specified\n", level);
2272 return ERROR_INVALID_LEVEL;
2274 return NERR_Success;
2277 /************************************************************
2278 * NetUserGetLocalGroups (NETAPI32.@)
2280 NET_API_STATUS WINAPI
2281 NetUserGetLocalGroups(LPCWSTR servername, LPCWSTR username, DWORD level,
2282 DWORD flags, LPBYTE* bufptr, DWORD prefmaxlen,
2283 LPDWORD entriesread, LPDWORD totalentries)
2285 NET_API_STATUS status;
2286 const WCHAR admins[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0};
2287 LPWSTR currentuser;
2288 LOCALGROUP_USERS_INFO_0* info;
2289 DWORD size;
2291 FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
2292 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
2293 prefmaxlen, entriesread, totalentries);
2295 status = NETAPI_ValidateServername(servername);
2296 if (status != NERR_Success)
2297 return status;
2299 size = UNLEN + 1;
2300 NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)&currentuser);
2301 if (!GetUserNameW(currentuser, &size)) {
2302 NetApiBufferFree(currentuser);
2303 return ERROR_NOT_ENOUGH_MEMORY;
2306 if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
2308 NetApiBufferFree(currentuser);
2309 return NERR_UserNotFound;
2312 NetApiBufferFree(currentuser);
2313 *totalentries = 1;
2314 size = sizeof(*info) + sizeof(admins);
2316 if(prefmaxlen < size)
2317 status = ERROR_MORE_DATA;
2318 else
2319 status = NetApiBufferAllocate(size, (LPVOID*)&info);
2321 if(status != NERR_Success)
2323 *bufptr = NULL;
2324 *entriesread = 0;
2325 return status;
2328 info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
2329 lstrcpyW(info->lgrui0_name, admins);
2331 *bufptr = (LPBYTE)info;
2332 *entriesread = 1;
2334 return NERR_Success;
2337 /************************************************************
2338 * NetUserEnum (NETAPI32.@)
2340 NET_API_STATUS WINAPI
2341 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
2342 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
2343 LPDWORD resume_handle)
2345 NET_API_STATUS status;
2346 WCHAR user[UNLEN + 1];
2347 DWORD size, len = sizeof(user)/sizeof(user[0]);
2349 TRACE("(%s, %u, 0x%x, %p, %u, %p, %p, %p)\n", debugstr_w(servername), level,
2350 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2352 status = NETAPI_ValidateServername(servername);
2353 if (status != NERR_Success)
2354 return status;
2356 if (!NETAPI_IsLocalComputer(servername))
2358 FIXME("Only implemented for local computer, but remote server"
2359 "%s was requested.\n", debugstr_w(servername));
2360 return NERR_InvalidComputer;
2363 if (!GetUserNameW(user, &len)) return GetLastError();
2365 switch (level)
2367 case 0:
2369 USER_INFO_0 *info;
2371 size = sizeof(*info) + (strlenW(user) + 1) * sizeof(WCHAR);
2373 if (prefmaxlen < size)
2374 status = ERROR_MORE_DATA;
2375 else
2376 status = NetApiBufferAllocate(size, (void **)&info);
2378 if (status != NERR_Success)
2379 return status;
2381 info->usri0_name = (WCHAR *)((char *)info + sizeof(*info));
2382 strcpyW(info->usri0_name, user);
2384 *bufptr = (BYTE *)info;
2385 *entriesread = *totalentries = 1;
2386 break;
2388 case 20:
2390 USER_INFO_20 *info;
2391 SID *sid;
2392 UCHAR *count;
2393 DWORD *rid;
2394 SID_NAME_USE use;
2396 size = sizeof(*info) + (strlenW(user) + 1) * sizeof(WCHAR);
2398 if (prefmaxlen < size)
2399 status = ERROR_MORE_DATA;
2400 else
2401 status = NetApiBufferAllocate(size, (void **)&info);
2403 if (status != NERR_Success)
2404 return status;
2406 size = len = 0;
2407 LookupAccountNameW(NULL, user, NULL, &size, NULL, &len, &use);
2408 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2409 return GetLastError();
2411 status = NetApiBufferAllocate(size, (void **)&sid);
2412 if (status != NERR_Success)
2413 return status;
2415 if (!LookupAccountNameW(NULL, user, sid, &size, NULL, &len, &use))
2416 return GetLastError();
2418 count = GetSidSubAuthorityCount(sid);
2419 rid = GetSidSubAuthority(sid, *count - 1);
2421 info->usri20_name = (WCHAR *)((char *)info + sizeof(*info));
2422 strcpyW(info->usri20_name, user);
2423 info->usri20_full_name = NULL;
2424 info->usri20_comment = NULL;
2425 info->usri20_flags = UF_NORMAL_ACCOUNT;
2426 info->usri20_user_id = *rid;
2428 *bufptr = (BYTE *)info;
2429 *entriesread = *totalentries = 1;
2431 NetApiBufferFree(sid);
2432 break;
2434 default:
2435 FIXME("level %u not supported\n", level);
2436 return ERROR_INVALID_LEVEL;
2438 return NERR_Success;
2441 /************************************************************
2442 * ACCESS_QueryAdminDisplayInformation
2444 * Creates a buffer with information for the Admin User
2446 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
2448 static const WCHAR sAdminUserName[] = {
2449 'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2451 /* sizes of the field buffers in WCHARS */
2452 int name_sz, comment_sz, full_name_sz;
2453 PNET_DISPLAY_USER usr;
2455 /* set up buffer */
2456 name_sz = lstrlenW(sAdminUserName) + 1;
2457 comment_sz = 1;
2458 full_name_sz = 1;
2460 *pdwSize = sizeof(NET_DISPLAY_USER);
2461 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
2462 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
2464 usr = *buf;
2465 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
2466 usr->usri1_comment = (LPWSTR) (
2467 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
2468 usr->usri1_full_name = (LPWSTR) (
2469 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
2471 /* set data */
2472 lstrcpyW(usr->usri1_name, sAdminUserName);
2473 usr->usri1_comment[0] = 0;
2474 usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
2475 usr->usri1_full_name[0] = 0;
2476 usr->usri1_user_id = DOMAIN_USER_RID_ADMIN;
2477 usr->usri1_next_index = 0;
2480 /************************************************************
2481 * ACCESS_QueryGuestDisplayInformation
2483 * Creates a buffer with information for the Guest User
2485 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
2487 static const WCHAR sGuestUserName[] = {
2488 'G','u','e','s','t',0 };
2490 /* sizes of the field buffers in WCHARS */
2491 int name_sz, comment_sz, full_name_sz;
2492 PNET_DISPLAY_USER usr;
2494 /* set up buffer */
2495 name_sz = lstrlenW(sGuestUserName) + 1;
2496 comment_sz = 1;
2497 full_name_sz = 1;
2499 *pdwSize = sizeof(NET_DISPLAY_USER);
2500 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
2501 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
2503 usr = *buf;
2504 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
2505 usr->usri1_comment = (LPWSTR) (
2506 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
2507 usr->usri1_full_name = (LPWSTR) (
2508 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
2510 /* set data */
2511 lstrcpyW(usr->usri1_name, sGuestUserName);
2512 usr->usri1_comment[0] = 0;
2513 usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
2514 UF_DONT_EXPIRE_PASSWD;
2515 usr->usri1_full_name[0] = 0;
2516 usr->usri1_user_id = DOMAIN_USER_RID_GUEST;
2517 usr->usri1_next_index = 0;
2520 /************************************************************
2521 * Copies NET_DISPLAY_USER record.
2523 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER *dest, LPWSTR *dest_buf,
2524 PNET_DISPLAY_USER src)
2526 LPWSTR str = *dest_buf;
2528 src->usri1_name = str;
2529 lstrcpyW(src->usri1_name, dest->usri1_name);
2530 str = (LPWSTR) (
2531 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
2533 src->usri1_comment = str;
2534 lstrcpyW(src->usri1_comment, dest->usri1_comment);
2535 str = (LPWSTR) (
2536 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
2538 src->usri1_flags = dest->usri1_flags;
2540 src->usri1_full_name = str;
2541 lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
2542 str = (LPWSTR) (
2543 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
2545 src->usri1_user_id = dest->usri1_user_id;
2546 src->usri1_next_index = dest->usri1_next_index;
2547 *dest_buf = str;
2550 /************************************************************
2551 * NetQueryDisplayInformation (NETAPI32.@)
2553 * The buffer structure:
2554 * - array of fixed size record of the level type
2555 * - strings, referenced by the record of the level type
2557 NET_API_STATUS WINAPI
2558 NetQueryDisplayInformation(
2559 LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
2560 DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
2561 PVOID *SortedBuffer)
2563 TRACE("(%s, %d, %d, %d, %d, %p, %p)\n", debugstr_w(ServerName),
2564 Level, Index, EntriesRequested, PreferredMaximumLength,
2565 ReturnedEntryCount, SortedBuffer);
2567 if(!NETAPI_IsLocalComputer(ServerName))
2569 FIXME("Only implemented on local computer, but requested for "
2570 "remote server %s\n", debugstr_w(ServerName));
2571 return ERROR_ACCESS_DENIED;
2574 switch (Level)
2576 case 1:
2578 /* current record */
2579 PNET_DISPLAY_USER inf;
2580 /* current available strings buffer */
2581 LPWSTR str;
2582 PNET_DISPLAY_USER admin, guest;
2583 DWORD admin_size, guest_size;
2584 LPWSTR name = NULL;
2585 DWORD dwSize;
2587 /* sizes of the field buffers in WCHARS */
2588 int name_sz, comment_sz, full_name_sz;
2590 /* number of the records, returned in SortedBuffer
2591 3 - for current user, Administrator and Guest users
2593 int records = 3;
2595 FIXME("Level %d partially implemented\n", Level);
2596 *ReturnedEntryCount = records;
2597 comment_sz = 1;
2598 full_name_sz = 1;
2600 /* get data */
2601 dwSize = UNLEN + 1;
2602 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &name);
2603 if (!GetUserNameW(name, &dwSize))
2605 NetApiBufferFree(name);
2606 return ERROR_ACCESS_DENIED;
2608 name_sz = dwSize;
2609 ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
2610 ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
2612 /* set up buffer */
2613 dwSize = sizeof(NET_DISPLAY_USER) * records;
2614 dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
2616 NetApiBufferAllocate(dwSize +
2617 admin_size - sizeof(NET_DISPLAY_USER) +
2618 guest_size - sizeof(NET_DISPLAY_USER),
2619 SortedBuffer);
2620 inf = *SortedBuffer;
2621 str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
2622 inf->usri1_name = str;
2623 str = (LPWSTR) (
2624 ((PBYTE) str) + name_sz * sizeof(WCHAR));
2625 inf->usri1_comment = str;
2626 str = (LPWSTR) (
2627 ((PBYTE) str) + comment_sz * sizeof(WCHAR));
2628 inf->usri1_full_name = str;
2629 str = (LPWSTR) (
2630 ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
2632 /* set data */
2633 lstrcpyW(inf->usri1_name, name);
2634 NetApiBufferFree(name);
2635 inf->usri1_comment[0] = 0;
2636 inf->usri1_flags =
2637 UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
2638 inf->usri1_full_name[0] = 0;
2639 inf->usri1_user_id = 0;
2640 inf->usri1_next_index = 0;
2642 inf++;
2643 ACCESS_CopyDisplayUser(admin, &str, inf);
2644 NetApiBufferFree(admin);
2646 inf++;
2647 ACCESS_CopyDisplayUser(guest, &str, inf);
2648 NetApiBufferFree(guest);
2649 break;
2652 case 2:
2653 case 3:
2655 FIXME("Level %d is not implemented\n", Level);
2656 break;
2659 default:
2660 TRACE("Invalid level %d is specified\n", Level);
2661 return ERROR_INVALID_LEVEL;
2663 return NERR_Success;
2666 /************************************************************
2667 * NetGetDCName (NETAPI32.@)
2669 * Return the name of the primary domain controller (PDC)
2672 NET_API_STATUS WINAPI
2673 NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
2675 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
2676 debugstr_w(domainname), bufptr);
2677 return NERR_DCNotFound; /* say we can't find a domain controller */
2680 /************************************************************
2681 * NetGetAnyDCName (NETAPI32.@)
2683 * Return the name of any domain controller (DC) for a
2684 * domain that is directly trusted by the specified server
2687 NET_API_STATUS WINAPI NetGetAnyDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
2689 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
2690 debugstr_w(domainname), bufptr);
2691 return ERROR_NO_SUCH_DOMAIN;
2694 /************************************************************
2695 * NetGroupAddUser (NETAPI32.@)
2697 NET_API_STATUS WINAPI
2698 NetGroupAddUser(LPCWSTR servername, LPCWSTR groupname, LPCWSTR username)
2700 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername),
2701 debugstr_w(groupname), debugstr_w(username));
2702 return NERR_Success;
2705 /************************************************************
2706 * NetGroupEnum (NETAPI32.@)
2709 NET_API_STATUS WINAPI
2710 NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen,
2711 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
2713 FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername),
2714 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2715 return ERROR_ACCESS_DENIED;
2718 /************************************************************
2719 * NetGroupGetInfo (NETAPI32.@)
2722 NET_API_STATUS WINAPI NetGroupGetInfo(LPCWSTR servername, LPCWSTR groupname, DWORD level, LPBYTE *bufptr)
2724 FIXME("(%s, %s, %d, %p) stub!\n", debugstr_w(servername), debugstr_w(groupname), level, bufptr);
2725 return ERROR_ACCESS_DENIED;
2728 /******************************************************************************
2729 * NetUserModalsGet (NETAPI32.@)
2731 * Retrieves global information for all users and global groups in the security
2732 * database.
2734 * PARAMS
2735 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
2736 * on which the function is to execute.
2737 * level [I] Information level of the data.
2738 * 0 Return global passwords parameters. bufptr points to a
2739 * USER_MODALS_INFO_0 struct.
2740 * 1 Return logon server and domain controller information. bufptr
2741 * points to a USER_MODALS_INFO_1 struct.
2742 * 2 Return domain name and identifier. bufptr points to a
2743 * USER_MODALS_INFO_2 struct.
2744 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
2745 * struct.
2746 * pbuffer [I] Buffer that receives the data.
2748 * RETURNS
2749 * Success: NERR_Success.
2750 * Failure:
2751 * ERROR_ACCESS_DENIED - the user does not have access to the info.
2752 * NERR_InvalidComputer - computer name is invalid.
2754 NET_API_STATUS WINAPI NetUserModalsGet(
2755 LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
2757 TRACE("(%s %d %p)\n", debugstr_w(szServer), level, pbuffer);
2759 switch (level)
2761 case 0:
2762 /* return global passwords parameters */
2763 FIXME("level 0 not implemented!\n");
2764 *pbuffer = NULL;
2765 return NERR_InternalError;
2766 case 1:
2767 /* return logon server and domain controller info */
2768 FIXME("level 1 not implemented!\n");
2769 *pbuffer = NULL;
2770 return NERR_InternalError;
2771 case 2:
2773 /* return domain name and identifier */
2774 PUSER_MODALS_INFO_2 umi;
2775 LSA_HANDLE policyHandle;
2776 LSA_OBJECT_ATTRIBUTES objectAttributes;
2777 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo;
2778 NTSTATUS ntStatus;
2779 PSID domainIdentifier = NULL;
2780 int domainNameLen;
2782 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
2783 objectAttributes.Length = sizeof(objectAttributes);
2785 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
2786 POLICY_VIEW_LOCAL_INFORMATION,
2787 &policyHandle);
2788 if (ntStatus != STATUS_SUCCESS)
2790 WARN("LsaOpenPolicy failed with NT status %x\n",
2791 LsaNtStatusToWinError(ntStatus));
2792 return ntStatus;
2795 ntStatus = LsaQueryInformationPolicy(policyHandle,
2796 PolicyAccountDomainInformation,
2797 (PVOID *)&domainInfo);
2798 if (ntStatus != STATUS_SUCCESS)
2800 WARN("LsaQueryInformationPolicy failed with NT status %x\n",
2801 LsaNtStatusToWinError(ntStatus));
2802 LsaClose(policyHandle);
2803 return ntStatus;
2806 domainIdentifier = domainInfo->DomainSid;
2807 domainNameLen = lstrlenW(domainInfo->DomainName.Buffer) + 1;
2808 LsaClose(policyHandle);
2810 ntStatus = NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2) +
2811 GetLengthSid(domainIdentifier) +
2812 domainNameLen * sizeof(WCHAR),
2813 (LPVOID *)pbuffer);
2815 if (ntStatus != NERR_Success)
2817 WARN("NetApiBufferAllocate() failed\n");
2818 LsaFreeMemory(domainInfo);
2819 return ntStatus;
2822 umi = (USER_MODALS_INFO_2 *) *pbuffer;
2823 umi->usrmod2_domain_id = *pbuffer + sizeof(USER_MODALS_INFO_2);
2824 umi->usrmod2_domain_name = (LPWSTR)(*pbuffer +
2825 sizeof(USER_MODALS_INFO_2) + GetLengthSid(domainIdentifier));
2827 lstrcpynW(umi->usrmod2_domain_name,
2828 domainInfo->DomainName.Buffer,
2829 domainNameLen);
2830 CopySid(GetLengthSid(domainIdentifier), umi->usrmod2_domain_id,
2831 domainIdentifier);
2833 LsaFreeMemory(domainInfo);
2835 break;
2837 case 3:
2838 /* return lockout information */
2839 FIXME("level 3 not implemented!\n");
2840 *pbuffer = NULL;
2841 return NERR_InternalError;
2842 default:
2843 TRACE("Invalid level %d is specified\n", level);
2844 *pbuffer = NULL;
2845 return ERROR_INVALID_LEVEL;
2848 return NERR_Success;
2851 static NET_API_STATUS change_password_smb( LPCWSTR domainname, LPCWSTR username,
2852 LPCWSTR oldpassword, LPCWSTR newpassword )
2854 #ifdef HAVE_FORK
2855 NET_API_STATUS ret = NERR_Success;
2856 static char option_silent[] = "-s";
2857 static char option_user[] = "-U";
2858 static char option_remote[] = "-r";
2859 static char smbpasswd[] = "smbpasswd";
2860 int pipe_out[2];
2861 pid_t pid, wret;
2862 int status;
2863 char *server = NULL, *user, *argv[7], *old = NULL, *new = NULL;
2865 if (domainname && !(server = strdup_unixcp( domainname ))) return ERROR_OUTOFMEMORY;
2866 if (!(user = strdup_unixcp( username )))
2868 ret = ERROR_OUTOFMEMORY;
2869 goto end;
2871 if (!(old = strdup_unixcp( oldpassword )))
2873 ret = ERROR_OUTOFMEMORY;
2874 goto end;
2876 if (!(new = strdup_unixcp( newpassword )))
2878 ret = ERROR_OUTOFMEMORY;
2879 goto end;
2881 argv[0] = smbpasswd;
2882 argv[1] = option_silent;
2883 argv[2] = option_user;
2884 argv[3] = user;
2885 if (server)
2887 argv[4] = option_remote;
2888 argv[5] = server;
2889 argv[6] = NULL;
2891 else argv[4] = NULL;
2893 if (pipe( pipe_out ) == -1)
2895 ret = NERR_InternalError;
2896 goto end;
2898 fcntl( pipe_out[0], F_SETFD, FD_CLOEXEC );
2899 fcntl( pipe_out[1], F_SETFD, FD_CLOEXEC );
2901 switch ((pid = fork()))
2903 case -1:
2904 close( pipe_out[0] );
2905 close( pipe_out[1] );
2906 ret = NERR_InternalError;
2907 goto end;
2908 case 0:
2909 dup2( pipe_out[0], 0 );
2910 close( pipe_out[0] );
2911 close( pipe_out[1] );
2912 execvp( "smbpasswd", argv );
2913 ERR( "can't execute smbpasswd, is it installed?\n" );
2914 _exit(1);
2915 default:
2916 close( pipe_out[0] );
2917 break;
2919 write( pipe_out[1], old, strlen( old ) );
2920 write( pipe_out[1], "\n", 1 );
2921 write( pipe_out[1], new, strlen( new ) );
2922 write( pipe_out[1], "\n", 1 );
2923 write( pipe_out[1], new, strlen( new ) );
2924 write( pipe_out[1], "\n", 1 );
2925 close( pipe_out[1] );
2927 do {
2928 wret = waitpid(pid, &status, 0);
2929 } while (wret < 0 && errno == EINTR);
2931 if (ret == NERR_Success && (wret < 0 || !WIFEXITED(status) || WEXITSTATUS(status)))
2932 ret = NERR_InternalError;
2934 end:
2935 HeapFree( GetProcessHeap(), 0, server );
2936 HeapFree( GetProcessHeap(), 0, user );
2937 HeapFree( GetProcessHeap(), 0, old );
2938 HeapFree( GetProcessHeap(), 0, new );
2939 return ret;
2940 #else
2941 ERR( "no fork support on this platform\n" );
2942 return NERR_InternalError;
2943 #endif
2946 /******************************************************************************
2947 * NetUserChangePassword (NETAPI32.@)
2948 * PARAMS
2949 * domainname [I] Optional. Domain on which the user resides or the logon
2950 * domain of the current user if NULL.
2951 * username [I] Optional. Username to change the password for or the name
2952 * of the current user if NULL.
2953 * oldpassword [I] The user's current password.
2954 * newpassword [I] The password that the user will be changed to using.
2956 * RETURNS
2957 * Success: NERR_Success.
2958 * Failure: NERR_* failure code or win error code.
2961 NET_API_STATUS WINAPI NetUserChangePassword(LPCWSTR domainname, LPCWSTR username,
2962 LPCWSTR oldpassword, LPCWSTR newpassword)
2964 struct sam_user *user;
2966 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2968 if (!change_password_smb( domainname, username, oldpassword, newpassword ))
2969 return NERR_Success;
2971 if(domainname)
2972 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
2974 if((user = NETAPI_FindUser(username)) == NULL)
2975 return NERR_UserNotFound;
2977 if(lstrcmpW(user->user_password, oldpassword) != 0)
2978 return ERROR_INVALID_PASSWORD;
2980 if(lstrlenW(newpassword) > PWLEN)
2981 return ERROR_PASSWORD_RESTRICTION;
2983 lstrcpyW(user->user_password, newpassword);
2985 return NERR_Success;
2988 NET_API_STATUS WINAPI NetUseAdd(LMSTR servername, DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2990 FIXME("%s %d %p %p stub\n", debugstr_w(servername), level, bufptr, parm_err);
2991 return NERR_Success;
2994 NET_API_STATUS WINAPI NetUseDel(LMSTR servername, LMSTR usename, DWORD forcecond)
2996 FIXME("%s %s %d stub\n", debugstr_w(servername), debugstr_w(usename), forcecond);
2997 return NERR_Success;
3000 /************************************************************
3001 * I_BrowserSetNetlogonState (NETAPI32.@)
3003 NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
3004 LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
3005 DWORD Role)
3007 return ERROR_NOT_SUPPORTED;
3010 /************************************************************
3011 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
3013 NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
3014 LPWSTR ServerName, PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
3015 LPDWORD EntriesRead)
3017 return ERROR_NOT_SUPPORTED;
3020 DWORD WINAPI DsGetDcNameW(LPCWSTR ComputerName, LPCWSTR AvoidDCName,
3021 GUID* DomainGuid, LPCWSTR SiteName, ULONG Flags,
3022 PDOMAIN_CONTROLLER_INFOW *DomainControllerInfo)
3024 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_w(ComputerName),
3025 debugstr_w(AvoidDCName), debugstr_guid(DomainGuid),
3026 debugstr_w(SiteName), Flags, DomainControllerInfo);
3027 return ERROR_CALL_NOT_IMPLEMENTED;
3030 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
3031 GUID* DomainGuid, LPCSTR SiteName, ULONG Flags,
3032 PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo)
3034 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_a(ComputerName),
3035 debugstr_a(AvoidDCName), debugstr_guid(DomainGuid),
3036 debugstr_a(SiteName), Flags, DomainControllerInfo);
3037 return ERROR_CALL_NOT_IMPLEMENTED;
3040 DWORD WINAPI DsGetSiteNameW(LPCWSTR ComputerName, LPWSTR *SiteName)
3042 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName), SiteName);
3043 return ERROR_CALL_NOT_IMPLEMENTED;
3046 DWORD WINAPI DsGetSiteNameA(LPCSTR ComputerName, LPSTR *SiteName)
3048 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName), SiteName);
3049 return ERROR_CALL_NOT_IMPLEMENTED;
3052 /************************************************************
3053 * DsRoleFreeMemory (NETAPI32.@)
3055 * PARAMS
3056 * Buffer [I] Pointer to the to-be-freed buffer.
3058 * RETURNS
3059 * Nothing
3061 VOID WINAPI DsRoleFreeMemory(PVOID Buffer)
3063 TRACE("(%p)\n", Buffer);
3064 HeapFree(GetProcessHeap(), 0, Buffer);
3067 /************************************************************
3068 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
3070 * PARAMS
3071 * lpServer [I] Pointer to UNICODE string with ComputerName
3072 * InfoLevel [I] Type of data to retrieve
3073 * Buffer [O] Pointer to to the requested data
3075 * RETURNS
3077 * NOTES
3078 * When lpServer is NULL, use the local computer
3080 DWORD WINAPI DsRoleGetPrimaryDomainInformation(
3081 LPCWSTR lpServer, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
3082 PBYTE* Buffer)
3084 DWORD ret;
3086 FIXME("(%p, %d, %p) stub\n", lpServer, InfoLevel, Buffer);
3088 /* Check some input parameters */
3090 if (!Buffer) return ERROR_INVALID_PARAMETER;
3091 if ((InfoLevel < DsRolePrimaryDomainInfoBasic) || (InfoLevel > DsRoleOperationState)) return ERROR_INVALID_PARAMETER;
3093 *Buffer = NULL;
3094 switch (InfoLevel)
3096 case DsRolePrimaryDomainInfoBasic:
3098 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
3099 LSA_HANDLE PolicyHandle;
3100 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
3101 NTSTATUS NtStatus;
3102 int logon_domain_sz;
3103 DWORD size;
3104 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic;
3106 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
3107 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
3108 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
3109 if (NtStatus != STATUS_SUCCESS)
3111 TRACE("LsaOpenPolicyFailed with NT status %x\n",
3112 LsaNtStatusToWinError(NtStatus));
3113 return ERROR_OUTOFMEMORY;
3115 LsaQueryInformationPolicy(PolicyHandle,
3116 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
3117 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
3118 LsaClose(PolicyHandle);
3120 size = sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC) +
3121 logon_domain_sz * sizeof(WCHAR);
3122 basic = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3123 if (basic)
3125 basic->MachineRole = DsRole_RoleStandaloneWorkstation;
3126 basic->DomainNameFlat = (LPWSTR)((LPBYTE)basic +
3127 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
3128 lstrcpyW(basic->DomainNameFlat, DomainInfo->DomainName.Buffer);
3129 ret = ERROR_SUCCESS;
3131 else
3132 ret = ERROR_OUTOFMEMORY;
3133 *Buffer = (PBYTE)basic;
3134 LsaFreeMemory(DomainInfo);
3136 break;
3137 default:
3138 ret = ERROR_CALL_NOT_IMPLEMENTED;
3140 return ret;
3143 /************************************************************
3144 * NetLocalGroupAdd (NETAPI32.@)
3146 NET_API_STATUS WINAPI NetLocalGroupAdd(
3147 LPCWSTR servername,
3148 DWORD level,
3149 LPBYTE buf,
3150 LPDWORD parm_err)
3152 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
3153 parm_err);
3154 return NERR_Success;
3157 /************************************************************
3158 * NetLocalGroupAddMember (NETAPI32.@)
3160 NET_API_STATUS WINAPI NetLocalGroupAddMember(
3161 LPCWSTR servername,
3162 LPCWSTR groupname,
3163 PSID membersid)
3165 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
3166 debugstr_w(groupname), membersid);
3167 return NERR_Success;
3170 /************************************************************
3171 * NetLocalGroupAddMembers (NETAPI32.@)
3173 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
3174 LPCWSTR servername,
3175 LPCWSTR groupname,
3176 DWORD level,
3177 LPBYTE buf,
3178 DWORD totalentries)
3180 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
3181 debugstr_w(groupname), level, buf, totalentries);
3182 return NERR_Success;
3185 /************************************************************
3186 * NetLocalGroupDel (NETAPI32.@)
3188 NET_API_STATUS WINAPI NetLocalGroupDel(
3189 LPCWSTR servername,
3190 LPCWSTR groupname)
3192 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
3193 return NERR_Success;
3196 /************************************************************
3197 * NetLocalGroupDelMember (NETAPI32.@)
3199 NET_API_STATUS WINAPI NetLocalGroupDelMember(
3200 LPCWSTR servername,
3201 LPCWSTR groupname,
3202 PSID membersid)
3204 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
3205 debugstr_w(groupname), membersid);
3206 return NERR_Success;
3209 /************************************************************
3210 * NetLocalGroupDelMembers (NETAPI32.@)
3212 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
3213 LPCWSTR servername,
3214 LPCWSTR groupname,
3215 DWORD level,
3216 LPBYTE buf,
3217 DWORD totalentries)
3219 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
3220 debugstr_w(groupname), level, buf, totalentries);
3221 return NERR_Success;
3224 /************************************************************
3225 * NetLocalGroupEnum (NETAPI32.@)
3227 NET_API_STATUS WINAPI NetLocalGroupEnum(
3228 LPCWSTR servername,
3229 DWORD level,
3230 LPBYTE* bufptr,
3231 DWORD prefmaxlen,
3232 LPDWORD entriesread,
3233 LPDWORD totalentries,
3234 PDWORD_PTR resumehandle)
3236 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
3237 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
3238 *entriesread = 0;
3239 *totalentries = 0;
3240 return NERR_Success;
3243 /************************************************************
3244 * NetLocalGroupGetInfo (NETAPI32.@)
3246 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
3247 LPCWSTR servername,
3248 LPCWSTR groupname,
3249 DWORD level,
3250 LPBYTE* bufptr)
3252 static const WCHAR commentW[]={'N','o',' ','c','o','m','m','e','n','t',0};
3253 LOCALGROUP_INFO_1* info;
3254 DWORD size;
3256 FIXME("(%s %s %d %p) semi-stub!\n", debugstr_w(servername),
3257 debugstr_w(groupname), level, bufptr);
3259 size = sizeof(*info) + sizeof(WCHAR) * (lstrlenW(groupname)+1) + sizeof(commentW);
3260 NetApiBufferAllocate(size, (LPVOID*)&info);
3262 info->lgrpi1_name = (LPWSTR)(info + 1);
3263 lstrcpyW(info->lgrpi1_name, groupname);
3265 info->lgrpi1_comment = info->lgrpi1_name + lstrlenW(groupname) + 1;
3266 lstrcpyW(info->lgrpi1_comment, commentW);
3268 *bufptr = (LPBYTE)info;
3270 return NERR_Success;
3273 /************************************************************
3274 * NetLocalGroupGetMembers (NETAPI32.@)
3276 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
3277 LPCWSTR servername,
3278 LPCWSTR localgroupname,
3279 DWORD level,
3280 LPBYTE* bufptr,
3281 DWORD prefmaxlen,
3282 LPDWORD entriesread,
3283 LPDWORD totalentries,
3284 PDWORD_PTR resumehandle)
3286 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
3287 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
3288 totalentries, resumehandle);
3290 if (level == 3)
3292 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
3293 DWORD userNameLen;
3294 DWORD len,needlen;
3295 PLOCALGROUP_MEMBERS_INFO_3 ptr;
3297 /* still a stub, current user is belonging to all groups */
3299 *totalentries = 1;
3300 *entriesread = 0;
3302 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
3303 if (!GetUserNameW(userName,&userNameLen))
3304 return ERROR_NOT_ENOUGH_MEMORY;
3306 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
3307 (userNameLen+2) * sizeof(WCHAR);
3308 if (prefmaxlen != MAX_PREFERRED_LENGTH)
3309 len = min(prefmaxlen,needlen);
3310 else
3311 len = needlen;
3313 NetApiBufferAllocate(len, (LPVOID *) bufptr);
3314 if (len < needlen)
3315 return ERROR_MORE_DATA;
3317 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
3318 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
3319 lstrcpyW(ptr->lgrmi3_domainandname,userName);
3321 *entriesread = 1;
3324 return NERR_Success;
3327 /************************************************************
3328 * NetLocalGroupSetInfo (NETAPI32.@)
3330 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
3331 LPCWSTR servername,
3332 LPCWSTR groupname,
3333 DWORD level,
3334 LPBYTE buf,
3335 LPDWORD parm_err)
3337 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
3338 debugstr_w(groupname), level, buf, parm_err);
3339 return NERR_Success;
3342 /************************************************************
3343 * NetLocalGroupSetMember (NETAPI32.@)
3345 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
3346 LPCWSTR servername,
3347 LPCWSTR groupname,
3348 DWORD level,
3349 LPBYTE buf,
3350 DWORD totalentries)
3352 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
3353 debugstr_w(groupname), level, buf, totalentries);
3354 return NERR_Success;
3357 /************************************************************
3358 * DavGetHTTPFromUNCPath (NETAPI32.@)
3360 DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buflen)
3362 static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0};
3363 static const WCHAR httpsW[] = {'h','t','t','p','s',':','/','/',0};
3364 static const WCHAR sslW[] = {'S','S','L',0};
3365 static const WCHAR fmtW[] = {':','%','u',0};
3366 const WCHAR *p = unc_path, *q, *server, *path, *scheme = httpW;
3367 UINT i, len_server, len_path = 0, len_port = 0, len, port = 0;
3368 WCHAR *end, portbuf[12];
3370 TRACE("(%s %p %p)\n", debugstr_w(unc_path), buf, buflen);
3372 if (p[0] != '\\' || p[1] != '\\' || !p[2]) return ERROR_INVALID_PARAMETER;
3373 q = p += 2;
3374 while (*q && *q != '\\' && *q != '/' && *q != '@') q++;
3375 server = p;
3376 len_server = q - p;
3377 if (*q == '@')
3379 p = ++q;
3380 while (*p && (*p != '\\' && *p != '/' && *p != '@')) p++;
3381 if (p - q == 3 && !memicmpW( q, sslW, 3 ))
3383 scheme = httpsW;
3384 q = p;
3386 else if ((port = strtolW( q, &end, 10 ))) q = end;
3387 else return ERROR_INVALID_PARAMETER;
3389 if (*q == '@')
3391 if (!(port = strtolW( ++q, &end, 10 ))) return ERROR_INVALID_PARAMETER;
3392 q = end;
3394 if (*q == '\\' || *q == '/') q++;
3395 path = q;
3396 while (*q++) len_path++;
3397 if (len_path && (path[len_path - 1] == '\\' || path[len_path - 1] == '/'))
3398 len_path--; /* remove trailing slash */
3400 sprintfW( portbuf, fmtW, port );
3401 if (scheme == httpsW)
3403 len = strlenW( httpsW );
3404 if (port && port != 443) len_port = strlenW( portbuf );
3406 else
3408 len = strlenW( httpW );
3409 if (port && port != 80) len_port = strlenW( portbuf );
3411 len += len_server;
3412 len += len_port;
3413 if (len_path) len += len_path + 1; /* leading '/' */
3414 len++; /* nul */
3416 if (*buflen < len)
3418 *buflen = len;
3419 return ERROR_INSUFFICIENT_BUFFER;
3422 memcpy( buf, scheme, strlenW(scheme) * sizeof(WCHAR) );
3423 buf += strlenW( scheme );
3424 memcpy( buf, server, len_server * sizeof(WCHAR) );
3425 buf += len_server;
3426 if (len_port)
3428 memcpy( buf, portbuf, len_port * sizeof(WCHAR) );
3429 buf += len_port;
3431 if (len_path)
3433 *buf++ = '/';
3434 for (i = 0; i < len_path; i++)
3436 if (path[i] == '\\') *buf++ = '/';
3437 else *buf++ = path[i];
3440 *buf = 0;
3441 *buflen = len;
3443 return ERROR_SUCCESS;
3446 /************************************************************
3447 * DavGetUNCFromHTTPPath (NETAPI32.@)
3449 DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen)
3451 static const WCHAR httpW[] = {'h','t','t','p'};
3452 static const WCHAR httpsW[] = {'h','t','t','p','s'};
3453 static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
3454 static const WCHAR sslW[] = {'@','S','S','L'};
3455 static const WCHAR port80W[] = {'8','0'};
3456 static const WCHAR port443W[] = {'4','4','3'};
3457 const WCHAR *p = http_path, *server, *port = NULL, *path = NULL;
3458 DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0;
3459 BOOL ssl;
3461 TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen);
3463 while (*p && *p != ':') { p++; len++; };
3464 if (len == sizeof(httpW)/sizeof(httpW[0]) && !memicmpW( http_path, httpW, len )) ssl = FALSE;
3465 else if (len == sizeof(httpsW)/sizeof(httpsW[0]) && !memicmpW( http_path, httpsW, len )) ssl = TRUE;
3466 else return ERROR_INVALID_PARAMETER;
3468 if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER;
3469 server = p += 3;
3471 while (*p && *p != ':' && *p != '/') { p++; len_server++; };
3472 if (!len_server) return ERROR_BAD_NET_NAME;
3473 if (*p == ':')
3475 port = ++p;
3476 while (*p && isdigitW(*p)) { p++; len_port++; };
3477 if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL;
3478 else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL;
3479 path = p;
3481 else if (*p == '/') path = p;
3483 while (*p)
3485 if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME;
3486 p++; len_path++;
3488 if (len_path && path[len_path - 1] == '/') len_path--;
3490 len = len_server + 2; /* \\ */
3491 if (ssl) len += 4; /* @SSL */
3492 if (port) len += len_port + 1 /* @ */;
3493 len += sizeof(davrootW)/sizeof(davrootW[0]);
3494 len += len_path + 1; /* nul */
3496 if (*buflen < len)
3498 *buflen = len;
3499 return ERROR_INSUFFICIENT_BUFFER;
3502 buf[0] = buf[1] = '\\';
3503 buf += 2;
3504 memcpy( buf, server, len_server * sizeof(WCHAR) );
3505 buf += len_server;
3506 if (ssl)
3508 memcpy( buf, sslW, sizeof(sslW) );
3509 buf += 4;
3511 if (port)
3513 *buf++ = '@';
3514 memcpy( buf, port, len_port * sizeof(WCHAR) );
3515 buf += len_port;
3517 memcpy( buf, davrootW, sizeof(davrootW) );
3518 buf += sizeof(davrootW)/sizeof(davrootW[0]);
3519 for (i = 0; i < len_path; i++)
3521 if (path[i] == '/') *buf++ = '\\';
3522 else *buf++ = path[i];
3525 *buf = 0;
3526 *buflen = len;
3528 return ERROR_SUCCESS;