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
25 #include "wine/port.h"
30 #ifdef HAVE_SYS_WAIT_H
38 #define WIN32_NO_STATUS
59 #include "wine/debug.h"
60 #include "wine/list.h"
61 #include "wine/unicode.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
)
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
);
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
);
102 static BOOL
init_context(void)
106 if ((status
= plibnetapi_init( &libnetapi_ctx
)))
108 ERR( "Failed to initialize context %u\n", status
);
111 if (TRACE_ON( netapi32
) && (status
= plibnetapi_set_debuglevel( libnetapi_ctx
, "10" )))
113 ERR( "Failed to set debug level %u\n", status
);
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
);
124 if ((status
= plibnetapi_set_password( libnetapi_ctx
, "" )))
126 ERR( "Failed to set password %u\n", status
);
130 TRACE( "using %p\n", libnetapi_ctx
);
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() );
143 #define LOAD_FUNCPTR(f) \
144 if (!(p##f = dlsym( libnetapi_handle, #f ))) \
146 ERR( "Failed to load %s: %s\n", #f, dlerror() ); \
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
)
164 if (init_context()) return TRUE
;
167 dlclose( libnetapi_handle
);
168 libnetapi_handle
= NULL
;
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
;
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
;
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
;
208 ret
->sv101_comment
= ptr
;
209 MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_comment
, -1, ptr
, len
);
211 *bufptr
= (BYTE
*)ret
;
215 static NET_API_STATUS
server_info_from_samba( DWORD level
, const unsigned char *buf
, BYTE
**bufptr
)
219 case 101: return server_info_101_from_samba( buf
, bufptr
);
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
;
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
);
237 status
= server_info_from_samba( level
, buf
, bufptr
);
238 pNetApiBufferFree( buf
);
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
;
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
);
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
;
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
;
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
;
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
;
299 ret
->shi2_passwd
= ptr
;
300 WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_passwd
, -1, ptr
, len
, NULL
, NULL
);
302 *bufptr
= (unsigned char *)ret
;
308 unsigned char sid_rev_num
;
309 unsigned char num_auths
;
310 unsigned char id_auth
[6];
311 unsigned int sub_auths
[15];
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
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
349 union ace_object_inherited_type
351 struct guid inherited_type
;
357 union ace_object_type type
;
358 union ace_object_inherited_type inherited_type
;
363 struct ace_object object
;
371 unsigned int access_mask
;
372 union ace_object_ctr object
;
378 ACL_REVISION_NT4
= 2,
384 enum acl_revision revision
;
386 unsigned int num_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
;
416 struct sid
*owner_sid
;
417 struct sid
*group_sid
;
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
;
456 static NET_API_STATUS
sid_to_samba( const SID
*src
, struct sid
*dst
)
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
];
477 static enum ace_type
ace_type_to_samba( BYTE 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
;
486 ERR( "unhandled type %u\n", type
);
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
);
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
;
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
);
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
;
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
);
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
);
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
);
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
);
576 ERR( "unhandled type %u\n", src
->AceType
);
577 return ERROR_INVALID_PARAMETER
;
582 static NET_API_STATUS
acl_to_samba( const ACL
*src
, struct acl
*dst
)
584 NET_API_STATUS status
;
588 switch (src
->AclRevision
)
591 dst
->revision
= ACL_REVISION_ADS
;
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
;
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
;
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
;
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
;
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
;
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
;
661 if (!src
->Owner
) dst
->owner_sid
= NULL
;
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
;
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
;
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
;
685 dst
->dacl
= (struct acl
*)((char *)dst
+ offset
);
686 if ((status
= acl_to_samba( src
->Dacl
, dst
->dacl
))) return status
;
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
);
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;
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
;
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
;
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
;
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
;
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
;
760 status
= sd_to_samba( info
->shi502_security_descriptor
, (struct security_descriptor
*)ptr
);
763 HeapFree( GetProcessHeap(), 0, ret
);
766 ret
->shi502_security_descriptor
= (struct security_descriptor
*)ptr
;
768 *bufptr
= (unsigned char *)ret
;
772 static NET_API_STATUS
share_info_to_samba( DWORD level
, const BYTE
*buf
, unsigned char **bufptr
)
776 case 2: return share_info_2_to_samba( buf
, bufptr
);
777 case 502: return share_info_502_to_samba( buf
, bufptr
);
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
)
788 NET_API_STATUS status
;
790 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
791 status
= share_info_to_samba( level
, buf
, &info
);
796 status
= pNetShareAdd( server
, level
, info
, &err
);
797 HeapFree( GetProcessHeap(), 0, info
);
798 if (parm_err
) *parm_err
= err
;
800 HeapFree( GetProcessHeap(), 0, server
);
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
);
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
)
833 struct wksta_info_100
*info
= (struct wksta_info_100
*)buf
;
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
;
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
;
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
;
864 static NET_API_STATUS
wksta_info_from_samba( DWORD level
, const unsigned char *buf
, BYTE
**bufptr
)
868 case 100: return wksta_info_100_from_samba( buf
, bufptr
);
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
;
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
);
886 status
= wksta_info_from_samba( level
, buf
, bufptr
);
887 pNetApiBufferFree( buf
);
894 static BOOL
libnetapi_init(void)
899 static NET_API_STATUS
server_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
902 return ERROR_NOT_SUPPORTED
;
904 static NET_API_STATUS
share_add( LMSTR servername
, DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
907 return ERROR_NOT_SUPPORTED
;
909 static NET_API_STATUS
share_del( LMSTR servername
, LMSTR netname
, DWORD reserved
)
912 return ERROR_NOT_SUPPORTED
;
914 static NET_API_STATUS
wksta_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
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
);
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
);
945 case DLL_PROCESS_ATTACH
:
946 DisableThreadLibraryCalls(hinstDLL
);
950 case DLL_PROCESS_DETACH
:
951 if (lpvReserved
) break;
959 /************************************************************
960 * NetServerEnum (NETAPI32.@)
962 NET_API_STATUS WINAPI
NetServerEnum(
968 LPDWORD totalentries
,
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(
990 LPDWORD totalentries
,
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(
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
)
1026 BOOL local
= NETAPI_IsLocalComputer( servername
);
1028 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
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
;
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';
1077 FIXME("level %d unimplemented\n", level
);
1078 ret
= ERROR_INVALID_LEVEL
;
1084 /************************************************************
1085 * NetStatisticsGet (NETAPI32.@)
1087 NET_API_STATUS WINAPI
NetStatisticsGet(LMSTR server
, LMSTR service
,
1088 DWORD level
, DWORD options
,
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'};
1100 STAT_WORKSTATION_0 workst
;
1101 STAT_SERVER_0 server
;
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
;
1116 if (!lstrcmpW(service
, SERVICE_WORKSTATION
))
1118 /* Fill the struct STAT_WORKSTATION_0 properly */
1119 memset(&stat
->workst
, 0, sizeof(stat
->workst
));
1122 else if (!lstrcmpW(service
, SERVICE_SERVER
))
1124 /* Fill the struct STAT_SERVER_0 properly */
1125 memset(&stat
->server
, 0, sizeof(stat
->server
));
1130 if (res
!= NERR_Success
)
1131 NetApiBufferFree(dataptr
);
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
;
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
;
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
);
1200 return NERR_Success
;
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
,
1221 TRACE("(%p, %d, %p)\n", OldBuffer
, NewByteCount
, NewBuffer
);
1225 *NewBuffer
= HeapReAlloc(GetProcessHeap(), 0, OldBuffer
, NewByteCount
);
1227 *NewBuffer
= HeapAlloc(GetProcessHeap(), 0, NewByteCount
);
1228 return *NewBuffer
? NERR_Success
: GetLastError();
1232 if (!HeapFree(GetProcessHeap(), 0, OldBuffer
)) return GetLastError();
1234 return NERR_Success
;
1238 /************************************************************
1239 * NetApiBufferSize (NETAPI32.@)
1241 NET_API_STATUS WINAPI
NetApiBufferSize(LPVOID Buffer
, LPDWORD ByteCount
)
1245 TRACE("(%p, %p)\n", Buffer
, ByteCount
);
1247 return ERROR_INVALID_PARAMETER
;
1248 dw
= HeapSize(GetProcessHeap(), 0, Buffer
);
1249 TRACE("size: %d\n", dw
);
1250 if (dw
!= 0xFFFFFFFF)
1255 return NERR_Success
;
1258 /************************************************************
1259 * NetSessionEnum (NETAPI32.@)
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
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.@)
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
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
);
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
);
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
)
1399 for (i
= 0; i
< ifRow
->dwPhysAddrLen
&& 2 * i
< len
; i
++)
1401 val
= ifRow
->bPhysAddr
[i
];
1403 buffer
[2*i
] = (WCHAR
)((val
>>4) + 'A' - 10);
1405 buffer
[2*i
] = (WCHAR
)((val
>>4) + '0');
1406 if ((val
& 0xf ) >9)
1407 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + 'A' - 10);
1409 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + '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
,
1439 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
1440 name
= NBT_TRANSPORT_NAME_HEADER
;
1442 name
= UNKNOWN_TRANSPORT_NAME_HEADER
;
1444 for (ptr1
= buffer
; *name
&& ptr1
< buffer
+ len
; ptr1
++, name
++)
1446 for (ptr2
= ifRow
->wszName
; *ptr2
&& ptr1
< buffer
+ len
; ptr1
++, ptr2
++)
1451 /***********************************************************************
1452 * NetWkstaTransportEnum (NETAPI32.@)
1455 struct WkstaTransportEnumData
1464 /**********************************************************************/
1466 static BOOL
WkstaEnumAdaptersCallback(UCHAR totalLANAs
, UCHAR lanaIndex
,
1467 ULONG transport
, const NetBIOSAdapterImpl
*data
, void *closure
)
1470 struct WkstaTransportEnumData
*enumData
= closure
;
1472 if (enumData
&& enumData
->pbuf
)
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
))
1492 if (enumData
->prefmaxlen
== MAX_PREFERRED_LENGTH
)
1493 spaceFor
= totalLANAs
;
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
;
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
;
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
,
1521 ti
->wkti0_transport_address
= transport_addr
;
1522 wprint_mac(ti
->wkti0_transport_address
, MAX_TRANSPORT_ADDR
,
1524 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
1525 ti
->wkti0_wan_ish
= TRUE
;
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
));
1536 enumData
->ret
= NERR_Success
;
1541 enumData
->ret
= ERROR_MORE_DATA
;
1547 enumData
->ret
= ERROR_OUTOFMEMORY
;
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
)
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
;
1574 if (hresume
&& *hresume
)
1576 FIXME(":resume handle not implemented\n");
1577 return ERROR_INVALID_LEVEL
;
1582 case 0: /* transport info */
1584 ULONG allTransports
;
1585 struct WkstaTransportEnumData enumData
;
1587 if (NetBIOSNumAdapters() == 0)
1588 return ERROR_NETWORK_UNREACHABLE
;
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
,
1599 *read_entries
= enumData
.n_read
;
1600 *total_entries
= enumData
.n_adapt
;
1601 if (hresume
) *hresume
= 0;
1606 TRACE("Invalid level %d is specified\n", level
);
1607 ret
= ERROR_INVALID_LEVEL
;
1613 /************************************************************
1614 * NetWkstaUserGetInfo (NETAPI32.@)
1616 NET_API_STATUS WINAPI
NetWkstaUserGetInfo(LMSTR reserved
, DWORD level
,
1619 NET_API_STATUS nastatus
;
1621 TRACE("(%s, %d, %p)\n", debugstr_w(reserved
), level
, bufptr
);
1626 PWKSTA_USER_INFO_0 ui
;
1627 DWORD dwSize
= UNLEN
+ 1;
1630 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0
) + dwSize
* sizeof(WCHAR
),
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
));
1639 if (!GetUserNameW(ui
->wkui0_username
, &dwSize
))
1641 NetApiBufferFree(ui
);
1642 return ERROR_NOT_ENOUGH_MEMORY
;
1645 nastatus
= NetApiBufferReallocate(
1646 *bufptr
, sizeof(WKSTA_USER_INFO_0
) +
1647 (lstrlenW(ui
->wkui0_username
) + 1) * sizeof(WCHAR
),
1649 if (nastatus
!= NERR_Success
)
1651 NetApiBufferFree(ui
);
1654 ui
= (PWKSTA_USER_INFO_0
) *bufptr
;
1655 ui
->wkui0_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_0
));
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
;
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");
1674 logon_server_sz
= 1;
1676 /* get some information first to estimate size of the buffer */
1678 nastatus
= NetWkstaUserGetInfo(NULL
, 0, (PBYTE
*) &ui0
);
1679 if (nastatus
!= NERR_Success
)
1681 username_sz
= lstrlenW(ui0
->wkui0_username
) + 1;
1683 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
1684 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
1685 POLICY_VIEW_LOCAL_INFORMATION
,
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
);
1700 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1
) +
1701 (username_sz
+ logon_domain_sz
+
1702 oth_domains_sz
+ logon_server_sz
) * sizeof(WCHAR
),
1704 if (nastatus
!= NERR_Success
) {
1705 NetApiBufferFree(ui0
);
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
));
1720 lstrcpyW(ui
->wkui1_username
, ui0
->wkui0_username
);
1721 NetApiBufferFree(ui0
);
1723 lstrcpynW(ui
->wkui1_logon_domain
, DomainInfo
->DomainName
.Buffer
,
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;
1734 PWKSTA_USER_INFO_1101 ui
;
1737 FIXME("Stub. Level 1101 processing is not implemented\n");
1738 /* FIXME see also wkui1_oth_domains for level 1 */
1741 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101
) + dwSize
* sizeof(WCHAR
),
1743 if (nastatus
!= NERR_Success
)
1745 ui
= (PWKSTA_USER_INFO_1101
) *bufptr
;
1746 ui
->wkui1101_oth_domains
= (LMSTR
)(ui
+ 1);
1749 ui
->wkui1101_oth_domains
[0] = 0;
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
),
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
),
1799 return ERROR_INVALID_PARAMETER
;
1802 NET_API_STATUS WINAPI
I_NetNameValidate(LPVOID p1
, LPWSTR wkgrp
, LPVOID p3
,
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
,
1813 BOOL local
= NETAPI_IsLocalComputer( servername
);
1815 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
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
;
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
;
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
);
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
);
1887 FIXME("level %d unimplemented\n", level
);
1888 ret
= ERROR_INVALID_LEVEL
;
1893 /************************************************************
1894 * NetGetJoinInformation (NETAPI32.@)
1896 NET_API_STATUS NET_API_FUNCTION
NetGetJoinInformation(
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
);
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(
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
,
1935 return ERROR_INVALID_LEVEL
;
1941 WCHAR user_name
[LM20_UNLEN
+1];
1942 WCHAR user_password
[PWLEN
+ 1];
1943 DWORD sec_since_passwd_change
;
1946 LPWSTR user_comment
;
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
)
1962 if (ServerName
[0] == 0)
1963 return ERROR_BAD_NETPATH
;
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 /************************************************************
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)
1996 static BOOL
NETAPI_IsCurrentUser(LPCWSTR username
)
1998 LPWSTR curr_user
= NULL
;
2002 dwSize
= LM20_UNLEN
+1;
2003 curr_user
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(WCHAR
));
2006 ERR("Failed to allocate memory for user name.\n");
2009 if(!GetUserNameW(curr_user
, &dwSize
))
2011 ERR("Failed to get current user's user name.\n");
2014 if (!lstrcmpW(curr_user
, username
))
2020 HeapFree(GetProcessHeap(), 0, curr_user
);
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
)
2040 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
2043 FIXME("Level 3 and 4 not implemented.\n");
2046 FIXME("Level 2 not implemented.\n");
2050 PUSER_INFO_1 ui
= (PUSER_INFO_1
) bufptr
;
2051 su
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user
));
2054 status
= NERR_InternalError
;
2058 if(lstrlenW(ui
->usri1_name
) > LM20_UNLEN
)
2060 status
= NERR_BadUsername
;
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
;
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
;
2088 TRACE("Invalid level %d specified.\n", level
);
2089 status
= ERROR_INVALID_LEVEL
;
2093 HeapFree(GetProcessHeap(), 0, su
);
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
)
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
,
2131 NET_API_STATUS status
;
2132 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername
), debugstr_w(username
),
2134 status
= NETAPI_ValidateServername(servername
);
2135 if (status
!= NERR_Success
)
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
;
2158 name_sz
= lstrlenW(username
) + 1;
2161 NetApiBufferAllocate(sizeof(USER_INFO_0
) + name_sz
* sizeof(WCHAR
),
2164 ui
= (PUSER_INFO_0
) *bufptr
;
2165 ui
->usri0_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_0
));
2168 lstrcpyW(ui
->usri0_name
, username
);
2176 /* sizes of the field buffers in WCHARS */
2177 int name_sz
, comment_sz
, usr_comment_sz
, full_name_sz
;
2184 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
2185 if (status
!= NERR_Success
)
2187 NetApiBufferFree(ui0
);
2190 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
2193 NetApiBufferAllocate(sizeof(USER_INFO_10
) +
2194 (name_sz
+ comment_sz
+ usr_comment_sz
+
2195 full_name_sz
) * sizeof(WCHAR
),
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
));
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;
2217 static const WCHAR homedirW
[] = {'H','O','M','E',0};
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*/
2228 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
2229 if (status
!= NERR_Success
)
2231 NetApiBufferFree(ui0
);
2234 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
2235 home_dir_sz
= GetEnvironmentVariableW(homedirW
, NULL
,0);
2237 NetApiBufferAllocate(sizeof(USER_INFO_1
) +
2238 (name_sz
+ password_sz
+ home_dir_sz
+
2239 comment_sz
+ script_path_sz
) * sizeof(WCHAR
),
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
;
2249 lstrcpyW(ui
->usri1_name
, ui0
->usri0_name
);
2250 NetApiBufferFree(ui0
);
2251 ui
->usri1_password
[0] = 0;
2252 ui
->usri1_password_age
= 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;
2287 FIXME("Level %d is not implemented\n", level
);
2288 return NERR_InternalError
;
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
;
2308 LOCALGROUP_USERS_INFO_0
* info
;
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
)
2320 NetApiBufferAllocate(size
* sizeof(WCHAR
), (LPVOID
*)¤tuser
);
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
);
2334 size
= sizeof(*info
) + sizeof(admins
);
2336 if(prefmaxlen
< size
)
2337 status
= ERROR_MORE_DATA
;
2339 status
= NetApiBufferAllocate(size
, (LPVOID
*)&info
);
2341 if(status
!= NERR_Success
)
2348 info
->lgrui0_name
= (LPWSTR
)((LPBYTE
)info
+ sizeof(*info
));
2349 lstrcpyW(info
->lgrui0_name
, admins
);
2351 *bufptr
= (LPBYTE
)info
;
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
)
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();
2391 size
= sizeof(*info
) + (strlenW(user
) + 1) * sizeof(WCHAR
);
2393 if (prefmaxlen
< size
)
2394 status
= ERROR_MORE_DATA
;
2396 status
= NetApiBufferAllocate(size
, (void **)&info
);
2398 if (status
!= NERR_Success
)
2401 info
->usri0_name
= (WCHAR
*)((char *)info
+ sizeof(*info
));
2402 strcpyW(info
->usri0_name
, user
);
2404 *bufptr
= (BYTE
*)info
;
2405 *entriesread
= *totalentries
= 1;
2416 size
= sizeof(*info
) + (strlenW(user
) + 1) * sizeof(WCHAR
);
2418 if (prefmaxlen
< size
)
2419 status
= ERROR_MORE_DATA
;
2421 status
= NetApiBufferAllocate(size
, (void **)&info
);
2423 if (status
!= NERR_Success
)
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
)
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
);
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
;
2476 name_sz
= lstrlenW(sAdminUserName
) + 1;
2480 *pdwSize
= sizeof(NET_DISPLAY_USER
);
2481 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2482 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) 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
));
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
;
2515 name_sz
= lstrlenW(sGuestUserName
) + 1;
2519 *pdwSize
= sizeof(NET_DISPLAY_USER
);
2520 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2521 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) 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
));
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
);
2551 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2553 src
->usri1_comment
= str
;
2554 lstrcpyW(src
->usri1_comment
, dest
->usri1_comment
);
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
);
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
;
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
;
2598 /* current record */
2599 PNET_DISPLAY_USER inf
;
2600 /* current available strings buffer */
2602 PNET_DISPLAY_USER admin
, guest
;
2603 DWORD admin_size
, guest_size
;
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
2615 FIXME("Level %d partially implemented\n", Level
);
2616 *ReturnedEntryCount
= records
;
2622 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) &name
);
2623 if (!GetUserNameW(name
, &dwSize
))
2625 NetApiBufferFree(name
);
2626 return ERROR_ACCESS_DENIED
;
2629 ACCESS_QueryAdminDisplayInformation(&admin
, &admin_size
);
2630 ACCESS_QueryGuestDisplayInformation(&guest
, &guest_size
);
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
),
2640 inf
= *SortedBuffer
;
2641 str
= (LPWSTR
) ((PBYTE
) inf
+ sizeof(NET_DISPLAY_USER
) * records
);
2642 inf
->usri1_name
= str
;
2644 ((PBYTE
) str
) + name_sz
* sizeof(WCHAR
));
2645 inf
->usri1_comment
= str
;
2647 ((PBYTE
) str
) + comment_sz
* sizeof(WCHAR
));
2648 inf
->usri1_full_name
= str
;
2650 ((PBYTE
) str
) + full_name_sz
* sizeof(WCHAR
));
2653 lstrcpyW(inf
->usri1_name
, name
);
2654 NetApiBufferFree(name
);
2655 inf
->usri1_comment
[0] = 0;
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;
2663 ACCESS_CopyDisplayUser(admin
, &str
, inf
);
2664 NetApiBufferFree(admin
);
2667 ACCESS_CopyDisplayUser(guest
, &str
, inf
);
2668 NetApiBufferFree(guest
);
2675 FIXME("Level %d is not implemented\n", Level
);
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
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
2766 * pbuffer [I] Buffer that receives the data.
2769 * Success: NERR_Success.
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
);
2782 /* return global passwords parameters */
2783 FIXME("level 0 not implemented!\n");
2785 return NERR_InternalError
;
2787 /* return logon server and domain controller info */
2788 FIXME("level 1 not implemented!\n");
2790 return NERR_InternalError
;
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
;
2799 PSID domainIdentifier
= NULL
;
2802 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
2803 objectAttributes
.Length
= sizeof(objectAttributes
);
2805 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
2806 POLICY_VIEW_LOCAL_INFORMATION
,
2808 if (ntStatus
!= STATUS_SUCCESS
)
2810 WARN("LsaOpenPolicy failed with NT status %x\n",
2811 LsaNtStatusToWinError(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
);
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
),
2835 if (ntStatus
!= NERR_Success
)
2837 WARN("NetApiBufferAllocate() failed\n");
2838 LsaFreeMemory(domainInfo
);
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
,
2850 CopySid(GetLengthSid(domainIdentifier
), umi
->usrmod2_domain_id
,
2853 LsaFreeMemory(domainInfo
);
2858 /* return lockout information */
2859 FIXME("level 3 not implemented!\n");
2861 return NERR_InternalError
;
2863 TRACE("Invalid level %d is specified\n", level
);
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
)
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";
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
;
2891 if (!(old
= strdup_unixcp( oldpassword
)))
2893 ret
= ERROR_OUTOFMEMORY
;
2896 if (!(new = strdup_unixcp( newpassword
)))
2898 ret
= ERROR_OUTOFMEMORY
;
2901 argv
[0] = smbpasswd
;
2902 argv
[1] = option_silent
;
2903 argv
[2] = option_user
;
2907 argv
[4] = option_remote
;
2911 else argv
[4] = NULL
;
2913 if (pipe( pipe_out
) == -1)
2915 ret
= NERR_InternalError
;
2918 fcntl( pipe_out
[0], F_SETFD
, FD_CLOEXEC
);
2919 fcntl( pipe_out
[1], F_SETFD
, FD_CLOEXEC
);
2921 switch ((pid
= fork()))
2924 close( pipe_out
[0] );
2925 close( pipe_out
[1] );
2926 ret
= NERR_InternalError
;
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" );
2936 close( pipe_out
[0] );
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] );
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
;
2955 HeapFree( GetProcessHeap(), 0, server
);
2956 HeapFree( GetProcessHeap(), 0, user
);
2957 HeapFree( GetProcessHeap(), 0, old
);
2958 HeapFree( GetProcessHeap(), 0, new );
2961 ERR( "no fork support on this platform\n" );
2962 return NERR_InternalError
;
2966 /******************************************************************************
2967 * NetUserChangePassword (NETAPI32.@)
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.
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
;
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
,
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
];
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
);
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
)
3068 addr
.sin_family
= AF_INET
;
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
);
3074 TRACE("WSAAddressToStringW => %d, %s\n", ret
, wine_dbgstr_w(ip
));
3076 DnsRecordListFree(rec
, DnsFreeRecordList
);
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
)
3088 addr
.sin6_family
= AF_INET6
;
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
);
3095 TRACE("WSAAddressToStringW => %d, %s\n", ret
, wine_dbgstr_w(ip
));
3097 DnsRecordListFree(rec
, DnsFreeRecordList
);
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};
3110 POLICY_DNS_DOMAIN_INFO
*dns_domain_info
= NULL
;
3111 DOMAIN_CONTROLLER_INFOW
*info
;
3112 WCHAR dc
[NS_MAXDNAME
], ip
[IP6_ADDRESS_STRING_LENGTH
];
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
;
3122 LSA_OBJECT_ATTRIBUTES attrs
;
3125 memset(&attrs
, 0, sizeof(attrs
));
3126 attrs
.Length
= sizeof(attrs
);
3127 status
= LsaOpenPolicy(NULL
, &attrs
, POLICY_VIEW_LOCAL_INFORMATION
, &lsa
);
3129 return LsaNtStatusToWinError(status
);
3131 status
= LsaQueryInformationPolicy(lsa
, PolicyDnsDomainInformation
, (void **)&dns_domain_info
);
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
);
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.@)
3204 * Buffer [I] Pointer to the to-be-freed buffer.
3209 VOID WINAPI
DsRoleFreeMemory(PVOID Buffer
)
3211 TRACE("(%p)\n", Buffer
);
3212 HeapFree(GetProcessHeap(), 0, Buffer
);
3215 /************************************************************
3216 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
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
3226 * When lpServer is NULL, use the local computer
3228 DWORD WINAPI
DsRoleGetPrimaryDomainInformation(
3229 LPCWSTR lpServer
, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel
,
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
;
3244 case DsRolePrimaryDomainInfoBasic
:
3246 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
3247 LSA_HANDLE PolicyHandle
;
3248 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
3250 int logon_domain_sz
;
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
);
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
;
3280 ret
= ERROR_OUTOFMEMORY
;
3281 *Buffer
= (PBYTE
)basic
;
3282 LsaFreeMemory(DomainInfo
);
3286 ret
= ERROR_CALL_NOT_IMPLEMENTED
;
3291 /************************************************************
3292 * NetLocalGroupAdd (NETAPI32.@)
3294 NET_API_STATUS WINAPI
NetLocalGroupAdd(
3300 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername
), level
, buf
,
3302 return NERR_Success
;
3305 /************************************************************
3306 * NetLocalGroupAddMember (NETAPI32.@)
3308 NET_API_STATUS WINAPI
NetLocalGroupAddMember(
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(
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(
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(
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(
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(
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
);
3388 return NERR_Success
;
3391 /************************************************************
3392 * NetLocalGroupGetInfo (NETAPI32.@)
3394 NET_API_STATUS WINAPI
NetLocalGroupGetInfo(
3400 static const WCHAR commentW
[]={'N','o',' ','c','o','m','m','e','n','t',0};
3401 LOCALGROUP_INFO_1
* info
;
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(
3426 LPCWSTR localgroupname
,
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
);
3440 WCHAR userName
[MAX_COMPUTERNAME_LENGTH
+ 1];
3443 PLOCALGROUP_MEMBERS_INFO_3 ptr
;
3445 /* still a stub, current user is belonging to all groups */
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
);
3461 NetApiBufferAllocate(len
, (LPVOID
*) bufptr
);
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
);
3472 return NERR_Success
;
3475 /************************************************************
3476 * NetLocalGroupSetInfo (NETAPI32.@)
3478 NET_API_STATUS WINAPI
NetLocalGroupSetInfo(
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(
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
;
3522 while (*q
&& *q
!= '\\' && *q
!= '/' && *q
!= '@') q
++;
3528 while (*p
&& (*p
!= '\\' && *p
!= '/' && *p
!= '@')) p
++;
3529 if (p
- q
== 3 && !strncmpiW( q
, sslW
, 3 ))
3534 else if ((port
= strtolW( q
, &end
, 10 ))) q
= end
;
3535 else return ERROR_INVALID_PARAMETER
;
3539 if (!(port
= strtolW( ++q
, &end
, 10 ))) return ERROR_INVALID_PARAMETER
;
3542 if (*q
== '\\' || *q
== '/') 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
);
3556 len
= strlenW( httpW
);
3557 if (port
&& port
!= 80) len_port
= strlenW( portbuf
);
3561 if (len_path
) len
+= len_path
+ 1; /* leading '/' */
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
) );
3576 memcpy( buf
, portbuf
, len_port
* sizeof(WCHAR
) );
3582 for (i
= 0; i
< len_path
; i
++)
3584 if (path
[i
] == '\\') *buf
++ = '/';
3585 else *buf
++ = path
[i
];
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;
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
;
3619 while (*p
&& *p
!= ':' && *p
!= '/') { p
++; len_server
++; };
3620 if (!len_server
) return ERROR_BAD_NET_NAME
;
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
;
3629 else if (*p
== '/') path
= p
;
3633 if (p
[0] == '/' && p
[1] == '/') return ERROR_BAD_NET_NAME
;
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 */
3647 return ERROR_INSUFFICIENT_BUFFER
;
3650 buf
[0] = buf
[1] = '\\';
3652 memcpy( buf
, server
, len_server
* sizeof(WCHAR
) );
3656 memcpy( buf
, sslW
, sizeof(sslW
) );
3662 memcpy( buf
, port
, len_port
* sizeof(WCHAR
) );
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
];
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
);
3721 DECLSPEC_HIDDEN
void __RPC_USER
ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName
, handle_t rpc_handle
)
3723 RpcBindingFree(&rpc_handle
);