shell32: Resize Run program window.
[wine.git] / dlls / netapi32 / netapi32.c
blob2e2ac84a49c56c152045c3f671f2d020a5606e6d
1 /* Copyright 2001 Mike McCormack
2 * Copyright 2002 Andriy Palamarchuk
3 * Copyright 2003 Juan Lang
4 * Copyright 2005,2006 Paul Vriens
5 * Copyright 2006 Robert Reif
6 * Copyright 2013 Hans Leidekker for CodeWeavers
7 * Copyright 2020 Dmitry Timoshkov
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #ifdef HAVE_SYS_WAIT_H
31 #include <sys/wait.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include "ntstatus.h"
38 #define WIN32_NO_STATUS
39 #include "windef.h"
40 #include "winbase.h"
41 #include "winsock2.h"
42 #include "ws2ipdef.h"
43 #include "windns.h"
44 #include "lm.h"
45 #include "lmaccess.h"
46 #include "atsvc.h"
47 #include "lmapibuf.h"
48 #include "lmbrowsr.h"
49 #include "lmshare.h"
50 #include "lmwksta.h"
51 #include "netbios.h"
52 #include "ifmib.h"
53 #include "iphlpapi.h"
54 #include "ntsecapi.h"
55 #include "winnls.h"
56 #include "dsrole.h"
57 #include "dsgetdc.h"
58 #include "davclnt.h"
59 #include "wine/debug.h"
60 #include "wine/list.h"
61 #include "wine/unicode.h"
62 #include "initguid.h"
64 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
66 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
68 static char *strdup_unixcp( const WCHAR *str )
70 char *ret;
71 int len = WideCharToMultiByte( CP_UNIXCP, 0, str, -1, NULL, 0, NULL, NULL );
72 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
73 WideCharToMultiByte( CP_UNIXCP, 0, str, -1, ret, len, NULL, NULL );
74 return ret;
77 #ifdef SONAME_LIBNETAPI
79 static void *libnetapi_handle;
80 static void *libnetapi_ctx;
82 static DWORD (*plibnetapi_init)(void **);
83 static DWORD (*plibnetapi_free)(void *);
84 static DWORD (*plibnetapi_set_debuglevel)(void *, const char *);
85 static DWORD (*plibnetapi_set_username)(void *, const char *);
86 static DWORD (*plibnetapi_set_password)(void *, const char *);
88 static NET_API_STATUS (*pNetApiBufferAllocate)(unsigned int, void **);
89 static NET_API_STATUS (*pNetApiBufferFree)(void *);
90 static NET_API_STATUS (*pNetServerGetInfo)(const char *, unsigned int, unsigned char **);
91 static NET_API_STATUS (*pNetShareAdd)(const char *, unsigned int, unsigned char *, unsigned int *);
92 static NET_API_STATUS (*pNetShareDel)(const char *, const char *, unsigned int);
93 static NET_API_STATUS (*pNetWkstaGetInfo)(const char *, unsigned int, unsigned char **);
95 static void destroy_context(void)
97 TRACE( "destroying %p\n", libnetapi_ctx );
98 plibnetapi_free( libnetapi_ctx );
99 libnetapi_ctx = NULL;
102 static BOOL init_context(void)
104 DWORD status;
106 if ((status = plibnetapi_init( &libnetapi_ctx )))
108 ERR( "Failed to initialize context %u\n", status );
109 return FALSE;
111 if (TRACE_ON( netapi32 ) && (status = plibnetapi_set_debuglevel( libnetapi_ctx, "10" )))
113 ERR( "Failed to set debug level %u\n", status );
114 destroy_context();
115 return FALSE;
117 /* perform an anonymous login by default (avoids a password prompt) */
118 if ((status = plibnetapi_set_username( libnetapi_ctx, "Guest" )))
120 ERR( "Failed to set username %u\n", status );
121 destroy_context();
122 return FALSE;
124 if ((status = plibnetapi_set_password( libnetapi_ctx, "" )))
126 ERR( "Failed to set password %u\n", status );
127 destroy_context();
128 return FALSE;
130 TRACE( "using %p\n", libnetapi_ctx );
131 return TRUE;
134 static BOOL libnetapi_init(void)
136 if (libnetapi_handle) return TRUE;
137 if (!(libnetapi_handle = dlopen( SONAME_LIBNETAPI, RTLD_NOW )))
139 WARN( "Failed to load libnetapi: %s\n", dlerror() );
140 return FALSE;
143 #define LOAD_FUNCPTR(f) \
144 if (!(p##f = dlsym( libnetapi_handle, #f ))) \
146 ERR( "Failed to load %s: %s\n", #f, dlerror() ); \
147 goto error; \
150 LOAD_FUNCPTR(libnetapi_init)
151 LOAD_FUNCPTR(libnetapi_free)
152 LOAD_FUNCPTR(libnetapi_set_debuglevel)
153 LOAD_FUNCPTR(libnetapi_set_username)
154 LOAD_FUNCPTR(libnetapi_set_password)
156 LOAD_FUNCPTR(NetApiBufferAllocate)
157 LOAD_FUNCPTR(NetApiBufferFree)
158 LOAD_FUNCPTR(NetServerGetInfo)
159 LOAD_FUNCPTR(NetShareAdd)
160 LOAD_FUNCPTR(NetShareDel)
161 LOAD_FUNCPTR(NetWkstaGetInfo)
162 #undef LOAD_FUNCPTR
164 if (init_context()) return TRUE;
166 error:
167 dlclose( libnetapi_handle );
168 libnetapi_handle = NULL;
169 return FALSE;
172 struct server_info_101
174 unsigned int sv101_platform_id;
175 const char *sv101_name;
176 unsigned int sv101_version_major;
177 unsigned int sv101_version_minor;
178 unsigned int sv101_type;
179 const char *sv101_comment;
182 static NET_API_STATUS server_info_101_from_samba( const unsigned char *buf, BYTE **bufptr )
184 SERVER_INFO_101 *ret;
185 struct server_info_101 *info = (struct server_info_101 *)buf;
186 DWORD len = 0;
187 WCHAR *ptr;
189 if (info->sv101_name) len += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_name, -1, NULL, 0 );
190 if (info->sv101_comment) len += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_comment, -1, NULL, 0 );
191 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
192 return ERROR_OUTOFMEMORY;
194 ptr = (WCHAR *)(ret + 1);
195 ret->sv101_platform_id = info->sv101_platform_id;
196 if (!info->sv101_name) ret->sv101_name = NULL;
197 else
199 ret->sv101_name = ptr;
200 ptr += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_name, -1, ptr, len );
202 ret->sv101_version_major = info->sv101_version_major;
203 ret->sv101_version_minor = info->sv101_version_minor;
204 ret->sv101_type = info->sv101_type;
205 if (!info->sv101_comment) ret->sv101_comment = NULL;
206 else
208 ret->sv101_comment = ptr;
209 MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_comment, -1, ptr, len );
211 *bufptr = (BYTE *)ret;
212 return NERR_Success;
215 static NET_API_STATUS server_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
217 switch (level)
219 case 101: return server_info_101_from_samba( buf, bufptr );
220 default:
221 FIXME( "level %u not supported\n", level );
222 return ERROR_NOT_SUPPORTED;
226 static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
228 NET_API_STATUS status;
229 char *server = NULL;
230 unsigned char *buf = NULL;
232 if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
233 status = pNetServerGetInfo( server, level, &buf );
234 HeapFree( GetProcessHeap(), 0, server );
235 if (!status)
237 status = server_info_from_samba( level, buf, bufptr );
238 pNetApiBufferFree( buf );
240 return status;
243 struct share_info_2
245 const char *shi2_netname;
246 unsigned int shi2_type;
247 const char *shi2_remark;
248 unsigned int shi2_permissions;
249 unsigned int shi2_max_uses;
250 unsigned int shi2_current_uses;
251 const char *shi2_path;
252 const char *shi2_passwd;
255 static NET_API_STATUS share_info_2_to_samba( const BYTE *buf, unsigned char **bufptr )
257 struct share_info_2 *ret;
258 SHARE_INFO_2 *info = (SHARE_INFO_2 *)buf;
259 DWORD len = 0;
260 char *ptr;
262 if (info->shi2_netname)
263 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_netname, -1, NULL, 0, NULL, NULL );
264 if (info->shi2_remark)
265 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_remark, -1, NULL, 0, NULL, NULL );
266 if (info->shi2_path)
267 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_path, -1, NULL, 0, NULL, NULL );
268 if (info->shi2_passwd)
269 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_passwd, -1, NULL, 0, NULL, NULL );
270 if (!(ret = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) + len )))
271 return ERROR_OUTOFMEMORY;
273 ptr = (char *)(ret + 1);
274 if (!info->shi2_netname) ret->shi2_netname = NULL;
275 else
277 ret->shi2_netname = ptr;
278 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_netname, -1, ptr, len, NULL, NULL );
280 ret->shi2_type = info->shi2_type;
281 if (!info->shi2_remark) ret->shi2_remark = NULL;
282 else
284 ret->shi2_remark = ptr;
285 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_remark, -1, ptr, len, NULL, NULL );
287 ret->shi2_permissions = info->shi2_permissions;
288 ret->shi2_max_uses = info->shi2_max_uses;
289 ret->shi2_current_uses = info->shi2_current_uses;
290 if (!info->shi2_path) ret->shi2_path = NULL;
291 else
293 ret->shi2_path = ptr;
294 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_path, -1, ptr, len, NULL, NULL );
296 if (!info->shi2_passwd) ret->shi2_passwd = NULL;
297 else
299 ret->shi2_passwd = ptr;
300 WideCharToMultiByte( CP_UNIXCP, 0, info->shi2_passwd, -1, ptr, len, NULL, NULL );
302 *bufptr = (unsigned char *)ret;
303 return NERR_Success;
306 struct sid
308 unsigned char sid_rev_num;
309 unsigned char num_auths;
310 unsigned char id_auth[6];
311 unsigned int sub_auths[15];
314 enum ace_type
316 ACE_TYPE_ACCESS_ALLOWED,
317 ACE_TYPE_ACCESS_DENIED,
318 ACE_TYPE_SYSTEM_AUDIT,
319 ACE_TYPE_SYSTEM_ALARM,
320 ACE_TYPE_ALLOWED_COMPOUND,
321 ACE_TYPE_ACCESS_ALLOWED_OBJECT,
322 ACE_TYPE_ACCESS_DENIED_OBJECT,
323 ACE_TYPE_SYSTEM_AUDIT_OBJECT,
324 ACE_TYPE_SYSTEM_ALARM_OBJECT
327 #define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
328 #define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
329 #define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
330 #define SEC_ACE_FLAG_INHERIT_ONLY 0x08
331 #define SEC_ACE_FLAG_INHERITED_ACE 0x10
332 #define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
333 #define SEC_ACE_FLAG_FAILED_ACCESS 0x80
335 struct guid
337 unsigned int time_low;
338 unsigned short time_mid;
339 unsigned short time_hi_and_version;
340 unsigned char clock_seq[2];
341 unsigned char node[6];
344 union ace_object_type
346 struct guid type;
349 union ace_object_inherited_type
351 struct guid inherited_type;
354 struct ace_object
356 unsigned int flags;
357 union ace_object_type type;
358 union ace_object_inherited_type inherited_type;
361 union ace_object_ctr
363 struct ace_object object;
366 struct ace
368 enum ace_type type;
369 unsigned char flags;
370 unsigned short size;
371 unsigned int access_mask;
372 union ace_object_ctr object;
373 struct sid trustee;
376 enum acl_revision
378 ACL_REVISION_NT4 = 2,
379 ACL_REVISION_ADS = 4
382 struct acl
384 enum acl_revision revision;
385 unsigned short size;
386 unsigned int num_aces;
387 struct ace *aces;
390 enum security_descriptor_revision
392 SECURITY_DESCRIPTOR_REVISION_1 = 1
395 #define SEC_DESC_OWNER_DEFAULTED 0x0001
396 #define SEC_DESC_GROUP_DEFAULTED 0x0002
397 #define SEC_DESC_DACL_PRESENT 0x0004
398 #define SEC_DESC_DACL_DEFAULTED 0x0008
399 #define SEC_DESC_SACL_PRESENT 0x0010
400 #define SEC_DESC_SACL_DEFAULTED 0x0020
401 #define SEC_DESC_DACL_TRUSTED 0x0040
402 #define SEC_DESC_SERVER_SECURITY 0x0080
403 #define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
404 #define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
405 #define SEC_DESC_DACL_AUTO_INHERITED 0x0400
406 #define SEC_DESC_SACL_AUTO_INHERITED 0x0800
407 #define SEC_DESC_DACL_PROTECTED 0x1000
408 #define SEC_DESC_SACL_PROTECTED 0x2000
409 #define SEC_DESC_RM_CONTROL_VALID 0x4000
410 #define SEC_DESC_SELF_RELATIVE 0x8000
412 struct security_descriptor
414 enum security_descriptor_revision revision;
415 unsigned short type;
416 struct sid *owner_sid;
417 struct sid *group_sid;
418 struct acl *sacl;
419 struct acl *dacl;
422 struct share_info_502
424 const char *shi502_netname;
425 unsigned int shi502_type;
426 const char *shi502_remark;
427 unsigned int shi502_permissions;
428 unsigned int shi502_max_uses;
429 unsigned int shi502_current_uses;
430 const char *shi502_path;
431 const char *shi502_passwd;
432 unsigned int shi502_reserved;
433 struct security_descriptor *shi502_security_descriptor;
436 static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control )
438 unsigned short ret = 0;
440 if (control & SE_OWNER_DEFAULTED) ret |= SEC_DESC_OWNER_DEFAULTED;
441 if (control & SE_GROUP_DEFAULTED) ret |= SEC_DESC_GROUP_DEFAULTED;
442 if (control & SE_DACL_PRESENT) ret |= SEC_DESC_DACL_PRESENT;
443 if (control & SE_DACL_DEFAULTED) ret |= SEC_DESC_DACL_DEFAULTED;
444 if (control & SE_SACL_PRESENT) ret |= SEC_DESC_SACL_PRESENT;
445 if (control & SE_SACL_DEFAULTED) ret |= SEC_DESC_SACL_DEFAULTED;
446 if (control & SE_DACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_DACL_AUTO_INHERIT_REQ;
447 if (control & SE_SACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_SACL_AUTO_INHERIT_REQ;
448 if (control & SE_DACL_AUTO_INHERITED) ret |= SEC_DESC_DACL_AUTO_INHERITED;
449 if (control & SE_SACL_AUTO_INHERITED) ret |= SEC_DESC_SACL_AUTO_INHERITED;
450 if (control & SE_DACL_PROTECTED) ret |= SEC_DESC_DACL_PROTECTED;
451 if (control & SE_SACL_PROTECTED) ret |= SEC_DESC_SACL_PROTECTED;
452 if (control & SE_RM_CONTROL_VALID) ret |= SEC_DESC_RM_CONTROL_VALID;
453 return ret;
456 static NET_API_STATUS sid_to_samba( const SID *src, struct sid *dst )
458 unsigned int i;
460 if (src->Revision != 1)
462 ERR( "unknown revision %u\n", src->Revision );
463 return ERROR_UNKNOWN_REVISION;
465 if (src->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
467 WARN( "invalid subauthority count %u\n", src->SubAuthorityCount );
468 return ERROR_INVALID_PARAMETER;
470 dst->sid_rev_num = SECURITY_DESCRIPTOR_REVISION_1;
471 dst->num_auths = src->SubAuthorityCount;
472 for (i = 0; i < 6; i++) dst->id_auth[i] = src->IdentifierAuthority.Value[i];
473 for (i = 0; i < dst->num_auths; i++) dst->sub_auths[i] = src->SubAuthority[i];
474 return NERR_Success;
477 static enum ace_type ace_type_to_samba( BYTE type )
479 switch (type)
481 case ACCESS_ALLOWED_ACE_TYPE: return ACE_TYPE_ACCESS_ALLOWED;
482 case ACCESS_DENIED_ACE_TYPE: return ACE_TYPE_ACCESS_DENIED;
483 case SYSTEM_AUDIT_ACE_TYPE: return ACE_TYPE_SYSTEM_AUDIT;
484 case SYSTEM_ALARM_ACE_TYPE: return ACE_TYPE_SYSTEM_ALARM;
485 default:
486 ERR( "unhandled type %u\n", type );
487 return 0;
491 static unsigned char ace_flags_to_samba( BYTE flags )
493 static const BYTE known_flags =
494 OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | NO_PROPAGATE_INHERIT_ACE |
495 INHERIT_ONLY_ACE | INHERITED_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
496 unsigned char ret = 0;
498 if (flags & ~known_flags)
500 ERR( "unknown flags %x\n", flags & ~known_flags );
501 return 0;
503 if (flags & OBJECT_INHERIT_ACE) ret |= SEC_ACE_FLAG_OBJECT_INHERIT;
504 if (flags & CONTAINER_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
505 if (flags & NO_PROPAGATE_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
506 if (flags & INHERIT_ONLY_ACE) ret |= SEC_ACE_FLAG_INHERIT_ONLY;
507 if (flags & INHERITED_ACE) ret |= SEC_ACE_FLAG_INHERITED_ACE;
508 if (flags & SUCCESSFUL_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_SUCCESSFUL_ACCESS;
509 if (flags & FAILED_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_FAILED_ACCESS;
510 return ret;
513 #define GENERIC_ALL_ACCESS (1u << 28)
514 #define GENERIC_EXECUTE_ACCESS (1u << 29)
515 #define GENERIC_WRITE_ACCESS (1u << 30)
516 #define GENERIC_READ_ACCESS (1u << 31)
518 static unsigned int access_mask_to_samba( DWORD mask )
520 static const DWORD known_rights =
521 GENERIC_ALL | GENERIC_EXECUTE | GENERIC_WRITE | GENERIC_READ;
522 unsigned int ret = 0;
524 if (mask & ~known_rights)
526 ERR( "unknown rights %x\n", mask & ~known_rights );
527 return 0;
529 if (mask & GENERIC_ALL) ret |= GENERIC_ALL_ACCESS;
530 if (mask & GENERIC_EXECUTE) ret |= GENERIC_EXECUTE_ACCESS;
531 if (mask & GENERIC_WRITE) ret |= GENERIC_WRITE_ACCESS;
532 if (mask & GENERIC_READ) ret |= GENERIC_READ_ACCESS;
533 return ret;
536 static NET_API_STATUS ace_to_samba( const ACE_HEADER *src, struct ace *dst )
538 dst->type = ace_type_to_samba( src->AceType );
539 dst->flags = ace_flags_to_samba( src->AceFlags );
540 dst->size = sizeof(*dst);
541 switch (src->AceType)
543 case ACCESS_ALLOWED_ACE_TYPE:
545 ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *)src;
546 dst->access_mask = access_mask_to_samba( ace->Mask );
547 memset( &dst->object, 0, sizeof(dst->object) );
548 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
549 break;
551 case ACCESS_DENIED_ACE_TYPE:
553 ACCESS_DENIED_ACE *ace = (ACCESS_DENIED_ACE *)src;
554 dst->access_mask = access_mask_to_samba( ace->Mask );
555 memset( &dst->object, 0, sizeof(dst->object) );
556 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
557 break;
559 case SYSTEM_AUDIT_ACE_TYPE:
561 SYSTEM_AUDIT_ACE *ace = (SYSTEM_AUDIT_ACE *)src;
562 dst->access_mask = access_mask_to_samba( ace->Mask );
563 memset( &dst->object, 0, sizeof(dst->object) );
564 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
565 break;
567 case SYSTEM_ALARM_ACE_TYPE:
569 SYSTEM_ALARM_ACE *ace = (SYSTEM_ALARM_ACE *)src;
570 dst->access_mask = access_mask_to_samba( ace->Mask );
571 memset( &dst->object, 0, sizeof(dst->object) );
572 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
573 break;
575 default:
576 ERR( "unhandled type %u\n", src->AceType );
577 return ERROR_INVALID_PARAMETER;
579 return NERR_Success;
582 static NET_API_STATUS acl_to_samba( const ACL *src, struct acl *dst )
584 NET_API_STATUS status;
585 ACE_HEADER *src_ace;
586 unsigned int i;
588 switch (src->AclRevision)
590 case ACL_REVISION4:
591 dst->revision = ACL_REVISION_ADS;
592 break;
593 default:
594 ERR( "unkhandled revision %u\n", src->AclRevision );
595 return ERROR_UNKNOWN_REVISION;
597 dst->size = sizeof(*dst);
598 src_ace = (ACE_HEADER *)(src + 1);
599 dst->aces = (struct ace *)(dst + 1);
600 for (i = 0; i < src->AceCount; i++)
602 if ((status = ace_to_samba( src_ace, &dst->aces[i] ))) return status;
603 src_ace = (ACE_HEADER *)((char *)src_ace + src_ace->AceSize);
604 dst->size += dst->aces[i].size;
606 return NERR_Success;
609 #define SELF_RELATIVE_FIELD(sd,field)\
610 ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
612 static NET_API_STATUS sd_to_samba( const SECURITY_DESCRIPTOR *src, struct security_descriptor *dst )
614 NET_API_STATUS status;
615 const SID *owner, *group;
616 const ACL *dacl, *sacl;
617 unsigned int offset = sizeof(*dst);
619 if (src->Revision != SECURITY_DESCRIPTOR_REVISION1)
620 return ERROR_UNKNOWN_REVISION;
622 dst->revision = SECURITY_DESCRIPTOR_REVISION_1;
623 dst->type = sd_control_to_samba( src->Control );
625 if (src->Control & SE_SELF_RELATIVE)
627 if (!src->Owner) dst->owner_sid = NULL;
628 else
630 dst->owner_sid = (struct sid *)((char *)dst + offset);
631 owner = (const SID *)SELF_RELATIVE_FIELD( src, Owner );
632 if ((status = sid_to_samba( owner, dst->owner_sid ))) return status;
633 offset += sizeof(struct sid);
635 if (!src->Group) dst->group_sid = NULL;
636 else
638 dst->group_sid = (struct sid *)((char *)dst + offset);
639 group = (const SID *)SELF_RELATIVE_FIELD( src, Group );
640 if ((status = sid_to_samba( group, dst->group_sid ))) return status;
641 offset += sizeof(struct sid);
643 if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
644 else
646 dst->sacl = (struct acl *)((char *)dst + offset);
647 sacl = (const ACL *)SELF_RELATIVE_FIELD( src, Sacl );
648 if ((status = acl_to_samba( sacl, dst->sacl ))) return status;
649 offset += dst->sacl->size;
651 if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
652 else
654 dst->dacl = (struct acl *)((char *)dst + offset);
655 dacl = (const ACL *)SELF_RELATIVE_FIELD( src, Dacl );
656 if ((status = acl_to_samba( dacl, dst->dacl ))) return status;
659 else
661 if (!src->Owner) dst->owner_sid = NULL;
662 else
664 dst->owner_sid = (struct sid *)((char *)dst + offset);
665 if ((status = sid_to_samba( src->Owner, dst->owner_sid ))) return status;
666 offset += sizeof(struct sid);
668 if (!src->Group) dst->group_sid = NULL;
669 else
671 dst->group_sid = (struct sid *)((char *)dst + offset);
672 if ((status = sid_to_samba( src->Group, dst->group_sid ))) return status;
673 offset += sizeof(struct sid);
675 if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
676 else
678 dst->sacl = (struct acl *)((char *)dst + offset);
679 if ((status = acl_to_samba( src->Sacl, dst->sacl ))) return status;
680 offset += dst->sacl->size;
682 if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
683 else
685 dst->dacl = (struct acl *)((char *)dst + offset);
686 if ((status = acl_to_samba( src->Dacl, dst->dacl ))) return status;
689 return NERR_Success;
692 static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR *sd )
694 unsigned int ret = sizeof(struct security_descriptor);
696 if (sd->Owner) ret += sizeof(struct sid);
697 if (sd->Group) ret += sizeof(struct sid);
698 if (sd->Control & SE_SACL_PRESENT)
699 ret += sizeof(struct acl) + sd->Sacl->AceCount * sizeof(struct ace);
700 if (sd->Control & SE_DACL_PRESENT)
701 ret += sizeof(struct acl) + sd->Dacl->AceCount * sizeof(struct ace);
702 return ret;
705 static NET_API_STATUS share_info_502_to_samba( const BYTE *buf, unsigned char **bufptr )
707 NET_API_STATUS status;
708 struct share_info_502 *ret;
709 SHARE_INFO_502 *info = (SHARE_INFO_502 *)buf;
710 DWORD len = 0, size = 0;
711 char *ptr;
713 *bufptr = NULL;
714 if (info->shi502_netname)
715 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_netname, -1, NULL, 0, NULL, NULL );
716 if (info->shi502_remark)
717 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_remark, -1, NULL, 0, NULL, NULL );
718 if (info->shi502_path)
719 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_path, -1, NULL, 0, NULL, NULL );
720 if (info->shi502_passwd)
721 len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_passwd, -1, NULL, 0, NULL, NULL );
722 if (info->shi502_security_descriptor)
723 size = sd_to_samba_size( info->shi502_security_descriptor );
724 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR)) + size )))
725 return ERROR_OUTOFMEMORY;
727 ptr = (char *)(ret + 1);
728 if (!info->shi502_netname) ret->shi502_netname = NULL;
729 else
731 ret->shi502_netname = ptr;
732 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_netname, -1, ptr, len, NULL, NULL );
734 ret->shi502_type = info->shi502_type;
735 if (!info->shi502_remark) ret->shi502_remark = NULL;
736 else
738 ret->shi502_remark = ptr;
739 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_remark, -1, ptr, len, NULL, NULL );
741 ret->shi502_permissions = info->shi502_permissions;
742 ret->shi502_max_uses = info->shi502_max_uses;
743 ret->shi502_current_uses = info->shi502_current_uses;
744 if (!info->shi502_path) ret->shi502_path = NULL;
745 else
747 ret->shi502_path = ptr;
748 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_path, -1, ptr, len, NULL, NULL );
750 if (!info->shi502_passwd) ret->shi502_passwd = NULL;
751 else
753 ret->shi502_passwd = ptr;
754 ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_passwd, -1, ptr, len, NULL, NULL );
756 ret->shi502_reserved = info->shi502_reserved;
757 if (!info->shi502_security_descriptor) ret->shi502_security_descriptor = NULL;
758 else
760 status = sd_to_samba( info->shi502_security_descriptor, (struct security_descriptor *)ptr );
761 if (status)
763 HeapFree( GetProcessHeap(), 0, ret );
764 return status;
766 ret->shi502_security_descriptor = (struct security_descriptor *)ptr;
768 *bufptr = (unsigned char *)ret;
769 return NERR_Success;
772 static NET_API_STATUS share_info_to_samba( DWORD level, const BYTE *buf, unsigned char **bufptr )
774 switch (level)
776 case 2: return share_info_2_to_samba( buf, bufptr );
777 case 502: return share_info_502_to_samba( buf, bufptr );
778 default:
779 FIXME( "level %u not supported\n", level );
780 return ERROR_NOT_SUPPORTED;
784 static NET_API_STATUS share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
786 char *server = NULL;
787 unsigned char *info;
788 NET_API_STATUS status;
790 if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
791 status = share_info_to_samba( level, buf, &info );
792 if (!status)
794 unsigned int err;
796 status = pNetShareAdd( server, level, info, &err );
797 HeapFree( GetProcessHeap(), 0, info );
798 if (parm_err) *parm_err = err;
800 HeapFree( GetProcessHeap(), 0, server );
801 return status;
804 static NET_API_STATUS share_del( LMSTR servername, LMSTR netname, DWORD reserved )
806 char *server = NULL, *share;
807 NET_API_STATUS status;
809 if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
810 if (!(share = strdup_unixcp( netname )))
812 HeapFree( GetProcessHeap(), 0, server );
813 return ERROR_OUTOFMEMORY;
815 status = pNetShareDel( server, share, reserved );
816 HeapFree( GetProcessHeap(), 0, server );
817 HeapFree( GetProcessHeap(), 0, share );
818 return status;
821 struct wksta_info_100
823 unsigned int wki100_platform_id;
824 const char *wki100_computername;
825 const char *wki100_langroup;
826 unsigned int wki100_ver_major;
827 unsigned int wki100_ver_minor;
830 static NET_API_STATUS wksta_info_100_from_samba( const unsigned char *buf, BYTE **bufptr )
832 WKSTA_INFO_100 *ret;
833 struct wksta_info_100 *info = (struct wksta_info_100 *)buf;
834 DWORD len = 0;
835 WCHAR *ptr;
837 if (info->wki100_computername)
838 len += MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_computername, -1, NULL, 0 );
839 if (info->wki100_langroup)
840 len += MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_langroup, -1, NULL, 0 );
841 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
842 return ERROR_OUTOFMEMORY;
844 ptr = (WCHAR *)(ret + 1);
845 ret->wki100_platform_id = info->wki100_platform_id;
846 if (!info->wki100_computername) ret->wki100_computername = NULL;
847 else
849 ret->wki100_computername = ptr;
850 ptr += MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_computername, -1, ptr, len );
852 if (!info->wki100_langroup) ret->wki100_langroup = NULL;
853 else
855 ret->wki100_langroup = ptr;
856 MultiByteToWideChar( CP_UNIXCP, 0, info->wki100_langroup, -1, ptr, len );
858 ret->wki100_ver_major = info->wki100_ver_major;
859 ret->wki100_ver_minor = info->wki100_ver_minor;
860 *bufptr = (BYTE *)ret;
861 return NERR_Success;
864 static NET_API_STATUS wksta_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
866 switch (level)
868 case 100: return wksta_info_100_from_samba( buf, bufptr );
869 default:
870 FIXME( "level %u not supported\n", level );
871 return ERROR_NOT_SUPPORTED;
875 static NET_API_STATUS wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
877 NET_API_STATUS status;
878 char *wksta = NULL;
879 unsigned char *buf = NULL;
881 if (servername && !(wksta = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
882 status = pNetWkstaGetInfo( wksta, level, &buf );
883 HeapFree( GetProcessHeap(), 0, wksta );
884 if (!status)
886 status = wksta_info_from_samba( level, buf, bufptr );
887 pNetApiBufferFree( buf );
889 return status;
892 #else
894 static BOOL libnetapi_init(void)
896 return FALSE;
899 static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
901 ERR( "\n" );
902 return ERROR_NOT_SUPPORTED;
904 static NET_API_STATUS share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
906 ERR( "\n" );
907 return ERROR_NOT_SUPPORTED;
909 static NET_API_STATUS share_del( LMSTR servername, LMSTR netname, DWORD reserved )
911 ERR( "\n" );
912 return ERROR_NOT_SUPPORTED;
914 static NET_API_STATUS wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
916 ERR( "\n" );
917 return ERROR_NOT_SUPPORTED;
920 #endif /* SONAME_LIBNETAPI */
922 /************************************************************
923 * NETAPI_IsLocalComputer
925 * Checks whether the server name indicates local machine.
927 static BOOL NETAPI_IsLocalComputer( LMCSTR name )
929 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
930 DWORD size = ARRAY_SIZE(buf);
931 BOOL ret;
933 if (!name || !name[0]) return TRUE;
935 ret = GetComputerNameW( buf, &size );
936 if (ret && name[0] == '\\' && name[1] == '\\') name += 2;
937 return ret && !strcmpiW( name, buf );
940 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
942 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
944 switch (fdwReason) {
945 case DLL_PROCESS_ATTACH:
946 DisableThreadLibraryCalls(hinstDLL);
947 NetBIOSInit();
948 NetBTInit();
949 break;
950 case DLL_PROCESS_DETACH:
951 if (lpvReserved) break;
952 NetBIOSShutdown();
953 break;
956 return TRUE;
959 /************************************************************
960 * NetServerEnum (NETAPI32.@)
962 NET_API_STATUS WINAPI NetServerEnum(
963 LMCSTR servername,
964 DWORD level,
965 LPBYTE* bufptr,
966 DWORD prefmaxlen,
967 LPDWORD entriesread,
968 LPDWORD totalentries,
969 DWORD servertype,
970 LMCSTR domain,
971 LPDWORD resume_handle
974 FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(servername),
975 level, bufptr, prefmaxlen, entriesread, totalentries, servertype,
976 debugstr_w(domain), resume_handle);
978 return ERROR_NO_BROWSER_SERVERS_FOUND;
981 /************************************************************
982 * NetServerEnumEx (NETAPI32.@)
984 NET_API_STATUS WINAPI NetServerEnumEx(
985 LMCSTR ServerName,
986 DWORD Level,
987 LPBYTE *Bufptr,
988 DWORD PrefMaxlen,
989 LPDWORD EntriesRead,
990 LPDWORD totalentries,
991 DWORD servertype,
992 LMCSTR domain,
993 LMCSTR FirstNameToReturn)
995 FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
996 debugstr_w(ServerName), Level, Bufptr, PrefMaxlen, EntriesRead, totalentries,
997 servertype, debugstr_w(domain), debugstr_w(FirstNameToReturn));
999 return ERROR_NO_BROWSER_SERVERS_FOUND;
1002 /************************************************************
1003 * NetServerDiskEnum (NETAPI32.@)
1005 NET_API_STATUS WINAPI NetServerDiskEnum(
1006 LMCSTR ServerName,
1007 DWORD Level,
1008 LPBYTE *Bufptr,
1009 DWORD PrefMaxlen,
1010 LPDWORD EntriesRead,
1011 LPDWORD totalentries,
1012 LPDWORD Resume_Handle)
1014 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName),
1015 Level, Bufptr, PrefMaxlen, EntriesRead, totalentries, Resume_Handle);
1017 return ERROR_NO_BROWSER_SERVERS_FOUND;
1020 /************************************************************
1021 * NetServerGetInfo (NETAPI32.@)
1023 NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr)
1025 NET_API_STATUS ret;
1026 BOOL local = NETAPI_IsLocalComputer( servername );
1028 TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr );
1030 if (!local)
1032 if (libnetapi_init()) return server_getinfo( servername, level, bufptr );
1033 FIXME( "remote computers not supported\n" );
1034 return ERROR_INVALID_LEVEL;
1036 if (!bufptr) return ERROR_INVALID_PARAMETER;
1038 switch (level)
1040 case 100:
1041 case 101:
1043 DWORD computerNameLen, size;
1044 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1046 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1047 GetComputerNameW(computerName, &computerNameLen);
1048 computerNameLen++; /* include NULL terminator */
1050 /* Plus 1 for empty comment */
1051 size = sizeof(SERVER_INFO_101) + (computerNameLen + 1) * sizeof(WCHAR);
1052 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1053 if (ret == NERR_Success)
1055 /* INFO_100 structure is a subset of INFO_101 */
1056 PSERVER_INFO_101 info = (PSERVER_INFO_101)*bufptr;
1057 OSVERSIONINFOW verInfo;
1059 info->sv101_platform_id = PLATFORM_ID_NT;
1060 info->sv101_name = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101));
1061 memcpy(info->sv101_name, computerName,
1062 computerNameLen * sizeof(WCHAR));
1063 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1064 GetVersionExW(&verInfo);
1065 info->sv101_version_major = verInfo.dwMajorVersion;
1066 info->sv101_version_minor = verInfo.dwMinorVersion;
1067 /* Use generic type as no wine equivalent of DC / Server */
1068 info->sv101_type = SV_TYPE_NT;
1069 info->sv101_comment = (LMSTR)(*bufptr + sizeof(SERVER_INFO_101)
1070 + computerNameLen * sizeof(WCHAR));
1071 info->sv101_comment[0] = '\0';
1073 break;
1076 default:
1077 FIXME("level %d unimplemented\n", level);
1078 ret = ERROR_INVALID_LEVEL;
1080 return ret;
1084 /************************************************************
1085 * NetStatisticsGet (NETAPI32.@)
1087 NET_API_STATUS WINAPI NetStatisticsGet(LMSTR server, LMSTR service,
1088 DWORD level, DWORD options,
1089 LPBYTE *bufptr)
1091 int res;
1092 static const WCHAR SERVICE_WORKSTATION[] = {
1093 'L', 'a', 'n', 'm', 'a', 'n',
1094 'W', 'o', 'r', 'k', 's', 't', 'a', 't', 'i', 'o', 'n', '\0'};
1095 static const WCHAR SERVICE_SERVER[] = {
1096 'L', 'a', 'n', 'm', 'a', 'n',
1097 'S', 'e', 'r', 'v', 'e', 'r', '\0'};
1098 union
1100 STAT_WORKSTATION_0 workst;
1101 STAT_SERVER_0 server;
1102 } *stat;
1103 void *dataptr;
1105 TRACE("(server %s, service %s, level %d, options %d, buffer %p): stub\n",
1106 debugstr_w(server), debugstr_w(service), level, options, bufptr);
1108 res = NetApiBufferAllocate(sizeof(*stat), &dataptr);
1109 if (res != NERR_Success) return res;
1111 res = NERR_InternalError;
1112 stat = dataptr;
1113 switch (level)
1115 case 0:
1116 if (!lstrcmpW(service, SERVICE_WORKSTATION))
1118 /* Fill the struct STAT_WORKSTATION_0 properly */
1119 memset(&stat->workst, 0, sizeof(stat->workst));
1120 res = NERR_Success;
1122 else if (!lstrcmpW(service, SERVICE_SERVER))
1124 /* Fill the struct STAT_SERVER_0 properly */
1125 memset(&stat->server, 0, sizeof(stat->server));
1126 res = NERR_Success;
1128 break;
1130 if (res != NERR_Success)
1131 NetApiBufferFree(dataptr);
1132 else
1133 *bufptr = dataptr;
1135 return res;
1138 NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize,
1139 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle)
1141 FIXME("stub (%p, %d, %p, %d, %p, %p, %p)\n", server, level, bufptr, prefmaxsize,
1142 entriesread, totalentries, resumehandle);
1143 return ERROR_NOT_SUPPORTED;
1146 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR server, LPBYTE bufptr, LPDWORD jobid)
1148 TRACE("(%s, %p, %p)\n", debugstr_w(server), bufptr, jobid);
1149 return NetrJobAdd(server, (AT_INFO *)bufptr, jobid);
1152 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR server, DWORD minjobid, DWORD maxjobid)
1154 TRACE("(%s, %u, %u)\n", debugstr_w(server), minjobid, maxjobid);
1155 return NetrJobDel(server, minjobid, maxjobid);
1158 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR server, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread,
1159 LPDWORD totalentries, LPDWORD resumehandle)
1161 AT_ENUM_CONTAINER container;
1162 NET_API_STATUS ret;
1164 TRACE("(%s, %p, %u, %p, %p, %p)\n", debugstr_w(server), bufptr, prefmaxsize, entriesread, totalentries, resumehandle);
1166 container.EntriesRead = 0;
1167 container.Buffer = NULL;
1168 ret = NetrJobEnum(server, &container, prefmaxsize, totalentries, resumehandle);
1169 if (ret == ERROR_SUCCESS)
1171 *bufptr = (LPBYTE)container.Buffer;
1172 *entriesread = container.EntriesRead;
1174 return ret;
1177 NET_API_STATUS WINAPI NetScheduleJobGetInfo(LPCWSTR server, DWORD jobid, LPBYTE *bufptr)
1179 TRACE("(%s, %u, %p)\n", debugstr_w(server), jobid, bufptr);
1180 return NetrJobGetInfo(server, jobid, (LPAT_INFO *)bufptr);
1183 NET_API_STATUS WINAPI NetUseGetInfo(LMSTR server, LMSTR name, DWORD level, LPBYTE *bufptr)
1185 FIXME("stub (%p, %p, %d, %p)\n", server, name, level, bufptr);
1186 return ERROR_NOT_SUPPORTED;
1190 /************************************************************
1191 * NetApiBufferAllocate (NETAPI32.@)
1193 NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer)
1195 TRACE("(%d, %p)\n", ByteCount, Buffer);
1197 if (Buffer == NULL) return ERROR_INVALID_PARAMETER;
1198 *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount);
1199 if (*Buffer)
1200 return NERR_Success;
1201 else
1202 return GetLastError();
1205 /************************************************************
1206 * NetApiBufferFree (NETAPI32.@)
1208 NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
1210 TRACE("(%p)\n", Buffer);
1211 MIDL_user_free(Buffer);
1212 return NERR_Success;
1215 /************************************************************
1216 * NetApiBufferReallocate (NETAPI32.@)
1218 NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount,
1219 LPVOID* NewBuffer)
1221 TRACE("(%p, %d, %p)\n", OldBuffer, NewByteCount, NewBuffer);
1222 if (NewByteCount)
1224 if (OldBuffer)
1225 *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount);
1226 else
1227 *NewBuffer = HeapAlloc(GetProcessHeap(), 0, NewByteCount);
1228 return *NewBuffer ? NERR_Success : GetLastError();
1230 else
1232 if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError();
1233 *NewBuffer = 0;
1234 return NERR_Success;
1238 /************************************************************
1239 * NetApiBufferSize (NETAPI32.@)
1241 NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount)
1243 DWORD dw;
1245 TRACE("(%p, %p)\n", Buffer, ByteCount);
1246 if (Buffer == NULL)
1247 return ERROR_INVALID_PARAMETER;
1248 dw = HeapSize(GetProcessHeap(), 0, Buffer);
1249 TRACE("size: %d\n", dw);
1250 if (dw != 0xFFFFFFFF)
1251 *ByteCount = dw;
1252 else
1253 *ByteCount = 0;
1255 return NERR_Success;
1258 /************************************************************
1259 * NetSessionEnum (NETAPI32.@)
1261 * PARAMS
1262 * servername [I] Pointer to a string with the name of the server
1263 * UncClientName [I] Pointer to a string with the name of the session
1264 * username [I] Pointer to a string with the name of the user
1265 * level [I] Data information level
1266 * bufptr [O] Buffer to the data
1267 * prefmaxlen [I] Preferred maximum length of the data
1268 * entriesread [O] Pointer to the number of entries enumerated
1269 * totalentries [O] Pointer to the possible number of entries
1270 * resume_handle [I/O] Pointer to a handle for subsequent searches
1272 * RETURNS
1273 * If successful, the function returns NERR_Success
1274 * On failure it returns:
1275 * ERROR_ACCESS_DENIED User has no access to the requested information
1276 * ERROR_INVALID_LEVEL Value of 'level' is not correct
1277 * ERROR_INVALID_PARAMETER Wrong parameter
1278 * ERROR_MORE_DATA Need a larger buffer
1279 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
1280 * NERR_ClientNameNotFound A session does not exist on a given computer
1281 * NERR_InvalidComputer Invalid computer name
1282 * NERR_UserNotFound User name could not be found.
1284 NET_API_STATUS WINAPI NetSessionEnum(LMSTR servername, LMSTR UncClientName,
1285 LMSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread,
1286 LPDWORD totalentries, LPDWORD resume_handle)
1288 FIXME("Stub (%s %s %s %d %p %d %p %p %p)\n", debugstr_w(servername),
1289 debugstr_w(UncClientName), debugstr_w(username),
1290 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
1292 return NERR_Success;
1295 /************************************************************
1296 * NetShareEnum (NETAPI32.@)
1298 * PARAMS
1299 * servername [I] Pointer to a string with the name of the server
1300 * level [I] Data information level
1301 * bufptr [O] Buffer to the data
1302 * prefmaxlen [I] Preferred maximum length of the data
1303 * entriesread [O] Pointer to the number of entries enumerated
1304 * totalentries [O] Pointer to the possible number of entries
1305 * resume_handle [I/O] Pointer to a handle for subsequent searches
1307 * RETURNS
1308 * If successful, the function returns NERR_Success
1309 * On failure it returns a system error code (FIXME: find out which)
1312 NET_API_STATUS WINAPI NetShareEnum( LMSTR servername, DWORD level, LPBYTE* bufptr,
1313 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
1315 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(servername), level, bufptr,
1316 prefmaxlen, entriesread, totalentries, resume_handle);
1318 return ERROR_NOT_SUPPORTED;
1321 /************************************************************
1322 * NetShareDel (NETAPI32.@)
1324 NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserved)
1326 BOOL local = NETAPI_IsLocalComputer( servername );
1328 TRACE("%s %s %d\n", debugstr_w(servername), debugstr_w(netname), reserved);
1330 if (!local)
1332 if (libnetapi_init()) return share_del( servername, netname, reserved );
1333 FIXME( "remote computers not supported\n" );
1336 FIXME("%s %s %d\n", debugstr_w(servername), debugstr_w(netname), reserved);
1337 return NERR_Success;
1340 /************************************************************
1341 * NetShareGetInfo (NETAPI32.@)
1343 NET_API_STATUS WINAPI NetShareGetInfo(LMSTR servername, LMSTR netname,
1344 DWORD level, LPBYTE *bufptr)
1346 FIXME("Stub (%s %s %d %p)\n", debugstr_w(servername),
1347 debugstr_w(netname),level, bufptr);
1348 return NERR_NetNameNotFound;
1351 /************************************************************
1352 * NetShareAdd (NETAPI32.@)
1354 NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
1355 DWORD level, LPBYTE buf, LPDWORD parm_err)
1357 BOOL local = NETAPI_IsLocalComputer( servername );
1359 TRACE("%s %d %p %p\n", debugstr_w(servername), level, buf, parm_err);
1361 if (!local)
1363 if (libnetapi_init()) return share_add( servername, level, buf, parm_err );
1364 FIXME( "remote computers not supported\n" );
1367 FIXME("%s %d %p %p\n", debugstr_w(servername), level, buf, parm_err);
1368 return ERROR_NOT_SUPPORTED;
1371 /************************************************************
1372 * NetFileEnum (NETAPI32.@)
1374 NET_API_STATUS WINAPI NetFileEnum(
1375 LPWSTR ServerName, LPWSTR BasePath, LPWSTR UserName,
1376 DWORD Level, LPBYTE* BufPtr, DWORD PrefMaxLen,
1377 LPDWORD EntriesRead, LPDWORD TotalEntries, PDWORD_PTR ResumeHandle)
1379 FIXME("(%s, %s, %s, %u): stub\n", debugstr_w(ServerName), debugstr_w(BasePath),
1380 debugstr_w(UserName), Level);
1381 return ERROR_NOT_SUPPORTED;
1384 static void wprint_mac(WCHAR* buffer, int len, const MIB_IFROW *ifRow)
1386 int i;
1387 unsigned char val;
1389 if (!buffer)
1390 return;
1391 if (len < 1)
1392 return;
1393 if (!ifRow)
1395 *buffer = '\0';
1396 return;
1399 for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++)
1401 val = ifRow->bPhysAddr[i];
1402 if ((val >>4) >9)
1403 buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
1404 else
1405 buffer[2*i] = (WCHAR)((val >>4) + '0');
1406 if ((val & 0xf ) >9)
1407 buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
1408 else
1409 buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
1411 buffer[2*i]=0;
1414 /* Theoretically this could be too short, except that MS defines
1415 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
1416 * represent a count of WCHARs, so even with an extraordinarily long header
1417 * this will be plenty
1419 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
1420 #define MAX_TRANSPORT_ADDR 13
1422 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
1423 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
1425 static void wprint_name(WCHAR *buffer, int len, ULONG transport,
1426 PMIB_IFROW ifRow)
1428 WCHAR *ptr1, *ptr2;
1429 const char *name;
1431 if (!buffer)
1432 return;
1433 if (!ifRow)
1435 *buffer = '\0';
1436 return;
1439 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
1440 name = NBT_TRANSPORT_NAME_HEADER;
1441 else
1442 name = UNKNOWN_TRANSPORT_NAME_HEADER;
1444 for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++)
1445 *ptr1 = *name;
1446 for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++)
1447 *ptr1 = *ptr2;
1448 *ptr1 = '\0';
1451 /***********************************************************************
1452 * NetWkstaTransportEnum (NETAPI32.@)
1455 struct WkstaTransportEnumData
1457 UCHAR n_adapt;
1458 UCHAR n_read;
1459 DWORD prefmaxlen;
1460 LPBYTE *pbuf;
1461 NET_API_STATUS ret;
1464 /**********************************************************************/
1466 static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex,
1467 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
1469 BOOL ret;
1470 struct WkstaTransportEnumData *enumData = closure;
1472 if (enumData && enumData->pbuf)
1474 if (lanaIndex == 0)
1476 DWORD toAllocate;
1478 enumData->n_adapt = totalLANAs;
1479 enumData->n_read = 0;
1481 toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0)
1482 + MAX_TRANSPORT_NAME * sizeof(WCHAR) +
1483 MAX_TRANSPORT_ADDR * sizeof(WCHAR));
1484 if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH)
1485 toAllocate = enumData->prefmaxlen;
1486 NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf);
1488 if (*(enumData->pbuf))
1490 UCHAR spaceFor;
1492 if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH)
1493 spaceFor = totalLANAs;
1494 else
1495 spaceFor = enumData->prefmaxlen /
1496 (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME +
1497 MAX_TRANSPORT_ADDR) * sizeof(WCHAR));
1498 if (enumData->n_read < spaceFor)
1500 PWKSTA_TRANSPORT_INFO_0 ti;
1501 LMSTR transport_name, transport_addr;
1502 MIB_IFROW ifRow;
1504 ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) +
1505 enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0));
1506 transport_name = (LMSTR)(*(enumData->pbuf) +
1507 totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) +
1508 enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR));
1509 transport_addr = (LMSTR)(*(enumData->pbuf) +
1510 totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) +
1511 MAX_TRANSPORT_NAME * sizeof(WCHAR)) +
1512 enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR));
1514 ifRow.dwIndex = data->ifIndex;
1515 GetIfEntry(&ifRow);
1516 ti->wkti0_quality_of_service = 0;
1517 ti->wkti0_number_of_vcs = 0;
1518 ti->wkti0_transport_name = transport_name;
1519 wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME,
1520 transport, &ifRow);
1521 ti->wkti0_transport_address = transport_addr;
1522 wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR,
1523 &ifRow);
1524 if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG)))
1525 ti->wkti0_wan_ish = TRUE;
1526 else
1527 ti->wkti0_wan_ish = FALSE;
1528 TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti);
1529 TRACE("transport_name at %p %s\n",
1530 ti->wkti0_transport_name,
1531 debugstr_w(ti->wkti0_transport_name));
1532 TRACE("transport_address at %p %s\n",
1533 ti->wkti0_transport_address,
1534 debugstr_w(ti->wkti0_transport_address));
1535 enumData->n_read++;
1536 enumData->ret = NERR_Success;
1537 ret = TRUE;
1539 else
1541 enumData->ret = ERROR_MORE_DATA;
1542 ret = FALSE;
1545 else
1547 enumData->ret = ERROR_OUTOFMEMORY;
1548 ret = FALSE;
1551 else
1552 ret = FALSE;
1553 return ret;
1556 /**********************************************************************/
1558 NET_API_STATUS WINAPI
1559 NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
1560 DWORD prefmaxlen, LPDWORD read_entries,
1561 PDWORD total_entries, PDWORD hresume)
1563 NET_API_STATUS ret;
1565 TRACE(":%s, 0x%08x, %p, 0x%08x, %p, %p, %p\n", debugstr_w(ServerName),
1566 level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
1567 if (!NETAPI_IsLocalComputer(ServerName))
1569 FIXME(":not implemented for non-local computers\n");
1570 ret = ERROR_INVALID_LEVEL;
1572 else
1574 if (hresume && *hresume)
1576 FIXME(":resume handle not implemented\n");
1577 return ERROR_INVALID_LEVEL;
1580 switch (level)
1582 case 0: /* transport info */
1584 ULONG allTransports;
1585 struct WkstaTransportEnumData enumData;
1587 if (NetBIOSNumAdapters() == 0)
1588 return ERROR_NETWORK_UNREACHABLE;
1589 if (!read_entries)
1590 return STATUS_ACCESS_VIOLATION;
1591 if (!total_entries || !pbuf)
1592 return RPC_X_NULL_REF_POINTER;
1594 enumData.prefmaxlen = prefmaxlen;
1595 enumData.pbuf = pbuf;
1596 memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG));
1597 NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback,
1598 &enumData);
1599 *read_entries = enumData.n_read;
1600 *total_entries = enumData.n_adapt;
1601 if (hresume) *hresume= 0;
1602 ret = enumData.ret;
1603 break;
1605 default:
1606 TRACE("Invalid level %d is specified\n", level);
1607 ret = ERROR_INVALID_LEVEL;
1610 return ret;
1613 /************************************************************
1614 * NetWkstaUserGetInfo (NETAPI32.@)
1616 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
1617 PBYTE* bufptr)
1619 NET_API_STATUS nastatus;
1621 TRACE("(%s, %d, %p)\n", debugstr_w(reserved), level, bufptr);
1622 switch (level)
1624 case 0:
1626 PWKSTA_USER_INFO_0 ui;
1627 DWORD dwSize = UNLEN + 1;
1629 /* set up buffer */
1630 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
1631 (LPVOID *) bufptr);
1632 if (nastatus != NERR_Success)
1633 return ERROR_NOT_ENOUGH_MEMORY;
1635 ui = (PWKSTA_USER_INFO_0) *bufptr;
1636 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
1638 /* get data */
1639 if (!GetUserNameW(ui->wkui0_username, &dwSize))
1641 NetApiBufferFree(ui);
1642 return ERROR_NOT_ENOUGH_MEMORY;
1644 else {
1645 nastatus = NetApiBufferReallocate(
1646 *bufptr, sizeof(WKSTA_USER_INFO_0) +
1647 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
1648 (LPVOID *) bufptr);
1649 if (nastatus != NERR_Success)
1651 NetApiBufferFree(ui);
1652 return nastatus;
1654 ui = (PWKSTA_USER_INFO_0) *bufptr;
1655 ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
1657 break;
1660 case 1:
1662 PWKSTA_USER_INFO_1 ui;
1663 PWKSTA_USER_INFO_0 ui0;
1664 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1665 LSA_HANDLE PolicyHandle;
1666 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1667 NTSTATUS NtStatus;
1669 /* sizes of the field buffers in WCHARS */
1670 int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
1672 FIXME("Level 1 processing is partially implemented\n");
1673 oth_domains_sz = 1;
1674 logon_server_sz = 1;
1676 /* get some information first to estimate size of the buffer */
1677 ui0 = NULL;
1678 nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
1679 if (nastatus != NERR_Success)
1680 return nastatus;
1681 username_sz = lstrlenW(ui0->wkui0_username) + 1;
1683 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1684 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1685 POLICY_VIEW_LOCAL_INFORMATION,
1686 &PolicyHandle);
1687 if (NtStatus != STATUS_SUCCESS)
1689 TRACE("LsaOpenPolicyFailed with NT status %x\n",
1690 LsaNtStatusToWinError(NtStatus));
1691 NetApiBufferFree(ui0);
1692 return ERROR_NOT_ENOUGH_MEMORY;
1694 LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
1695 (PVOID*) &DomainInfo);
1696 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1697 LsaClose(PolicyHandle);
1699 /* set up buffer */
1700 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
1701 (username_sz + logon_domain_sz +
1702 oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
1703 (LPVOID *) bufptr);
1704 if (nastatus != NERR_Success) {
1705 NetApiBufferFree(ui0);
1706 return nastatus;
1708 ui = (WKSTA_USER_INFO_1 *) *bufptr;
1709 ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
1710 ui->wkui1_logon_domain = (LMSTR) (
1711 ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
1712 ui->wkui1_oth_domains = (LMSTR) (
1713 ((PBYTE) ui->wkui1_logon_domain) +
1714 logon_domain_sz * sizeof(WCHAR));
1715 ui->wkui1_logon_server = (LMSTR) (
1716 ((PBYTE) ui->wkui1_oth_domains) +
1717 oth_domains_sz * sizeof(WCHAR));
1719 /* get data */
1720 lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
1721 NetApiBufferFree(ui0);
1723 lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
1724 logon_domain_sz);
1725 LsaFreeMemory(DomainInfo);
1727 /* FIXME. Not implemented. Populated with empty strings */
1728 ui->wkui1_oth_domains[0] = 0;
1729 ui->wkui1_logon_server[0] = 0;
1730 break;
1732 case 1101:
1734 PWKSTA_USER_INFO_1101 ui;
1735 DWORD dwSize = 1;
1737 FIXME("Stub. Level 1101 processing is not implemented\n");
1738 /* FIXME see also wkui1_oth_domains for level 1 */
1740 /* set up buffer */
1741 nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
1742 (LPVOID *) bufptr);
1743 if (nastatus != NERR_Success)
1744 return nastatus;
1745 ui = (PWKSTA_USER_INFO_1101) *bufptr;
1746 ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
1748 /* get data */
1749 ui->wkui1101_oth_domains[0] = 0;
1750 break;
1752 default:
1753 TRACE("Invalid level %d is specified\n", level);
1754 return ERROR_INVALID_LEVEL;
1756 return NERR_Success;
1759 /************************************************************
1760 * NetWkstaUserEnum (NETAPI32.@)
1762 NET_API_STATUS WINAPI
1763 NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr,
1764 DWORD prefmaxlen, LPDWORD entriesread,
1765 LPDWORD totalentries, LPDWORD resumehandle)
1767 FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername),
1768 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
1769 return ERROR_INVALID_PARAMETER;
1772 /************************************************************
1773 * NetpGetComputerName (NETAPI32.@)
1775 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
1777 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
1779 TRACE("(%p)\n", Buffer);
1780 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
1781 if (GetComputerNameW(*Buffer, &dwSize))
1783 return NetApiBufferReallocate(
1784 *Buffer, (dwSize + 1) * sizeof(WCHAR),
1785 (LPVOID *) Buffer);
1787 else
1789 NetApiBufferFree(*Buffer);
1790 return ERROR_NOT_ENOUGH_MEMORY;
1794 NET_API_STATUS WINAPI I_NetNameCompare(LPVOID p1, LPWSTR wkgrp, LPWSTR comp,
1795 LPVOID p4, LPVOID p5)
1797 FIXME("(%p %s %s %p %p): stub\n", p1, debugstr_w(wkgrp), debugstr_w(comp),
1798 p4, p5);
1799 return ERROR_INVALID_PARAMETER;
1802 NET_API_STATUS WINAPI I_NetNameValidate(LPVOID p1, LPWSTR wkgrp, LPVOID p3,
1803 LPVOID p4)
1805 FIXME("(%p %s %p %p): stub\n", p1, debugstr_w(wkgrp), p3, p4);
1806 return ERROR_INVALID_PARAMETER;
1809 NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
1810 LPBYTE* bufptr)
1812 NET_API_STATUS ret;
1813 BOOL local = NETAPI_IsLocalComputer( servername );
1815 TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr );
1817 if (!local)
1819 if (libnetapi_init()) return wksta_getinfo( servername, level, bufptr );
1820 FIXME( "remote computers not supported\n" );
1821 return ERROR_INVALID_LEVEL;
1823 if (!bufptr) return ERROR_INVALID_PARAMETER;
1825 switch (level)
1827 case 100:
1828 case 101:
1829 case 102:
1831 static const WCHAR lanroot[] = {'c',':','\\','l','a','n','m','a','n',0}; /* FIXME */
1832 DWORD computerNameLen, domainNameLen, size;
1833 WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
1834 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
1835 LSA_HANDLE PolicyHandle;
1836 NTSTATUS NtStatus;
1838 computerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
1839 GetComputerNameW(computerName, &computerNameLen);
1840 computerNameLen++; /* include NULL terminator */
1842 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
1843 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
1844 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
1845 if (NtStatus != STATUS_SUCCESS)
1846 ret = LsaNtStatusToWinError(NtStatus);
1847 else
1849 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
1851 LsaQueryInformationPolicy(PolicyHandle,
1852 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
1853 domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
1854 size = sizeof(WKSTA_INFO_102) + computerNameLen * sizeof(WCHAR)
1855 + domainNameLen * sizeof(WCHAR) + sizeof(lanroot);
1856 ret = NetApiBufferAllocate(size, (LPVOID *)bufptr);
1857 if (ret == NERR_Success)
1859 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1860 PWKSTA_INFO_102 info = (PWKSTA_INFO_102)*bufptr;
1861 OSVERSIONINFOW verInfo;
1863 info->wki102_platform_id = PLATFORM_ID_NT;
1864 info->wki102_computername = (LMSTR)(*bufptr +
1865 sizeof(WKSTA_INFO_102));
1866 memcpy(info->wki102_computername, computerName,
1867 computerNameLen * sizeof(WCHAR));
1868 info->wki102_langroup = info->wki102_computername + computerNameLen;
1869 memcpy(info->wki102_langroup, DomainInfo->DomainName.Buffer,
1870 domainNameLen * sizeof(WCHAR));
1871 info->wki102_lanroot = info->wki102_langroup + domainNameLen;
1872 memcpy(info->wki102_lanroot, lanroot, sizeof(lanroot));
1873 memset(&verInfo, 0, sizeof(verInfo));
1874 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
1875 GetVersionExW(&verInfo);
1876 info->wki102_ver_major = verInfo.dwMajorVersion;
1877 info->wki102_ver_minor = verInfo.dwMinorVersion;
1878 info->wki102_logged_on_users = 1;
1880 LsaFreeMemory(DomainInfo);
1881 LsaClose(PolicyHandle);
1883 break;
1886 default:
1887 FIXME("level %d unimplemented\n", level);
1888 ret = ERROR_INVALID_LEVEL;
1890 return ret;
1893 /************************************************************
1894 * NetGetJoinInformation (NETAPI32.@)
1896 NET_API_STATUS NET_API_FUNCTION NetGetJoinInformation(
1897 LPCWSTR Server,
1898 LPWSTR *Name,
1899 PNETSETUP_JOIN_STATUS type)
1901 static const WCHAR workgroupW[] = {'W','o','r','k','g','r','o','u','p',0};
1903 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server), Name, type);
1905 if (!Name || !type)
1906 return ERROR_INVALID_PARAMETER;
1908 NetApiBufferAllocate(sizeof(workgroupW), (LPVOID *)Name);
1909 lstrcpyW(*Name, workgroupW);
1910 *type = NetSetupWorkgroupName;
1912 return NERR_Success;
1915 /************************************************************
1916 * NetUserGetGroups (NETAPI32.@)
1918 NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
1919 LPCWSTR servername,
1920 LPCWSTR username,
1921 DWORD level,
1922 LPBYTE *bufptr,
1923 DWORD prefixmaxlen,
1924 LPDWORD entriesread,
1925 LPDWORD totalentries)
1927 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
1928 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
1929 totalentries);
1931 *bufptr = NULL;
1932 *entriesread = 0;
1933 *totalentries = 0;
1935 return ERROR_INVALID_LEVEL;
1938 struct sam_user
1940 struct list entry;
1941 WCHAR user_name[LM20_UNLEN+1];
1942 WCHAR user_password[PWLEN + 1];
1943 DWORD sec_since_passwd_change;
1944 DWORD user_priv;
1945 LPWSTR home_dir;
1946 LPWSTR user_comment;
1947 DWORD user_flags;
1948 LPWSTR user_logon_script_path;
1951 static struct list user_list = LIST_INIT( user_list );
1953 /************************************************************
1954 * NETAPI_ValidateServername
1956 * Validates server name
1958 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
1960 if (ServerName)
1962 if (ServerName[0] == 0)
1963 return ERROR_BAD_NETPATH;
1964 else if (
1965 ((ServerName[0] == '\\') &&
1966 (ServerName[1] != '\\'))
1968 ((ServerName[0] == '\\') &&
1969 (ServerName[1] == '\\') &&
1970 (ServerName[2] == 0))
1972 return ERROR_INVALID_NAME;
1974 return NERR_Success;
1977 /************************************************************
1978 * NETAPI_FindUser
1980 * Looks for a user in the user database.
1981 * Returns a pointer to the entry in the user list when the user
1982 * is found, NULL otherwise.
1984 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
1986 struct sam_user *user;
1988 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
1990 if(lstrcmpW(user->user_name, UserName) == 0)
1991 return user;
1993 return NULL;
1996 static BOOL NETAPI_IsCurrentUser(LPCWSTR username)
1998 LPWSTR curr_user = NULL;
1999 DWORD dwSize;
2000 BOOL ret = FALSE;
2002 dwSize = LM20_UNLEN+1;
2003 curr_user = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
2004 if(!curr_user)
2006 ERR("Failed to allocate memory for user name.\n");
2007 goto end;
2009 if(!GetUserNameW(curr_user, &dwSize))
2011 ERR("Failed to get current user's user name.\n");
2012 goto end;
2014 if (!lstrcmpW(curr_user, username))
2016 ret = TRUE;
2019 end:
2020 HeapFree(GetProcessHeap(), 0, curr_user);
2021 return ret;
2024 /************************************************************
2025 * NetUserAdd (NETAPI32.@)
2027 NET_API_STATUS WINAPI NetUserAdd(LPCWSTR servername,
2028 DWORD level, LPBYTE bufptr, LPDWORD parm_err)
2030 NET_API_STATUS status;
2031 struct sam_user * su = NULL;
2033 FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername), level, bufptr, parm_err);
2035 if((status = NETAPI_ValidateServername(servername)) != NERR_Success)
2036 return status;
2038 switch(level)
2040 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
2041 case 4:
2042 case 3:
2043 FIXME("Level 3 and 4 not implemented.\n");
2044 /* Fall through */
2045 case 2:
2046 FIXME("Level 2 not implemented.\n");
2047 /* Fall through */
2048 case 1:
2050 PUSER_INFO_1 ui = (PUSER_INFO_1) bufptr;
2051 su = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user));
2052 if(!su)
2054 status = NERR_InternalError;
2055 break;
2058 if(lstrlenW(ui->usri1_name) > LM20_UNLEN)
2060 status = NERR_BadUsername;
2061 break;
2064 /*FIXME: do other checks for a valid username */
2065 lstrcpyW(su->user_name, ui->usri1_name);
2067 if(lstrlenW(ui->usri1_password) > PWLEN)
2069 /* Always return PasswordTooShort on invalid passwords. */
2070 status = NERR_PasswordTooShort;
2071 break;
2073 lstrcpyW(su->user_password, ui->usri1_password);
2075 su->sec_since_passwd_change = ui->usri1_password_age;
2076 su->user_priv = ui->usri1_priv;
2077 su->user_flags = ui->usri1_flags;
2079 /*FIXME: set the other LPWSTRs to NULL for now */
2080 su->home_dir = NULL;
2081 su->user_comment = NULL;
2082 su->user_logon_script_path = NULL;
2084 list_add_head(&user_list, &su->entry);
2085 return NERR_Success;
2087 default:
2088 TRACE("Invalid level %d specified.\n", level);
2089 status = ERROR_INVALID_LEVEL;
2090 break;
2093 HeapFree(GetProcessHeap(), 0, su);
2095 return status;
2098 /************************************************************
2099 * NetUserDel (NETAPI32.@)
2101 NET_API_STATUS WINAPI NetUserDel(LPCWSTR servername, LPCWSTR username)
2103 NET_API_STATUS status;
2104 struct sam_user *user;
2106 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
2108 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
2109 return status;
2111 if ((user = NETAPI_FindUser(username)) == NULL)
2112 return NERR_UserNotFound;
2114 list_remove(&user->entry);
2116 HeapFree(GetProcessHeap(), 0, user->home_dir);
2117 HeapFree(GetProcessHeap(), 0, user->user_comment);
2118 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
2119 HeapFree(GetProcessHeap(), 0, user);
2121 return NERR_Success;
2124 /************************************************************
2125 * NetUserGetInfo (NETAPI32.@)
2127 NET_API_STATUS WINAPI
2128 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
2129 LPBYTE* bufptr)
2131 NET_API_STATUS status;
2132 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername), debugstr_w(username),
2133 level, bufptr);
2134 status = NETAPI_ValidateServername(servername);
2135 if (status != NERR_Success)
2136 return status;
2138 if(!NETAPI_IsLocalComputer(servername))
2140 FIXME("Only implemented for local computer, but remote server"
2141 "%s was requested.\n", debugstr_w(servername));
2142 return NERR_InvalidComputer;
2145 if(!NETAPI_FindUser(username) && !NETAPI_IsCurrentUser(username))
2147 TRACE("User %s is unknown.\n", debugstr_w(username));
2148 return NERR_UserNotFound;
2151 switch (level)
2153 case 0:
2155 PUSER_INFO_0 ui;
2156 int name_sz;
2158 name_sz = lstrlenW(username) + 1;
2160 /* set up buffer */
2161 NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
2162 (LPVOID *) bufptr);
2164 ui = (PUSER_INFO_0) *bufptr;
2165 ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
2167 /* get data */
2168 lstrcpyW(ui->usri0_name, username);
2169 break;
2172 case 10:
2174 PUSER_INFO_10 ui;
2175 PUSER_INFO_0 ui0;
2176 /* sizes of the field buffers in WCHARS */
2177 int name_sz, comment_sz, usr_comment_sz, full_name_sz;
2179 comment_sz = 1;
2180 usr_comment_sz = 1;
2181 full_name_sz = 1;
2183 /* get data */
2184 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
2185 if (status != NERR_Success)
2187 NetApiBufferFree(ui0);
2188 return status;
2190 name_sz = lstrlenW(ui0->usri0_name) + 1;
2192 /* set up buffer */
2193 NetApiBufferAllocate(sizeof(USER_INFO_10) +
2194 (name_sz + comment_sz + usr_comment_sz +
2195 full_name_sz) * sizeof(WCHAR),
2196 (LPVOID *) bufptr);
2197 ui = (PUSER_INFO_10) *bufptr;
2198 ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
2199 ui->usri10_comment = (LPWSTR) (
2200 ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
2201 ui->usri10_usr_comment = (LPWSTR) (
2202 ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
2203 ui->usri10_full_name = (LPWSTR) (
2204 ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
2206 /* set data */
2207 lstrcpyW(ui->usri10_name, ui0->usri0_name);
2208 NetApiBufferFree(ui0);
2209 ui->usri10_comment[0] = 0;
2210 ui->usri10_usr_comment[0] = 0;
2211 ui->usri10_full_name[0] = 0;
2212 break;
2215 case 1:
2217 static const WCHAR homedirW[] = {'H','O','M','E',0};
2218 PUSER_INFO_1 ui;
2219 PUSER_INFO_0 ui0;
2220 /* sizes of the field buffers in WCHARS */
2221 int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
2223 password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
2224 comment_sz = 1;
2225 script_path_sz = 1;
2227 /* get data */
2228 status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
2229 if (status != NERR_Success)
2231 NetApiBufferFree(ui0);
2232 return status;
2234 name_sz = lstrlenW(ui0->usri0_name) + 1;
2235 home_dir_sz = GetEnvironmentVariableW(homedirW, NULL,0);
2236 /* set up buffer */
2237 NetApiBufferAllocate(sizeof(USER_INFO_1) +
2238 (name_sz + password_sz + home_dir_sz +
2239 comment_sz + script_path_sz) * sizeof(WCHAR),
2240 (LPVOID *) bufptr);
2242 ui = (PUSER_INFO_1) *bufptr;
2243 ui->usri1_name = (LPWSTR) (ui + 1);
2244 ui->usri1_password = ui->usri1_name + name_sz;
2245 ui->usri1_home_dir = ui->usri1_password + password_sz;
2246 ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
2247 ui->usri1_script_path = ui->usri1_comment + comment_sz;
2248 /* set data */
2249 lstrcpyW(ui->usri1_name, ui0->usri0_name);
2250 NetApiBufferFree(ui0);
2251 ui->usri1_password[0] = 0;
2252 ui->usri1_password_age = 0;
2253 ui->usri1_priv = 0;
2254 GetEnvironmentVariableW(homedirW, ui->usri1_home_dir,home_dir_sz);
2255 ui->usri1_comment[0] = 0;
2256 ui->usri1_flags = 0;
2257 ui->usri1_script_path[0] = 0;
2258 break;
2260 case 2:
2261 case 3:
2262 case 4:
2263 case 11:
2264 case 20:
2265 case 23:
2266 case 1003:
2267 case 1005:
2268 case 1006:
2269 case 1007:
2270 case 1008:
2271 case 1009:
2272 case 1010:
2273 case 1011:
2274 case 1012:
2275 case 1013:
2276 case 1014:
2277 case 1017:
2278 case 1018:
2279 case 1020:
2280 case 1023:
2281 case 1024:
2282 case 1025:
2283 case 1051:
2284 case 1052:
2285 case 1053:
2287 FIXME("Level %d is not implemented\n", level);
2288 return NERR_InternalError;
2290 default:
2291 TRACE("Invalid level %d is specified\n", level);
2292 return ERROR_INVALID_LEVEL;
2294 return NERR_Success;
2297 /************************************************************
2298 * NetUserGetLocalGroups (NETAPI32.@)
2300 NET_API_STATUS WINAPI
2301 NetUserGetLocalGroups(LPCWSTR servername, LPCWSTR username, DWORD level,
2302 DWORD flags, LPBYTE* bufptr, DWORD prefmaxlen,
2303 LPDWORD entriesread, LPDWORD totalentries)
2305 static const WCHAR admins[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0};
2306 NET_API_STATUS status;
2307 LPWSTR currentuser;
2308 LOCALGROUP_USERS_INFO_0* info;
2309 DWORD size;
2311 FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
2312 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
2313 prefmaxlen, entriesread, totalentries);
2315 status = NETAPI_ValidateServername(servername);
2316 if (status != NERR_Success)
2317 return status;
2319 size = UNLEN + 1;
2320 NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)&currentuser);
2321 if (!GetUserNameW(currentuser, &size)) {
2322 NetApiBufferFree(currentuser);
2323 return ERROR_NOT_ENOUGH_MEMORY;
2326 if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
2328 NetApiBufferFree(currentuser);
2329 return NERR_UserNotFound;
2332 NetApiBufferFree(currentuser);
2333 *totalentries = 1;
2334 size = sizeof(*info) + sizeof(admins);
2336 if(prefmaxlen < size)
2337 status = ERROR_MORE_DATA;
2338 else
2339 status = NetApiBufferAllocate(size, (LPVOID*)&info);
2341 if(status != NERR_Success)
2343 *bufptr = NULL;
2344 *entriesread = 0;
2345 return status;
2348 info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
2349 lstrcpyW(info->lgrui0_name, admins);
2351 *bufptr = (LPBYTE)info;
2352 *entriesread = 1;
2354 return NERR_Success;
2357 /************************************************************
2358 * NetUserEnum (NETAPI32.@)
2360 NET_API_STATUS WINAPI
2361 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
2362 DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
2363 LPDWORD resume_handle)
2365 NET_API_STATUS status;
2366 WCHAR user[UNLEN + 1];
2367 DWORD size, len = ARRAY_SIZE(user);
2369 TRACE("(%s, %u, 0x%x, %p, %u, %p, %p, %p)\n", debugstr_w(servername), level,
2370 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2372 status = NETAPI_ValidateServername(servername);
2373 if (status != NERR_Success)
2374 return status;
2376 if (!NETAPI_IsLocalComputer(servername))
2378 FIXME("Only implemented for local computer, but remote server"
2379 "%s was requested.\n", debugstr_w(servername));
2380 return NERR_InvalidComputer;
2383 if (!GetUserNameW(user, &len)) return GetLastError();
2385 switch (level)
2387 case 0:
2389 USER_INFO_0 *info;
2391 size = sizeof(*info) + (strlenW(user) + 1) * sizeof(WCHAR);
2393 if (prefmaxlen < size)
2394 status = ERROR_MORE_DATA;
2395 else
2396 status = NetApiBufferAllocate(size, (void **)&info);
2398 if (status != NERR_Success)
2399 return status;
2401 info->usri0_name = (WCHAR *)((char *)info + sizeof(*info));
2402 strcpyW(info->usri0_name, user);
2404 *bufptr = (BYTE *)info;
2405 *entriesread = *totalentries = 1;
2406 break;
2408 case 20:
2410 USER_INFO_20 *info;
2411 SID *sid;
2412 UCHAR *count;
2413 DWORD *rid;
2414 SID_NAME_USE use;
2416 size = sizeof(*info) + (strlenW(user) + 1) * sizeof(WCHAR);
2418 if (prefmaxlen < size)
2419 status = ERROR_MORE_DATA;
2420 else
2421 status = NetApiBufferAllocate(size, (void **)&info);
2423 if (status != NERR_Success)
2424 return status;
2426 size = len = 0;
2427 LookupAccountNameW(NULL, user, NULL, &size, NULL, &len, &use);
2428 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2429 return GetLastError();
2431 status = NetApiBufferAllocate(size, (void **)&sid);
2432 if (status != NERR_Success)
2433 return status;
2435 if (!LookupAccountNameW(NULL, user, sid, &size, NULL, &len, &use))
2436 return GetLastError();
2438 count = GetSidSubAuthorityCount(sid);
2439 rid = GetSidSubAuthority(sid, *count - 1);
2441 info->usri20_name = (WCHAR *)((char *)info + sizeof(*info));
2442 strcpyW(info->usri20_name, user);
2443 info->usri20_full_name = NULL;
2444 info->usri20_comment = NULL;
2445 info->usri20_flags = UF_NORMAL_ACCOUNT;
2446 info->usri20_user_id = *rid;
2448 *bufptr = (BYTE *)info;
2449 *entriesread = *totalentries = 1;
2451 NetApiBufferFree(sid);
2452 break;
2454 default:
2455 FIXME("level %u not supported\n", level);
2456 return ERROR_INVALID_LEVEL;
2458 return NERR_Success;
2461 /************************************************************
2462 * ACCESS_QueryAdminDisplayInformation
2464 * Creates a buffer with information for the Admin User
2466 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
2468 static const WCHAR sAdminUserName[] = {
2469 'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2471 /* sizes of the field buffers in WCHARS */
2472 int name_sz, comment_sz, full_name_sz;
2473 PNET_DISPLAY_USER usr;
2475 /* set up buffer */
2476 name_sz = lstrlenW(sAdminUserName) + 1;
2477 comment_sz = 1;
2478 full_name_sz = 1;
2480 *pdwSize = sizeof(NET_DISPLAY_USER);
2481 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
2482 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
2484 usr = *buf;
2485 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
2486 usr->usri1_comment = (LPWSTR) (
2487 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
2488 usr->usri1_full_name = (LPWSTR) (
2489 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
2491 /* set data */
2492 lstrcpyW(usr->usri1_name, sAdminUserName);
2493 usr->usri1_comment[0] = 0;
2494 usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
2495 usr->usri1_full_name[0] = 0;
2496 usr->usri1_user_id = DOMAIN_USER_RID_ADMIN;
2497 usr->usri1_next_index = 0;
2500 /************************************************************
2501 * ACCESS_QueryGuestDisplayInformation
2503 * Creates a buffer with information for the Guest User
2505 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
2507 static const WCHAR sGuestUserName[] = {
2508 'G','u','e','s','t',0 };
2510 /* sizes of the field buffers in WCHARS */
2511 int name_sz, comment_sz, full_name_sz;
2512 PNET_DISPLAY_USER usr;
2514 /* set up buffer */
2515 name_sz = lstrlenW(sGuestUserName) + 1;
2516 comment_sz = 1;
2517 full_name_sz = 1;
2519 *pdwSize = sizeof(NET_DISPLAY_USER);
2520 *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
2521 NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
2523 usr = *buf;
2524 usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
2525 usr->usri1_comment = (LPWSTR) (
2526 ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
2527 usr->usri1_full_name = (LPWSTR) (
2528 ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
2530 /* set data */
2531 lstrcpyW(usr->usri1_name, sGuestUserName);
2532 usr->usri1_comment[0] = 0;
2533 usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
2534 UF_DONT_EXPIRE_PASSWD;
2535 usr->usri1_full_name[0] = 0;
2536 usr->usri1_user_id = DOMAIN_USER_RID_GUEST;
2537 usr->usri1_next_index = 0;
2540 /************************************************************
2541 * Copies NET_DISPLAY_USER record.
2543 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER *dest, LPWSTR *dest_buf,
2544 PNET_DISPLAY_USER src)
2546 LPWSTR str = *dest_buf;
2548 src->usri1_name = str;
2549 lstrcpyW(src->usri1_name, dest->usri1_name);
2550 str = (LPWSTR) (
2551 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
2553 src->usri1_comment = str;
2554 lstrcpyW(src->usri1_comment, dest->usri1_comment);
2555 str = (LPWSTR) (
2556 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
2558 src->usri1_flags = dest->usri1_flags;
2560 src->usri1_full_name = str;
2561 lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
2562 str = (LPWSTR) (
2563 ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
2565 src->usri1_user_id = dest->usri1_user_id;
2566 src->usri1_next_index = dest->usri1_next_index;
2567 *dest_buf = str;
2570 /************************************************************
2571 * NetQueryDisplayInformation (NETAPI32.@)
2573 * The buffer structure:
2574 * - array of fixed size record of the level type
2575 * - strings, referenced by the record of the level type
2577 NET_API_STATUS WINAPI
2578 NetQueryDisplayInformation(
2579 LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
2580 DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
2581 PVOID *SortedBuffer)
2583 TRACE("(%s, %d, %d, %d, %d, %p, %p)\n", debugstr_w(ServerName),
2584 Level, Index, EntriesRequested, PreferredMaximumLength,
2585 ReturnedEntryCount, SortedBuffer);
2587 if(!NETAPI_IsLocalComputer(ServerName))
2589 FIXME("Only implemented on local computer, but requested for "
2590 "remote server %s\n", debugstr_w(ServerName));
2591 return ERROR_ACCESS_DENIED;
2594 switch (Level)
2596 case 1:
2598 /* current record */
2599 PNET_DISPLAY_USER inf;
2600 /* current available strings buffer */
2601 LPWSTR str;
2602 PNET_DISPLAY_USER admin, guest;
2603 DWORD admin_size, guest_size;
2604 LPWSTR name = NULL;
2605 DWORD dwSize;
2607 /* sizes of the field buffers in WCHARS */
2608 int name_sz, comment_sz, full_name_sz;
2610 /* number of the records, returned in SortedBuffer
2611 3 - for current user, Administrator and Guest users
2613 int records = 3;
2615 FIXME("Level %d partially implemented\n", Level);
2616 *ReturnedEntryCount = records;
2617 comment_sz = 1;
2618 full_name_sz = 1;
2620 /* get data */
2621 dwSize = UNLEN + 1;
2622 NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &name);
2623 if (!GetUserNameW(name, &dwSize))
2625 NetApiBufferFree(name);
2626 return ERROR_ACCESS_DENIED;
2628 name_sz = dwSize;
2629 ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
2630 ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
2632 /* set up buffer */
2633 dwSize = sizeof(NET_DISPLAY_USER) * records;
2634 dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
2636 NetApiBufferAllocate(dwSize +
2637 admin_size - sizeof(NET_DISPLAY_USER) +
2638 guest_size - sizeof(NET_DISPLAY_USER),
2639 SortedBuffer);
2640 inf = *SortedBuffer;
2641 str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
2642 inf->usri1_name = str;
2643 str = (LPWSTR) (
2644 ((PBYTE) str) + name_sz * sizeof(WCHAR));
2645 inf->usri1_comment = str;
2646 str = (LPWSTR) (
2647 ((PBYTE) str) + comment_sz * sizeof(WCHAR));
2648 inf->usri1_full_name = str;
2649 str = (LPWSTR) (
2650 ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
2652 /* set data */
2653 lstrcpyW(inf->usri1_name, name);
2654 NetApiBufferFree(name);
2655 inf->usri1_comment[0] = 0;
2656 inf->usri1_flags =
2657 UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
2658 inf->usri1_full_name[0] = 0;
2659 inf->usri1_user_id = 0;
2660 inf->usri1_next_index = 0;
2662 inf++;
2663 ACCESS_CopyDisplayUser(admin, &str, inf);
2664 NetApiBufferFree(admin);
2666 inf++;
2667 ACCESS_CopyDisplayUser(guest, &str, inf);
2668 NetApiBufferFree(guest);
2669 break;
2672 case 2:
2673 case 3:
2675 FIXME("Level %d is not implemented\n", Level);
2676 break;
2679 default:
2680 TRACE("Invalid level %d is specified\n", Level);
2681 return ERROR_INVALID_LEVEL;
2683 return NERR_Success;
2686 /************************************************************
2687 * NetGetDCName (NETAPI32.@)
2689 * Return the name of the primary domain controller (PDC)
2692 NET_API_STATUS WINAPI
2693 NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
2695 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
2696 debugstr_w(domainname), bufptr);
2697 return NERR_DCNotFound; /* say we can't find a domain controller */
2700 /************************************************************
2701 * NetGetAnyDCName (NETAPI32.@)
2703 * Return the name of any domain controller (DC) for a
2704 * domain that is directly trusted by the specified server
2707 NET_API_STATUS WINAPI NetGetAnyDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr)
2709 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername),
2710 debugstr_w(domainname), bufptr);
2711 return ERROR_NO_SUCH_DOMAIN;
2714 /************************************************************
2715 * NetGroupAddUser (NETAPI32.@)
2717 NET_API_STATUS WINAPI
2718 NetGroupAddUser(LPCWSTR servername, LPCWSTR groupname, LPCWSTR username)
2720 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername),
2721 debugstr_w(groupname), debugstr_w(username));
2722 return NERR_Success;
2725 /************************************************************
2726 * NetGroupEnum (NETAPI32.@)
2729 NET_API_STATUS WINAPI
2730 NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen,
2731 LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle)
2733 FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername),
2734 level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2735 return ERROR_ACCESS_DENIED;
2738 /************************************************************
2739 * NetGroupGetInfo (NETAPI32.@)
2742 NET_API_STATUS WINAPI NetGroupGetInfo(LPCWSTR servername, LPCWSTR groupname, DWORD level, LPBYTE *bufptr)
2744 FIXME("(%s, %s, %d, %p) stub!\n", debugstr_w(servername), debugstr_w(groupname), level, bufptr);
2745 return ERROR_ACCESS_DENIED;
2748 /******************************************************************************
2749 * NetUserModalsGet (NETAPI32.@)
2751 * Retrieves global information for all users and global groups in the security
2752 * database.
2754 * PARAMS
2755 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
2756 * on which the function is to execute.
2757 * level [I] Information level of the data.
2758 * 0 Return global passwords parameters. bufptr points to a
2759 * USER_MODALS_INFO_0 struct.
2760 * 1 Return logon server and domain controller information. bufptr
2761 * points to a USER_MODALS_INFO_1 struct.
2762 * 2 Return domain name and identifier. bufptr points to a
2763 * USER_MODALS_INFO_2 struct.
2764 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
2765 * struct.
2766 * pbuffer [I] Buffer that receives the data.
2768 * RETURNS
2769 * Success: NERR_Success.
2770 * Failure:
2771 * ERROR_ACCESS_DENIED - the user does not have access to the info.
2772 * NERR_InvalidComputer - computer name is invalid.
2774 NET_API_STATUS WINAPI NetUserModalsGet(
2775 LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
2777 TRACE("(%s %d %p)\n", debugstr_w(szServer), level, pbuffer);
2779 switch (level)
2781 case 0:
2782 /* return global passwords parameters */
2783 FIXME("level 0 not implemented!\n");
2784 *pbuffer = NULL;
2785 return NERR_InternalError;
2786 case 1:
2787 /* return logon server and domain controller info */
2788 FIXME("level 1 not implemented!\n");
2789 *pbuffer = NULL;
2790 return NERR_InternalError;
2791 case 2:
2793 /* return domain name and identifier */
2794 PUSER_MODALS_INFO_2 umi;
2795 LSA_HANDLE policyHandle;
2796 LSA_OBJECT_ATTRIBUTES objectAttributes;
2797 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo;
2798 NTSTATUS ntStatus;
2799 PSID domainIdentifier = NULL;
2800 int domainNameLen;
2802 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
2803 objectAttributes.Length = sizeof(objectAttributes);
2805 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
2806 POLICY_VIEW_LOCAL_INFORMATION,
2807 &policyHandle);
2808 if (ntStatus != STATUS_SUCCESS)
2810 WARN("LsaOpenPolicy failed with NT status %x\n",
2811 LsaNtStatusToWinError(ntStatus));
2812 return ntStatus;
2815 ntStatus = LsaQueryInformationPolicy(policyHandle,
2816 PolicyAccountDomainInformation,
2817 (PVOID *)&domainInfo);
2818 if (ntStatus != STATUS_SUCCESS)
2820 WARN("LsaQueryInformationPolicy failed with NT status %x\n",
2821 LsaNtStatusToWinError(ntStatus));
2822 LsaClose(policyHandle);
2823 return ntStatus;
2826 domainIdentifier = domainInfo->DomainSid;
2827 domainNameLen = lstrlenW(domainInfo->DomainName.Buffer) + 1;
2828 LsaClose(policyHandle);
2830 ntStatus = NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2) +
2831 GetLengthSid(domainIdentifier) +
2832 domainNameLen * sizeof(WCHAR),
2833 (LPVOID *)pbuffer);
2835 if (ntStatus != NERR_Success)
2837 WARN("NetApiBufferAllocate() failed\n");
2838 LsaFreeMemory(domainInfo);
2839 return ntStatus;
2842 umi = (USER_MODALS_INFO_2 *) *pbuffer;
2843 umi->usrmod2_domain_id = *pbuffer + sizeof(USER_MODALS_INFO_2);
2844 umi->usrmod2_domain_name = (LPWSTR)(*pbuffer +
2845 sizeof(USER_MODALS_INFO_2) + GetLengthSid(domainIdentifier));
2847 lstrcpynW(umi->usrmod2_domain_name,
2848 domainInfo->DomainName.Buffer,
2849 domainNameLen);
2850 CopySid(GetLengthSid(domainIdentifier), umi->usrmod2_domain_id,
2851 domainIdentifier);
2853 LsaFreeMemory(domainInfo);
2855 break;
2857 case 3:
2858 /* return lockout information */
2859 FIXME("level 3 not implemented!\n");
2860 *pbuffer = NULL;
2861 return NERR_InternalError;
2862 default:
2863 TRACE("Invalid level %d is specified\n", level);
2864 *pbuffer = NULL;
2865 return ERROR_INVALID_LEVEL;
2868 return NERR_Success;
2871 static NET_API_STATUS change_password_smb( LPCWSTR domainname, LPCWSTR username,
2872 LPCWSTR oldpassword, LPCWSTR newpassword )
2874 #ifdef HAVE_FORK
2875 NET_API_STATUS ret = NERR_Success;
2876 static char option_silent[] = "-s";
2877 static char option_user[] = "-U";
2878 static char option_remote[] = "-r";
2879 static char smbpasswd[] = "smbpasswd";
2880 int pipe_out[2];
2881 pid_t pid, wret;
2882 int status;
2883 char *server = NULL, *user, *argv[7], *old = NULL, *new = NULL;
2885 if (domainname && !(server = strdup_unixcp( domainname ))) return ERROR_OUTOFMEMORY;
2886 if (!(user = strdup_unixcp( username )))
2888 ret = ERROR_OUTOFMEMORY;
2889 goto end;
2891 if (!(old = strdup_unixcp( oldpassword )))
2893 ret = ERROR_OUTOFMEMORY;
2894 goto end;
2896 if (!(new = strdup_unixcp( newpassword )))
2898 ret = ERROR_OUTOFMEMORY;
2899 goto end;
2901 argv[0] = smbpasswd;
2902 argv[1] = option_silent;
2903 argv[2] = option_user;
2904 argv[3] = user;
2905 if (server)
2907 argv[4] = option_remote;
2908 argv[5] = server;
2909 argv[6] = NULL;
2911 else argv[4] = NULL;
2913 if (pipe( pipe_out ) == -1)
2915 ret = NERR_InternalError;
2916 goto end;
2918 fcntl( pipe_out[0], F_SETFD, FD_CLOEXEC );
2919 fcntl( pipe_out[1], F_SETFD, FD_CLOEXEC );
2921 switch ((pid = fork()))
2923 case -1:
2924 close( pipe_out[0] );
2925 close( pipe_out[1] );
2926 ret = NERR_InternalError;
2927 goto end;
2928 case 0:
2929 dup2( pipe_out[0], 0 );
2930 close( pipe_out[0] );
2931 close( pipe_out[1] );
2932 execvp( "smbpasswd", argv );
2933 ERR( "can't execute smbpasswd, is it installed?\n" );
2934 _exit(1);
2935 default:
2936 close( pipe_out[0] );
2937 break;
2939 write( pipe_out[1], old, strlen( old ) );
2940 write( pipe_out[1], "\n", 1 );
2941 write( pipe_out[1], new, strlen( new ) );
2942 write( pipe_out[1], "\n", 1 );
2943 write( pipe_out[1], new, strlen( new ) );
2944 write( pipe_out[1], "\n", 1 );
2945 close( pipe_out[1] );
2947 do {
2948 wret = waitpid(pid, &status, 0);
2949 } while (wret < 0 && errno == EINTR);
2951 if (ret == NERR_Success && (wret < 0 || !WIFEXITED(status) || WEXITSTATUS(status)))
2952 ret = NERR_InternalError;
2954 end:
2955 HeapFree( GetProcessHeap(), 0, server );
2956 HeapFree( GetProcessHeap(), 0, user );
2957 HeapFree( GetProcessHeap(), 0, old );
2958 HeapFree( GetProcessHeap(), 0, new );
2959 return ret;
2960 #else
2961 ERR( "no fork support on this platform\n" );
2962 return NERR_InternalError;
2963 #endif
2966 /******************************************************************************
2967 * NetUserChangePassword (NETAPI32.@)
2968 * PARAMS
2969 * domainname [I] Optional. Domain on which the user resides or the logon
2970 * domain of the current user if NULL.
2971 * username [I] Optional. Username to change the password for or the name
2972 * of the current user if NULL.
2973 * oldpassword [I] The user's current password.
2974 * newpassword [I] The password that the user will be changed to using.
2976 * RETURNS
2977 * Success: NERR_Success.
2978 * Failure: NERR_* failure code or win error code.
2981 NET_API_STATUS WINAPI NetUserChangePassword(LPCWSTR domainname, LPCWSTR username,
2982 LPCWSTR oldpassword, LPCWSTR newpassword)
2984 struct sam_user *user;
2986 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2988 if (!change_password_smb( domainname, username, oldpassword, newpassword ))
2989 return NERR_Success;
2991 if(domainname)
2992 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
2994 if((user = NETAPI_FindUser(username)) == NULL)
2995 return NERR_UserNotFound;
2997 if(lstrcmpW(user->user_password, oldpassword) != 0)
2998 return ERROR_INVALID_PASSWORD;
3000 if(lstrlenW(newpassword) > PWLEN)
3001 return ERROR_PASSWORD_RESTRICTION;
3003 lstrcpyW(user->user_password, newpassword);
3005 return NERR_Success;
3008 NET_API_STATUS WINAPI NetUseAdd(LMSTR servername, DWORD level, LPBYTE bufptr, LPDWORD parm_err)
3010 FIXME("%s %d %p %p stub\n", debugstr_w(servername), level, bufptr, parm_err);
3011 return NERR_Success;
3014 NET_API_STATUS WINAPI NetUseDel(LMSTR servername, LMSTR usename, DWORD forcecond)
3016 FIXME("%s %s %d stub\n", debugstr_w(servername), debugstr_w(usename), forcecond);
3017 return NERR_Success;
3020 /************************************************************
3021 * I_BrowserSetNetlogonState (NETAPI32.@)
3023 NET_API_STATUS WINAPI I_BrowserSetNetlogonState(
3024 LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName,
3025 DWORD Role)
3027 return ERROR_NOT_SUPPORTED;
3030 /************************************************************
3031 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
3033 NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
3034 LPWSTR ServerName, PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
3035 LPDWORD EntriesRead)
3037 return ERROR_NOT_SUPPORTED;
3040 #define NS_MAXDNAME 1025
3042 static DWORD get_dc_info(const WCHAR *domain, WCHAR *dc, WCHAR *ip)
3044 static const WCHAR pfx[] = {'_','l','d','a','p','.','_','t','c','p','.','d','c','.','_','m','s','d','c','s','.',0};
3045 WCHAR name[NS_MAXDNAME];
3046 DWORD ret, size;
3047 DNS_RECORDW *rec;
3049 lstrcpyW(name, pfx);
3050 lstrcatW(name, domain);
3052 ret = DnsQuery_W(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL);
3053 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(domain), ret);
3054 if (ret == ERROR_SUCCESS)
3056 TRACE("target %s, port %d\n", wine_dbgstr_w(rec->Data.Srv.pNameTarget), rec->Data.Srv.wPort);
3058 lstrcpynW(dc, rec->Data.Srv.pNameTarget, NS_MAXDNAME);
3059 DnsRecordListFree(rec, DnsFreeRecordList);
3061 /* IPv4 */
3062 ret = DnsQuery_W(dc, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &rec, NULL);
3063 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc), ret);
3064 if (ret == ERROR_SUCCESS)
3066 SOCKADDR_IN addr;
3068 addr.sin_family = AF_INET;
3069 addr.sin_port = 0;
3070 addr.sin_addr.s_addr = rec->Data.A.IpAddress;
3071 size = IP6_ADDRESS_STRING_LENGTH;
3072 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
3073 if (!ret)
3074 TRACE("WSAAddressToStringW => %d, %s\n", ret, wine_dbgstr_w(ip));
3076 DnsRecordListFree(rec, DnsFreeRecordList);
3078 return ret;
3081 /* IPv6 */
3082 ret = DnsQuery_W(dc, DNS_TYPE_AAAA, DNS_QUERY_STANDARD, NULL, &rec, NULL);
3083 TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc), ret);
3084 if (ret == ERROR_SUCCESS)
3086 SOCKADDR_IN6 addr;
3088 addr.sin6_family = AF_INET6;
3089 addr.sin6_port = 0;
3090 addr.sin6_scope_id = 0;
3091 memcpy(addr.sin6_addr.s6_addr, &rec->Data.AAAA.Ip6Address, sizeof(rec->Data.AAAA.Ip6Address));
3092 size = IP6_ADDRESS_STRING_LENGTH;
3093 ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
3094 if (!ret)
3095 TRACE("WSAAddressToStringW => %d, %s\n", ret, wine_dbgstr_w(ip));
3097 DnsRecordListFree(rec, DnsFreeRecordList);
3101 return ret;
3104 DWORD WINAPI DsGetDcNameW(LPCWSTR computer, LPCWSTR domain, GUID *domain_guid,
3105 LPCWSTR site, ULONG flags, PDOMAIN_CONTROLLER_INFOW *dc_info)
3107 static const WCHAR pfxW[] = {'\\','\\'};
3108 static const WCHAR default_site_nameW[] = {'D','e','f','a','u','l','t','-','F','i','r','s','t','-','S','i','t','e','-','N','a','m','e',0};
3109 NTSTATUS status;
3110 POLICY_DNS_DOMAIN_INFO *dns_domain_info = NULL;
3111 DOMAIN_CONTROLLER_INFOW *info;
3112 WCHAR dc[NS_MAXDNAME], ip[IP6_ADDRESS_STRING_LENGTH];
3113 DWORD size;
3115 FIXME("(%s, %s, %s, %s, %08x, %p): semi-stub\n", debugstr_w(computer),
3116 debugstr_w(domain), debugstr_guid(domain_guid), debugstr_w(site), flags, dc_info);
3118 if (!dc_info) return ERROR_INVALID_PARAMETER;
3120 if (!domain)
3122 LSA_OBJECT_ATTRIBUTES attrs;
3123 LSA_HANDLE lsa;
3125 memset(&attrs, 0, sizeof(attrs));
3126 attrs.Length = sizeof(attrs);
3127 status = LsaOpenPolicy(NULL, &attrs, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
3128 if (status)
3129 return LsaNtStatusToWinError(status);
3131 status = LsaQueryInformationPolicy(lsa, PolicyDnsDomainInformation, (void **)&dns_domain_info);
3132 LsaClose(lsa);
3133 if (status)
3134 return LsaNtStatusToWinError(status);
3136 domain = dns_domain_info->DnsDomainName.Buffer;
3139 status = get_dc_info(domain, dc, ip);
3140 if (status) return status;
3142 size = sizeof(DOMAIN_CONTROLLER_INFOW) + lstrlenW(domain) * sizeof(WCHAR) +
3143 sizeof(pfxW) * 2 + (lstrlenW(dc) + 1 + lstrlenW(ip) + 1) * sizeof(WCHAR) +
3144 lstrlenW(domain) * sizeof(WCHAR) /* assume forest == domain */ +
3145 sizeof(default_site_nameW) * 2;
3146 status = NetApiBufferAllocate(size, (void **)&info);
3147 if (status != NERR_Success)
3149 LsaFreeMemory(dns_domain_info);
3150 return ERROR_NOT_ENOUGH_MEMORY;
3153 info->DomainControllerName = (WCHAR *)(info + 1);
3154 memcpy(info->DomainControllerName, pfxW, sizeof(pfxW));
3155 lstrcpyW(info->DomainControllerName + 2, dc);
3156 info->DomainControllerAddress = (WCHAR *)((char *)info->DomainControllerName + (strlenW(info->DomainControllerName) + 1) * sizeof(WCHAR));
3157 memcpy(info->DomainControllerAddress, pfxW, sizeof(pfxW));
3158 lstrcpyW(info->DomainControllerAddress + 2, ip);
3159 info->DomainControllerAddressType = DS_INET_ADDRESS;
3160 info->DomainGuid = dns_domain_info ? dns_domain_info->DomainGuid : GUID_NULL /* FIXME */;
3161 info->DomainName = (WCHAR *)((char *)info->DomainControllerAddress + (strlenW(info->DomainControllerAddress) + 1) * sizeof(WCHAR));
3162 lstrcpyW(info->DomainName, domain);
3163 info->DnsForestName = (WCHAR *)((char *)info->DomainName + (lstrlenW(info->DomainName) + 1) * sizeof(WCHAR));
3164 lstrcpyW(info->DnsForestName, domain);
3165 info->DcSiteName = (WCHAR *)((char *)info->DnsForestName + (lstrlenW(info->DnsForestName) + 1) * sizeof(WCHAR));
3166 lstrcpyW(info->DcSiteName, default_site_nameW);
3167 info->ClientSiteName = (WCHAR *)((char *)info->DcSiteName + sizeof(default_site_nameW));
3168 lstrcpyW(info->ClientSiteName, default_site_nameW);
3169 info->Flags = DS_DNS_DOMAIN_FLAG | DS_DNS_FOREST_FLAG;
3171 LsaFreeMemory(dns_domain_info);
3173 *dc_info = info;
3175 return ERROR_SUCCESS;
3178 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
3179 GUID* DomainGuid, LPCSTR SiteName, ULONG Flags,
3180 PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo)
3182 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_a(ComputerName),
3183 debugstr_a(AvoidDCName), debugstr_guid(DomainGuid),
3184 debugstr_a(SiteName), Flags, DomainControllerInfo);
3185 return ERROR_CALL_NOT_IMPLEMENTED;
3188 DWORD WINAPI DsGetSiteNameW(LPCWSTR ComputerName, LPWSTR *SiteName)
3190 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName), SiteName);
3191 return ERROR_CALL_NOT_IMPLEMENTED;
3194 DWORD WINAPI DsGetSiteNameA(LPCSTR ComputerName, LPSTR *SiteName)
3196 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName), SiteName);
3197 return ERROR_CALL_NOT_IMPLEMENTED;
3200 /************************************************************
3201 * DsRoleFreeMemory (NETAPI32.@)
3203 * PARAMS
3204 * Buffer [I] Pointer to the to-be-freed buffer.
3206 * RETURNS
3207 * Nothing
3209 VOID WINAPI DsRoleFreeMemory(PVOID Buffer)
3211 TRACE("(%p)\n", Buffer);
3212 HeapFree(GetProcessHeap(), 0, Buffer);
3215 /************************************************************
3216 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
3218 * PARAMS
3219 * lpServer [I] Pointer to UNICODE string with ComputerName
3220 * InfoLevel [I] Type of data to retrieve
3221 * Buffer [O] Pointer to to the requested data
3223 * RETURNS
3225 * NOTES
3226 * When lpServer is NULL, use the local computer
3228 DWORD WINAPI DsRoleGetPrimaryDomainInformation(
3229 LPCWSTR lpServer, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
3230 PBYTE* Buffer)
3232 DWORD ret;
3234 FIXME("(%p, %d, %p) stub\n", lpServer, InfoLevel, Buffer);
3236 /* Check some input parameters */
3238 if (!Buffer) return ERROR_INVALID_PARAMETER;
3239 if ((InfoLevel < DsRolePrimaryDomainInfoBasic) || (InfoLevel > DsRoleOperationState)) return ERROR_INVALID_PARAMETER;
3241 *Buffer = NULL;
3242 switch (InfoLevel)
3244 case DsRolePrimaryDomainInfoBasic:
3246 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
3247 LSA_HANDLE PolicyHandle;
3248 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
3249 NTSTATUS NtStatus;
3250 int logon_domain_sz;
3251 DWORD size;
3252 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic;
3254 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
3255 NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
3256 POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
3257 if (NtStatus != STATUS_SUCCESS)
3259 TRACE("LsaOpenPolicyFailed with NT status %x\n",
3260 LsaNtStatusToWinError(NtStatus));
3261 return ERROR_OUTOFMEMORY;
3263 LsaQueryInformationPolicy(PolicyHandle,
3264 PolicyAccountDomainInformation, (PVOID*)&DomainInfo);
3265 logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
3266 LsaClose(PolicyHandle);
3268 size = sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC) +
3269 logon_domain_sz * sizeof(WCHAR);
3270 basic = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3271 if (basic)
3273 basic->MachineRole = DsRole_RoleStandaloneWorkstation;
3274 basic->DomainNameFlat = (LPWSTR)((LPBYTE)basic +
3275 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
3276 lstrcpyW(basic->DomainNameFlat, DomainInfo->DomainName.Buffer);
3277 ret = ERROR_SUCCESS;
3279 else
3280 ret = ERROR_OUTOFMEMORY;
3281 *Buffer = (PBYTE)basic;
3282 LsaFreeMemory(DomainInfo);
3284 break;
3285 default:
3286 ret = ERROR_CALL_NOT_IMPLEMENTED;
3288 return ret;
3291 /************************************************************
3292 * NetLocalGroupAdd (NETAPI32.@)
3294 NET_API_STATUS WINAPI NetLocalGroupAdd(
3295 LPCWSTR servername,
3296 DWORD level,
3297 LPBYTE buf,
3298 LPDWORD parm_err)
3300 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
3301 parm_err);
3302 return NERR_Success;
3305 /************************************************************
3306 * NetLocalGroupAddMember (NETAPI32.@)
3308 NET_API_STATUS WINAPI NetLocalGroupAddMember(
3309 LPCWSTR servername,
3310 LPCWSTR groupname,
3311 PSID membersid)
3313 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
3314 debugstr_w(groupname), membersid);
3315 return NERR_Success;
3318 /************************************************************
3319 * NetLocalGroupAddMembers (NETAPI32.@)
3321 NET_API_STATUS WINAPI NetLocalGroupAddMembers(
3322 LPCWSTR servername,
3323 LPCWSTR groupname,
3324 DWORD level,
3325 LPBYTE buf,
3326 DWORD totalentries)
3328 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
3329 debugstr_w(groupname), level, buf, totalentries);
3330 return NERR_Success;
3333 /************************************************************
3334 * NetLocalGroupDel (NETAPI32.@)
3336 NET_API_STATUS WINAPI NetLocalGroupDel(
3337 LPCWSTR servername,
3338 LPCWSTR groupname)
3340 FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
3341 return NERR_Success;
3344 /************************************************************
3345 * NetLocalGroupDelMember (NETAPI32.@)
3347 NET_API_STATUS WINAPI NetLocalGroupDelMember(
3348 LPCWSTR servername,
3349 LPCWSTR groupname,
3350 PSID membersid)
3352 FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
3353 debugstr_w(groupname), membersid);
3354 return NERR_Success;
3357 /************************************************************
3358 * NetLocalGroupDelMembers (NETAPI32.@)
3360 NET_API_STATUS WINAPI NetLocalGroupDelMembers(
3361 LPCWSTR servername,
3362 LPCWSTR groupname,
3363 DWORD level,
3364 LPBYTE buf,
3365 DWORD totalentries)
3367 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
3368 debugstr_w(groupname), level, buf, totalentries);
3369 return NERR_Success;
3372 /************************************************************
3373 * NetLocalGroupEnum (NETAPI32.@)
3375 NET_API_STATUS WINAPI NetLocalGroupEnum(
3376 LPCWSTR servername,
3377 DWORD level,
3378 LPBYTE* bufptr,
3379 DWORD prefmaxlen,
3380 LPDWORD entriesread,
3381 LPDWORD totalentries,
3382 PDWORD_PTR resumehandle)
3384 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
3385 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
3386 *entriesread = 0;
3387 *totalentries = 0;
3388 return NERR_Success;
3391 /************************************************************
3392 * NetLocalGroupGetInfo (NETAPI32.@)
3394 NET_API_STATUS WINAPI NetLocalGroupGetInfo(
3395 LPCWSTR servername,
3396 LPCWSTR groupname,
3397 DWORD level,
3398 LPBYTE* bufptr)
3400 static const WCHAR commentW[]={'N','o',' ','c','o','m','m','e','n','t',0};
3401 LOCALGROUP_INFO_1* info;
3402 DWORD size;
3404 FIXME("(%s %s %d %p) semi-stub!\n", debugstr_w(servername),
3405 debugstr_w(groupname), level, bufptr);
3407 size = sizeof(*info) + sizeof(WCHAR) * (lstrlenW(groupname)+1) + sizeof(commentW);
3408 NetApiBufferAllocate(size, (LPVOID*)&info);
3410 info->lgrpi1_name = (LPWSTR)(info + 1);
3411 lstrcpyW(info->lgrpi1_name, groupname);
3413 info->lgrpi1_comment = info->lgrpi1_name + lstrlenW(groupname) + 1;
3414 lstrcpyW(info->lgrpi1_comment, commentW);
3416 *bufptr = (LPBYTE)info;
3418 return NERR_Success;
3421 /************************************************************
3422 * NetLocalGroupGetMembers (NETAPI32.@)
3424 NET_API_STATUS WINAPI NetLocalGroupGetMembers(
3425 LPCWSTR servername,
3426 LPCWSTR localgroupname,
3427 DWORD level,
3428 LPBYTE* bufptr,
3429 DWORD prefmaxlen,
3430 LPDWORD entriesread,
3431 LPDWORD totalentries,
3432 PDWORD_PTR resumehandle)
3434 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
3435 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
3436 totalentries, resumehandle);
3438 if (level == 3)
3440 WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
3441 DWORD userNameLen;
3442 DWORD len,needlen;
3443 PLOCALGROUP_MEMBERS_INFO_3 ptr;
3445 /* still a stub, current user is belonging to all groups */
3447 *totalentries = 1;
3448 *entriesread = 0;
3450 userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
3451 if (!GetUserNameW(userName,&userNameLen))
3452 return ERROR_NOT_ENOUGH_MEMORY;
3454 needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
3455 (userNameLen+2) * sizeof(WCHAR);
3456 if (prefmaxlen != MAX_PREFERRED_LENGTH)
3457 len = min(prefmaxlen,needlen);
3458 else
3459 len = needlen;
3461 NetApiBufferAllocate(len, (LPVOID *) bufptr);
3462 if (len < needlen)
3463 return ERROR_MORE_DATA;
3465 ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
3466 ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
3467 lstrcpyW(ptr->lgrmi3_domainandname,userName);
3469 *entriesread = 1;
3472 return NERR_Success;
3475 /************************************************************
3476 * NetLocalGroupSetInfo (NETAPI32.@)
3478 NET_API_STATUS WINAPI NetLocalGroupSetInfo(
3479 LPCWSTR servername,
3480 LPCWSTR groupname,
3481 DWORD level,
3482 LPBYTE buf,
3483 LPDWORD parm_err)
3485 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
3486 debugstr_w(groupname), level, buf, parm_err);
3487 return NERR_Success;
3490 /************************************************************
3491 * NetLocalGroupSetMember (NETAPI32.@)
3493 NET_API_STATUS WINAPI NetLocalGroupSetMembers(
3494 LPCWSTR servername,
3495 LPCWSTR groupname,
3496 DWORD level,
3497 LPBYTE buf,
3498 DWORD totalentries)
3500 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
3501 debugstr_w(groupname), level, buf, totalentries);
3502 return NERR_Success;
3505 /************************************************************
3506 * DavGetHTTPFromUNCPath (NETAPI32.@)
3508 DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buflen)
3510 static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0};
3511 static const WCHAR httpsW[] = {'h','t','t','p','s',':','/','/',0};
3512 static const WCHAR sslW[] = {'S','S','L',0};
3513 static const WCHAR fmtW[] = {':','%','u',0};
3514 const WCHAR *p = unc_path, *q, *server, *path, *scheme = httpW;
3515 UINT i, len_server, len_path = 0, len_port = 0, len, port = 0;
3516 WCHAR *end, portbuf[12];
3518 TRACE("(%s %p %p)\n", debugstr_w(unc_path), buf, buflen);
3520 if (p[0] != '\\' || p[1] != '\\' || !p[2]) return ERROR_INVALID_PARAMETER;
3521 q = p += 2;
3522 while (*q && *q != '\\' && *q != '/' && *q != '@') q++;
3523 server = p;
3524 len_server = q - p;
3525 if (*q == '@')
3527 p = ++q;
3528 while (*p && (*p != '\\' && *p != '/' && *p != '@')) p++;
3529 if (p - q == 3 && !strncmpiW( q, sslW, 3 ))
3531 scheme = httpsW;
3532 q = p;
3534 else if ((port = strtolW( q, &end, 10 ))) q = end;
3535 else return ERROR_INVALID_PARAMETER;
3537 if (*q == '@')
3539 if (!(port = strtolW( ++q, &end, 10 ))) return ERROR_INVALID_PARAMETER;
3540 q = end;
3542 if (*q == '\\' || *q == '/') q++;
3543 path = q;
3544 while (*q++) len_path++;
3545 if (len_path && (path[len_path - 1] == '\\' || path[len_path - 1] == '/'))
3546 len_path--; /* remove trailing slash */
3548 sprintfW( portbuf, fmtW, port );
3549 if (scheme == httpsW)
3551 len = strlenW( httpsW );
3552 if (port && port != 443) len_port = strlenW( portbuf );
3554 else
3556 len = strlenW( httpW );
3557 if (port && port != 80) len_port = strlenW( portbuf );
3559 len += len_server;
3560 len += len_port;
3561 if (len_path) len += len_path + 1; /* leading '/' */
3562 len++; /* nul */
3564 if (*buflen < len)
3566 *buflen = len;
3567 return ERROR_INSUFFICIENT_BUFFER;
3570 memcpy( buf, scheme, strlenW(scheme) * sizeof(WCHAR) );
3571 buf += strlenW( scheme );
3572 memcpy( buf, server, len_server * sizeof(WCHAR) );
3573 buf += len_server;
3574 if (len_port)
3576 memcpy( buf, portbuf, len_port * sizeof(WCHAR) );
3577 buf += len_port;
3579 if (len_path)
3581 *buf++ = '/';
3582 for (i = 0; i < len_path; i++)
3584 if (path[i] == '\\') *buf++ = '/';
3585 else *buf++ = path[i];
3588 *buf = 0;
3589 *buflen = len;
3591 return ERROR_SUCCESS;
3594 /************************************************************
3595 * DavGetUNCFromHTTPPath (NETAPI32.@)
3597 DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen)
3599 static const WCHAR httpW[] = {'h','t','t','p'};
3600 static const WCHAR httpsW[] = {'h','t','t','p','s'};
3601 static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
3602 static const WCHAR sslW[] = {'@','S','S','L'};
3603 static const WCHAR port80W[] = {'8','0'};
3604 static const WCHAR port443W[] = {'4','4','3'};
3605 const WCHAR *p = http_path, *server, *port = NULL, *path = NULL;
3606 DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0;
3607 BOOL ssl;
3609 TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen);
3611 while (*p && *p != ':') { p++; len++; };
3612 if (len == ARRAY_SIZE(httpW) && !strncmpiW( http_path, httpW, len )) ssl = FALSE;
3613 else if (len == ARRAY_SIZE(httpsW) && !strncmpiW( http_path, httpsW, len )) ssl = TRUE;
3614 else return ERROR_INVALID_PARAMETER;
3616 if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER;
3617 server = p += 3;
3619 while (*p && *p != ':' && *p != '/') { p++; len_server++; };
3620 if (!len_server) return ERROR_BAD_NET_NAME;
3621 if (*p == ':')
3623 port = ++p;
3624 while (*p >= '0' && *p <= '9') { p++; len_port++; };
3625 if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL;
3626 else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL;
3627 path = p;
3629 else if (*p == '/') path = p;
3631 while (*p)
3633 if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME;
3634 p++; len_path++;
3636 if (len_path && path[len_path - 1] == '/') len_path--;
3638 len = len_server + 2; /* \\ */
3639 if (ssl) len += 4; /* @SSL */
3640 if (port) len += len_port + 1 /* @ */;
3641 len += ARRAY_SIZE(davrootW);
3642 len += len_path + 1; /* nul */
3644 if (*buflen < len)
3646 *buflen = len;
3647 return ERROR_INSUFFICIENT_BUFFER;
3650 buf[0] = buf[1] = '\\';
3651 buf += 2;
3652 memcpy( buf, server, len_server * sizeof(WCHAR) );
3653 buf += len_server;
3654 if (ssl)
3656 memcpy( buf, sslW, sizeof(sslW) );
3657 buf += 4;
3659 if (port)
3661 *buf++ = '@';
3662 memcpy( buf, port, len_port * sizeof(WCHAR) );
3663 buf += len_port;
3665 memcpy( buf, davrootW, sizeof(davrootW) );
3666 buf += ARRAY_SIZE(davrootW);
3667 for (i = 0; i < len_path; i++)
3669 if (path[i] == '/') *buf++ = '\\';
3670 else *buf++ = path[i];
3673 *buf = 0;
3674 *buflen = len;
3676 return ERROR_SUCCESS;
3679 /************************************************************
3680 * DsEnumerateDomainTrustsA (NETAPI32.@)
3682 DWORD WINAPI DsEnumerateDomainTrustsA(LPSTR server, ULONG flags, PDS_DOMAIN_TRUSTSA* domains, PULONG count)
3684 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_a(server), flags, domains, count);
3685 return ERROR_NO_LOGON_SERVERS;
3688 /************************************************************
3689 * DsEnumerateDomainTrustsW (NETAPI32.@)
3691 DWORD WINAPI DsEnumerateDomainTrustsW(LPWSTR server, ULONG flags, PDS_DOMAIN_TRUSTSW* domains, PULONG count)
3693 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_w(server), flags, domains, count);
3694 return ERROR_NO_LOGON_SERVERS;
3697 DECLSPEC_HIDDEN void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
3699 return HeapAlloc(GetProcessHeap(), 0, n);
3702 DECLSPEC_HIDDEN void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
3704 HeapFree(GetProcessHeap(), 0, p);
3707 DECLSPEC_HIDDEN handle_t __RPC_USER ATSVC_HANDLE_bind(ATSVC_HANDLE str)
3709 static unsigned char ncalrpc[] = "ncalrpc";
3710 unsigned char *binding_str;
3711 handle_t rpc_handle = 0;
3713 if (RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str) == RPC_S_OK)
3715 RpcBindingFromStringBindingA(binding_str, &rpc_handle);
3716 RpcStringFreeA(&binding_str);
3718 return rpc_handle;
3721 DECLSPEC_HIDDEN void __RPC_USER ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, handle_t rpc_handle)
3723 RpcBindingFree(&rpc_handle);