1 /* Copyright 2001 Mike McCormack
2 * Copyright 2002 Andriy Palamarchuk
3 * Copyright 2003 Juan Lang
4 * Copyright 2005,2006 Paul Vriens
5 * Copyright 2006 Robert Reif
6 * Copyright 2013 Hans Leidekker for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
29 #ifdef HAVE_SYS_WAIT_H
37 #define WIN32_NO_STATUS
54 #include "wine/debug.h"
55 #include "wine/library.h"
56 #include "wine/list.h"
57 #include "wine/unicode.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(netapi32
);
61 static char *strdup_unixcp( const WCHAR
*str
)
64 int len
= WideCharToMultiByte( CP_UNIXCP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
65 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
66 WideCharToMultiByte( CP_UNIXCP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
70 #ifdef SONAME_LIBNETAPI
72 static void *libnetapi_handle
;
73 static void *libnetapi_ctx
;
75 static DWORD (*plibnetapi_init
)(void **);
76 static DWORD (*plibnetapi_free
)(void *);
77 static DWORD (*plibnetapi_set_debuglevel
)(void *, const char *);
78 static DWORD (*plibnetapi_set_username
)(void *, const char *);
79 static DWORD (*plibnetapi_set_password
)(void *, const char *);
81 static NET_API_STATUS (*pNetApiBufferAllocate
)(unsigned int, void **);
82 static NET_API_STATUS (*pNetApiBufferFree
)(void *);
83 static NET_API_STATUS (*pNetServerGetInfo
)(const char *, unsigned int, unsigned char **);
84 static NET_API_STATUS (*pNetShareAdd
)(const char *, unsigned int, unsigned char *, unsigned int *);
85 static NET_API_STATUS (*pNetShareDel
)(const char *, const char *, unsigned int);
86 static NET_API_STATUS (*pNetWkstaGetInfo
)(const char *, unsigned int, unsigned char **);
88 static void destroy_context(void)
90 TRACE( "destroying %p\n", libnetapi_ctx
);
91 plibnetapi_free( libnetapi_ctx
);
95 static BOOL
init_context(void)
99 if ((status
= plibnetapi_init( &libnetapi_ctx
)))
101 ERR( "Failed to initialize context %u\n", status
);
104 if (TRACE_ON( netapi32
) && (status
= plibnetapi_set_debuglevel( libnetapi_ctx
, "10" )))
106 ERR( "Failed to set debug level %u\n", status
);
110 /* perform an anonymous login by default (avoids a password prompt) */
111 if ((status
= plibnetapi_set_username( libnetapi_ctx
, "Guest" )))
113 ERR( "Failed to set username %u\n", status
);
117 if ((status
= plibnetapi_set_password( libnetapi_ctx
, "" )))
119 ERR( "Failed to set password %u\n", status
);
123 TRACE( "using %p\n", libnetapi_ctx
);
127 static BOOL
libnetapi_init(void)
131 if (libnetapi_handle
) return TRUE
;
132 if (!(libnetapi_handle
= wine_dlopen( SONAME_LIBNETAPI
, RTLD_NOW
, buf
, sizeof(buf
) )))
134 WARN( "Failed to load libnetapi: %s\n", buf
);
138 #define LOAD_FUNCPTR(f) \
139 if (!(p##f = wine_dlsym( libnetapi_handle, #f, buf, sizeof(buf) ))) \
141 ERR( "Failed to load %s: %s\n", #f, buf ); \
145 LOAD_FUNCPTR(libnetapi_init
)
146 LOAD_FUNCPTR(libnetapi_free
)
147 LOAD_FUNCPTR(libnetapi_set_debuglevel
)
148 LOAD_FUNCPTR(libnetapi_set_username
)
149 LOAD_FUNCPTR(libnetapi_set_password
)
151 LOAD_FUNCPTR(NetApiBufferAllocate
)
152 LOAD_FUNCPTR(NetApiBufferFree
)
153 LOAD_FUNCPTR(NetServerGetInfo
)
154 LOAD_FUNCPTR(NetShareAdd
)
155 LOAD_FUNCPTR(NetShareDel
)
156 LOAD_FUNCPTR(NetWkstaGetInfo
)
159 if (init_context()) return TRUE
;
162 wine_dlclose( libnetapi_handle
, NULL
, 0 );
163 libnetapi_handle
= NULL
;
167 struct server_info_101
169 unsigned int sv101_platform_id
;
170 const char *sv101_name
;
171 unsigned int sv101_version_major
;
172 unsigned int sv101_version_minor
;
173 unsigned int sv101_type
;
174 const char *sv101_comment
;
177 static NET_API_STATUS
server_info_101_from_samba( const unsigned char *buf
, BYTE
**bufptr
)
179 SERVER_INFO_101
*ret
;
180 struct server_info_101
*info
= (struct server_info_101
*)buf
;
184 if (info
->sv101_name
) len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_name
, -1, NULL
, 0 );
185 if (info
->sv101_comment
) len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_comment
, -1, NULL
, 0 );
186 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ret
) + (len
* sizeof(WCHAR
) ))))
187 return ERROR_OUTOFMEMORY
;
189 ptr
= (WCHAR
*)(ret
+ 1);
190 ret
->sv101_platform_id
= info
->sv101_platform_id
;
191 if (!info
->sv101_name
) ret
->sv101_name
= NULL
;
194 ret
->sv101_name
= ptr
;
195 ptr
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_name
, -1, ptr
, len
);
197 ret
->sv101_version_major
= info
->sv101_version_major
;
198 ret
->sv101_version_minor
= info
->sv101_version_minor
;
199 ret
->sv101_type
= info
->sv101_type
;
200 if (!info
->sv101_comment
) ret
->sv101_comment
= NULL
;
203 ret
->sv101_comment
= ptr
;
204 MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_comment
, -1, ptr
, len
);
206 *bufptr
= (BYTE
*)ret
;
210 static NET_API_STATUS
server_info_from_samba( DWORD level
, const unsigned char *buf
, BYTE
**bufptr
)
214 case 101: return server_info_101_from_samba( buf
, bufptr
);
216 FIXME( "level %u not supported\n", level
);
217 return ERROR_NOT_SUPPORTED
;
221 static NET_API_STATUS
server_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
223 NET_API_STATUS status
;
225 unsigned char *buf
= NULL
;
227 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
228 status
= pNetServerGetInfo( server
, level
, &buf
);
229 HeapFree( GetProcessHeap(), 0, server
);
232 status
= server_info_from_samba( level
, buf
, bufptr
);
233 pNetApiBufferFree( buf
);
240 const char *shi2_netname
;
241 unsigned int shi2_type
;
242 const char *shi2_remark
;
243 unsigned int shi2_permissions
;
244 unsigned int shi2_max_uses
;
245 unsigned int shi2_current_uses
;
246 const char *shi2_path
;
247 const char *shi2_passwd
;
250 static NET_API_STATUS
share_info_2_to_samba( const BYTE
*buf
, unsigned char **bufptr
)
252 struct share_info_2
*ret
;
253 SHARE_INFO_2
*info
= (SHARE_INFO_2
*)buf
;
257 if (info
->shi2_netname
)
258 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_netname
, -1, NULL
, 0, NULL
, NULL
);
259 if (info
->shi2_remark
)
260 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_remark
, -1, NULL
, 0, NULL
, NULL
);
262 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_path
, -1, NULL
, 0, NULL
, NULL
);
263 if (info
->shi2_passwd
)
264 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_passwd
, -1, NULL
, 0, NULL
, NULL
);
265 if (!(ret
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret
) + len
)))
266 return ERROR_OUTOFMEMORY
;
268 ptr
= (char *)(ret
+ 1);
269 if (!info
->shi2_netname
) ret
->shi2_netname
= NULL
;
272 ret
->shi2_netname
= ptr
;
273 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_netname
, -1, ptr
, len
, NULL
, NULL
);
275 ret
->shi2_type
= info
->shi2_type
;
276 if (!info
->shi2_remark
) ret
->shi2_remark
= NULL
;
279 ret
->shi2_remark
= ptr
;
280 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_remark
, -1, ptr
, len
, NULL
, NULL
);
282 ret
->shi2_permissions
= info
->shi2_permissions
;
283 ret
->shi2_max_uses
= info
->shi2_max_uses
;
284 ret
->shi2_current_uses
= info
->shi2_current_uses
;
285 if (!info
->shi2_path
) ret
->shi2_path
= NULL
;
288 ret
->shi2_path
= ptr
;
289 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_path
, -1, ptr
, len
, NULL
, NULL
);
291 if (!info
->shi2_passwd
) ret
->shi2_passwd
= NULL
;
294 ret
->shi2_passwd
= ptr
;
295 WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_passwd
, -1, ptr
, len
, NULL
, NULL
);
297 *bufptr
= (unsigned char *)ret
;
303 unsigned char sid_rev_num
;
304 unsigned char num_auths
;
305 unsigned char id_auth
[6];
306 unsigned int sub_auths
[15];
311 ACE_TYPE_ACCESS_ALLOWED
,
312 ACE_TYPE_ACCESS_DENIED
,
313 ACE_TYPE_SYSTEM_AUDIT
,
314 ACE_TYPE_SYSTEM_ALARM
,
315 ACE_TYPE_ALLOWED_COMPOUND
,
316 ACE_TYPE_ACCESS_ALLOWED_OBJECT
,
317 ACE_TYPE_ACCESS_DENIED_OBJECT
,
318 ACE_TYPE_SYSTEM_AUDIT_OBJECT
,
319 ACE_TYPE_SYSTEM_ALARM_OBJECT
322 #define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
323 #define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
324 #define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
325 #define SEC_ACE_FLAG_INHERIT_ONLY 0x08
326 #define SEC_ACE_FLAG_INHERITED_ACE 0x10
327 #define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
328 #define SEC_ACE_FLAG_FAILED_ACCESS 0x80
332 unsigned int time_low
;
333 unsigned short time_mid
;
334 unsigned short time_hi_and_version
;
335 unsigned char clock_seq
[2];
336 unsigned char node
[6];
339 union ace_object_type
344 union ace_object_inherited_type
346 struct guid inherited_type
;
352 union ace_object_type type
;
353 union ace_object_inherited_type inherited_type
;
358 struct ace_object object
;
366 unsigned int access_mask
;
367 union ace_object_ctr object
;
373 ACL_REVISION_NT4
= 2,
379 enum acl_revision revision
;
381 unsigned int num_aces
;
385 enum security_descriptor_revision
387 SECURITY_DESCRIPTOR_REVISION_1
= 1
390 #define SEC_DESC_OWNER_DEFAULTED 0x0001
391 #define SEC_DESC_GROUP_DEFAULTED 0x0002
392 #define SEC_DESC_DACL_PRESENT 0x0004
393 #define SEC_DESC_DACL_DEFAULTED 0x0008
394 #define SEC_DESC_SACL_PRESENT 0x0010
395 #define SEC_DESC_SACL_DEFAULTED 0x0020
396 #define SEC_DESC_DACL_TRUSTED 0x0040
397 #define SEC_DESC_SERVER_SECURITY 0x0080
398 #define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
399 #define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
400 #define SEC_DESC_DACL_AUTO_INHERITED 0x0400
401 #define SEC_DESC_SACL_AUTO_INHERITED 0x0800
402 #define SEC_DESC_DACL_PROTECTED 0x1000
403 #define SEC_DESC_SACL_PROTECTED 0x2000
404 #define SEC_DESC_RM_CONTROL_VALID 0x4000
405 #define SEC_DESC_SELF_RELATIVE 0x8000
407 struct security_descriptor
409 enum security_descriptor_revision revision
;
411 struct sid
*owner_sid
;
412 struct sid
*group_sid
;
417 struct share_info_502
419 const char *shi502_netname
;
420 unsigned int shi502_type
;
421 const char *shi502_remark
;
422 unsigned int shi502_permissions
;
423 unsigned int shi502_max_uses
;
424 unsigned int shi502_current_uses
;
425 const char *shi502_path
;
426 const char *shi502_passwd
;
427 unsigned int shi502_reserved
;
428 struct security_descriptor
*shi502_security_descriptor
;
431 static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control
)
433 unsigned short ret
= 0;
435 if (control
& SE_OWNER_DEFAULTED
) ret
|= SEC_DESC_OWNER_DEFAULTED
;
436 if (control
& SE_GROUP_DEFAULTED
) ret
|= SEC_DESC_GROUP_DEFAULTED
;
437 if (control
& SE_DACL_PRESENT
) ret
|= SEC_DESC_DACL_PRESENT
;
438 if (control
& SE_DACL_DEFAULTED
) ret
|= SEC_DESC_DACL_DEFAULTED
;
439 if (control
& SE_SACL_PRESENT
) ret
|= SEC_DESC_SACL_PRESENT
;
440 if (control
& SE_SACL_DEFAULTED
) ret
|= SEC_DESC_SACL_DEFAULTED
;
441 if (control
& SE_DACL_AUTO_INHERIT_REQ
) ret
|= SEC_DESC_DACL_AUTO_INHERIT_REQ
;
442 if (control
& SE_SACL_AUTO_INHERIT_REQ
) ret
|= SEC_DESC_SACL_AUTO_INHERIT_REQ
;
443 if (control
& SE_DACL_AUTO_INHERITED
) ret
|= SEC_DESC_DACL_AUTO_INHERITED
;
444 if (control
& SE_SACL_AUTO_INHERITED
) ret
|= SEC_DESC_SACL_AUTO_INHERITED
;
445 if (control
& SE_DACL_PROTECTED
) ret
|= SEC_DESC_DACL_PROTECTED
;
446 if (control
& SE_SACL_PROTECTED
) ret
|= SEC_DESC_SACL_PROTECTED
;
447 if (control
& SE_RM_CONTROL_VALID
) ret
|= SEC_DESC_RM_CONTROL_VALID
;
451 static NET_API_STATUS
sid_to_samba( const SID
*src
, struct sid
*dst
)
455 if (src
->Revision
!= 1)
457 ERR( "unknown revision %u\n", src
->Revision
);
458 return ERROR_UNKNOWN_REVISION
;
460 if (src
->SubAuthorityCount
> SID_MAX_SUB_AUTHORITIES
)
462 WARN( "invalid subauthority count %u\n", src
->SubAuthorityCount
);
463 return ERROR_INVALID_PARAMETER
;
465 dst
->sid_rev_num
= SECURITY_DESCRIPTOR_REVISION_1
;
466 dst
->num_auths
= src
->SubAuthorityCount
;
467 for (i
= 0; i
< 6; i
++) dst
->id_auth
[i
] = src
->IdentifierAuthority
.Value
[i
];
468 for (i
= 0; i
< dst
->num_auths
; i
++) dst
->sub_auths
[i
] = src
->SubAuthority
[i
];
472 static enum ace_type
ace_type_to_samba( BYTE type
)
476 case ACCESS_ALLOWED_ACE_TYPE
: return ACE_TYPE_ACCESS_ALLOWED
;
477 case ACCESS_DENIED_ACE_TYPE
: return ACE_TYPE_ACCESS_DENIED
;
478 case SYSTEM_AUDIT_ACE_TYPE
: return ACE_TYPE_SYSTEM_AUDIT
;
479 case SYSTEM_ALARM_ACE_TYPE
: return ACE_TYPE_SYSTEM_ALARM
;
481 ERR( "unhandled type %u\n", type
);
486 static unsigned char ace_flags_to_samba( BYTE flags
)
488 static const BYTE known_flags
=
489 OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| NO_PROPAGATE_INHERIT_ACE
|
490 INHERIT_ONLY_ACE
| INHERITED_ACE
| SUCCESSFUL_ACCESS_ACE_FLAG
| FAILED_ACCESS_ACE_FLAG
;
491 unsigned char ret
= 0;
493 if (flags
& ~known_flags
)
495 ERR( "unknown flags %x\n", flags
& ~known_flags
);
498 if (flags
& OBJECT_INHERIT_ACE
) ret
|= SEC_ACE_FLAG_OBJECT_INHERIT
;
499 if (flags
& CONTAINER_INHERIT_ACE
) ret
|= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
;
500 if (flags
& NO_PROPAGATE_INHERIT_ACE
) ret
|= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
;
501 if (flags
& INHERIT_ONLY_ACE
) ret
|= SEC_ACE_FLAG_INHERIT_ONLY
;
502 if (flags
& INHERITED_ACE
) ret
|= SEC_ACE_FLAG_INHERITED_ACE
;
503 if (flags
& SUCCESSFUL_ACCESS_ACE_FLAG
) ret
|= SEC_ACE_FLAG_SUCCESSFUL_ACCESS
;
504 if (flags
& FAILED_ACCESS_ACE_FLAG
) ret
|= SEC_ACE_FLAG_FAILED_ACCESS
;
508 #define GENERIC_ALL_ACCESS (1 << 28)
509 #define GENERIC_EXECUTE_ACCESS (1 << 29)
510 #define GENERIC_WRITE_ACCESS (1 << 30)
511 #define GENERIC_READ_ACCESS (1 << 31)
513 static unsigned int access_mask_to_samba( DWORD mask
)
515 static const DWORD known_rights
=
516 GENERIC_ALL
| GENERIC_EXECUTE
| GENERIC_WRITE
| GENERIC_READ
;
517 unsigned int ret
= 0;
519 if (mask
& ~known_rights
)
521 ERR( "unknown rights %x\n", mask
& ~known_rights
);
524 if (mask
& GENERIC_ALL
) ret
|= GENERIC_ALL_ACCESS
;
525 if (mask
& GENERIC_EXECUTE
) ret
|= GENERIC_EXECUTE_ACCESS
;
526 if (mask
& GENERIC_WRITE
) ret
|= GENERIC_WRITE_ACCESS
;
527 if (mask
& GENERIC_READ
) ret
|= GENERIC_READ_ACCESS
;
531 static NET_API_STATUS
ace_to_samba( const ACE_HEADER
*src
, struct ace
*dst
)
533 dst
->type
= ace_type_to_samba( src
->AceType
);
534 dst
->flags
= ace_flags_to_samba( src
->AceFlags
);
535 dst
->size
= sizeof(*dst
);
536 switch (src
->AceType
)
538 case ACCESS_ALLOWED_ACE_TYPE
:
540 ACCESS_ALLOWED_ACE
*ace
= (ACCESS_ALLOWED_ACE
*)src
;
541 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
542 memset( &dst
->object
, 0, sizeof(dst
->object
) );
543 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
546 case ACCESS_DENIED_ACE_TYPE
:
548 ACCESS_DENIED_ACE
*ace
= (ACCESS_DENIED_ACE
*)src
;
549 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
550 memset( &dst
->object
, 0, sizeof(dst
->object
) );
551 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
554 case SYSTEM_AUDIT_ACE_TYPE
:
556 SYSTEM_AUDIT_ACE
*ace
= (SYSTEM_AUDIT_ACE
*)src
;
557 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
558 memset( &dst
->object
, 0, sizeof(dst
->object
) );
559 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
562 case SYSTEM_ALARM_ACE_TYPE
:
564 SYSTEM_ALARM_ACE
*ace
= (SYSTEM_ALARM_ACE
*)src
;
565 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
566 memset( &dst
->object
, 0, sizeof(dst
->object
) );
567 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
571 ERR( "unhandled type %u\n", src
->AceType
);
572 return ERROR_INVALID_PARAMETER
;
577 static NET_API_STATUS
acl_to_samba( const ACL
*src
, struct acl
*dst
)
579 NET_API_STATUS status
;
583 switch (src
->AclRevision
)
586 dst
->revision
= ACL_REVISION_ADS
;
589 ERR( "unkhandled revision %u\n", src
->AclRevision
);
590 return ERROR_UNKNOWN_REVISION
;
592 dst
->size
= sizeof(*dst
);
593 src_ace
= (ACE_HEADER
*)(src
+ 1);
594 dst
->aces
= (struct ace
*)(dst
+ 1);
595 for (i
= 0; i
< src
->AceCount
; i
++)
597 if ((status
= ace_to_samba( src_ace
, &dst
->aces
[i
] ))) return status
;
598 src_ace
= (ACE_HEADER
*)((char *)src_ace
+ src_ace
->AceSize
);
599 dst
->size
+= dst
->aces
[i
].size
;
604 #define SELF_RELATIVE_FIELD(sd,field)\
605 ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
607 static NET_API_STATUS
sd_to_samba( const SECURITY_DESCRIPTOR
*src
, struct security_descriptor
*dst
)
609 NET_API_STATUS status
;
610 const SID
*owner
, *group
;
611 const ACL
*dacl
, *sacl
;
612 unsigned int offset
= sizeof(*dst
);
614 if (src
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
615 return ERROR_UNKNOWN_REVISION
;
617 dst
->revision
= SECURITY_DESCRIPTOR_REVISION_1
;
618 dst
->type
= sd_control_to_samba( src
->Control
);
620 if (src
->Control
& SE_SELF_RELATIVE
)
622 if (!src
->Owner
) dst
->owner_sid
= NULL
;
625 dst
->owner_sid
= (struct sid
*)((char *)dst
+ offset
);
626 owner
= (const SID
*)SELF_RELATIVE_FIELD( src
, Owner
);
627 if ((status
= sid_to_samba( owner
, dst
->owner_sid
))) return status
;
628 offset
+= sizeof(struct sid
);
630 if (!src
->Group
) dst
->group_sid
= NULL
;
633 dst
->group_sid
= (struct sid
*)((char *)dst
+ offset
);
634 group
= (const SID
*)SELF_RELATIVE_FIELD( src
, Group
);
635 if ((status
= sid_to_samba( group
, dst
->group_sid
))) return status
;
636 offset
+= sizeof(struct sid
);
638 if (!(src
->Control
& SE_SACL_PRESENT
)) dst
->sacl
= NULL
;
641 dst
->sacl
= (struct acl
*)((char *)dst
+ offset
);
642 sacl
= (const ACL
*)SELF_RELATIVE_FIELD( src
, Sacl
);
643 if ((status
= acl_to_samba( sacl
, dst
->sacl
))) return status
;
644 offset
+= dst
->sacl
->size
;
646 if (!(src
->Control
& SE_DACL_PRESENT
)) dst
->dacl
= NULL
;
649 dst
->dacl
= (struct acl
*)((char *)dst
+ offset
);
650 dacl
= (const ACL
*)SELF_RELATIVE_FIELD( src
, Dacl
);
651 if ((status
= acl_to_samba( dacl
, dst
->dacl
))) return status
;
656 if (!src
->Owner
) dst
->owner_sid
= NULL
;
659 dst
->owner_sid
= (struct sid
*)((char *)dst
+ offset
);
660 if ((status
= sid_to_samba( src
->Owner
, dst
->owner_sid
))) return status
;
661 offset
+= sizeof(struct sid
);
663 if (!src
->Group
) dst
->group_sid
= NULL
;
666 dst
->group_sid
= (struct sid
*)((char *)dst
+ offset
);
667 if ((status
= sid_to_samba( src
->Group
, dst
->group_sid
))) return status
;
668 offset
+= sizeof(struct sid
);
670 if (!(src
->Control
& SE_SACL_PRESENT
)) dst
->sacl
= NULL
;
673 dst
->sacl
= (struct acl
*)((char *)dst
+ offset
);
674 if ((status
= acl_to_samba( src
->Sacl
, dst
->sacl
))) return status
;
675 offset
+= dst
->sacl
->size
;
677 if (!(src
->Control
& SE_DACL_PRESENT
)) dst
->dacl
= NULL
;
680 dst
->dacl
= (struct acl
*)((char *)dst
+ offset
);
681 if ((status
= acl_to_samba( src
->Dacl
, dst
->dacl
))) return status
;
687 static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR
*sd
)
689 unsigned int ret
= sizeof(struct security_descriptor
);
691 if (sd
->Owner
) ret
+= sizeof(struct sid
);
692 if (sd
->Group
) ret
+= sizeof(struct sid
);
693 if (sd
->Control
& SE_SACL_PRESENT
)
694 ret
+= sizeof(struct acl
) + sd
->Sacl
->AceCount
* sizeof(struct ace
);
695 if (sd
->Control
& SE_DACL_PRESENT
)
696 ret
+= sizeof(struct acl
) + sd
->Dacl
->AceCount
* sizeof(struct ace
);
700 static NET_API_STATUS
share_info_502_to_samba( const BYTE
*buf
, unsigned char **bufptr
)
702 NET_API_STATUS status
;
703 struct share_info_502
*ret
;
704 SHARE_INFO_502
*info
= (SHARE_INFO_502
*)buf
;
705 DWORD len
= 0, size
= 0;
709 if (info
->shi502_netname
)
710 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_netname
, -1, NULL
, 0, NULL
, NULL
);
711 if (info
->shi502_remark
)
712 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_remark
, -1, NULL
, 0, NULL
, NULL
);
713 if (info
->shi502_path
)
714 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_path
, -1, NULL
, 0, NULL
, NULL
);
715 if (info
->shi502_passwd
)
716 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_passwd
, -1, NULL
, 0, NULL
, NULL
);
717 if (info
->shi502_security_descriptor
)
718 size
= sd_to_samba_size( info
->shi502_security_descriptor
);
719 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ret
) + (len
* sizeof(WCHAR
)) + size
)))
720 return ERROR_OUTOFMEMORY
;
722 ptr
= (char *)(ret
+ 1);
723 if (!info
->shi502_netname
) ret
->shi502_netname
= NULL
;
726 ret
->shi502_netname
= ptr
;
727 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_netname
, -1, ptr
, len
, NULL
, NULL
);
729 ret
->shi502_type
= info
->shi502_type
;
730 if (!info
->shi502_remark
) ret
->shi502_remark
= NULL
;
733 ret
->shi502_remark
= ptr
;
734 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_remark
, -1, ptr
, len
, NULL
, NULL
);
736 ret
->shi502_permissions
= info
->shi502_permissions
;
737 ret
->shi502_max_uses
= info
->shi502_max_uses
;
738 ret
->shi502_current_uses
= info
->shi502_current_uses
;
739 if (!info
->shi502_path
) ret
->shi502_path
= NULL
;
742 ret
->shi502_path
= ptr
;
743 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_path
, -1, ptr
, len
, NULL
, NULL
);
745 if (!info
->shi502_passwd
) ret
->shi502_passwd
= NULL
;
748 ret
->shi502_passwd
= ptr
;
749 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_passwd
, -1, ptr
, len
, NULL
, NULL
);
751 ret
->shi502_reserved
= info
->shi502_reserved
;
752 if (!info
->shi502_security_descriptor
) ret
->shi502_security_descriptor
= NULL
;
755 status
= sd_to_samba( info
->shi502_security_descriptor
, (struct security_descriptor
*)ptr
);
758 HeapFree( GetProcessHeap(), 0, ret
);
761 ret
->shi502_security_descriptor
= (struct security_descriptor
*)ptr
;
763 *bufptr
= (unsigned char *)ret
;
767 static NET_API_STATUS
share_info_to_samba( DWORD level
, const BYTE
*buf
, unsigned char **bufptr
)
771 case 2: return share_info_2_to_samba( buf
, bufptr
);
772 case 502: return share_info_502_to_samba( buf
, bufptr
);
774 FIXME( "level %u not supported\n", level
);
775 return ERROR_NOT_SUPPORTED
;
779 static NET_API_STATUS
share_add( LMSTR servername
, DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
783 NET_API_STATUS status
;
785 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
786 status
= share_info_to_samba( level
, buf
, &info
);
791 status
= pNetShareAdd( server
, level
, info
, &err
);
792 HeapFree( GetProcessHeap(), 0, info
);
793 if (parm_err
) *parm_err
= err
;
795 HeapFree( GetProcessHeap(), 0, server
);
799 static NET_API_STATUS
share_del( LMSTR servername
, LMSTR netname
, DWORD reserved
)
801 char *server
= NULL
, *share
;
802 NET_API_STATUS status
;
804 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
805 if (!(share
= strdup_unixcp( netname
)))
807 HeapFree( GetProcessHeap(), 0, server
);
808 return ERROR_OUTOFMEMORY
;
810 status
= pNetShareDel( server
, share
, reserved
);
811 HeapFree( GetProcessHeap(), 0, server
);
812 HeapFree( GetProcessHeap(), 0, share
);
816 struct wksta_info_100
818 unsigned int wki100_platform_id
;
819 const char *wki100_computername
;
820 const char *wki100_langroup
;
821 unsigned int wki100_ver_major
;
822 unsigned int wki100_ver_minor
;
825 static NET_API_STATUS
wksta_info_100_from_samba( const unsigned char *buf
, BYTE
**bufptr
)
828 struct wksta_info_100
*info
= (struct wksta_info_100
*)buf
;
832 if (info
->wki100_computername
)
833 len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_computername
, -1, NULL
, 0 );
834 if (info
->wki100_langroup
)
835 len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_langroup
, -1, NULL
, 0 );
836 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ret
) + (len
* sizeof(WCHAR
) ))))
837 return ERROR_OUTOFMEMORY
;
839 ptr
= (WCHAR
*)(ret
+ 1);
840 ret
->wki100_platform_id
= info
->wki100_platform_id
;
841 if (!info
->wki100_computername
) ret
->wki100_computername
= NULL
;
844 ret
->wki100_computername
= ptr
;
845 ptr
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_computername
, -1, ptr
, len
);
847 if (!info
->wki100_langroup
) ret
->wki100_langroup
= NULL
;
850 ret
->wki100_langroup
= ptr
;
851 MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_langroup
, -1, ptr
, len
);
853 ret
->wki100_ver_major
= info
->wki100_ver_major
;
854 ret
->wki100_ver_minor
= info
->wki100_ver_minor
;
855 *bufptr
= (BYTE
*)ret
;
859 static NET_API_STATUS
wksta_info_from_samba( DWORD level
, const unsigned char *buf
, BYTE
**bufptr
)
863 case 100: return wksta_info_100_from_samba( buf
, bufptr
);
865 FIXME( "level %u not supported\n", level
);
866 return ERROR_NOT_SUPPORTED
;
870 static NET_API_STATUS
wksta_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
872 NET_API_STATUS status
;
874 unsigned char *buf
= NULL
;
876 if (servername
&& !(wksta
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
877 status
= pNetWkstaGetInfo( wksta
, level
, &buf
);
878 HeapFree( GetProcessHeap(), 0, wksta
);
881 status
= wksta_info_from_samba( level
, buf
, bufptr
);
882 pNetApiBufferFree( buf
);
889 static BOOL
libnetapi_init(void)
894 static NET_API_STATUS
server_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
897 return ERROR_NOT_SUPPORTED
;
899 static NET_API_STATUS
share_add( LMSTR servername
, DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
902 return ERROR_NOT_SUPPORTED
;
904 static NET_API_STATUS
share_del( LMSTR servername
, LMSTR netname
, DWORD reserved
)
907 return ERROR_NOT_SUPPORTED
;
909 static NET_API_STATUS
wksta_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
912 return ERROR_NOT_SUPPORTED
;
915 #endif /* SONAME_LIBNETAPI */
917 /************************************************************
918 * NETAPI_IsLocalComputer
920 * Checks whether the server name indicates local machine.
922 static BOOL
NETAPI_IsLocalComputer( LMCSTR name
)
924 WCHAR buf
[MAX_COMPUTERNAME_LENGTH
+ 1];
925 DWORD size
= sizeof(buf
) / sizeof(buf
[0]);
928 if (!name
|| !name
[0]) return TRUE
;
930 ret
= GetComputerNameW( buf
, &size
);
931 if (ret
&& name
[0] == '\\' && name
[1] == '\\') name
+= 2;
932 return ret
&& !strcmpiW( name
, buf
);
935 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
937 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
940 case DLL_PROCESS_ATTACH
:
941 DisableThreadLibraryCalls(hinstDLL
);
945 case DLL_PROCESS_DETACH
:
946 if (lpvReserved
) break;
954 /************************************************************
955 * NetServerEnum (NETAPI32.@)
957 NET_API_STATUS WINAPI
NetServerEnum(
963 LPDWORD totalentries
,
966 LPDWORD resume_handle
969 FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(servername
),
970 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, servertype
,
971 debugstr_w(domain
), resume_handle
);
973 return ERROR_NO_BROWSER_SERVERS_FOUND
;
976 /************************************************************
977 * NetServerEnumEx (NETAPI32.@)
979 NET_API_STATUS WINAPI
NetServerEnumEx(
985 LPDWORD totalentries
,
988 LMCSTR FirstNameToReturn
)
990 FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
991 debugstr_w(ServerName
), Level
, Bufptr
, PrefMaxlen
, EntriesRead
, totalentries
,
992 servertype
, debugstr_w(domain
), debugstr_w(FirstNameToReturn
));
994 return ERROR_NO_BROWSER_SERVERS_FOUND
;
997 /************************************************************
998 * NetServerDiskEnum (NETAPI32.@)
1000 NET_API_STATUS WINAPI
NetServerDiskEnum(
1005 LPDWORD EntriesRead
,
1006 LPDWORD totalentries
,
1007 LPDWORD Resume_Handle
)
1009 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName
),
1010 Level
, Bufptr
, PrefMaxlen
, EntriesRead
, totalentries
, Resume_Handle
);
1012 return ERROR_NO_BROWSER_SERVERS_FOUND
;
1015 /************************************************************
1016 * NetServerGetInfo (NETAPI32.@)
1018 NET_API_STATUS WINAPI
NetServerGetInfo(LMSTR servername
, DWORD level
, LPBYTE
* bufptr
)
1021 BOOL local
= NETAPI_IsLocalComputer( servername
);
1023 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
1027 if (libnetapi_init()) return server_getinfo( servername
, level
, bufptr
);
1028 FIXME( "remote computers not supported\n" );
1029 return ERROR_INVALID_LEVEL
;
1031 if (!bufptr
) return ERROR_INVALID_PARAMETER
;
1038 DWORD computerNameLen
, size
;
1039 WCHAR computerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1041 computerNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
1042 GetComputerNameW(computerName
, &computerNameLen
);
1043 computerNameLen
++; /* include NULL terminator */
1045 size
= sizeof(SERVER_INFO_101
) + computerNameLen
* sizeof(WCHAR
);
1046 ret
= NetApiBufferAllocate(size
, (LPVOID
*)bufptr
);
1047 if (ret
== NERR_Success
)
1049 /* INFO_100 structure is a subset of INFO_101 */
1050 PSERVER_INFO_101 info
= (PSERVER_INFO_101
)*bufptr
;
1051 OSVERSIONINFOW verInfo
;
1053 info
->sv101_platform_id
= PLATFORM_ID_NT
;
1054 info
->sv101_name
= (LMSTR
)(*bufptr
+ sizeof(SERVER_INFO_101
));
1055 memcpy(info
->sv101_name
, computerName
,
1056 computerNameLen
* sizeof(WCHAR
));
1057 verInfo
.dwOSVersionInfoSize
= sizeof(verInfo
);
1058 GetVersionExW(&verInfo
);
1059 info
->sv101_version_major
= verInfo
.dwMajorVersion
;
1060 info
->sv101_version_minor
= verInfo
.dwMinorVersion
;
1061 /* Use generic type as no wine equivalent of DC / Server */
1062 info
->sv101_type
= SV_TYPE_NT
;
1063 info
->sv101_comment
= NULL
;
1069 FIXME("level %d unimplemented\n", level
);
1070 ret
= ERROR_INVALID_LEVEL
;
1076 /************************************************************
1077 * NetStatisticsGet (NETAPI32.@)
1079 NET_API_STATUS WINAPI
NetStatisticsGet(LMSTR server
, LMSTR service
,
1080 DWORD level
, DWORD options
,
1083 TRACE("(%p, %p, %d, %d, %p)\n", server
, service
, level
, options
, bufptr
);
1084 return NERR_InternalError
;
1087 NET_API_STATUS WINAPI
NetUseEnum(LMSTR server
, DWORD level
, LPBYTE
* bufptr
, DWORD prefmaxsize
,
1088 LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resumehandle
)
1090 FIXME("stub (%p, %d, %p, %d, %p, %p, %p)\n", server
, level
, bufptr
, prefmaxsize
,
1091 entriesread
, totalentries
, resumehandle
);
1092 return ERROR_NOT_SUPPORTED
;
1095 NET_API_STATUS WINAPI
NetScheduleJobAdd(LPCWSTR server
, LPBYTE bufptr
, LPDWORD jobid
)
1097 FIXME("stub (%s, %p, %p)\n", debugstr_w(server
), bufptr
, jobid
);
1098 return NERR_Success
;
1101 NET_API_STATUS WINAPI
NetScheduleJobDel(LPCWSTR server
, DWORD minjobid
, DWORD maxjobid
)
1103 FIXME("stub (%s, %d, %d)\n", debugstr_w(server
), minjobid
, maxjobid
);
1104 return NERR_Success
;
1107 NET_API_STATUS WINAPI
NetScheduleJobEnum(LPCWSTR server
, LPBYTE
* bufptr
, DWORD prefmaxsize
, LPDWORD entriesread
,
1108 LPDWORD totalentries
, LPDWORD resumehandle
)
1110 FIXME("stub (%s, %p, %d, %p, %p, %p)\n", debugstr_w(server
), bufptr
, prefmaxsize
, entriesread
, totalentries
, resumehandle
);
1113 return NERR_Success
;
1116 NET_API_STATUS WINAPI
NetUseGetInfo(LMSTR server
, LMSTR name
, DWORD level
, LPBYTE
*bufptr
)
1118 FIXME("stub (%p, %p, %d, %p)\n", server
, name
, level
, bufptr
);
1119 return ERROR_NOT_SUPPORTED
;
1123 /************************************************************
1124 * NetApiBufferAllocate (NETAPI32.@)
1126 NET_API_STATUS WINAPI
NetApiBufferAllocate(DWORD ByteCount
, LPVOID
* Buffer
)
1128 TRACE("(%d, %p)\n", ByteCount
, Buffer
);
1130 if (Buffer
== NULL
) return ERROR_INVALID_PARAMETER
;
1131 *Buffer
= HeapAlloc(GetProcessHeap(), 0, ByteCount
);
1133 return NERR_Success
;
1135 return GetLastError();
1138 /************************************************************
1139 * NetApiBufferFree (NETAPI32.@)
1141 NET_API_STATUS WINAPI
NetApiBufferFree(LPVOID Buffer
)
1143 TRACE("(%p)\n", Buffer
);
1144 HeapFree(GetProcessHeap(), 0, Buffer
);
1145 return NERR_Success
;
1148 /************************************************************
1149 * NetApiBufferReallocate (NETAPI32.@)
1151 NET_API_STATUS WINAPI
NetApiBufferReallocate(LPVOID OldBuffer
, DWORD NewByteCount
,
1154 TRACE("(%p, %d, %p)\n", OldBuffer
, NewByteCount
, NewBuffer
);
1158 *NewBuffer
= HeapReAlloc(GetProcessHeap(), 0, OldBuffer
, NewByteCount
);
1160 *NewBuffer
= HeapAlloc(GetProcessHeap(), 0, NewByteCount
);
1161 return *NewBuffer
? NERR_Success
: GetLastError();
1165 if (!HeapFree(GetProcessHeap(), 0, OldBuffer
)) return GetLastError();
1167 return NERR_Success
;
1171 /************************************************************
1172 * NetApiBufferSize (NETAPI32.@)
1174 NET_API_STATUS WINAPI
NetApiBufferSize(LPVOID Buffer
, LPDWORD ByteCount
)
1178 TRACE("(%p, %p)\n", Buffer
, ByteCount
);
1180 return ERROR_INVALID_PARAMETER
;
1181 dw
= HeapSize(GetProcessHeap(), 0, Buffer
);
1182 TRACE("size: %d\n", dw
);
1183 if (dw
!= 0xFFFFFFFF)
1188 return NERR_Success
;
1191 /************************************************************
1192 * NetSessionEnum (NETAPI32.@)
1195 * servername [I] Pointer to a string with the name of the server
1196 * UncClientName [I] Pointer to a string with the name of the session
1197 * username [I] Pointer to a string with the name of the user
1198 * level [I] Data information level
1199 * bufptr [O] Buffer to the data
1200 * prefmaxlen [I] Preferred maximum length of the data
1201 * entriesread [O] Pointer to the number of entries enumerated
1202 * totalentries [O] Pointer to the possible number of entries
1203 * resume_handle [I/O] Pointer to a handle for subsequent searches
1206 * If successful, the function returns NERR_Success
1207 * On failure it returns:
1208 * ERROR_ACCESS_DENIED User has no access to the requested information
1209 * ERROR_INVALID_LEVEL Value of 'level' is not correct
1210 * ERROR_INVALID_PARAMETER Wrong parameter
1211 * ERROR_MORE_DATA Need a larger buffer
1212 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
1213 * NERR_ClientNameNotFound A session does not exist on a given computer
1214 * NERR_InvalidComputer Invalid computer name
1215 * NERR_UserNotFound User name could not be found.
1217 NET_API_STATUS WINAPI
NetSessionEnum(LMSTR servername
, LMSTR UncClientName
,
1218 LMSTR username
, DWORD level
, LPBYTE
* bufptr
, DWORD prefmaxlen
, LPDWORD entriesread
,
1219 LPDWORD totalentries
, LPDWORD resume_handle
)
1221 FIXME("Stub (%s %s %s %d %p %d %p %p %p)\n", debugstr_w(servername
),
1222 debugstr_w(UncClientName
), debugstr_w(username
),
1223 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1225 return NERR_Success
;
1228 /************************************************************
1229 * NetShareEnum (NETAPI32.@)
1232 * servername [I] Pointer to a string with the name of the server
1233 * level [I] Data information level
1234 * bufptr [O] Buffer to the data
1235 * prefmaxlen [I] Preferred maximum length of the data
1236 * entriesread [O] Pointer to the number of entries enumerated
1237 * totalentries [O] Pointer to the possible number of entries
1238 * resume_handle [I/O] Pointer to a handle for subsequent searches
1241 * If successful, the function returns NERR_Success
1242 * On failure it returns a system error code (FIXME: find out which)
1245 NET_API_STATUS WINAPI
NetShareEnum( LMSTR servername
, DWORD level
, LPBYTE
* bufptr
,
1246 DWORD prefmaxlen
, LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resume_handle
)
1248 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(servername
), level
, bufptr
,
1249 prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1251 return ERROR_NOT_SUPPORTED
;
1254 /************************************************************
1255 * NetShareDel (NETAPI32.@)
1257 NET_API_STATUS WINAPI
NetShareDel(LMSTR servername
, LMSTR netname
, DWORD reserved
)
1259 BOOL local
= NETAPI_IsLocalComputer( servername
);
1261 TRACE("%s %s %d\n", debugstr_w(servername
), debugstr_w(netname
), reserved
);
1265 if (libnetapi_init()) return share_del( servername
, netname
, reserved
);
1266 FIXME( "remote computers not supported\n" );
1269 FIXME("%s %s %d\n", debugstr_w(servername
), debugstr_w(netname
), reserved
);
1270 return NERR_Success
;
1273 /************************************************************
1274 * NetShareGetInfo (NETAPI32.@)
1276 NET_API_STATUS WINAPI
NetShareGetInfo(LMSTR servername
, LMSTR netname
,
1277 DWORD level
, LPBYTE
*bufptr
)
1279 FIXME("Stub (%s %s %d %p)\n", debugstr_w(servername
),
1280 debugstr_w(netname
),level
, bufptr
);
1281 return NERR_NetNameNotFound
;
1284 /************************************************************
1285 * NetShareAdd (NETAPI32.@)
1287 NET_API_STATUS WINAPI
NetShareAdd(LMSTR servername
,
1288 DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
1290 BOOL local
= NETAPI_IsLocalComputer( servername
);
1292 TRACE("%s %d %p %p\n", debugstr_w(servername
), level
, buf
, parm_err
);
1296 if (libnetapi_init()) return share_add( servername
, level
, buf
, parm_err
);
1297 FIXME( "remote computers not supported\n" );
1300 FIXME("%s %d %p %p\n", debugstr_w(servername
), level
, buf
, parm_err
);
1301 return ERROR_NOT_SUPPORTED
;
1304 /************************************************************
1305 * NetFileEnum (NETAPI32.@)
1307 NET_API_STATUS WINAPI
NetFileEnum(
1308 LPWSTR ServerName
, LPWSTR BasePath
, LPWSTR UserName
,
1309 DWORD Level
, LPBYTE
* BufPtr
, DWORD PrefMaxLen
,
1310 LPDWORD EntriesRead
, LPDWORD TotalEntries
, PDWORD_PTR ResumeHandle
)
1312 FIXME("(%s, %s, %s, %u): stub\n", debugstr_w(ServerName
), debugstr_w(BasePath
),
1313 debugstr_w(UserName
), Level
);
1314 return ERROR_NOT_SUPPORTED
;
1317 static void wprint_mac(WCHAR
* buffer
, int len
, const MIB_IFROW
*ifRow
)
1332 for (i
= 0; i
< ifRow
->dwPhysAddrLen
&& 2 * i
< len
; i
++)
1334 val
= ifRow
->bPhysAddr
[i
];
1336 buffer
[2*i
] = (WCHAR
)((val
>>4) + 'A' - 10);
1338 buffer
[2*i
] = (WCHAR
)((val
>>4) + '0');
1339 if ((val
& 0xf ) >9)
1340 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + 'A' - 10);
1342 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + '0');
1347 /* Theoretically this could be too short, except that MS defines
1348 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
1349 * represent a count of WCHARs, so even with an extraordinarily long header
1350 * this will be plenty
1352 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
1353 #define MAX_TRANSPORT_ADDR 13
1355 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
1356 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
1358 static void wprint_name(WCHAR
*buffer
, int len
, ULONG transport
,
1372 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
1373 name
= NBT_TRANSPORT_NAME_HEADER
;
1375 name
= UNKNOWN_TRANSPORT_NAME_HEADER
;
1377 for (ptr1
= buffer
; *name
&& ptr1
< buffer
+ len
; ptr1
++, name
++)
1379 for (ptr2
= ifRow
->wszName
; *ptr2
&& ptr1
< buffer
+ len
; ptr1
++, ptr2
++)
1384 /***********************************************************************
1385 * NetWkstaTransportEnum (NETAPI32.@)
1388 struct WkstaTransportEnumData
1397 /**********************************************************************/
1399 static BOOL
WkstaEnumAdaptersCallback(UCHAR totalLANAs
, UCHAR lanaIndex
,
1400 ULONG transport
, const NetBIOSAdapterImpl
*data
, void *closure
)
1403 struct WkstaTransportEnumData
*enumData
= closure
;
1405 if (enumData
&& enumData
->pbuf
)
1411 enumData
->n_adapt
= totalLANAs
;
1412 enumData
->n_read
= 0;
1414 toAllocate
= totalLANAs
* (sizeof(WKSTA_TRANSPORT_INFO_0
)
1415 + MAX_TRANSPORT_NAME
* sizeof(WCHAR
) +
1416 MAX_TRANSPORT_ADDR
* sizeof(WCHAR
));
1417 if (enumData
->prefmaxlen
!= MAX_PREFERRED_LENGTH
)
1418 toAllocate
= enumData
->prefmaxlen
;
1419 NetApiBufferAllocate(toAllocate
, (LPVOID
*)enumData
->pbuf
);
1421 if (*(enumData
->pbuf
))
1425 if (enumData
->prefmaxlen
== MAX_PREFERRED_LENGTH
)
1426 spaceFor
= totalLANAs
;
1428 spaceFor
= enumData
->prefmaxlen
/
1429 (sizeof(WKSTA_TRANSPORT_INFO_0
) + (MAX_TRANSPORT_NAME
+
1430 MAX_TRANSPORT_ADDR
) * sizeof(WCHAR
));
1431 if (enumData
->n_read
< spaceFor
)
1433 PWKSTA_TRANSPORT_INFO_0 ti
;
1434 LMSTR transport_name
, transport_addr
;
1437 ti
= (PWKSTA_TRANSPORT_INFO_0
)(*(enumData
->pbuf
) +
1438 enumData
->n_read
* sizeof(WKSTA_TRANSPORT_INFO_0
));
1439 transport_name
= (LMSTR
)(*(enumData
->pbuf
) +
1440 totalLANAs
* sizeof(WKSTA_TRANSPORT_INFO_0
) +
1441 enumData
->n_read
* MAX_TRANSPORT_NAME
* sizeof(WCHAR
));
1442 transport_addr
= (LMSTR
)(*(enumData
->pbuf
) +
1443 totalLANAs
* (sizeof(WKSTA_TRANSPORT_INFO_0
) +
1444 MAX_TRANSPORT_NAME
* sizeof(WCHAR
)) +
1445 enumData
->n_read
* MAX_TRANSPORT_ADDR
* sizeof(WCHAR
));
1447 ifRow
.dwIndex
= data
->ifIndex
;
1449 ti
->wkti0_quality_of_service
= 0;
1450 ti
->wkti0_number_of_vcs
= 0;
1451 ti
->wkti0_transport_name
= transport_name
;
1452 wprint_name(ti
->wkti0_transport_name
, MAX_TRANSPORT_NAME
,
1454 ti
->wkti0_transport_address
= transport_addr
;
1455 wprint_mac(ti
->wkti0_transport_address
, MAX_TRANSPORT_ADDR
,
1457 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
1458 ti
->wkti0_wan_ish
= TRUE
;
1460 ti
->wkti0_wan_ish
= FALSE
;
1461 TRACE("%d of %d:ti at %p\n", lanaIndex
, totalLANAs
, ti
);
1462 TRACE("transport_name at %p %s\n",
1463 ti
->wkti0_transport_name
,
1464 debugstr_w(ti
->wkti0_transport_name
));
1465 TRACE("transport_address at %p %s\n",
1466 ti
->wkti0_transport_address
,
1467 debugstr_w(ti
->wkti0_transport_address
));
1469 enumData
->ret
= NERR_Success
;
1474 enumData
->ret
= ERROR_MORE_DATA
;
1480 enumData
->ret
= ERROR_OUTOFMEMORY
;
1489 /**********************************************************************/
1491 NET_API_STATUS WINAPI
1492 NetWkstaTransportEnum(LMSTR ServerName
, DWORD level
, PBYTE
* pbuf
,
1493 DWORD prefmaxlen
, LPDWORD read_entries
,
1494 PDWORD total_entries
, PDWORD hresume
)
1498 TRACE(":%s, 0x%08x, %p, 0x%08x, %p, %p, %p\n", debugstr_w(ServerName
),
1499 level
, pbuf
, prefmaxlen
, read_entries
, total_entries
,hresume
);
1500 if (!NETAPI_IsLocalComputer(ServerName
))
1502 FIXME(":not implemented for non-local computers\n");
1503 ret
= ERROR_INVALID_LEVEL
;
1507 if (hresume
&& *hresume
)
1509 FIXME(":resume handle not implemented\n");
1510 return ERROR_INVALID_LEVEL
;
1515 case 0: /* transport info */
1517 ULONG allTransports
;
1518 struct WkstaTransportEnumData enumData
;
1520 if (NetBIOSNumAdapters() == 0)
1521 return ERROR_NETWORK_UNREACHABLE
;
1523 return STATUS_ACCESS_VIOLATION
;
1524 if (!total_entries
|| !pbuf
)
1525 return RPC_X_NULL_REF_POINTER
;
1527 enumData
.prefmaxlen
= prefmaxlen
;
1528 enumData
.pbuf
= pbuf
;
1529 memcpy(&allTransports
, ALL_TRANSPORTS
, sizeof(ULONG
));
1530 NetBIOSEnumAdapters(allTransports
, WkstaEnumAdaptersCallback
,
1532 *read_entries
= enumData
.n_read
;
1533 *total_entries
= enumData
.n_adapt
;
1534 if (hresume
) *hresume
= 0;
1539 TRACE("Invalid level %d is specified\n", level
);
1540 ret
= ERROR_INVALID_LEVEL
;
1546 /************************************************************
1547 * NetWkstaUserGetInfo (NETAPI32.@)
1549 NET_API_STATUS WINAPI
NetWkstaUserGetInfo(LMSTR reserved
, DWORD level
,
1552 NET_API_STATUS nastatus
;
1554 TRACE("(%s, %d, %p)\n", debugstr_w(reserved
), level
, bufptr
);
1559 PWKSTA_USER_INFO_0 ui
;
1560 DWORD dwSize
= UNLEN
+ 1;
1563 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0
) + dwSize
* sizeof(WCHAR
),
1565 if (nastatus
!= NERR_Success
)
1566 return ERROR_NOT_ENOUGH_MEMORY
;
1568 ui
= (PWKSTA_USER_INFO_0
) *bufptr
;
1569 ui
->wkui0_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_0
));
1572 if (!GetUserNameW(ui
->wkui0_username
, &dwSize
))
1574 NetApiBufferFree(ui
);
1575 return ERROR_NOT_ENOUGH_MEMORY
;
1578 nastatus
= NetApiBufferReallocate(
1579 *bufptr
, sizeof(WKSTA_USER_INFO_0
) +
1580 (lstrlenW(ui
->wkui0_username
) + 1) * sizeof(WCHAR
),
1582 if (nastatus
!= NERR_Success
)
1590 PWKSTA_USER_INFO_1 ui
;
1591 PWKSTA_USER_INFO_0 ui0
;
1592 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
1593 LSA_HANDLE PolicyHandle
;
1594 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
1597 /* sizes of the field buffers in WCHARS */
1598 int username_sz
, logon_domain_sz
, oth_domains_sz
, logon_server_sz
;
1600 FIXME("Level 1 processing is partially implemented\n");
1602 logon_server_sz
= 1;
1604 /* get some information first to estimate size of the buffer */
1606 nastatus
= NetWkstaUserGetInfo(NULL
, 0, (PBYTE
*) &ui0
);
1607 if (nastatus
!= NERR_Success
)
1609 username_sz
= lstrlenW(ui0
->wkui0_username
) + 1;
1611 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
1612 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
1613 POLICY_VIEW_LOCAL_INFORMATION
,
1615 if (NtStatus
!= STATUS_SUCCESS
)
1617 TRACE("LsaOpenPolicyFailed with NT status %x\n",
1618 LsaNtStatusToWinError(NtStatus
));
1619 NetApiBufferFree(ui0
);
1620 return ERROR_NOT_ENOUGH_MEMORY
;
1622 LsaQueryInformationPolicy(PolicyHandle
, PolicyAccountDomainInformation
,
1623 (PVOID
*) &DomainInfo
);
1624 logon_domain_sz
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
1625 LsaClose(PolicyHandle
);
1628 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1
) +
1629 (username_sz
+ logon_domain_sz
+
1630 oth_domains_sz
+ logon_server_sz
) * sizeof(WCHAR
),
1632 if (nastatus
!= NERR_Success
) {
1633 NetApiBufferFree(ui0
);
1636 ui
= (WKSTA_USER_INFO_1
*) *bufptr
;
1637 ui
->wkui1_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_1
));
1638 ui
->wkui1_logon_domain
= (LMSTR
) (
1639 ((PBYTE
) ui
->wkui1_username
) + username_sz
* sizeof(WCHAR
));
1640 ui
->wkui1_oth_domains
= (LMSTR
) (
1641 ((PBYTE
) ui
->wkui1_logon_domain
) +
1642 logon_domain_sz
* sizeof(WCHAR
));
1643 ui
->wkui1_logon_server
= (LMSTR
) (
1644 ((PBYTE
) ui
->wkui1_oth_domains
) +
1645 oth_domains_sz
* sizeof(WCHAR
));
1648 lstrcpyW(ui
->wkui1_username
, ui0
->wkui0_username
);
1649 NetApiBufferFree(ui0
);
1651 lstrcpynW(ui
->wkui1_logon_domain
, DomainInfo
->DomainName
.Buffer
,
1653 LsaFreeMemory(DomainInfo
);
1655 /* FIXME. Not implemented. Populated with empty strings */
1656 ui
->wkui1_oth_domains
[0] = 0;
1657 ui
->wkui1_logon_server
[0] = 0;
1662 PWKSTA_USER_INFO_1101 ui
;
1665 FIXME("Stub. Level 1101 processing is not implemented\n");
1666 /* FIXME see also wkui1_oth_domains for level 1 */
1669 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101
) + dwSize
* sizeof(WCHAR
),
1671 if (nastatus
!= NERR_Success
)
1673 ui
= (PWKSTA_USER_INFO_1101
) *bufptr
;
1674 ui
->wkui1101_oth_domains
= (LMSTR
)(ui
+ 1);
1677 ui
->wkui1101_oth_domains
[0] = 0;
1681 TRACE("Invalid level %d is specified\n", level
);
1682 return ERROR_INVALID_LEVEL
;
1684 return NERR_Success
;
1687 /************************************************************
1688 * NetWkstaUserEnum (NETAPI32.@)
1690 NET_API_STATUS WINAPI
1691 NetWkstaUserEnum(LMSTR servername
, DWORD level
, LPBYTE
* bufptr
,
1692 DWORD prefmaxlen
, LPDWORD entriesread
,
1693 LPDWORD totalentries
, LPDWORD resumehandle
)
1695 FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername
),
1696 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
1697 return ERROR_INVALID_PARAMETER
;
1700 /************************************************************
1701 * NetpGetComputerName (NETAPI32.@)
1703 NET_API_STATUS WINAPI
NetpGetComputerName(LPWSTR
*Buffer
)
1705 DWORD dwSize
= MAX_COMPUTERNAME_LENGTH
+ 1;
1707 TRACE("(%p)\n", Buffer
);
1708 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) Buffer
);
1709 if (GetComputerNameW(*Buffer
, &dwSize
))
1711 return NetApiBufferReallocate(
1712 *Buffer
, (dwSize
+ 1) * sizeof(WCHAR
),
1717 NetApiBufferFree(*Buffer
);
1718 return ERROR_NOT_ENOUGH_MEMORY
;
1722 NET_API_STATUS WINAPI
I_NetNameCompare(LPVOID p1
, LPWSTR wkgrp
, LPWSTR comp
,
1723 LPVOID p4
, LPVOID p5
)
1725 FIXME("(%p %s %s %p %p): stub\n", p1
, debugstr_w(wkgrp
), debugstr_w(comp
),
1727 return ERROR_INVALID_PARAMETER
;
1730 NET_API_STATUS WINAPI
I_NetNameValidate(LPVOID p1
, LPWSTR wkgrp
, LPVOID p3
,
1733 FIXME("(%p %s %p %p): stub\n", p1
, debugstr_w(wkgrp
), p3
, p4
);
1734 return ERROR_INVALID_PARAMETER
;
1737 NET_API_STATUS WINAPI
NetWkstaGetInfo( LMSTR servername
, DWORD level
,
1741 BOOL local
= NETAPI_IsLocalComputer( servername
);
1743 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
1747 if (libnetapi_init()) return wksta_getinfo( servername
, level
, bufptr
);
1748 FIXME( "remote computers not supported\n" );
1749 return ERROR_INVALID_LEVEL
;
1751 if (!bufptr
) return ERROR_INVALID_PARAMETER
;
1759 static const WCHAR lanroot
[] = {'c',':','\\','l','a','n','m','a','n',0}; /* FIXME */
1760 DWORD computerNameLen
, domainNameLen
, size
;
1761 WCHAR computerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1762 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
1763 LSA_HANDLE PolicyHandle
;
1766 computerNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
1767 GetComputerNameW(computerName
, &computerNameLen
);
1768 computerNameLen
++; /* include NULL terminator */
1770 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
1771 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
1772 POLICY_VIEW_LOCAL_INFORMATION
, &PolicyHandle
);
1773 if (NtStatus
!= STATUS_SUCCESS
)
1774 ret
= LsaNtStatusToWinError(NtStatus
);
1777 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
1779 LsaQueryInformationPolicy(PolicyHandle
,
1780 PolicyAccountDomainInformation
, (PVOID
*)&DomainInfo
);
1781 domainNameLen
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
1782 size
= sizeof(WKSTA_INFO_102
) + computerNameLen
* sizeof(WCHAR
)
1783 + domainNameLen
* sizeof(WCHAR
) + sizeof(lanroot
);
1784 ret
= NetApiBufferAllocate(size
, (LPVOID
*)bufptr
);
1785 if (ret
== NERR_Success
)
1787 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1788 PWKSTA_INFO_102 info
= (PWKSTA_INFO_102
)*bufptr
;
1789 OSVERSIONINFOW verInfo
;
1791 info
->wki102_platform_id
= PLATFORM_ID_NT
;
1792 info
->wki102_computername
= (LMSTR
)(*bufptr
+
1793 sizeof(WKSTA_INFO_102
));
1794 memcpy(info
->wki102_computername
, computerName
,
1795 computerNameLen
* sizeof(WCHAR
));
1796 info
->wki102_langroup
= info
->wki102_computername
+ computerNameLen
;
1797 memcpy(info
->wki102_langroup
, DomainInfo
->DomainName
.Buffer
,
1798 domainNameLen
* sizeof(WCHAR
));
1799 info
->wki102_lanroot
= info
->wki102_langroup
+ domainNameLen
;
1800 memcpy(info
->wki102_lanroot
, lanroot
, sizeof(lanroot
));
1801 memset(&verInfo
, 0, sizeof(verInfo
));
1802 verInfo
.dwOSVersionInfoSize
= sizeof(verInfo
);
1803 GetVersionExW(&verInfo
);
1804 info
->wki102_ver_major
= verInfo
.dwMajorVersion
;
1805 info
->wki102_ver_minor
= verInfo
.dwMinorVersion
;
1806 info
->wki102_logged_on_users
= 1;
1808 LsaFreeMemory(DomainInfo
);
1809 LsaClose(PolicyHandle
);
1815 FIXME("level %d unimplemented\n", level
);
1816 ret
= ERROR_INVALID_LEVEL
;
1821 /************************************************************
1822 * NetGetJoinInformation (NETAPI32.@)
1824 NET_API_STATUS NET_API_FUNCTION
NetGetJoinInformation(
1827 PNETSETUP_JOIN_STATUS type
)
1829 static const WCHAR workgroupW
[] = {'W','o','r','k','g','r','o','u','p',0};
1831 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server
), Name
, type
);
1834 return ERROR_INVALID_PARAMETER
;
1836 NetApiBufferAllocate(sizeof(workgroupW
), (LPVOID
*)Name
);
1837 lstrcpyW(*Name
, workgroupW
);
1838 *type
= NetSetupWorkgroupName
;
1840 return NERR_Success
;
1843 /************************************************************
1844 * NetUserGetGroups (NETAPI32.@)
1846 NET_API_STATUS NET_API_FUNCTION
NetUserGetGroups(
1852 LPDWORD entriesread
,
1853 LPDWORD totalentries
)
1855 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername
),
1856 debugstr_w(username
), level
, bufptr
, prefixmaxlen
, entriesread
,
1863 return ERROR_INVALID_LEVEL
;
1869 WCHAR user_name
[LM20_UNLEN
+1];
1870 WCHAR user_password
[PWLEN
+ 1];
1871 DWORD sec_since_passwd_change
;
1874 LPWSTR user_comment
;
1876 LPWSTR user_logon_script_path
;
1879 static struct list user_list
= LIST_INIT( user_list
);
1881 /************************************************************
1882 * NETAPI_ValidateServername
1884 * Validates server name
1886 static NET_API_STATUS
NETAPI_ValidateServername(LPCWSTR ServerName
)
1890 if (ServerName
[0] == 0)
1891 return ERROR_BAD_NETPATH
;
1893 ((ServerName
[0] == '\\') &&
1894 (ServerName
[1] != '\\'))
1896 ((ServerName
[0] == '\\') &&
1897 (ServerName
[1] == '\\') &&
1898 (ServerName
[2] == 0))
1900 return ERROR_INVALID_NAME
;
1902 return NERR_Success
;
1905 /************************************************************
1908 * Looks for a user in the user database.
1909 * Returns a pointer to the entry in the user list when the user
1910 * is found, NULL otherwise.
1912 static struct sam_user
* NETAPI_FindUser(LPCWSTR UserName
)
1914 struct sam_user
*user
;
1916 LIST_FOR_EACH_ENTRY(user
, &user_list
, struct sam_user
, entry
)
1918 if(lstrcmpW(user
->user_name
, UserName
) == 0)
1924 static BOOL
NETAPI_IsCurrentUser(LPCWSTR username
)
1926 LPWSTR curr_user
= NULL
;
1930 dwSize
= LM20_UNLEN
+1;
1931 curr_user
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(WCHAR
));
1934 ERR("Failed to allocate memory for user name.\n");
1937 if(!GetUserNameW(curr_user
, &dwSize
))
1939 ERR("Failed to get current user's user name.\n");
1942 if (!lstrcmpW(curr_user
, username
))
1948 HeapFree(GetProcessHeap(), 0, curr_user
);
1952 /************************************************************
1953 * NetUserAdd (NETAPI32.@)
1955 NET_API_STATUS WINAPI
NetUserAdd(LPCWSTR servername
,
1956 DWORD level
, LPBYTE bufptr
, LPDWORD parm_err
)
1958 NET_API_STATUS status
;
1959 struct sam_user
* su
= NULL
;
1961 FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
1963 if((status
= NETAPI_ValidateServername(servername
)) != NERR_Success
)
1968 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
1971 FIXME("Level 3 and 4 not implemented.\n");
1974 FIXME("Level 2 not implemented.\n");
1978 PUSER_INFO_1 ui
= (PUSER_INFO_1
) bufptr
;
1979 su
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user
));
1982 status
= NERR_InternalError
;
1986 if(lstrlenW(ui
->usri1_name
) > LM20_UNLEN
)
1988 status
= NERR_BadUsername
;
1992 /*FIXME: do other checks for a valid username */
1993 lstrcpyW(su
->user_name
, ui
->usri1_name
);
1995 if(lstrlenW(ui
->usri1_password
) > PWLEN
)
1997 /* Always return PasswordTooShort on invalid passwords. */
1998 status
= NERR_PasswordTooShort
;
2001 lstrcpyW(su
->user_password
, ui
->usri1_password
);
2003 su
->sec_since_passwd_change
= ui
->usri1_password_age
;
2004 su
->user_priv
= ui
->usri1_priv
;
2005 su
->user_flags
= ui
->usri1_flags
;
2007 /*FIXME: set the other LPWSTRs to NULL for now */
2008 su
->home_dir
= NULL
;
2009 su
->user_comment
= NULL
;
2010 su
->user_logon_script_path
= NULL
;
2012 list_add_head(&user_list
, &su
->entry
);
2013 return NERR_Success
;
2016 TRACE("Invalid level %d specified.\n", level
);
2017 status
= ERROR_INVALID_LEVEL
;
2021 HeapFree(GetProcessHeap(), 0, su
);
2026 /************************************************************
2027 * NetUserDel (NETAPI32.@)
2029 NET_API_STATUS WINAPI
NetUserDel(LPCWSTR servername
, LPCWSTR username
)
2031 NET_API_STATUS status
;
2032 struct sam_user
*user
;
2034 TRACE("(%s, %s)\n", debugstr_w(servername
), debugstr_w(username
));
2036 if((status
= NETAPI_ValidateServername(servername
))!= NERR_Success
)
2039 if ((user
= NETAPI_FindUser(username
)) == NULL
)
2040 return NERR_UserNotFound
;
2042 list_remove(&user
->entry
);
2044 HeapFree(GetProcessHeap(), 0, user
->home_dir
);
2045 HeapFree(GetProcessHeap(), 0, user
->user_comment
);
2046 HeapFree(GetProcessHeap(), 0, user
->user_logon_script_path
);
2047 HeapFree(GetProcessHeap(), 0, user
);
2049 return NERR_Success
;
2052 /************************************************************
2053 * NetUserGetInfo (NETAPI32.@)
2055 NET_API_STATUS WINAPI
2056 NetUserGetInfo(LPCWSTR servername
, LPCWSTR username
, DWORD level
,
2059 NET_API_STATUS status
;
2060 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername
), debugstr_w(username
),
2062 status
= NETAPI_ValidateServername(servername
);
2063 if (status
!= NERR_Success
)
2066 if(!NETAPI_IsLocalComputer(servername
))
2068 FIXME("Only implemented for local computer, but remote server"
2069 "%s was requested.\n", debugstr_w(servername
));
2070 return NERR_InvalidComputer
;
2073 if(!NETAPI_FindUser(username
) && !NETAPI_IsCurrentUser(username
))
2075 TRACE("User %s is unknown.\n", debugstr_w(username
));
2076 return NERR_UserNotFound
;
2086 name_sz
= lstrlenW(username
) + 1;
2089 NetApiBufferAllocate(sizeof(USER_INFO_0
) + name_sz
* sizeof(WCHAR
),
2092 ui
= (PUSER_INFO_0
) *bufptr
;
2093 ui
->usri0_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_0
));
2096 lstrcpyW(ui
->usri0_name
, username
);
2104 /* sizes of the field buffers in WCHARS */
2105 int name_sz
, comment_sz
, usr_comment_sz
, full_name_sz
;
2112 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
2113 if (status
!= NERR_Success
)
2115 NetApiBufferFree(ui0
);
2118 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
2121 NetApiBufferAllocate(sizeof(USER_INFO_10
) +
2122 (name_sz
+ comment_sz
+ usr_comment_sz
+
2123 full_name_sz
) * sizeof(WCHAR
),
2125 ui
= (PUSER_INFO_10
) *bufptr
;
2126 ui
->usri10_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_10
));
2127 ui
->usri10_comment
= (LPWSTR
) (
2128 ((PBYTE
) ui
->usri10_name
) + name_sz
* sizeof(WCHAR
));
2129 ui
->usri10_usr_comment
= (LPWSTR
) (
2130 ((PBYTE
) ui
->usri10_comment
) + comment_sz
* sizeof(WCHAR
));
2131 ui
->usri10_full_name
= (LPWSTR
) (
2132 ((PBYTE
) ui
->usri10_usr_comment
) + usr_comment_sz
* sizeof(WCHAR
));
2135 lstrcpyW(ui
->usri10_name
, ui0
->usri0_name
);
2136 NetApiBufferFree(ui0
);
2137 ui
->usri10_comment
[0] = 0;
2138 ui
->usri10_usr_comment
[0] = 0;
2139 ui
->usri10_full_name
[0] = 0;
2145 static const WCHAR homedirW
[] = {'H','O','M','E',0};
2148 /* sizes of the field buffers in WCHARS */
2149 int name_sz
, password_sz
, home_dir_sz
, comment_sz
, script_path_sz
;
2151 password_sz
= 1; /* not filled out for security reasons for NetUserGetInfo*/
2156 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
2157 if (status
!= NERR_Success
)
2159 NetApiBufferFree(ui0
);
2162 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
2163 home_dir_sz
= GetEnvironmentVariableW(homedirW
, NULL
,0);
2165 NetApiBufferAllocate(sizeof(USER_INFO_1
) +
2166 (name_sz
+ password_sz
+ home_dir_sz
+
2167 comment_sz
+ script_path_sz
) * sizeof(WCHAR
),
2170 ui
= (PUSER_INFO_1
) *bufptr
;
2171 ui
->usri1_name
= (LPWSTR
) (ui
+ 1);
2172 ui
->usri1_password
= ui
->usri1_name
+ name_sz
;
2173 ui
->usri1_home_dir
= ui
->usri1_password
+ password_sz
;
2174 ui
->usri1_comment
= ui
->usri1_home_dir
+ home_dir_sz
;
2175 ui
->usri1_script_path
= ui
->usri1_comment
+ comment_sz
;
2177 lstrcpyW(ui
->usri1_name
, ui0
->usri0_name
);
2178 NetApiBufferFree(ui0
);
2179 ui
->usri1_password
[0] = 0;
2180 ui
->usri1_password_age
= 0;
2182 GetEnvironmentVariableW(homedirW
, ui
->usri1_home_dir
,home_dir_sz
);
2183 ui
->usri1_comment
[0] = 0;
2184 ui
->usri1_flags
= 0;
2185 ui
->usri1_script_path
[0] = 0;
2215 FIXME("Level %d is not implemented\n", level
);
2216 return NERR_InternalError
;
2219 TRACE("Invalid level %d is specified\n", level
);
2220 return ERROR_INVALID_LEVEL
;
2222 return NERR_Success
;
2225 /************************************************************
2226 * NetUserGetLocalGroups (NETAPI32.@)
2228 NET_API_STATUS WINAPI
2229 NetUserGetLocalGroups(LPCWSTR servername
, LPCWSTR username
, DWORD level
,
2230 DWORD flags
, LPBYTE
* bufptr
, DWORD prefmaxlen
,
2231 LPDWORD entriesread
, LPDWORD totalentries
)
2233 NET_API_STATUS status
;
2234 const WCHAR admins
[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0};
2236 LOCALGROUP_USERS_INFO_0
* info
;
2239 FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
2240 debugstr_w(servername
), debugstr_w(username
), level
, flags
, bufptr
,
2241 prefmaxlen
, entriesread
, totalentries
);
2243 status
= NETAPI_ValidateServername(servername
);
2244 if (status
!= NERR_Success
)
2248 NetApiBufferAllocate(size
* sizeof(WCHAR
), (LPVOID
*)¤tuser
);
2249 if (!GetUserNameW(currentuser
, &size
)) {
2250 NetApiBufferFree(currentuser
);
2251 return ERROR_NOT_ENOUGH_MEMORY
;
2254 if (lstrcmpiW(username
, currentuser
) && NETAPI_FindUser(username
))
2256 NetApiBufferFree(currentuser
);
2257 return NERR_UserNotFound
;
2260 NetApiBufferFree(currentuser
);
2262 size
= sizeof(*info
) + sizeof(admins
);
2264 if(prefmaxlen
< size
)
2265 status
= ERROR_MORE_DATA
;
2267 status
= NetApiBufferAllocate(size
, (LPVOID
*)&info
);
2269 if(status
!= NERR_Success
)
2276 info
->lgrui0_name
= (LPWSTR
)((LPBYTE
)info
+ sizeof(*info
));
2277 lstrcpyW(info
->lgrui0_name
, admins
);
2279 *bufptr
= (LPBYTE
)info
;
2282 return NERR_Success
;
2285 /************************************************************
2286 * NetUserEnum (NETAPI32.@)
2288 NET_API_STATUS WINAPI
2289 NetUserEnum(LPCWSTR servername
, DWORD level
, DWORD filter
, LPBYTE
* bufptr
,
2290 DWORD prefmaxlen
, LPDWORD entriesread
, LPDWORD totalentries
,
2291 LPDWORD resume_handle
)
2293 NET_API_STATUS status
;
2298 TRACE("(%s, %u, 0x%x, %p, %u, %p, %p, %p)\n", debugstr_w(servername
), level
,
2299 filter
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
2301 status
= NETAPI_ValidateServername(servername
);
2302 if (status
!= NERR_Success
)
2305 if (!NETAPI_IsLocalComputer(servername
))
2307 FIXME("Only implemented for local computer, but remote server"
2308 "%s was requested.\n", debugstr_w(servername
));
2309 return NERR_InvalidComputer
;
2314 FIXME("level %u not supported\n", level
);
2315 return ERROR_INVALID_LEVEL
;
2319 status
= NetApiBufferAllocate(size
* sizeof(WCHAR
), (void **)&user
);
2320 if (status
!= NERR_Success
)
2323 if (!GetUserNameW(user
, &size
))
2325 NetApiBufferFree(user
);
2326 return ERROR_NOT_ENOUGH_MEMORY
;
2329 size
= sizeof(*info
) + (strlenW(user
) + 1) * sizeof(WCHAR
);
2331 if (prefmaxlen
< size
)
2332 status
= ERROR_MORE_DATA
;
2334 status
= NetApiBufferAllocate(size
, (void **)&info
);
2336 if (status
!= NERR_Success
)
2338 NetApiBufferFree(user
);
2342 info
->usri0_name
= (WCHAR
*)((char *)info
+ sizeof(*info
));
2343 strcpyW(info
->usri0_name
, user
);
2345 *bufptr
= (BYTE
*)info
;
2346 *entriesread
= *totalentries
= 1;
2348 NetApiBufferFree(user
);
2349 return NERR_Success
;
2352 /************************************************************
2353 * ACCESS_QueryAdminDisplayInformation
2355 * Creates a buffer with information for the Admin User
2357 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER
*buf
, PDWORD pdwSize
)
2359 static const WCHAR sAdminUserName
[] = {
2360 'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2362 /* sizes of the field buffers in WCHARS */
2363 int name_sz
, comment_sz
, full_name_sz
;
2364 PNET_DISPLAY_USER usr
;
2367 name_sz
= lstrlenW(sAdminUserName
) + 1;
2371 *pdwSize
= sizeof(NET_DISPLAY_USER
);
2372 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2373 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) buf
);
2376 usr
->usri1_name
= (LPWSTR
) ((PBYTE
) usr
+ sizeof(NET_DISPLAY_USER
));
2377 usr
->usri1_comment
= (LPWSTR
) (
2378 ((PBYTE
) usr
->usri1_name
) + name_sz
* sizeof(WCHAR
));
2379 usr
->usri1_full_name
= (LPWSTR
) (
2380 ((PBYTE
) usr
->usri1_comment
) + comment_sz
* sizeof(WCHAR
));
2383 lstrcpyW(usr
->usri1_name
, sAdminUserName
);
2384 usr
->usri1_comment
[0] = 0;
2385 usr
->usri1_flags
= UF_SCRIPT
| UF_NORMAL_ACCOUNT
| UF_DONT_EXPIRE_PASSWD
;
2386 usr
->usri1_full_name
[0] = 0;
2387 usr
->usri1_user_id
= DOMAIN_USER_RID_ADMIN
;
2388 usr
->usri1_next_index
= 0;
2391 /************************************************************
2392 * ACCESS_QueryGuestDisplayInformation
2394 * Creates a buffer with information for the Guest User
2396 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER
*buf
, PDWORD pdwSize
)
2398 static const WCHAR sGuestUserName
[] = {
2399 'G','u','e','s','t',0 };
2401 /* sizes of the field buffers in WCHARS */
2402 int name_sz
, comment_sz
, full_name_sz
;
2403 PNET_DISPLAY_USER usr
;
2406 name_sz
= lstrlenW(sGuestUserName
) + 1;
2410 *pdwSize
= sizeof(NET_DISPLAY_USER
);
2411 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2412 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) buf
);
2415 usr
->usri1_name
= (LPWSTR
) ((PBYTE
) usr
+ sizeof(NET_DISPLAY_USER
));
2416 usr
->usri1_comment
= (LPWSTR
) (
2417 ((PBYTE
) usr
->usri1_name
) + name_sz
* sizeof(WCHAR
));
2418 usr
->usri1_full_name
= (LPWSTR
) (
2419 ((PBYTE
) usr
->usri1_comment
) + comment_sz
* sizeof(WCHAR
));
2422 lstrcpyW(usr
->usri1_name
, sGuestUserName
);
2423 usr
->usri1_comment
[0] = 0;
2424 usr
->usri1_flags
= UF_ACCOUNTDISABLE
| UF_SCRIPT
| UF_NORMAL_ACCOUNT
|
2425 UF_DONT_EXPIRE_PASSWD
;
2426 usr
->usri1_full_name
[0] = 0;
2427 usr
->usri1_user_id
= DOMAIN_USER_RID_GUEST
;
2428 usr
->usri1_next_index
= 0;
2431 /************************************************************
2432 * Copies NET_DISPLAY_USER record.
2434 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER
*dest
, LPWSTR
*dest_buf
,
2435 PNET_DISPLAY_USER src
)
2437 LPWSTR str
= *dest_buf
;
2439 src
->usri1_name
= str
;
2440 lstrcpyW(src
->usri1_name
, dest
->usri1_name
);
2442 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2444 src
->usri1_comment
= str
;
2445 lstrcpyW(src
->usri1_comment
, dest
->usri1_comment
);
2447 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2449 src
->usri1_flags
= dest
->usri1_flags
;
2451 src
->usri1_full_name
= str
;
2452 lstrcpyW(src
->usri1_full_name
, dest
->usri1_full_name
);
2454 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2456 src
->usri1_user_id
= dest
->usri1_user_id
;
2457 src
->usri1_next_index
= dest
->usri1_next_index
;
2461 /************************************************************
2462 * NetQueryDisplayInformation (NETAPI32.@)
2464 * The buffer structure:
2465 * - array of fixed size record of the level type
2466 * - strings, referenced by the record of the level type
2468 NET_API_STATUS WINAPI
2469 NetQueryDisplayInformation(
2470 LPCWSTR ServerName
, DWORD Level
, DWORD Index
, DWORD EntriesRequested
,
2471 DWORD PreferredMaximumLength
, LPDWORD ReturnedEntryCount
,
2472 PVOID
*SortedBuffer
)
2474 TRACE("(%s, %d, %d, %d, %d, %p, %p)\n", debugstr_w(ServerName
),
2475 Level
, Index
, EntriesRequested
, PreferredMaximumLength
,
2476 ReturnedEntryCount
, SortedBuffer
);
2478 if(!NETAPI_IsLocalComputer(ServerName
))
2480 FIXME("Only implemented on local computer, but requested for "
2481 "remote server %s\n", debugstr_w(ServerName
));
2482 return ERROR_ACCESS_DENIED
;
2489 /* current record */
2490 PNET_DISPLAY_USER inf
;
2491 /* current available strings buffer */
2493 PNET_DISPLAY_USER admin
, guest
;
2494 DWORD admin_size
, guest_size
;
2498 /* sizes of the field buffers in WCHARS */
2499 int name_sz
, comment_sz
, full_name_sz
;
2501 /* number of the records, returned in SortedBuffer
2502 3 - for current user, Administrator and Guest users
2506 FIXME("Level %d partially implemented\n", Level
);
2507 *ReturnedEntryCount
= records
;
2513 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) &name
);
2514 if (!GetUserNameW(name
, &dwSize
))
2516 NetApiBufferFree(name
);
2517 return ERROR_ACCESS_DENIED
;
2520 ACCESS_QueryAdminDisplayInformation(&admin
, &admin_size
);
2521 ACCESS_QueryGuestDisplayInformation(&guest
, &guest_size
);
2524 dwSize
= sizeof(NET_DISPLAY_USER
) * records
;
2525 dwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2527 NetApiBufferAllocate(dwSize
+
2528 admin_size
- sizeof(NET_DISPLAY_USER
) +
2529 guest_size
- sizeof(NET_DISPLAY_USER
),
2531 inf
= *SortedBuffer
;
2532 str
= (LPWSTR
) ((PBYTE
) inf
+ sizeof(NET_DISPLAY_USER
) * records
);
2533 inf
->usri1_name
= str
;
2535 ((PBYTE
) str
) + name_sz
* sizeof(WCHAR
));
2536 inf
->usri1_comment
= str
;
2538 ((PBYTE
) str
) + comment_sz
* sizeof(WCHAR
));
2539 inf
->usri1_full_name
= str
;
2541 ((PBYTE
) str
) + full_name_sz
* sizeof(WCHAR
));
2544 lstrcpyW(inf
->usri1_name
, name
);
2545 NetApiBufferFree(name
);
2546 inf
->usri1_comment
[0] = 0;
2548 UF_SCRIPT
| UF_NORMAL_ACCOUNT
| UF_DONT_EXPIRE_PASSWD
;
2549 inf
->usri1_full_name
[0] = 0;
2550 inf
->usri1_user_id
= 0;
2551 inf
->usri1_next_index
= 0;
2554 ACCESS_CopyDisplayUser(admin
, &str
, inf
);
2555 NetApiBufferFree(admin
);
2558 ACCESS_CopyDisplayUser(guest
, &str
, inf
);
2559 NetApiBufferFree(guest
);
2566 FIXME("Level %d is not implemented\n", Level
);
2571 TRACE("Invalid level %d is specified\n", Level
);
2572 return ERROR_INVALID_LEVEL
;
2574 return NERR_Success
;
2577 /************************************************************
2578 * NetGetDCName (NETAPI32.@)
2580 * Return the name of the primary domain controller (PDC)
2583 NET_API_STATUS WINAPI
2584 NetGetDCName(LPCWSTR servername
, LPCWSTR domainname
, LPBYTE
*bufptr
)
2586 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername
),
2587 debugstr_w(domainname
), bufptr
);
2588 return NERR_DCNotFound
; /* say we can't find a domain controller */
2591 /************************************************************
2592 * NetGetAnyDCName (NETAPI32.@)
2594 * Return the name of any domain controller (DC) for a
2595 * domain that is directly trusted by the specified server
2598 NET_API_STATUS WINAPI
NetGetAnyDCName(LPCWSTR servername
, LPCWSTR domainname
, LPBYTE
*bufptr
)
2600 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername
),
2601 debugstr_w(domainname
), bufptr
);
2602 return ERROR_NO_SUCH_DOMAIN
;
2605 /************************************************************
2606 * NetGroupEnum (NETAPI32.@)
2609 NET_API_STATUS WINAPI
2610 NetGroupEnum(LPCWSTR servername
, DWORD level
, LPBYTE
*bufptr
, DWORD prefmaxlen
,
2611 LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resume_handle
)
2613 FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername
),
2614 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
2615 return ERROR_ACCESS_DENIED
;
2618 /************************************************************
2619 * NetGroupGetInfo (NETAPI32.@)
2622 NET_API_STATUS WINAPI
NetGroupGetInfo(LPCWSTR servername
, LPCWSTR groupname
, DWORD level
, LPBYTE
*bufptr
)
2624 FIXME("(%s, %s, %d, %p) stub!\n", debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
);
2625 return ERROR_ACCESS_DENIED
;
2628 /******************************************************************************
2629 * NetUserModalsGet (NETAPI32.@)
2631 * Retrieves global information for all users and global groups in the security
2635 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
2636 * on which the function is to execute.
2637 * level [I] Information level of the data.
2638 * 0 Return global passwords parameters. bufptr points to a
2639 * USER_MODALS_INFO_0 struct.
2640 * 1 Return logon server and domain controller information. bufptr
2641 * points to a USER_MODALS_INFO_1 struct.
2642 * 2 Return domain name and identifier. bufptr points to a
2643 * USER_MODALS_INFO_2 struct.
2644 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
2646 * pbuffer [I] Buffer that receives the data.
2649 * Success: NERR_Success.
2651 * ERROR_ACCESS_DENIED - the user does not have access to the info.
2652 * NERR_InvalidComputer - computer name is invalid.
2654 NET_API_STATUS WINAPI
NetUserModalsGet(
2655 LPCWSTR szServer
, DWORD level
, LPBYTE
*pbuffer
)
2657 TRACE("(%s %d %p)\n", debugstr_w(szServer
), level
, pbuffer
);
2662 /* return global passwords parameters */
2663 FIXME("level 0 not implemented!\n");
2665 return NERR_InternalError
;
2667 /* return logon server and domain controller info */
2668 FIXME("level 1 not implemented!\n");
2670 return NERR_InternalError
;
2673 /* return domain name and identifier */
2674 PUSER_MODALS_INFO_2 umi
;
2675 LSA_HANDLE policyHandle
;
2676 LSA_OBJECT_ATTRIBUTES objectAttributes
;
2677 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo
;
2679 PSID domainIdentifier
= NULL
;
2682 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
2683 objectAttributes
.Length
= sizeof(objectAttributes
);
2685 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
2686 POLICY_VIEW_LOCAL_INFORMATION
,
2688 if (ntStatus
!= STATUS_SUCCESS
)
2690 WARN("LsaOpenPolicy failed with NT status %x\n",
2691 LsaNtStatusToWinError(ntStatus
));
2695 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
2696 PolicyAccountDomainInformation
,
2697 (PVOID
*)&domainInfo
);
2698 if (ntStatus
!= STATUS_SUCCESS
)
2700 WARN("LsaQueryInformationPolicy failed with NT status %x\n",
2701 LsaNtStatusToWinError(ntStatus
));
2702 LsaClose(policyHandle
);
2706 domainIdentifier
= domainInfo
->DomainSid
;
2707 domainNameLen
= lstrlenW(domainInfo
->DomainName
.Buffer
) + 1;
2708 LsaClose(policyHandle
);
2710 ntStatus
= NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2
) +
2711 GetLengthSid(domainIdentifier
) +
2712 domainNameLen
* sizeof(WCHAR
),
2715 if (ntStatus
!= NERR_Success
)
2717 WARN("NetApiBufferAllocate() failed\n");
2718 LsaFreeMemory(domainInfo
);
2722 umi
= (USER_MODALS_INFO_2
*) *pbuffer
;
2723 umi
->usrmod2_domain_id
= *pbuffer
+ sizeof(USER_MODALS_INFO_2
);
2724 umi
->usrmod2_domain_name
= (LPWSTR
)(*pbuffer
+
2725 sizeof(USER_MODALS_INFO_2
) + GetLengthSid(domainIdentifier
));
2727 lstrcpynW(umi
->usrmod2_domain_name
,
2728 domainInfo
->DomainName
.Buffer
,
2730 CopySid(GetLengthSid(domainIdentifier
), umi
->usrmod2_domain_id
,
2733 LsaFreeMemory(domainInfo
);
2738 /* return lockout information */
2739 FIXME("level 3 not implemented!\n");
2741 return NERR_InternalError
;
2743 TRACE("Invalid level %d is specified\n", level
);
2745 return ERROR_INVALID_LEVEL
;
2748 return NERR_Success
;
2751 static NET_API_STATUS
change_password_smb( LPCWSTR domainname
, LPCWSTR username
,
2752 LPCWSTR oldpassword
, LPCWSTR newpassword
)
2755 NET_API_STATUS ret
= NERR_Success
;
2756 static char option_silent
[] = "-s";
2757 static char option_user
[] = "-U";
2758 static char option_remote
[] = "-r";
2759 static char smbpasswd
[] = "smbpasswd";
2763 char *server
= NULL
, *user
, *argv
[7], *old
= NULL
, *new = NULL
;
2765 if (domainname
&& !(server
= strdup_unixcp( domainname
))) return ERROR_OUTOFMEMORY
;
2766 if (!(user
= strdup_unixcp( username
)))
2768 ret
= ERROR_OUTOFMEMORY
;
2771 if (!(old
= strdup_unixcp( oldpassword
)))
2773 ret
= ERROR_OUTOFMEMORY
;
2776 if (!(new = strdup_unixcp( newpassword
)))
2778 ret
= ERROR_OUTOFMEMORY
;
2781 argv
[0] = smbpasswd
;
2782 argv
[1] = option_silent
;
2783 argv
[2] = option_user
;
2787 argv
[4] = option_remote
;
2791 else argv
[4] = NULL
;
2793 if (pipe( pipe_out
) == -1)
2795 ret
= NERR_InternalError
;
2798 fcntl( pipe_out
[0], F_SETFD
, FD_CLOEXEC
);
2799 fcntl( pipe_out
[1], F_SETFD
, FD_CLOEXEC
);
2801 switch ((pid
= fork()))
2804 close( pipe_out
[0] );
2805 close( pipe_out
[1] );
2806 ret
= NERR_InternalError
;
2809 dup2( pipe_out
[0], 0 );
2810 close( pipe_out
[0] );
2811 close( pipe_out
[1] );
2812 execvp( "smbpasswd", argv
);
2813 ERR( "can't execute smbpasswd, is it installed?\n" );
2816 close( pipe_out
[0] );
2819 write( pipe_out
[1], old
, strlen( old
) );
2820 write( pipe_out
[1], "\n", 1 );
2821 write( pipe_out
[1], new, strlen( new ) );
2822 write( pipe_out
[1], "\n", 1 );
2823 write( pipe_out
[1], new, strlen( new ) );
2824 write( pipe_out
[1], "\n", 1 );
2825 close( pipe_out
[1] );
2828 wret
= waitpid(pid
, &status
, 0);
2829 } while (wret
< 0 && errno
== EINTR
);
2831 if (ret
== NERR_Success
&& (wret
< 0 || !WIFEXITED(status
) || WEXITSTATUS(status
)))
2832 ret
= NERR_InternalError
;
2835 HeapFree( GetProcessHeap(), 0, server
);
2836 HeapFree( GetProcessHeap(), 0, user
);
2837 HeapFree( GetProcessHeap(), 0, old
);
2838 HeapFree( GetProcessHeap(), 0, new );
2841 ERR( "no fork support on this platform\n" );
2842 return NERR_InternalError
;
2846 /******************************************************************************
2847 * NetUserChangePassword (NETAPI32.@)
2849 * domainname [I] Optional. Domain on which the user resides or the logon
2850 * domain of the current user if NULL.
2851 * username [I] Optional. Username to change the password for or the name
2852 * of the current user if NULL.
2853 * oldpassword [I] The user's current password.
2854 * newpassword [I] The password that the user will be changed to using.
2857 * Success: NERR_Success.
2858 * Failure: NERR_* failure code or win error code.
2861 NET_API_STATUS WINAPI
NetUserChangePassword(LPCWSTR domainname
, LPCWSTR username
,
2862 LPCWSTR oldpassword
, LPCWSTR newpassword
)
2864 struct sam_user
*user
;
2866 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname
), debugstr_w(username
));
2868 if (!change_password_smb( domainname
, username
, oldpassword
, newpassword
))
2869 return NERR_Success
;
2872 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname
));
2874 if((user
= NETAPI_FindUser(username
)) == NULL
)
2875 return NERR_UserNotFound
;
2877 if(lstrcmpW(user
->user_password
, oldpassword
) != 0)
2878 return ERROR_INVALID_PASSWORD
;
2880 if(lstrlenW(newpassword
) > PWLEN
)
2881 return ERROR_PASSWORD_RESTRICTION
;
2883 lstrcpyW(user
->user_password
, newpassword
);
2885 return NERR_Success
;
2888 NET_API_STATUS WINAPI
NetUseAdd(LMSTR servername
, DWORD level
, LPBYTE bufptr
, LPDWORD parm_err
)
2890 FIXME("%s %d %p %p stub\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
2891 return NERR_Success
;
2894 NET_API_STATUS WINAPI
NetUseDel(LMSTR servername
, LMSTR usename
, DWORD forcecond
)
2896 FIXME("%s %s %d stub\n", debugstr_w(servername
), debugstr_w(usename
), forcecond
);
2897 return NERR_Success
;
2900 /************************************************************
2901 * I_BrowserSetNetlogonState (NETAPI32.@)
2903 NET_API_STATUS WINAPI
I_BrowserSetNetlogonState(
2904 LPWSTR ServerName
, LPWSTR DomainName
, LPWSTR EmulatedServerName
,
2907 return ERROR_NOT_SUPPORTED
;
2910 /************************************************************
2911 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
2913 NET_API_STATUS WINAPI
I_BrowserQueryEmulatedDomains(
2914 LPWSTR ServerName
, PBROWSER_EMULATED_DOMAIN
*EmulatedDomains
,
2915 LPDWORD EntriesRead
)
2917 return ERROR_NOT_SUPPORTED
;
2920 DWORD WINAPI
DsGetDcNameW(LPCWSTR ComputerName
, LPCWSTR AvoidDCName
,
2921 GUID
* DomainGuid
, LPCWSTR SiteName
, ULONG Flags
,
2922 PDOMAIN_CONTROLLER_INFOW
*DomainControllerInfo
)
2924 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_w(ComputerName
),
2925 debugstr_w(AvoidDCName
), debugstr_guid(DomainGuid
),
2926 debugstr_w(SiteName
), Flags
, DomainControllerInfo
);
2927 return ERROR_CALL_NOT_IMPLEMENTED
;
2930 DWORD WINAPI
DsGetDcNameA(LPCSTR ComputerName
, LPCSTR AvoidDCName
,
2931 GUID
* DomainGuid
, LPCSTR SiteName
, ULONG Flags
,
2932 PDOMAIN_CONTROLLER_INFOA
*DomainControllerInfo
)
2934 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_a(ComputerName
),
2935 debugstr_a(AvoidDCName
), debugstr_guid(DomainGuid
),
2936 debugstr_a(SiteName
), Flags
, DomainControllerInfo
);
2937 return ERROR_CALL_NOT_IMPLEMENTED
;
2940 DWORD WINAPI
DsGetSiteNameW(LPCWSTR ComputerName
, LPWSTR
*SiteName
)
2942 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName
), SiteName
);
2943 return ERROR_CALL_NOT_IMPLEMENTED
;
2946 DWORD WINAPI
DsGetSiteNameA(LPCSTR ComputerName
, LPSTR
*SiteName
)
2948 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName
), SiteName
);
2949 return ERROR_CALL_NOT_IMPLEMENTED
;
2952 /************************************************************
2953 * DsRoleFreeMemory (NETAPI32.@)
2956 * Buffer [I] Pointer to the to-be-freed buffer.
2961 VOID WINAPI
DsRoleFreeMemory(PVOID Buffer
)
2963 TRACE("(%p)\n", Buffer
);
2964 HeapFree(GetProcessHeap(), 0, Buffer
);
2967 /************************************************************
2968 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
2971 * lpServer [I] Pointer to UNICODE string with ComputerName
2972 * InfoLevel [I] Type of data to retrieve
2973 * Buffer [O] Pointer to to the requested data
2978 * When lpServer is NULL, use the local computer
2980 DWORD WINAPI
DsRoleGetPrimaryDomainInformation(
2981 LPCWSTR lpServer
, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel
,
2986 FIXME("(%p, %d, %p) stub\n", lpServer
, InfoLevel
, Buffer
);
2988 /* Check some input parameters */
2990 if (!Buffer
) return ERROR_INVALID_PARAMETER
;
2991 if ((InfoLevel
< DsRolePrimaryDomainInfoBasic
) || (InfoLevel
> DsRoleOperationState
)) return ERROR_INVALID_PARAMETER
;
2996 case DsRolePrimaryDomainInfoBasic
:
2998 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
2999 LSA_HANDLE PolicyHandle
;
3000 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
3002 int logon_domain_sz
;
3004 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic
;
3006 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
3007 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
3008 POLICY_VIEW_LOCAL_INFORMATION
, &PolicyHandle
);
3009 if (NtStatus
!= STATUS_SUCCESS
)
3011 TRACE("LsaOpenPolicyFailed with NT status %x\n",
3012 LsaNtStatusToWinError(NtStatus
));
3013 return ERROR_OUTOFMEMORY
;
3015 LsaQueryInformationPolicy(PolicyHandle
,
3016 PolicyAccountDomainInformation
, (PVOID
*)&DomainInfo
);
3017 logon_domain_sz
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
3018 LsaClose(PolicyHandle
);
3020 size
= sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC
) +
3021 logon_domain_sz
* sizeof(WCHAR
);
3022 basic
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
3025 basic
->MachineRole
= DsRole_RoleStandaloneWorkstation
;
3026 basic
->DomainNameFlat
= (LPWSTR
)((LPBYTE
)basic
+
3027 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC
));
3028 lstrcpyW(basic
->DomainNameFlat
, DomainInfo
->DomainName
.Buffer
);
3029 ret
= ERROR_SUCCESS
;
3032 ret
= ERROR_OUTOFMEMORY
;
3033 *Buffer
= (PBYTE
)basic
;
3034 LsaFreeMemory(DomainInfo
);
3038 ret
= ERROR_CALL_NOT_IMPLEMENTED
;
3043 /************************************************************
3044 * NetLocalGroupAdd (NETAPI32.@)
3046 NET_API_STATUS WINAPI
NetLocalGroupAdd(
3052 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername
), level
, buf
,
3054 return NERR_Success
;
3057 /************************************************************
3058 * NetLocalGroupAddMember (NETAPI32.@)
3060 NET_API_STATUS WINAPI
NetLocalGroupAddMember(
3065 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
3066 debugstr_w(groupname
), membersid
);
3067 return NERR_Success
;
3070 /************************************************************
3071 * NetLocalGroupAddMembers (NETAPI32.@)
3073 NET_API_STATUS WINAPI
NetLocalGroupAddMembers(
3080 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
3081 debugstr_w(groupname
), level
, buf
, totalentries
);
3082 return NERR_Success
;
3085 /************************************************************
3086 * NetLocalGroupDel (NETAPI32.@)
3088 NET_API_STATUS WINAPI
NetLocalGroupDel(
3092 FIXME("(%s %s) stub!\n", debugstr_w(servername
), debugstr_w(groupname
));
3093 return NERR_Success
;
3096 /************************************************************
3097 * NetLocalGroupDelMember (NETAPI32.@)
3099 NET_API_STATUS WINAPI
NetLocalGroupDelMember(
3104 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
3105 debugstr_w(groupname
), membersid
);
3106 return NERR_Success
;
3109 /************************************************************
3110 * NetLocalGroupDelMembers (NETAPI32.@)
3112 NET_API_STATUS WINAPI
NetLocalGroupDelMembers(
3119 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
3120 debugstr_w(groupname
), level
, buf
, totalentries
);
3121 return NERR_Success
;
3124 /************************************************************
3125 * NetLocalGroupEnum (NETAPI32.@)
3127 NET_API_STATUS WINAPI
NetLocalGroupEnum(
3132 LPDWORD entriesread
,
3133 LPDWORD totalentries
,
3134 PDWORD_PTR resumehandle
)
3136 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername
),
3137 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
3140 return NERR_Success
;
3143 /************************************************************
3144 * NetLocalGroupGetInfo (NETAPI32.@)
3146 NET_API_STATUS WINAPI
NetLocalGroupGetInfo(
3152 static const WCHAR commentW
[]={'N','o',' ','c','o','m','m','e','n','t',0};
3153 LOCALGROUP_INFO_1
* info
;
3156 FIXME("(%s %s %d %p) semi-stub!\n", debugstr_w(servername
),
3157 debugstr_w(groupname
), level
, bufptr
);
3159 size
= sizeof(*info
) + sizeof(WCHAR
) * (lstrlenW(groupname
)+1) + sizeof(commentW
);
3160 NetApiBufferAllocate(size
, (LPVOID
*)&info
);
3162 info
->lgrpi1_name
= (LPWSTR
)(info
+ 1);
3163 lstrcpyW(info
->lgrpi1_name
, groupname
);
3165 info
->lgrpi1_comment
= info
->lgrpi1_name
+ lstrlenW(groupname
) + 1;
3166 lstrcpyW(info
->lgrpi1_comment
, commentW
);
3168 *bufptr
= (LPBYTE
)info
;
3170 return NERR_Success
;
3173 /************************************************************
3174 * NetLocalGroupGetMembers (NETAPI32.@)
3176 NET_API_STATUS WINAPI
NetLocalGroupGetMembers(
3178 LPCWSTR localgroupname
,
3182 LPDWORD entriesread
,
3183 LPDWORD totalentries
,
3184 PDWORD_PTR resumehandle
)
3186 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername
),
3187 debugstr_w(localgroupname
), level
, bufptr
, prefmaxlen
, entriesread
,
3188 totalentries
, resumehandle
);
3192 WCHAR userName
[MAX_COMPUTERNAME_LENGTH
+ 1];
3195 PLOCALGROUP_MEMBERS_INFO_3 ptr
;
3197 /* still a stub, current user is belonging to all groups */
3202 userNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
3203 if (!GetUserNameW(userName
,&userNameLen
))
3204 return ERROR_NOT_ENOUGH_MEMORY
;
3206 needlen
= sizeof(LOCALGROUP_MEMBERS_INFO_3
) +
3207 (userNameLen
+2) * sizeof(WCHAR
);
3208 if (prefmaxlen
!= MAX_PREFERRED_LENGTH
)
3209 len
= min(prefmaxlen
,needlen
);
3213 NetApiBufferAllocate(len
, (LPVOID
*) bufptr
);
3215 return ERROR_MORE_DATA
;
3217 ptr
= (PLOCALGROUP_MEMBERS_INFO_3
)*bufptr
;
3218 ptr
->lgrmi3_domainandname
= (LPWSTR
)(*bufptr
+sizeof(LOCALGROUP_MEMBERS_INFO_3
));
3219 lstrcpyW(ptr
->lgrmi3_domainandname
,userName
);
3224 return NERR_Success
;
3227 /************************************************************
3228 * NetLocalGroupSetInfo (NETAPI32.@)
3230 NET_API_STATUS WINAPI
NetLocalGroupSetInfo(
3237 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername
),
3238 debugstr_w(groupname
), level
, buf
, parm_err
);
3239 return NERR_Success
;
3242 /************************************************************
3243 * NetLocalGroupSetMember (NETAPI32.@)
3245 NET_API_STATUS WINAPI
NetLocalGroupSetMembers(
3252 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
3253 debugstr_w(groupname
), level
, buf
, totalentries
);
3254 return NERR_Success
;