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
55 #include "wine/debug.h"
56 #include "wine/library.h"
57 #include "wine/list.h"
58 #include "wine/unicode.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(netapi32
);
62 static char *strdup_unixcp( const WCHAR
*str
)
65 int len
= WideCharToMultiByte( CP_UNIXCP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
66 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
67 WideCharToMultiByte( CP_UNIXCP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
71 #ifdef SONAME_LIBNETAPI
73 static void *libnetapi_handle
;
74 static void *libnetapi_ctx
;
76 static DWORD (*plibnetapi_init
)(void **);
77 static DWORD (*plibnetapi_free
)(void *);
78 static DWORD (*plibnetapi_set_debuglevel
)(void *, const char *);
79 static DWORD (*plibnetapi_set_username
)(void *, const char *);
80 static DWORD (*plibnetapi_set_password
)(void *, const char *);
82 static NET_API_STATUS (*pNetApiBufferAllocate
)(unsigned int, void **);
83 static NET_API_STATUS (*pNetApiBufferFree
)(void *);
84 static NET_API_STATUS (*pNetServerGetInfo
)(const char *, unsigned int, unsigned char **);
85 static NET_API_STATUS (*pNetShareAdd
)(const char *, unsigned int, unsigned char *, unsigned int *);
86 static NET_API_STATUS (*pNetShareDel
)(const char *, const char *, unsigned int);
87 static NET_API_STATUS (*pNetWkstaGetInfo
)(const char *, unsigned int, unsigned char **);
89 static void destroy_context(void)
91 TRACE( "destroying %p\n", libnetapi_ctx
);
92 plibnetapi_free( libnetapi_ctx
);
96 static BOOL
init_context(void)
100 if ((status
= plibnetapi_init( &libnetapi_ctx
)))
102 ERR( "Failed to initialize context %u\n", status
);
105 if (TRACE_ON( netapi32
) && (status
= plibnetapi_set_debuglevel( libnetapi_ctx
, "10" )))
107 ERR( "Failed to set debug level %u\n", status
);
111 /* perform an anonymous login by default (avoids a password prompt) */
112 if ((status
= plibnetapi_set_username( libnetapi_ctx
, "Guest" )))
114 ERR( "Failed to set username %u\n", status
);
118 if ((status
= plibnetapi_set_password( libnetapi_ctx
, "" )))
120 ERR( "Failed to set password %u\n", status
);
124 TRACE( "using %p\n", libnetapi_ctx
);
128 static BOOL
libnetapi_init(void)
132 if (libnetapi_handle
) return TRUE
;
133 if (!(libnetapi_handle
= wine_dlopen( SONAME_LIBNETAPI
, RTLD_NOW
, buf
, sizeof(buf
) )))
135 WARN( "Failed to load libnetapi: %s\n", buf
);
139 #define LOAD_FUNCPTR(f) \
140 if (!(p##f = wine_dlsym( libnetapi_handle, #f, buf, sizeof(buf) ))) \
142 ERR( "Failed to load %s: %s\n", #f, buf ); \
146 LOAD_FUNCPTR(libnetapi_init
)
147 LOAD_FUNCPTR(libnetapi_free
)
148 LOAD_FUNCPTR(libnetapi_set_debuglevel
)
149 LOAD_FUNCPTR(libnetapi_set_username
)
150 LOAD_FUNCPTR(libnetapi_set_password
)
152 LOAD_FUNCPTR(NetApiBufferAllocate
)
153 LOAD_FUNCPTR(NetApiBufferFree
)
154 LOAD_FUNCPTR(NetServerGetInfo
)
155 LOAD_FUNCPTR(NetShareAdd
)
156 LOAD_FUNCPTR(NetShareDel
)
157 LOAD_FUNCPTR(NetWkstaGetInfo
)
160 if (init_context()) return TRUE
;
163 wine_dlclose( libnetapi_handle
, NULL
, 0 );
164 libnetapi_handle
= NULL
;
168 struct server_info_101
170 unsigned int sv101_platform_id
;
171 const char *sv101_name
;
172 unsigned int sv101_version_major
;
173 unsigned int sv101_version_minor
;
174 unsigned int sv101_type
;
175 const char *sv101_comment
;
178 static NET_API_STATUS
server_info_101_from_samba( const unsigned char *buf
, BYTE
**bufptr
)
180 SERVER_INFO_101
*ret
;
181 struct server_info_101
*info
= (struct server_info_101
*)buf
;
185 if (info
->sv101_name
) len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_name
, -1, NULL
, 0 );
186 if (info
->sv101_comment
) len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_comment
, -1, NULL
, 0 );
187 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ret
) + (len
* sizeof(WCHAR
) ))))
188 return ERROR_OUTOFMEMORY
;
190 ptr
= (WCHAR
*)(ret
+ 1);
191 ret
->sv101_platform_id
= info
->sv101_platform_id
;
192 if (!info
->sv101_name
) ret
->sv101_name
= NULL
;
195 ret
->sv101_name
= ptr
;
196 ptr
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_name
, -1, ptr
, len
);
198 ret
->sv101_version_major
= info
->sv101_version_major
;
199 ret
->sv101_version_minor
= info
->sv101_version_minor
;
200 ret
->sv101_type
= info
->sv101_type
;
201 if (!info
->sv101_comment
) ret
->sv101_comment
= NULL
;
204 ret
->sv101_comment
= ptr
;
205 MultiByteToWideChar( CP_UNIXCP
, 0, info
->sv101_comment
, -1, ptr
, len
);
207 *bufptr
= (BYTE
*)ret
;
211 static NET_API_STATUS
server_info_from_samba( DWORD level
, const unsigned char *buf
, BYTE
**bufptr
)
215 case 101: return server_info_101_from_samba( buf
, bufptr
);
217 FIXME( "level %u not supported\n", level
);
218 return ERROR_NOT_SUPPORTED
;
222 static NET_API_STATUS
server_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
224 NET_API_STATUS status
;
226 unsigned char *buf
= NULL
;
228 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
229 status
= pNetServerGetInfo( server
, level
, &buf
);
230 HeapFree( GetProcessHeap(), 0, server
);
233 status
= server_info_from_samba( level
, buf
, bufptr
);
234 pNetApiBufferFree( buf
);
241 const char *shi2_netname
;
242 unsigned int shi2_type
;
243 const char *shi2_remark
;
244 unsigned int shi2_permissions
;
245 unsigned int shi2_max_uses
;
246 unsigned int shi2_current_uses
;
247 const char *shi2_path
;
248 const char *shi2_passwd
;
251 static NET_API_STATUS
share_info_2_to_samba( const BYTE
*buf
, unsigned char **bufptr
)
253 struct share_info_2
*ret
;
254 SHARE_INFO_2
*info
= (SHARE_INFO_2
*)buf
;
258 if (info
->shi2_netname
)
259 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_netname
, -1, NULL
, 0, NULL
, NULL
);
260 if (info
->shi2_remark
)
261 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_remark
, -1, NULL
, 0, NULL
, NULL
);
263 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_path
, -1, NULL
, 0, NULL
, NULL
);
264 if (info
->shi2_passwd
)
265 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_passwd
, -1, NULL
, 0, NULL
, NULL
);
266 if (!(ret
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret
) + len
)))
267 return ERROR_OUTOFMEMORY
;
269 ptr
= (char *)(ret
+ 1);
270 if (!info
->shi2_netname
) ret
->shi2_netname
= NULL
;
273 ret
->shi2_netname
= ptr
;
274 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_netname
, -1, ptr
, len
, NULL
, NULL
);
276 ret
->shi2_type
= info
->shi2_type
;
277 if (!info
->shi2_remark
) ret
->shi2_remark
= NULL
;
280 ret
->shi2_remark
= ptr
;
281 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_remark
, -1, ptr
, len
, NULL
, NULL
);
283 ret
->shi2_permissions
= info
->shi2_permissions
;
284 ret
->shi2_max_uses
= info
->shi2_max_uses
;
285 ret
->shi2_current_uses
= info
->shi2_current_uses
;
286 if (!info
->shi2_path
) ret
->shi2_path
= NULL
;
289 ret
->shi2_path
= ptr
;
290 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_path
, -1, ptr
, len
, NULL
, NULL
);
292 if (!info
->shi2_passwd
) ret
->shi2_passwd
= NULL
;
295 ret
->shi2_passwd
= ptr
;
296 WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi2_passwd
, -1, ptr
, len
, NULL
, NULL
);
298 *bufptr
= (unsigned char *)ret
;
304 unsigned char sid_rev_num
;
305 unsigned char num_auths
;
306 unsigned char id_auth
[6];
307 unsigned int sub_auths
[15];
312 ACE_TYPE_ACCESS_ALLOWED
,
313 ACE_TYPE_ACCESS_DENIED
,
314 ACE_TYPE_SYSTEM_AUDIT
,
315 ACE_TYPE_SYSTEM_ALARM
,
316 ACE_TYPE_ALLOWED_COMPOUND
,
317 ACE_TYPE_ACCESS_ALLOWED_OBJECT
,
318 ACE_TYPE_ACCESS_DENIED_OBJECT
,
319 ACE_TYPE_SYSTEM_AUDIT_OBJECT
,
320 ACE_TYPE_SYSTEM_ALARM_OBJECT
323 #define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
324 #define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
325 #define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
326 #define SEC_ACE_FLAG_INHERIT_ONLY 0x08
327 #define SEC_ACE_FLAG_INHERITED_ACE 0x10
328 #define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
329 #define SEC_ACE_FLAG_FAILED_ACCESS 0x80
333 unsigned int time_low
;
334 unsigned short time_mid
;
335 unsigned short time_hi_and_version
;
336 unsigned char clock_seq
[2];
337 unsigned char node
[6];
340 union ace_object_type
345 union ace_object_inherited_type
347 struct guid inherited_type
;
353 union ace_object_type type
;
354 union ace_object_inherited_type inherited_type
;
359 struct ace_object object
;
367 unsigned int access_mask
;
368 union ace_object_ctr object
;
374 ACL_REVISION_NT4
= 2,
380 enum acl_revision revision
;
382 unsigned int num_aces
;
386 enum security_descriptor_revision
388 SECURITY_DESCRIPTOR_REVISION_1
= 1
391 #define SEC_DESC_OWNER_DEFAULTED 0x0001
392 #define SEC_DESC_GROUP_DEFAULTED 0x0002
393 #define SEC_DESC_DACL_PRESENT 0x0004
394 #define SEC_DESC_DACL_DEFAULTED 0x0008
395 #define SEC_DESC_SACL_PRESENT 0x0010
396 #define SEC_DESC_SACL_DEFAULTED 0x0020
397 #define SEC_DESC_DACL_TRUSTED 0x0040
398 #define SEC_DESC_SERVER_SECURITY 0x0080
399 #define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
400 #define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
401 #define SEC_DESC_DACL_AUTO_INHERITED 0x0400
402 #define SEC_DESC_SACL_AUTO_INHERITED 0x0800
403 #define SEC_DESC_DACL_PROTECTED 0x1000
404 #define SEC_DESC_SACL_PROTECTED 0x2000
405 #define SEC_DESC_RM_CONTROL_VALID 0x4000
406 #define SEC_DESC_SELF_RELATIVE 0x8000
408 struct security_descriptor
410 enum security_descriptor_revision revision
;
412 struct sid
*owner_sid
;
413 struct sid
*group_sid
;
418 struct share_info_502
420 const char *shi502_netname
;
421 unsigned int shi502_type
;
422 const char *shi502_remark
;
423 unsigned int shi502_permissions
;
424 unsigned int shi502_max_uses
;
425 unsigned int shi502_current_uses
;
426 const char *shi502_path
;
427 const char *shi502_passwd
;
428 unsigned int shi502_reserved
;
429 struct security_descriptor
*shi502_security_descriptor
;
432 static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control
)
434 unsigned short ret
= 0;
436 if (control
& SE_OWNER_DEFAULTED
) ret
|= SEC_DESC_OWNER_DEFAULTED
;
437 if (control
& SE_GROUP_DEFAULTED
) ret
|= SEC_DESC_GROUP_DEFAULTED
;
438 if (control
& SE_DACL_PRESENT
) ret
|= SEC_DESC_DACL_PRESENT
;
439 if (control
& SE_DACL_DEFAULTED
) ret
|= SEC_DESC_DACL_DEFAULTED
;
440 if (control
& SE_SACL_PRESENT
) ret
|= SEC_DESC_SACL_PRESENT
;
441 if (control
& SE_SACL_DEFAULTED
) ret
|= SEC_DESC_SACL_DEFAULTED
;
442 if (control
& SE_DACL_AUTO_INHERIT_REQ
) ret
|= SEC_DESC_DACL_AUTO_INHERIT_REQ
;
443 if (control
& SE_SACL_AUTO_INHERIT_REQ
) ret
|= SEC_DESC_SACL_AUTO_INHERIT_REQ
;
444 if (control
& SE_DACL_AUTO_INHERITED
) ret
|= SEC_DESC_DACL_AUTO_INHERITED
;
445 if (control
& SE_SACL_AUTO_INHERITED
) ret
|= SEC_DESC_SACL_AUTO_INHERITED
;
446 if (control
& SE_DACL_PROTECTED
) ret
|= SEC_DESC_DACL_PROTECTED
;
447 if (control
& SE_SACL_PROTECTED
) ret
|= SEC_DESC_SACL_PROTECTED
;
448 if (control
& SE_RM_CONTROL_VALID
) ret
|= SEC_DESC_RM_CONTROL_VALID
;
452 static NET_API_STATUS
sid_to_samba( const SID
*src
, struct sid
*dst
)
456 if (src
->Revision
!= 1)
458 ERR( "unknown revision %u\n", src
->Revision
);
459 return ERROR_UNKNOWN_REVISION
;
461 if (src
->SubAuthorityCount
> SID_MAX_SUB_AUTHORITIES
)
463 WARN( "invalid subauthority count %u\n", src
->SubAuthorityCount
);
464 return ERROR_INVALID_PARAMETER
;
466 dst
->sid_rev_num
= SECURITY_DESCRIPTOR_REVISION_1
;
467 dst
->num_auths
= src
->SubAuthorityCount
;
468 for (i
= 0; i
< 6; i
++) dst
->id_auth
[i
] = src
->IdentifierAuthority
.Value
[i
];
469 for (i
= 0; i
< dst
->num_auths
; i
++) dst
->sub_auths
[i
] = src
->SubAuthority
[i
];
473 static enum ace_type
ace_type_to_samba( BYTE type
)
477 case ACCESS_ALLOWED_ACE_TYPE
: return ACE_TYPE_ACCESS_ALLOWED
;
478 case ACCESS_DENIED_ACE_TYPE
: return ACE_TYPE_ACCESS_DENIED
;
479 case SYSTEM_AUDIT_ACE_TYPE
: return ACE_TYPE_SYSTEM_AUDIT
;
480 case SYSTEM_ALARM_ACE_TYPE
: return ACE_TYPE_SYSTEM_ALARM
;
482 ERR( "unhandled type %u\n", type
);
487 static unsigned char ace_flags_to_samba( BYTE flags
)
489 static const BYTE known_flags
=
490 OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| NO_PROPAGATE_INHERIT_ACE
|
491 INHERIT_ONLY_ACE
| INHERITED_ACE
| SUCCESSFUL_ACCESS_ACE_FLAG
| FAILED_ACCESS_ACE_FLAG
;
492 unsigned char ret
= 0;
494 if (flags
& ~known_flags
)
496 ERR( "unknown flags %x\n", flags
& ~known_flags
);
499 if (flags
& OBJECT_INHERIT_ACE
) ret
|= SEC_ACE_FLAG_OBJECT_INHERIT
;
500 if (flags
& CONTAINER_INHERIT_ACE
) ret
|= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
;
501 if (flags
& NO_PROPAGATE_INHERIT_ACE
) ret
|= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
;
502 if (flags
& INHERIT_ONLY_ACE
) ret
|= SEC_ACE_FLAG_INHERIT_ONLY
;
503 if (flags
& INHERITED_ACE
) ret
|= SEC_ACE_FLAG_INHERITED_ACE
;
504 if (flags
& SUCCESSFUL_ACCESS_ACE_FLAG
) ret
|= SEC_ACE_FLAG_SUCCESSFUL_ACCESS
;
505 if (flags
& FAILED_ACCESS_ACE_FLAG
) ret
|= SEC_ACE_FLAG_FAILED_ACCESS
;
509 #define GENERIC_ALL_ACCESS (1u << 28)
510 #define GENERIC_EXECUTE_ACCESS (1u << 29)
511 #define GENERIC_WRITE_ACCESS (1u << 30)
512 #define GENERIC_READ_ACCESS (1u << 31)
514 static unsigned int access_mask_to_samba( DWORD mask
)
516 static const DWORD known_rights
=
517 GENERIC_ALL
| GENERIC_EXECUTE
| GENERIC_WRITE
| GENERIC_READ
;
518 unsigned int ret
= 0;
520 if (mask
& ~known_rights
)
522 ERR( "unknown rights %x\n", mask
& ~known_rights
);
525 if (mask
& GENERIC_ALL
) ret
|= GENERIC_ALL_ACCESS
;
526 if (mask
& GENERIC_EXECUTE
) ret
|= GENERIC_EXECUTE_ACCESS
;
527 if (mask
& GENERIC_WRITE
) ret
|= GENERIC_WRITE_ACCESS
;
528 if (mask
& GENERIC_READ
) ret
|= GENERIC_READ_ACCESS
;
532 static NET_API_STATUS
ace_to_samba( const ACE_HEADER
*src
, struct ace
*dst
)
534 dst
->type
= ace_type_to_samba( src
->AceType
);
535 dst
->flags
= ace_flags_to_samba( src
->AceFlags
);
536 dst
->size
= sizeof(*dst
);
537 switch (src
->AceType
)
539 case ACCESS_ALLOWED_ACE_TYPE
:
541 ACCESS_ALLOWED_ACE
*ace
= (ACCESS_ALLOWED_ACE
*)src
;
542 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
543 memset( &dst
->object
, 0, sizeof(dst
->object
) );
544 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
547 case ACCESS_DENIED_ACE_TYPE
:
549 ACCESS_DENIED_ACE
*ace
= (ACCESS_DENIED_ACE
*)src
;
550 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
551 memset( &dst
->object
, 0, sizeof(dst
->object
) );
552 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
555 case SYSTEM_AUDIT_ACE_TYPE
:
557 SYSTEM_AUDIT_ACE
*ace
= (SYSTEM_AUDIT_ACE
*)src
;
558 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
559 memset( &dst
->object
, 0, sizeof(dst
->object
) );
560 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
563 case SYSTEM_ALARM_ACE_TYPE
:
565 SYSTEM_ALARM_ACE
*ace
= (SYSTEM_ALARM_ACE
*)src
;
566 dst
->access_mask
= access_mask_to_samba( ace
->Mask
);
567 memset( &dst
->object
, 0, sizeof(dst
->object
) );
568 sid_to_samba( (const SID
*)&ace
->SidStart
, &dst
->trustee
);
572 ERR( "unhandled type %u\n", src
->AceType
);
573 return ERROR_INVALID_PARAMETER
;
578 static NET_API_STATUS
acl_to_samba( const ACL
*src
, struct acl
*dst
)
580 NET_API_STATUS status
;
584 switch (src
->AclRevision
)
587 dst
->revision
= ACL_REVISION_ADS
;
590 ERR( "unkhandled revision %u\n", src
->AclRevision
);
591 return ERROR_UNKNOWN_REVISION
;
593 dst
->size
= sizeof(*dst
);
594 src_ace
= (ACE_HEADER
*)(src
+ 1);
595 dst
->aces
= (struct ace
*)(dst
+ 1);
596 for (i
= 0; i
< src
->AceCount
; i
++)
598 if ((status
= ace_to_samba( src_ace
, &dst
->aces
[i
] ))) return status
;
599 src_ace
= (ACE_HEADER
*)((char *)src_ace
+ src_ace
->AceSize
);
600 dst
->size
+= dst
->aces
[i
].size
;
605 #define SELF_RELATIVE_FIELD(sd,field)\
606 ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
608 static NET_API_STATUS
sd_to_samba( const SECURITY_DESCRIPTOR
*src
, struct security_descriptor
*dst
)
610 NET_API_STATUS status
;
611 const SID
*owner
, *group
;
612 const ACL
*dacl
, *sacl
;
613 unsigned int offset
= sizeof(*dst
);
615 if (src
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
616 return ERROR_UNKNOWN_REVISION
;
618 dst
->revision
= SECURITY_DESCRIPTOR_REVISION_1
;
619 dst
->type
= sd_control_to_samba( src
->Control
);
621 if (src
->Control
& SE_SELF_RELATIVE
)
623 if (!src
->Owner
) dst
->owner_sid
= NULL
;
626 dst
->owner_sid
= (struct sid
*)((char *)dst
+ offset
);
627 owner
= (const SID
*)SELF_RELATIVE_FIELD( src
, Owner
);
628 if ((status
= sid_to_samba( owner
, dst
->owner_sid
))) return status
;
629 offset
+= sizeof(struct sid
);
631 if (!src
->Group
) dst
->group_sid
= NULL
;
634 dst
->group_sid
= (struct sid
*)((char *)dst
+ offset
);
635 group
= (const SID
*)SELF_RELATIVE_FIELD( src
, Group
);
636 if ((status
= sid_to_samba( group
, dst
->group_sid
))) return status
;
637 offset
+= sizeof(struct sid
);
639 if (!(src
->Control
& SE_SACL_PRESENT
)) dst
->sacl
= NULL
;
642 dst
->sacl
= (struct acl
*)((char *)dst
+ offset
);
643 sacl
= (const ACL
*)SELF_RELATIVE_FIELD( src
, Sacl
);
644 if ((status
= acl_to_samba( sacl
, dst
->sacl
))) return status
;
645 offset
+= dst
->sacl
->size
;
647 if (!(src
->Control
& SE_DACL_PRESENT
)) dst
->dacl
= NULL
;
650 dst
->dacl
= (struct acl
*)((char *)dst
+ offset
);
651 dacl
= (const ACL
*)SELF_RELATIVE_FIELD( src
, Dacl
);
652 if ((status
= acl_to_samba( dacl
, dst
->dacl
))) return status
;
657 if (!src
->Owner
) dst
->owner_sid
= NULL
;
660 dst
->owner_sid
= (struct sid
*)((char *)dst
+ offset
);
661 if ((status
= sid_to_samba( src
->Owner
, dst
->owner_sid
))) return status
;
662 offset
+= sizeof(struct sid
);
664 if (!src
->Group
) dst
->group_sid
= NULL
;
667 dst
->group_sid
= (struct sid
*)((char *)dst
+ offset
);
668 if ((status
= sid_to_samba( src
->Group
, dst
->group_sid
))) return status
;
669 offset
+= sizeof(struct sid
);
671 if (!(src
->Control
& SE_SACL_PRESENT
)) dst
->sacl
= NULL
;
674 dst
->sacl
= (struct acl
*)((char *)dst
+ offset
);
675 if ((status
= acl_to_samba( src
->Sacl
, dst
->sacl
))) return status
;
676 offset
+= dst
->sacl
->size
;
678 if (!(src
->Control
& SE_DACL_PRESENT
)) dst
->dacl
= NULL
;
681 dst
->dacl
= (struct acl
*)((char *)dst
+ offset
);
682 if ((status
= acl_to_samba( src
->Dacl
, dst
->dacl
))) return status
;
688 static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR
*sd
)
690 unsigned int ret
= sizeof(struct security_descriptor
);
692 if (sd
->Owner
) ret
+= sizeof(struct sid
);
693 if (sd
->Group
) ret
+= sizeof(struct sid
);
694 if (sd
->Control
& SE_SACL_PRESENT
)
695 ret
+= sizeof(struct acl
) + sd
->Sacl
->AceCount
* sizeof(struct ace
);
696 if (sd
->Control
& SE_DACL_PRESENT
)
697 ret
+= sizeof(struct acl
) + sd
->Dacl
->AceCount
* sizeof(struct ace
);
701 static NET_API_STATUS
share_info_502_to_samba( const BYTE
*buf
, unsigned char **bufptr
)
703 NET_API_STATUS status
;
704 struct share_info_502
*ret
;
705 SHARE_INFO_502
*info
= (SHARE_INFO_502
*)buf
;
706 DWORD len
= 0, size
= 0;
710 if (info
->shi502_netname
)
711 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_netname
, -1, NULL
, 0, NULL
, NULL
);
712 if (info
->shi502_remark
)
713 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_remark
, -1, NULL
, 0, NULL
, NULL
);
714 if (info
->shi502_path
)
715 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_path
, -1, NULL
, 0, NULL
, NULL
);
716 if (info
->shi502_passwd
)
717 len
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_passwd
, -1, NULL
, 0, NULL
, NULL
);
718 if (info
->shi502_security_descriptor
)
719 size
= sd_to_samba_size( info
->shi502_security_descriptor
);
720 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ret
) + (len
* sizeof(WCHAR
)) + size
)))
721 return ERROR_OUTOFMEMORY
;
723 ptr
= (char *)(ret
+ 1);
724 if (!info
->shi502_netname
) ret
->shi502_netname
= NULL
;
727 ret
->shi502_netname
= ptr
;
728 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_netname
, -1, ptr
, len
, NULL
, NULL
);
730 ret
->shi502_type
= info
->shi502_type
;
731 if (!info
->shi502_remark
) ret
->shi502_remark
= NULL
;
734 ret
->shi502_remark
= ptr
;
735 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_remark
, -1, ptr
, len
, NULL
, NULL
);
737 ret
->shi502_permissions
= info
->shi502_permissions
;
738 ret
->shi502_max_uses
= info
->shi502_max_uses
;
739 ret
->shi502_current_uses
= info
->shi502_current_uses
;
740 if (!info
->shi502_path
) ret
->shi502_path
= NULL
;
743 ret
->shi502_path
= ptr
;
744 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_path
, -1, ptr
, len
, NULL
, NULL
);
746 if (!info
->shi502_passwd
) ret
->shi502_passwd
= NULL
;
749 ret
->shi502_passwd
= ptr
;
750 ptr
+= WideCharToMultiByte( CP_UNIXCP
, 0, info
->shi502_passwd
, -1, ptr
, len
, NULL
, NULL
);
752 ret
->shi502_reserved
= info
->shi502_reserved
;
753 if (!info
->shi502_security_descriptor
) ret
->shi502_security_descriptor
= NULL
;
756 status
= sd_to_samba( info
->shi502_security_descriptor
, (struct security_descriptor
*)ptr
);
759 HeapFree( GetProcessHeap(), 0, ret
);
762 ret
->shi502_security_descriptor
= (struct security_descriptor
*)ptr
;
764 *bufptr
= (unsigned char *)ret
;
768 static NET_API_STATUS
share_info_to_samba( DWORD level
, const BYTE
*buf
, unsigned char **bufptr
)
772 case 2: return share_info_2_to_samba( buf
, bufptr
);
773 case 502: return share_info_502_to_samba( buf
, bufptr
);
775 FIXME( "level %u not supported\n", level
);
776 return ERROR_NOT_SUPPORTED
;
780 static NET_API_STATUS
share_add( LMSTR servername
, DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
784 NET_API_STATUS status
;
786 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
787 status
= share_info_to_samba( level
, buf
, &info
);
792 status
= pNetShareAdd( server
, level
, info
, &err
);
793 HeapFree( GetProcessHeap(), 0, info
);
794 if (parm_err
) *parm_err
= err
;
796 HeapFree( GetProcessHeap(), 0, server
);
800 static NET_API_STATUS
share_del( LMSTR servername
, LMSTR netname
, DWORD reserved
)
802 char *server
= NULL
, *share
;
803 NET_API_STATUS status
;
805 if (servername
&& !(server
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
806 if (!(share
= strdup_unixcp( netname
)))
808 HeapFree( GetProcessHeap(), 0, server
);
809 return ERROR_OUTOFMEMORY
;
811 status
= pNetShareDel( server
, share
, reserved
);
812 HeapFree( GetProcessHeap(), 0, server
);
813 HeapFree( GetProcessHeap(), 0, share
);
817 struct wksta_info_100
819 unsigned int wki100_platform_id
;
820 const char *wki100_computername
;
821 const char *wki100_langroup
;
822 unsigned int wki100_ver_major
;
823 unsigned int wki100_ver_minor
;
826 static NET_API_STATUS
wksta_info_100_from_samba( const unsigned char *buf
, BYTE
**bufptr
)
829 struct wksta_info_100
*info
= (struct wksta_info_100
*)buf
;
833 if (info
->wki100_computername
)
834 len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_computername
, -1, NULL
, 0 );
835 if (info
->wki100_langroup
)
836 len
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_langroup
, -1, NULL
, 0 );
837 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ret
) + (len
* sizeof(WCHAR
) ))))
838 return ERROR_OUTOFMEMORY
;
840 ptr
= (WCHAR
*)(ret
+ 1);
841 ret
->wki100_platform_id
= info
->wki100_platform_id
;
842 if (!info
->wki100_computername
) ret
->wki100_computername
= NULL
;
845 ret
->wki100_computername
= ptr
;
846 ptr
+= MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_computername
, -1, ptr
, len
);
848 if (!info
->wki100_langroup
) ret
->wki100_langroup
= NULL
;
851 ret
->wki100_langroup
= ptr
;
852 MultiByteToWideChar( CP_UNIXCP
, 0, info
->wki100_langroup
, -1, ptr
, len
);
854 ret
->wki100_ver_major
= info
->wki100_ver_major
;
855 ret
->wki100_ver_minor
= info
->wki100_ver_minor
;
856 *bufptr
= (BYTE
*)ret
;
860 static NET_API_STATUS
wksta_info_from_samba( DWORD level
, const unsigned char *buf
, BYTE
**bufptr
)
864 case 100: return wksta_info_100_from_samba( buf
, bufptr
);
866 FIXME( "level %u not supported\n", level
);
867 return ERROR_NOT_SUPPORTED
;
871 static NET_API_STATUS
wksta_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
873 NET_API_STATUS status
;
875 unsigned char *buf
= NULL
;
877 if (servername
&& !(wksta
= strdup_unixcp( servername
))) return ERROR_OUTOFMEMORY
;
878 status
= pNetWkstaGetInfo( wksta
, level
, &buf
);
879 HeapFree( GetProcessHeap(), 0, wksta
);
882 status
= wksta_info_from_samba( level
, buf
, bufptr
);
883 pNetApiBufferFree( buf
);
890 static BOOL
libnetapi_init(void)
895 static NET_API_STATUS
server_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
898 return ERROR_NOT_SUPPORTED
;
900 static NET_API_STATUS
share_add( LMSTR servername
, DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
903 return ERROR_NOT_SUPPORTED
;
905 static NET_API_STATUS
share_del( LMSTR servername
, LMSTR netname
, DWORD reserved
)
908 return ERROR_NOT_SUPPORTED
;
910 static NET_API_STATUS
wksta_getinfo( LMSTR servername
, DWORD level
, LPBYTE
*bufptr
)
913 return ERROR_NOT_SUPPORTED
;
916 #endif /* SONAME_LIBNETAPI */
918 /************************************************************
919 * NETAPI_IsLocalComputer
921 * Checks whether the server name indicates local machine.
923 static BOOL
NETAPI_IsLocalComputer( LMCSTR name
)
925 WCHAR buf
[MAX_COMPUTERNAME_LENGTH
+ 1];
926 DWORD size
= sizeof(buf
) / sizeof(buf
[0]);
929 if (!name
|| !name
[0]) return TRUE
;
931 ret
= GetComputerNameW( buf
, &size
);
932 if (ret
&& name
[0] == '\\' && name
[1] == '\\') name
+= 2;
933 return ret
&& !strcmpiW( name
, buf
);
936 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
938 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
941 case DLL_PROCESS_ATTACH
:
942 DisableThreadLibraryCalls(hinstDLL
);
946 case DLL_PROCESS_DETACH
:
947 if (lpvReserved
) break;
955 /************************************************************
956 * NetServerEnum (NETAPI32.@)
958 NET_API_STATUS WINAPI
NetServerEnum(
964 LPDWORD totalentries
,
967 LPDWORD resume_handle
970 FIXME("Stub (%s %d %p %d %p %p %d %s %p)\n", debugstr_w(servername
),
971 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, servertype
,
972 debugstr_w(domain
), resume_handle
);
974 return ERROR_NO_BROWSER_SERVERS_FOUND
;
977 /************************************************************
978 * NetServerEnumEx (NETAPI32.@)
980 NET_API_STATUS WINAPI
NetServerEnumEx(
986 LPDWORD totalentries
,
989 LMCSTR FirstNameToReturn
)
991 FIXME("Stub (%s %d %p %d %p %p %d %s %s)\n",
992 debugstr_w(ServerName
), Level
, Bufptr
, PrefMaxlen
, EntriesRead
, totalentries
,
993 servertype
, debugstr_w(domain
), debugstr_w(FirstNameToReturn
));
995 return ERROR_NO_BROWSER_SERVERS_FOUND
;
998 /************************************************************
999 * NetServerDiskEnum (NETAPI32.@)
1001 NET_API_STATUS WINAPI
NetServerDiskEnum(
1006 LPDWORD EntriesRead
,
1007 LPDWORD totalentries
,
1008 LPDWORD Resume_Handle
)
1010 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(ServerName
),
1011 Level
, Bufptr
, PrefMaxlen
, EntriesRead
, totalentries
, Resume_Handle
);
1013 return ERROR_NO_BROWSER_SERVERS_FOUND
;
1016 /************************************************************
1017 * NetServerGetInfo (NETAPI32.@)
1019 NET_API_STATUS WINAPI
NetServerGetInfo(LMSTR servername
, DWORD level
, LPBYTE
* bufptr
)
1022 BOOL local
= NETAPI_IsLocalComputer( servername
);
1024 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
1028 if (libnetapi_init()) return server_getinfo( servername
, level
, bufptr
);
1029 FIXME( "remote computers not supported\n" );
1030 return ERROR_INVALID_LEVEL
;
1032 if (!bufptr
) return ERROR_INVALID_PARAMETER
;
1039 DWORD computerNameLen
, size
;
1040 WCHAR computerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1042 computerNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
1043 GetComputerNameW(computerName
, &computerNameLen
);
1044 computerNameLen
++; /* include NULL terminator */
1046 /* Plus 1 for empty comment */
1047 size
= sizeof(SERVER_INFO_101
) + (computerNameLen
+ 1) * sizeof(WCHAR
);
1048 ret
= NetApiBufferAllocate(size
, (LPVOID
*)bufptr
);
1049 if (ret
== NERR_Success
)
1051 /* INFO_100 structure is a subset of INFO_101 */
1052 PSERVER_INFO_101 info
= (PSERVER_INFO_101
)*bufptr
;
1053 OSVERSIONINFOW verInfo
;
1055 info
->sv101_platform_id
= PLATFORM_ID_NT
;
1056 info
->sv101_name
= (LMSTR
)(*bufptr
+ sizeof(SERVER_INFO_101
));
1057 memcpy(info
->sv101_name
, computerName
,
1058 computerNameLen
* sizeof(WCHAR
));
1059 verInfo
.dwOSVersionInfoSize
= sizeof(verInfo
);
1060 GetVersionExW(&verInfo
);
1061 info
->sv101_version_major
= verInfo
.dwMajorVersion
;
1062 info
->sv101_version_minor
= verInfo
.dwMinorVersion
;
1063 /* Use generic type as no wine equivalent of DC / Server */
1064 info
->sv101_type
= SV_TYPE_NT
;
1065 info
->sv101_comment
= (LMSTR
)(*bufptr
+ sizeof(SERVER_INFO_101
)
1066 + computerNameLen
* sizeof(WCHAR
));
1067 info
->sv101_comment
[0] = '\0';
1073 FIXME("level %d unimplemented\n", level
);
1074 ret
= ERROR_INVALID_LEVEL
;
1080 /************************************************************
1081 * NetStatisticsGet (NETAPI32.@)
1083 NET_API_STATUS WINAPI
NetStatisticsGet(LMSTR server
, LMSTR service
,
1084 DWORD level
, DWORD options
,
1088 static const WCHAR SERVICE_WORKSTATION
[] = {
1089 'L', 'a', 'n', 'm', 'a', 'n',
1090 'W', 'o', 'r', 'k', 's', 't', 'a', 't', 'i', 'o', 'n', '\0'};
1091 static const WCHAR SERVICE_SERVER
[] = {
1092 'L', 'a', 'n', 'm', 'a', 'n',
1093 'S', 'e', 'r', 'v', 'e', 'r', '\0'};
1096 STAT_WORKSTATION_0 workst
;
1097 STAT_SERVER_0 server
;
1101 TRACE("(server %s, service %s, level %d, options %d, buffer %p): stub\n",
1102 debugstr_w(server
), debugstr_w(service
), level
, options
, bufptr
);
1104 res
= NetApiBufferAllocate(sizeof(*stat
), &dataptr
);
1105 if (res
!= NERR_Success
) return res
;
1107 res
= NERR_InternalError
;
1112 if (!lstrcmpW(service
, SERVICE_WORKSTATION
))
1114 /* Fill the struct STAT_WORKSTATION_0 properly */
1115 memset(&stat
->workst
, 0, sizeof(stat
->workst
));
1118 else if (!lstrcmpW(service
, SERVICE_SERVER
))
1120 /* Fill the struct STAT_SERVER_0 properly */
1121 memset(&stat
->server
, 0, sizeof(stat
->server
));
1126 if (res
!= NERR_Success
)
1127 NetApiBufferFree(dataptr
);
1134 NET_API_STATUS WINAPI
NetUseEnum(LMSTR server
, DWORD level
, LPBYTE
* bufptr
, DWORD prefmaxsize
,
1135 LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resumehandle
)
1137 FIXME("stub (%p, %d, %p, %d, %p, %p, %p)\n", server
, level
, bufptr
, prefmaxsize
,
1138 entriesread
, totalentries
, resumehandle
);
1139 return ERROR_NOT_SUPPORTED
;
1142 NET_API_STATUS WINAPI
NetScheduleJobAdd(LPCWSTR server
, LPBYTE bufptr
, LPDWORD jobid
)
1144 TRACE("(%s, %p, %p)\n", debugstr_w(server
), bufptr
, jobid
);
1145 return NetrJobAdd(server
, (AT_INFO
*)bufptr
, jobid
);
1148 NET_API_STATUS WINAPI
NetScheduleJobDel(LPCWSTR server
, DWORD minjobid
, DWORD maxjobid
)
1150 TRACE("(%s, %u, %u)\n", debugstr_w(server
), minjobid
, maxjobid
);
1151 return NetrJobDel(server
, minjobid
, maxjobid
);
1154 NET_API_STATUS WINAPI
NetScheduleJobEnum(LPCWSTR server
, LPBYTE
* bufptr
, DWORD prefmaxsize
, LPDWORD entriesread
,
1155 LPDWORD totalentries
, LPDWORD resumehandle
)
1157 AT_ENUM_CONTAINER container
;
1160 TRACE("(%s, %p, %u, %p, %p, %p)\n", debugstr_w(server
), bufptr
, prefmaxsize
, entriesread
, totalentries
, resumehandle
);
1162 container
.EntriesRead
= 0;
1163 container
.Buffer
= NULL
;
1164 ret
= NetrJobEnum(server
, &container
, prefmaxsize
, totalentries
, resumehandle
);
1165 if (ret
== ERROR_SUCCESS
)
1167 *bufptr
= (LPBYTE
)container
.Buffer
;
1168 *entriesread
= container
.EntriesRead
;
1173 NET_API_STATUS WINAPI
NetScheduleJobGetInfo(LPCWSTR server
, DWORD jobid
, LPBYTE
*bufptr
)
1175 TRACE("(%s, %u, %p)\n", debugstr_w(server
), jobid
, bufptr
);
1176 return NetrJobGetInfo(server
, jobid
, (LPAT_INFO
*)bufptr
);
1179 NET_API_STATUS WINAPI
NetUseGetInfo(LMSTR server
, LMSTR name
, DWORD level
, LPBYTE
*bufptr
)
1181 FIXME("stub (%p, %p, %d, %p)\n", server
, name
, level
, bufptr
);
1182 return ERROR_NOT_SUPPORTED
;
1186 /************************************************************
1187 * NetApiBufferAllocate (NETAPI32.@)
1189 NET_API_STATUS WINAPI
NetApiBufferAllocate(DWORD ByteCount
, LPVOID
* Buffer
)
1191 TRACE("(%d, %p)\n", ByteCount
, Buffer
);
1193 if (Buffer
== NULL
) return ERROR_INVALID_PARAMETER
;
1194 *Buffer
= HeapAlloc(GetProcessHeap(), 0, ByteCount
);
1196 return NERR_Success
;
1198 return GetLastError();
1201 /************************************************************
1202 * NetApiBufferFree (NETAPI32.@)
1204 NET_API_STATUS WINAPI
NetApiBufferFree(LPVOID Buffer
)
1206 TRACE("(%p)\n", Buffer
);
1207 MIDL_user_free(Buffer
);
1208 return NERR_Success
;
1211 /************************************************************
1212 * NetApiBufferReallocate (NETAPI32.@)
1214 NET_API_STATUS WINAPI
NetApiBufferReallocate(LPVOID OldBuffer
, DWORD NewByteCount
,
1217 TRACE("(%p, %d, %p)\n", OldBuffer
, NewByteCount
, NewBuffer
);
1221 *NewBuffer
= HeapReAlloc(GetProcessHeap(), 0, OldBuffer
, NewByteCount
);
1223 *NewBuffer
= HeapAlloc(GetProcessHeap(), 0, NewByteCount
);
1224 return *NewBuffer
? NERR_Success
: GetLastError();
1228 if (!HeapFree(GetProcessHeap(), 0, OldBuffer
)) return GetLastError();
1230 return NERR_Success
;
1234 /************************************************************
1235 * NetApiBufferSize (NETAPI32.@)
1237 NET_API_STATUS WINAPI
NetApiBufferSize(LPVOID Buffer
, LPDWORD ByteCount
)
1241 TRACE("(%p, %p)\n", Buffer
, ByteCount
);
1243 return ERROR_INVALID_PARAMETER
;
1244 dw
= HeapSize(GetProcessHeap(), 0, Buffer
);
1245 TRACE("size: %d\n", dw
);
1246 if (dw
!= 0xFFFFFFFF)
1251 return NERR_Success
;
1254 /************************************************************
1255 * NetSessionEnum (NETAPI32.@)
1258 * servername [I] Pointer to a string with the name of the server
1259 * UncClientName [I] Pointer to a string with the name of the session
1260 * username [I] Pointer to a string with the name of the user
1261 * level [I] Data information level
1262 * bufptr [O] Buffer to the data
1263 * prefmaxlen [I] Preferred maximum length of the data
1264 * entriesread [O] Pointer to the number of entries enumerated
1265 * totalentries [O] Pointer to the possible number of entries
1266 * resume_handle [I/O] Pointer to a handle for subsequent searches
1269 * If successful, the function returns NERR_Success
1270 * On failure it returns:
1271 * ERROR_ACCESS_DENIED User has no access to the requested information
1272 * ERROR_INVALID_LEVEL Value of 'level' is not correct
1273 * ERROR_INVALID_PARAMETER Wrong parameter
1274 * ERROR_MORE_DATA Need a larger buffer
1275 * ERROR_NOT_ENOUGH_MEMORY Not enough memory
1276 * NERR_ClientNameNotFound A session does not exist on a given computer
1277 * NERR_InvalidComputer Invalid computer name
1278 * NERR_UserNotFound User name could not be found.
1280 NET_API_STATUS WINAPI
NetSessionEnum(LMSTR servername
, LMSTR UncClientName
,
1281 LMSTR username
, DWORD level
, LPBYTE
* bufptr
, DWORD prefmaxlen
, LPDWORD entriesread
,
1282 LPDWORD totalentries
, LPDWORD resume_handle
)
1284 FIXME("Stub (%s %s %s %d %p %d %p %p %p)\n", debugstr_w(servername
),
1285 debugstr_w(UncClientName
), debugstr_w(username
),
1286 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1288 return NERR_Success
;
1291 /************************************************************
1292 * NetShareEnum (NETAPI32.@)
1295 * servername [I] Pointer to a string with the name of the server
1296 * level [I] Data information level
1297 * bufptr [O] Buffer to the data
1298 * prefmaxlen [I] Preferred maximum length of the data
1299 * entriesread [O] Pointer to the number of entries enumerated
1300 * totalentries [O] Pointer to the possible number of entries
1301 * resume_handle [I/O] Pointer to a handle for subsequent searches
1304 * If successful, the function returns NERR_Success
1305 * On failure it returns a system error code (FIXME: find out which)
1308 NET_API_STATUS WINAPI
NetShareEnum( LMSTR servername
, DWORD level
, LPBYTE
* bufptr
,
1309 DWORD prefmaxlen
, LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resume_handle
)
1311 FIXME("Stub (%s %d %p %d %p %p %p)\n", debugstr_w(servername
), level
, bufptr
,
1312 prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1314 return ERROR_NOT_SUPPORTED
;
1317 /************************************************************
1318 * NetShareDel (NETAPI32.@)
1320 NET_API_STATUS WINAPI
NetShareDel(LMSTR servername
, LMSTR netname
, DWORD reserved
)
1322 BOOL local
= NETAPI_IsLocalComputer( servername
);
1324 TRACE("%s %s %d\n", debugstr_w(servername
), debugstr_w(netname
), reserved
);
1328 if (libnetapi_init()) return share_del( servername
, netname
, reserved
);
1329 FIXME( "remote computers not supported\n" );
1332 FIXME("%s %s %d\n", debugstr_w(servername
), debugstr_w(netname
), reserved
);
1333 return NERR_Success
;
1336 /************************************************************
1337 * NetShareGetInfo (NETAPI32.@)
1339 NET_API_STATUS WINAPI
NetShareGetInfo(LMSTR servername
, LMSTR netname
,
1340 DWORD level
, LPBYTE
*bufptr
)
1342 FIXME("Stub (%s %s %d %p)\n", debugstr_w(servername
),
1343 debugstr_w(netname
),level
, bufptr
);
1344 return NERR_NetNameNotFound
;
1347 /************************************************************
1348 * NetShareAdd (NETAPI32.@)
1350 NET_API_STATUS WINAPI
NetShareAdd(LMSTR servername
,
1351 DWORD level
, LPBYTE buf
, LPDWORD parm_err
)
1353 BOOL local
= NETAPI_IsLocalComputer( servername
);
1355 TRACE("%s %d %p %p\n", debugstr_w(servername
), level
, buf
, parm_err
);
1359 if (libnetapi_init()) return share_add( servername
, level
, buf
, parm_err
);
1360 FIXME( "remote computers not supported\n" );
1363 FIXME("%s %d %p %p\n", debugstr_w(servername
), level
, buf
, parm_err
);
1364 return ERROR_NOT_SUPPORTED
;
1367 /************************************************************
1368 * NetFileEnum (NETAPI32.@)
1370 NET_API_STATUS WINAPI
NetFileEnum(
1371 LPWSTR ServerName
, LPWSTR BasePath
, LPWSTR UserName
,
1372 DWORD Level
, LPBYTE
* BufPtr
, DWORD PrefMaxLen
,
1373 LPDWORD EntriesRead
, LPDWORD TotalEntries
, PDWORD_PTR ResumeHandle
)
1375 FIXME("(%s, %s, %s, %u): stub\n", debugstr_w(ServerName
), debugstr_w(BasePath
),
1376 debugstr_w(UserName
), Level
);
1377 return ERROR_NOT_SUPPORTED
;
1380 static void wprint_mac(WCHAR
* buffer
, int len
, const MIB_IFROW
*ifRow
)
1395 for (i
= 0; i
< ifRow
->dwPhysAddrLen
&& 2 * i
< len
; i
++)
1397 val
= ifRow
->bPhysAddr
[i
];
1399 buffer
[2*i
] = (WCHAR
)((val
>>4) + 'A' - 10);
1401 buffer
[2*i
] = (WCHAR
)((val
>>4) + '0');
1402 if ((val
& 0xf ) >9)
1403 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + 'A' - 10);
1405 buffer
[2*i
+1] = (WCHAR
)((val
& 0xf) + '0');
1410 /* Theoretically this could be too short, except that MS defines
1411 * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both
1412 * represent a count of WCHARs, so even with an extraordinarily long header
1413 * this will be plenty
1415 #define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN
1416 #define MAX_TRANSPORT_ADDR 13
1418 #define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
1419 #define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_"
1421 static void wprint_name(WCHAR
*buffer
, int len
, ULONG transport
,
1435 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
1436 name
= NBT_TRANSPORT_NAME_HEADER
;
1438 name
= UNKNOWN_TRANSPORT_NAME_HEADER
;
1440 for (ptr1
= buffer
; *name
&& ptr1
< buffer
+ len
; ptr1
++, name
++)
1442 for (ptr2
= ifRow
->wszName
; *ptr2
&& ptr1
< buffer
+ len
; ptr1
++, ptr2
++)
1447 /***********************************************************************
1448 * NetWkstaTransportEnum (NETAPI32.@)
1451 struct WkstaTransportEnumData
1460 /**********************************************************************/
1462 static BOOL
WkstaEnumAdaptersCallback(UCHAR totalLANAs
, UCHAR lanaIndex
,
1463 ULONG transport
, const NetBIOSAdapterImpl
*data
, void *closure
)
1466 struct WkstaTransportEnumData
*enumData
= closure
;
1468 if (enumData
&& enumData
->pbuf
)
1474 enumData
->n_adapt
= totalLANAs
;
1475 enumData
->n_read
= 0;
1477 toAllocate
= totalLANAs
* (sizeof(WKSTA_TRANSPORT_INFO_0
)
1478 + MAX_TRANSPORT_NAME
* sizeof(WCHAR
) +
1479 MAX_TRANSPORT_ADDR
* sizeof(WCHAR
));
1480 if (enumData
->prefmaxlen
!= MAX_PREFERRED_LENGTH
)
1481 toAllocate
= enumData
->prefmaxlen
;
1482 NetApiBufferAllocate(toAllocate
, (LPVOID
*)enumData
->pbuf
);
1484 if (*(enumData
->pbuf
))
1488 if (enumData
->prefmaxlen
== MAX_PREFERRED_LENGTH
)
1489 spaceFor
= totalLANAs
;
1491 spaceFor
= enumData
->prefmaxlen
/
1492 (sizeof(WKSTA_TRANSPORT_INFO_0
) + (MAX_TRANSPORT_NAME
+
1493 MAX_TRANSPORT_ADDR
) * sizeof(WCHAR
));
1494 if (enumData
->n_read
< spaceFor
)
1496 PWKSTA_TRANSPORT_INFO_0 ti
;
1497 LMSTR transport_name
, transport_addr
;
1500 ti
= (PWKSTA_TRANSPORT_INFO_0
)(*(enumData
->pbuf
) +
1501 enumData
->n_read
* sizeof(WKSTA_TRANSPORT_INFO_0
));
1502 transport_name
= (LMSTR
)(*(enumData
->pbuf
) +
1503 totalLANAs
* sizeof(WKSTA_TRANSPORT_INFO_0
) +
1504 enumData
->n_read
* MAX_TRANSPORT_NAME
* sizeof(WCHAR
));
1505 transport_addr
= (LMSTR
)(*(enumData
->pbuf
) +
1506 totalLANAs
* (sizeof(WKSTA_TRANSPORT_INFO_0
) +
1507 MAX_TRANSPORT_NAME
* sizeof(WCHAR
)) +
1508 enumData
->n_read
* MAX_TRANSPORT_ADDR
* sizeof(WCHAR
));
1510 ifRow
.dwIndex
= data
->ifIndex
;
1512 ti
->wkti0_quality_of_service
= 0;
1513 ti
->wkti0_number_of_vcs
= 0;
1514 ti
->wkti0_transport_name
= transport_name
;
1515 wprint_name(ti
->wkti0_transport_name
, MAX_TRANSPORT_NAME
,
1517 ti
->wkti0_transport_address
= transport_addr
;
1518 wprint_mac(ti
->wkti0_transport_address
, MAX_TRANSPORT_ADDR
,
1520 if (!memcmp(&transport
, TRANSPORT_NBT
, sizeof(ULONG
)))
1521 ti
->wkti0_wan_ish
= TRUE
;
1523 ti
->wkti0_wan_ish
= FALSE
;
1524 TRACE("%d of %d:ti at %p\n", lanaIndex
, totalLANAs
, ti
);
1525 TRACE("transport_name at %p %s\n",
1526 ti
->wkti0_transport_name
,
1527 debugstr_w(ti
->wkti0_transport_name
));
1528 TRACE("transport_address at %p %s\n",
1529 ti
->wkti0_transport_address
,
1530 debugstr_w(ti
->wkti0_transport_address
));
1532 enumData
->ret
= NERR_Success
;
1537 enumData
->ret
= ERROR_MORE_DATA
;
1543 enumData
->ret
= ERROR_OUTOFMEMORY
;
1552 /**********************************************************************/
1554 NET_API_STATUS WINAPI
1555 NetWkstaTransportEnum(LMSTR ServerName
, DWORD level
, PBYTE
* pbuf
,
1556 DWORD prefmaxlen
, LPDWORD read_entries
,
1557 PDWORD total_entries
, PDWORD hresume
)
1561 TRACE(":%s, 0x%08x, %p, 0x%08x, %p, %p, %p\n", debugstr_w(ServerName
),
1562 level
, pbuf
, prefmaxlen
, read_entries
, total_entries
,hresume
);
1563 if (!NETAPI_IsLocalComputer(ServerName
))
1565 FIXME(":not implemented for non-local computers\n");
1566 ret
= ERROR_INVALID_LEVEL
;
1570 if (hresume
&& *hresume
)
1572 FIXME(":resume handle not implemented\n");
1573 return ERROR_INVALID_LEVEL
;
1578 case 0: /* transport info */
1580 ULONG allTransports
;
1581 struct WkstaTransportEnumData enumData
;
1583 if (NetBIOSNumAdapters() == 0)
1584 return ERROR_NETWORK_UNREACHABLE
;
1586 return STATUS_ACCESS_VIOLATION
;
1587 if (!total_entries
|| !pbuf
)
1588 return RPC_X_NULL_REF_POINTER
;
1590 enumData
.prefmaxlen
= prefmaxlen
;
1591 enumData
.pbuf
= pbuf
;
1592 memcpy(&allTransports
, ALL_TRANSPORTS
, sizeof(ULONG
));
1593 NetBIOSEnumAdapters(allTransports
, WkstaEnumAdaptersCallback
,
1595 *read_entries
= enumData
.n_read
;
1596 *total_entries
= enumData
.n_adapt
;
1597 if (hresume
) *hresume
= 0;
1602 TRACE("Invalid level %d is specified\n", level
);
1603 ret
= ERROR_INVALID_LEVEL
;
1609 /************************************************************
1610 * NetWkstaUserGetInfo (NETAPI32.@)
1612 NET_API_STATUS WINAPI
NetWkstaUserGetInfo(LMSTR reserved
, DWORD level
,
1615 NET_API_STATUS nastatus
;
1617 TRACE("(%s, %d, %p)\n", debugstr_w(reserved
), level
, bufptr
);
1622 PWKSTA_USER_INFO_0 ui
;
1623 DWORD dwSize
= UNLEN
+ 1;
1626 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0
) + dwSize
* sizeof(WCHAR
),
1628 if (nastatus
!= NERR_Success
)
1629 return ERROR_NOT_ENOUGH_MEMORY
;
1631 ui
= (PWKSTA_USER_INFO_0
) *bufptr
;
1632 ui
->wkui0_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_0
));
1635 if (!GetUserNameW(ui
->wkui0_username
, &dwSize
))
1637 NetApiBufferFree(ui
);
1638 return ERROR_NOT_ENOUGH_MEMORY
;
1641 nastatus
= NetApiBufferReallocate(
1642 *bufptr
, sizeof(WKSTA_USER_INFO_0
) +
1643 (lstrlenW(ui
->wkui0_username
) + 1) * sizeof(WCHAR
),
1645 if (nastatus
!= NERR_Success
)
1647 NetApiBufferFree(ui
);
1650 ui
= (PWKSTA_USER_INFO_0
) *bufptr
;
1651 ui
->wkui0_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_0
));
1658 PWKSTA_USER_INFO_1 ui
;
1659 PWKSTA_USER_INFO_0 ui0
;
1660 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
1661 LSA_HANDLE PolicyHandle
;
1662 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
1665 /* sizes of the field buffers in WCHARS */
1666 int username_sz
, logon_domain_sz
, oth_domains_sz
, logon_server_sz
;
1668 FIXME("Level 1 processing is partially implemented\n");
1670 logon_server_sz
= 1;
1672 /* get some information first to estimate size of the buffer */
1674 nastatus
= NetWkstaUserGetInfo(NULL
, 0, (PBYTE
*) &ui0
);
1675 if (nastatus
!= NERR_Success
)
1677 username_sz
= lstrlenW(ui0
->wkui0_username
) + 1;
1679 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
1680 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
1681 POLICY_VIEW_LOCAL_INFORMATION
,
1683 if (NtStatus
!= STATUS_SUCCESS
)
1685 TRACE("LsaOpenPolicyFailed with NT status %x\n",
1686 LsaNtStatusToWinError(NtStatus
));
1687 NetApiBufferFree(ui0
);
1688 return ERROR_NOT_ENOUGH_MEMORY
;
1690 LsaQueryInformationPolicy(PolicyHandle
, PolicyAccountDomainInformation
,
1691 (PVOID
*) &DomainInfo
);
1692 logon_domain_sz
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
1693 LsaClose(PolicyHandle
);
1696 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1
) +
1697 (username_sz
+ logon_domain_sz
+
1698 oth_domains_sz
+ logon_server_sz
) * sizeof(WCHAR
),
1700 if (nastatus
!= NERR_Success
) {
1701 NetApiBufferFree(ui0
);
1704 ui
= (WKSTA_USER_INFO_1
*) *bufptr
;
1705 ui
->wkui1_username
= (LMSTR
) (*bufptr
+ sizeof(WKSTA_USER_INFO_1
));
1706 ui
->wkui1_logon_domain
= (LMSTR
) (
1707 ((PBYTE
) ui
->wkui1_username
) + username_sz
* sizeof(WCHAR
));
1708 ui
->wkui1_oth_domains
= (LMSTR
) (
1709 ((PBYTE
) ui
->wkui1_logon_domain
) +
1710 logon_domain_sz
* sizeof(WCHAR
));
1711 ui
->wkui1_logon_server
= (LMSTR
) (
1712 ((PBYTE
) ui
->wkui1_oth_domains
) +
1713 oth_domains_sz
* sizeof(WCHAR
));
1716 lstrcpyW(ui
->wkui1_username
, ui0
->wkui0_username
);
1717 NetApiBufferFree(ui0
);
1719 lstrcpynW(ui
->wkui1_logon_domain
, DomainInfo
->DomainName
.Buffer
,
1721 LsaFreeMemory(DomainInfo
);
1723 /* FIXME. Not implemented. Populated with empty strings */
1724 ui
->wkui1_oth_domains
[0] = 0;
1725 ui
->wkui1_logon_server
[0] = 0;
1730 PWKSTA_USER_INFO_1101 ui
;
1733 FIXME("Stub. Level 1101 processing is not implemented\n");
1734 /* FIXME see also wkui1_oth_domains for level 1 */
1737 nastatus
= NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101
) + dwSize
* sizeof(WCHAR
),
1739 if (nastatus
!= NERR_Success
)
1741 ui
= (PWKSTA_USER_INFO_1101
) *bufptr
;
1742 ui
->wkui1101_oth_domains
= (LMSTR
)(ui
+ 1);
1745 ui
->wkui1101_oth_domains
[0] = 0;
1749 TRACE("Invalid level %d is specified\n", level
);
1750 return ERROR_INVALID_LEVEL
;
1752 return NERR_Success
;
1755 /************************************************************
1756 * NetWkstaUserEnum (NETAPI32.@)
1758 NET_API_STATUS WINAPI
1759 NetWkstaUserEnum(LMSTR servername
, DWORD level
, LPBYTE
* bufptr
,
1760 DWORD prefmaxlen
, LPDWORD entriesread
,
1761 LPDWORD totalentries
, LPDWORD resumehandle
)
1763 FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername
),
1764 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
1765 return ERROR_INVALID_PARAMETER
;
1768 /************************************************************
1769 * NetpGetComputerName (NETAPI32.@)
1771 NET_API_STATUS WINAPI
NetpGetComputerName(LPWSTR
*Buffer
)
1773 DWORD dwSize
= MAX_COMPUTERNAME_LENGTH
+ 1;
1775 TRACE("(%p)\n", Buffer
);
1776 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) Buffer
);
1777 if (GetComputerNameW(*Buffer
, &dwSize
))
1779 return NetApiBufferReallocate(
1780 *Buffer
, (dwSize
+ 1) * sizeof(WCHAR
),
1785 NetApiBufferFree(*Buffer
);
1786 return ERROR_NOT_ENOUGH_MEMORY
;
1790 NET_API_STATUS WINAPI
I_NetNameCompare(LPVOID p1
, LPWSTR wkgrp
, LPWSTR comp
,
1791 LPVOID p4
, LPVOID p5
)
1793 FIXME("(%p %s %s %p %p): stub\n", p1
, debugstr_w(wkgrp
), debugstr_w(comp
),
1795 return ERROR_INVALID_PARAMETER
;
1798 NET_API_STATUS WINAPI
I_NetNameValidate(LPVOID p1
, LPWSTR wkgrp
, LPVOID p3
,
1801 FIXME("(%p %s %p %p): stub\n", p1
, debugstr_w(wkgrp
), p3
, p4
);
1802 return ERROR_INVALID_PARAMETER
;
1805 NET_API_STATUS WINAPI
NetWkstaGetInfo( LMSTR servername
, DWORD level
,
1809 BOOL local
= NETAPI_IsLocalComputer( servername
);
1811 TRACE("%s %d %p\n", debugstr_w( servername
), level
, bufptr
);
1815 if (libnetapi_init()) return wksta_getinfo( servername
, level
, bufptr
);
1816 FIXME( "remote computers not supported\n" );
1817 return ERROR_INVALID_LEVEL
;
1819 if (!bufptr
) return ERROR_INVALID_PARAMETER
;
1827 static const WCHAR lanroot
[] = {'c',':','\\','l','a','n','m','a','n',0}; /* FIXME */
1828 DWORD computerNameLen
, domainNameLen
, size
;
1829 WCHAR computerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1830 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
1831 LSA_HANDLE PolicyHandle
;
1834 computerNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
1835 GetComputerNameW(computerName
, &computerNameLen
);
1836 computerNameLen
++; /* include NULL terminator */
1838 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
1839 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
1840 POLICY_VIEW_LOCAL_INFORMATION
, &PolicyHandle
);
1841 if (NtStatus
!= STATUS_SUCCESS
)
1842 ret
= LsaNtStatusToWinError(NtStatus
);
1845 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
1847 LsaQueryInformationPolicy(PolicyHandle
,
1848 PolicyAccountDomainInformation
, (PVOID
*)&DomainInfo
);
1849 domainNameLen
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
1850 size
= sizeof(WKSTA_INFO_102
) + computerNameLen
* sizeof(WCHAR
)
1851 + domainNameLen
* sizeof(WCHAR
) + sizeof(lanroot
);
1852 ret
= NetApiBufferAllocate(size
, (LPVOID
*)bufptr
);
1853 if (ret
== NERR_Success
)
1855 /* INFO_100 and INFO_101 structures are subsets of INFO_102 */
1856 PWKSTA_INFO_102 info
= (PWKSTA_INFO_102
)*bufptr
;
1857 OSVERSIONINFOW verInfo
;
1859 info
->wki102_platform_id
= PLATFORM_ID_NT
;
1860 info
->wki102_computername
= (LMSTR
)(*bufptr
+
1861 sizeof(WKSTA_INFO_102
));
1862 memcpy(info
->wki102_computername
, computerName
,
1863 computerNameLen
* sizeof(WCHAR
));
1864 info
->wki102_langroup
= info
->wki102_computername
+ computerNameLen
;
1865 memcpy(info
->wki102_langroup
, DomainInfo
->DomainName
.Buffer
,
1866 domainNameLen
* sizeof(WCHAR
));
1867 info
->wki102_lanroot
= info
->wki102_langroup
+ domainNameLen
;
1868 memcpy(info
->wki102_lanroot
, lanroot
, sizeof(lanroot
));
1869 memset(&verInfo
, 0, sizeof(verInfo
));
1870 verInfo
.dwOSVersionInfoSize
= sizeof(verInfo
);
1871 GetVersionExW(&verInfo
);
1872 info
->wki102_ver_major
= verInfo
.dwMajorVersion
;
1873 info
->wki102_ver_minor
= verInfo
.dwMinorVersion
;
1874 info
->wki102_logged_on_users
= 1;
1876 LsaFreeMemory(DomainInfo
);
1877 LsaClose(PolicyHandle
);
1883 FIXME("level %d unimplemented\n", level
);
1884 ret
= ERROR_INVALID_LEVEL
;
1889 /************************************************************
1890 * NetGetJoinInformation (NETAPI32.@)
1892 NET_API_STATUS NET_API_FUNCTION
NetGetJoinInformation(
1895 PNETSETUP_JOIN_STATUS type
)
1897 static const WCHAR workgroupW
[] = {'W','o','r','k','g','r','o','u','p',0};
1899 FIXME("Semi-stub %s %p %p\n", wine_dbgstr_w(Server
), Name
, type
);
1902 return ERROR_INVALID_PARAMETER
;
1904 NetApiBufferAllocate(sizeof(workgroupW
), (LPVOID
*)Name
);
1905 lstrcpyW(*Name
, workgroupW
);
1906 *type
= NetSetupWorkgroupName
;
1908 return NERR_Success
;
1911 /************************************************************
1912 * NetUserGetGroups (NETAPI32.@)
1914 NET_API_STATUS NET_API_FUNCTION
NetUserGetGroups(
1920 LPDWORD entriesread
,
1921 LPDWORD totalentries
)
1923 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername
),
1924 debugstr_w(username
), level
, bufptr
, prefixmaxlen
, entriesread
,
1931 return ERROR_INVALID_LEVEL
;
1937 WCHAR user_name
[LM20_UNLEN
+1];
1938 WCHAR user_password
[PWLEN
+ 1];
1939 DWORD sec_since_passwd_change
;
1942 LPWSTR user_comment
;
1944 LPWSTR user_logon_script_path
;
1947 static struct list user_list
= LIST_INIT( user_list
);
1949 /************************************************************
1950 * NETAPI_ValidateServername
1952 * Validates server name
1954 static NET_API_STATUS
NETAPI_ValidateServername(LPCWSTR ServerName
)
1958 if (ServerName
[0] == 0)
1959 return ERROR_BAD_NETPATH
;
1961 ((ServerName
[0] == '\\') &&
1962 (ServerName
[1] != '\\'))
1964 ((ServerName
[0] == '\\') &&
1965 (ServerName
[1] == '\\') &&
1966 (ServerName
[2] == 0))
1968 return ERROR_INVALID_NAME
;
1970 return NERR_Success
;
1973 /************************************************************
1976 * Looks for a user in the user database.
1977 * Returns a pointer to the entry in the user list when the user
1978 * is found, NULL otherwise.
1980 static struct sam_user
* NETAPI_FindUser(LPCWSTR UserName
)
1982 struct sam_user
*user
;
1984 LIST_FOR_EACH_ENTRY(user
, &user_list
, struct sam_user
, entry
)
1986 if(lstrcmpW(user
->user_name
, UserName
) == 0)
1992 static BOOL
NETAPI_IsCurrentUser(LPCWSTR username
)
1994 LPWSTR curr_user
= NULL
;
1998 dwSize
= LM20_UNLEN
+1;
1999 curr_user
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(WCHAR
));
2002 ERR("Failed to allocate memory for user name.\n");
2005 if(!GetUserNameW(curr_user
, &dwSize
))
2007 ERR("Failed to get current user's user name.\n");
2010 if (!lstrcmpW(curr_user
, username
))
2016 HeapFree(GetProcessHeap(), 0, curr_user
);
2020 /************************************************************
2021 * NetUserAdd (NETAPI32.@)
2023 NET_API_STATUS WINAPI
NetUserAdd(LPCWSTR servername
,
2024 DWORD level
, LPBYTE bufptr
, LPDWORD parm_err
)
2026 NET_API_STATUS status
;
2027 struct sam_user
* su
= NULL
;
2029 FIXME("(%s, %d, %p, %p) stub!\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
2031 if((status
= NETAPI_ValidateServername(servername
)) != NERR_Success
)
2036 /* Level 3 and 4 are identical for the purposes of NetUserAdd */
2039 FIXME("Level 3 and 4 not implemented.\n");
2042 FIXME("Level 2 not implemented.\n");
2046 PUSER_INFO_1 ui
= (PUSER_INFO_1
) bufptr
;
2047 su
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct sam_user
));
2050 status
= NERR_InternalError
;
2054 if(lstrlenW(ui
->usri1_name
) > LM20_UNLEN
)
2056 status
= NERR_BadUsername
;
2060 /*FIXME: do other checks for a valid username */
2061 lstrcpyW(su
->user_name
, ui
->usri1_name
);
2063 if(lstrlenW(ui
->usri1_password
) > PWLEN
)
2065 /* Always return PasswordTooShort on invalid passwords. */
2066 status
= NERR_PasswordTooShort
;
2069 lstrcpyW(su
->user_password
, ui
->usri1_password
);
2071 su
->sec_since_passwd_change
= ui
->usri1_password_age
;
2072 su
->user_priv
= ui
->usri1_priv
;
2073 su
->user_flags
= ui
->usri1_flags
;
2075 /*FIXME: set the other LPWSTRs to NULL for now */
2076 su
->home_dir
= NULL
;
2077 su
->user_comment
= NULL
;
2078 su
->user_logon_script_path
= NULL
;
2080 list_add_head(&user_list
, &su
->entry
);
2081 return NERR_Success
;
2084 TRACE("Invalid level %d specified.\n", level
);
2085 status
= ERROR_INVALID_LEVEL
;
2089 HeapFree(GetProcessHeap(), 0, su
);
2094 /************************************************************
2095 * NetUserDel (NETAPI32.@)
2097 NET_API_STATUS WINAPI
NetUserDel(LPCWSTR servername
, LPCWSTR username
)
2099 NET_API_STATUS status
;
2100 struct sam_user
*user
;
2102 TRACE("(%s, %s)\n", debugstr_w(servername
), debugstr_w(username
));
2104 if((status
= NETAPI_ValidateServername(servername
))!= NERR_Success
)
2107 if ((user
= NETAPI_FindUser(username
)) == NULL
)
2108 return NERR_UserNotFound
;
2110 list_remove(&user
->entry
);
2112 HeapFree(GetProcessHeap(), 0, user
->home_dir
);
2113 HeapFree(GetProcessHeap(), 0, user
->user_comment
);
2114 HeapFree(GetProcessHeap(), 0, user
->user_logon_script_path
);
2115 HeapFree(GetProcessHeap(), 0, user
);
2117 return NERR_Success
;
2120 /************************************************************
2121 * NetUserGetInfo (NETAPI32.@)
2123 NET_API_STATUS WINAPI
2124 NetUserGetInfo(LPCWSTR servername
, LPCWSTR username
, DWORD level
,
2127 NET_API_STATUS status
;
2128 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername
), debugstr_w(username
),
2130 status
= NETAPI_ValidateServername(servername
);
2131 if (status
!= NERR_Success
)
2134 if(!NETAPI_IsLocalComputer(servername
))
2136 FIXME("Only implemented for local computer, but remote server"
2137 "%s was requested.\n", debugstr_w(servername
));
2138 return NERR_InvalidComputer
;
2141 if(!NETAPI_FindUser(username
) && !NETAPI_IsCurrentUser(username
))
2143 TRACE("User %s is unknown.\n", debugstr_w(username
));
2144 return NERR_UserNotFound
;
2154 name_sz
= lstrlenW(username
) + 1;
2157 NetApiBufferAllocate(sizeof(USER_INFO_0
) + name_sz
* sizeof(WCHAR
),
2160 ui
= (PUSER_INFO_0
) *bufptr
;
2161 ui
->usri0_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_0
));
2164 lstrcpyW(ui
->usri0_name
, username
);
2172 /* sizes of the field buffers in WCHARS */
2173 int name_sz
, comment_sz
, usr_comment_sz
, full_name_sz
;
2180 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
2181 if (status
!= NERR_Success
)
2183 NetApiBufferFree(ui0
);
2186 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
2189 NetApiBufferAllocate(sizeof(USER_INFO_10
) +
2190 (name_sz
+ comment_sz
+ usr_comment_sz
+
2191 full_name_sz
) * sizeof(WCHAR
),
2193 ui
= (PUSER_INFO_10
) *bufptr
;
2194 ui
->usri10_name
= (LPWSTR
) (*bufptr
+ sizeof(USER_INFO_10
));
2195 ui
->usri10_comment
= (LPWSTR
) (
2196 ((PBYTE
) ui
->usri10_name
) + name_sz
* sizeof(WCHAR
));
2197 ui
->usri10_usr_comment
= (LPWSTR
) (
2198 ((PBYTE
) ui
->usri10_comment
) + comment_sz
* sizeof(WCHAR
));
2199 ui
->usri10_full_name
= (LPWSTR
) (
2200 ((PBYTE
) ui
->usri10_usr_comment
) + usr_comment_sz
* sizeof(WCHAR
));
2203 lstrcpyW(ui
->usri10_name
, ui0
->usri0_name
);
2204 NetApiBufferFree(ui0
);
2205 ui
->usri10_comment
[0] = 0;
2206 ui
->usri10_usr_comment
[0] = 0;
2207 ui
->usri10_full_name
[0] = 0;
2213 static const WCHAR homedirW
[] = {'H','O','M','E',0};
2216 /* sizes of the field buffers in WCHARS */
2217 int name_sz
, password_sz
, home_dir_sz
, comment_sz
, script_path_sz
;
2219 password_sz
= 1; /* not filled out for security reasons for NetUserGetInfo*/
2224 status
= NetUserGetInfo(servername
, username
, 0, (LPBYTE
*) &ui0
);
2225 if (status
!= NERR_Success
)
2227 NetApiBufferFree(ui0
);
2230 name_sz
= lstrlenW(ui0
->usri0_name
) + 1;
2231 home_dir_sz
= GetEnvironmentVariableW(homedirW
, NULL
,0);
2233 NetApiBufferAllocate(sizeof(USER_INFO_1
) +
2234 (name_sz
+ password_sz
+ home_dir_sz
+
2235 comment_sz
+ script_path_sz
) * sizeof(WCHAR
),
2238 ui
= (PUSER_INFO_1
) *bufptr
;
2239 ui
->usri1_name
= (LPWSTR
) (ui
+ 1);
2240 ui
->usri1_password
= ui
->usri1_name
+ name_sz
;
2241 ui
->usri1_home_dir
= ui
->usri1_password
+ password_sz
;
2242 ui
->usri1_comment
= ui
->usri1_home_dir
+ home_dir_sz
;
2243 ui
->usri1_script_path
= ui
->usri1_comment
+ comment_sz
;
2245 lstrcpyW(ui
->usri1_name
, ui0
->usri0_name
);
2246 NetApiBufferFree(ui0
);
2247 ui
->usri1_password
[0] = 0;
2248 ui
->usri1_password_age
= 0;
2250 GetEnvironmentVariableW(homedirW
, ui
->usri1_home_dir
,home_dir_sz
);
2251 ui
->usri1_comment
[0] = 0;
2252 ui
->usri1_flags
= 0;
2253 ui
->usri1_script_path
[0] = 0;
2283 FIXME("Level %d is not implemented\n", level
);
2284 return NERR_InternalError
;
2287 TRACE("Invalid level %d is specified\n", level
);
2288 return ERROR_INVALID_LEVEL
;
2290 return NERR_Success
;
2293 /************************************************************
2294 * NetUserGetLocalGroups (NETAPI32.@)
2296 NET_API_STATUS WINAPI
2297 NetUserGetLocalGroups(LPCWSTR servername
, LPCWSTR username
, DWORD level
,
2298 DWORD flags
, LPBYTE
* bufptr
, DWORD prefmaxlen
,
2299 LPDWORD entriesread
, LPDWORD totalentries
)
2301 NET_API_STATUS status
;
2302 const WCHAR admins
[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0};
2304 LOCALGROUP_USERS_INFO_0
* info
;
2307 FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
2308 debugstr_w(servername
), debugstr_w(username
), level
, flags
, bufptr
,
2309 prefmaxlen
, entriesread
, totalentries
);
2311 status
= NETAPI_ValidateServername(servername
);
2312 if (status
!= NERR_Success
)
2316 NetApiBufferAllocate(size
* sizeof(WCHAR
), (LPVOID
*)¤tuser
);
2317 if (!GetUserNameW(currentuser
, &size
)) {
2318 NetApiBufferFree(currentuser
);
2319 return ERROR_NOT_ENOUGH_MEMORY
;
2322 if (lstrcmpiW(username
, currentuser
) && NETAPI_FindUser(username
))
2324 NetApiBufferFree(currentuser
);
2325 return NERR_UserNotFound
;
2328 NetApiBufferFree(currentuser
);
2330 size
= sizeof(*info
) + sizeof(admins
);
2332 if(prefmaxlen
< size
)
2333 status
= ERROR_MORE_DATA
;
2335 status
= NetApiBufferAllocate(size
, (LPVOID
*)&info
);
2337 if(status
!= NERR_Success
)
2344 info
->lgrui0_name
= (LPWSTR
)((LPBYTE
)info
+ sizeof(*info
));
2345 lstrcpyW(info
->lgrui0_name
, admins
);
2347 *bufptr
= (LPBYTE
)info
;
2350 return NERR_Success
;
2353 /************************************************************
2354 * NetUserEnum (NETAPI32.@)
2356 NET_API_STATUS WINAPI
2357 NetUserEnum(LPCWSTR servername
, DWORD level
, DWORD filter
, LPBYTE
* bufptr
,
2358 DWORD prefmaxlen
, LPDWORD entriesread
, LPDWORD totalentries
,
2359 LPDWORD resume_handle
)
2361 NET_API_STATUS status
;
2362 WCHAR user
[UNLEN
+ 1];
2363 DWORD size
, len
= sizeof(user
)/sizeof(user
[0]);
2365 TRACE("(%s, %u, 0x%x, %p, %u, %p, %p, %p)\n", debugstr_w(servername
), level
,
2366 filter
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
2368 status
= NETAPI_ValidateServername(servername
);
2369 if (status
!= NERR_Success
)
2372 if (!NETAPI_IsLocalComputer(servername
))
2374 FIXME("Only implemented for local computer, but remote server"
2375 "%s was requested.\n", debugstr_w(servername
));
2376 return NERR_InvalidComputer
;
2379 if (!GetUserNameW(user
, &len
)) return GetLastError();
2387 size
= sizeof(*info
) + (strlenW(user
) + 1) * sizeof(WCHAR
);
2389 if (prefmaxlen
< size
)
2390 status
= ERROR_MORE_DATA
;
2392 status
= NetApiBufferAllocate(size
, (void **)&info
);
2394 if (status
!= NERR_Success
)
2397 info
->usri0_name
= (WCHAR
*)((char *)info
+ sizeof(*info
));
2398 strcpyW(info
->usri0_name
, user
);
2400 *bufptr
= (BYTE
*)info
;
2401 *entriesread
= *totalentries
= 1;
2412 size
= sizeof(*info
) + (strlenW(user
) + 1) * sizeof(WCHAR
);
2414 if (prefmaxlen
< size
)
2415 status
= ERROR_MORE_DATA
;
2417 status
= NetApiBufferAllocate(size
, (void **)&info
);
2419 if (status
!= NERR_Success
)
2423 LookupAccountNameW(NULL
, user
, NULL
, &size
, NULL
, &len
, &use
);
2424 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2425 return GetLastError();
2427 status
= NetApiBufferAllocate(size
, (void **)&sid
);
2428 if (status
!= NERR_Success
)
2431 if (!LookupAccountNameW(NULL
, user
, sid
, &size
, NULL
, &len
, &use
))
2432 return GetLastError();
2434 count
= GetSidSubAuthorityCount(sid
);
2435 rid
= GetSidSubAuthority(sid
, *count
- 1);
2437 info
->usri20_name
= (WCHAR
*)((char *)info
+ sizeof(*info
));
2438 strcpyW(info
->usri20_name
, user
);
2439 info
->usri20_full_name
= NULL
;
2440 info
->usri20_comment
= NULL
;
2441 info
->usri20_flags
= UF_NORMAL_ACCOUNT
;
2442 info
->usri20_user_id
= *rid
;
2444 *bufptr
= (BYTE
*)info
;
2445 *entriesread
= *totalentries
= 1;
2447 NetApiBufferFree(sid
);
2451 FIXME("level %u not supported\n", level
);
2452 return ERROR_INVALID_LEVEL
;
2454 return NERR_Success
;
2457 /************************************************************
2458 * ACCESS_QueryAdminDisplayInformation
2460 * Creates a buffer with information for the Admin User
2462 static void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER
*buf
, PDWORD pdwSize
)
2464 static const WCHAR sAdminUserName
[] = {
2465 'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2467 /* sizes of the field buffers in WCHARS */
2468 int name_sz
, comment_sz
, full_name_sz
;
2469 PNET_DISPLAY_USER usr
;
2472 name_sz
= lstrlenW(sAdminUserName
) + 1;
2476 *pdwSize
= sizeof(NET_DISPLAY_USER
);
2477 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2478 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) buf
);
2481 usr
->usri1_name
= (LPWSTR
) ((PBYTE
) usr
+ sizeof(NET_DISPLAY_USER
));
2482 usr
->usri1_comment
= (LPWSTR
) (
2483 ((PBYTE
) usr
->usri1_name
) + name_sz
* sizeof(WCHAR
));
2484 usr
->usri1_full_name
= (LPWSTR
) (
2485 ((PBYTE
) usr
->usri1_comment
) + comment_sz
* sizeof(WCHAR
));
2488 lstrcpyW(usr
->usri1_name
, sAdminUserName
);
2489 usr
->usri1_comment
[0] = 0;
2490 usr
->usri1_flags
= UF_SCRIPT
| UF_NORMAL_ACCOUNT
| UF_DONT_EXPIRE_PASSWD
;
2491 usr
->usri1_full_name
[0] = 0;
2492 usr
->usri1_user_id
= DOMAIN_USER_RID_ADMIN
;
2493 usr
->usri1_next_index
= 0;
2496 /************************************************************
2497 * ACCESS_QueryGuestDisplayInformation
2499 * Creates a buffer with information for the Guest User
2501 static void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER
*buf
, PDWORD pdwSize
)
2503 static const WCHAR sGuestUserName
[] = {
2504 'G','u','e','s','t',0 };
2506 /* sizes of the field buffers in WCHARS */
2507 int name_sz
, comment_sz
, full_name_sz
;
2508 PNET_DISPLAY_USER usr
;
2511 name_sz
= lstrlenW(sGuestUserName
) + 1;
2515 *pdwSize
= sizeof(NET_DISPLAY_USER
);
2516 *pdwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2517 NetApiBufferAllocate(*pdwSize
, (LPVOID
*) buf
);
2520 usr
->usri1_name
= (LPWSTR
) ((PBYTE
) usr
+ sizeof(NET_DISPLAY_USER
));
2521 usr
->usri1_comment
= (LPWSTR
) (
2522 ((PBYTE
) usr
->usri1_name
) + name_sz
* sizeof(WCHAR
));
2523 usr
->usri1_full_name
= (LPWSTR
) (
2524 ((PBYTE
) usr
->usri1_comment
) + comment_sz
* sizeof(WCHAR
));
2527 lstrcpyW(usr
->usri1_name
, sGuestUserName
);
2528 usr
->usri1_comment
[0] = 0;
2529 usr
->usri1_flags
= UF_ACCOUNTDISABLE
| UF_SCRIPT
| UF_NORMAL_ACCOUNT
|
2530 UF_DONT_EXPIRE_PASSWD
;
2531 usr
->usri1_full_name
[0] = 0;
2532 usr
->usri1_user_id
= DOMAIN_USER_RID_GUEST
;
2533 usr
->usri1_next_index
= 0;
2536 /************************************************************
2537 * Copies NET_DISPLAY_USER record.
2539 static void ACCESS_CopyDisplayUser(const NET_DISPLAY_USER
*dest
, LPWSTR
*dest_buf
,
2540 PNET_DISPLAY_USER src
)
2542 LPWSTR str
= *dest_buf
;
2544 src
->usri1_name
= str
;
2545 lstrcpyW(src
->usri1_name
, dest
->usri1_name
);
2547 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2549 src
->usri1_comment
= str
;
2550 lstrcpyW(src
->usri1_comment
, dest
->usri1_comment
);
2552 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2554 src
->usri1_flags
= dest
->usri1_flags
;
2556 src
->usri1_full_name
= str
;
2557 lstrcpyW(src
->usri1_full_name
, dest
->usri1_full_name
);
2559 ((PBYTE
) str
) + (lstrlenW(str
) + 1) * sizeof(WCHAR
));
2561 src
->usri1_user_id
= dest
->usri1_user_id
;
2562 src
->usri1_next_index
= dest
->usri1_next_index
;
2566 /************************************************************
2567 * NetQueryDisplayInformation (NETAPI32.@)
2569 * The buffer structure:
2570 * - array of fixed size record of the level type
2571 * - strings, referenced by the record of the level type
2573 NET_API_STATUS WINAPI
2574 NetQueryDisplayInformation(
2575 LPCWSTR ServerName
, DWORD Level
, DWORD Index
, DWORD EntriesRequested
,
2576 DWORD PreferredMaximumLength
, LPDWORD ReturnedEntryCount
,
2577 PVOID
*SortedBuffer
)
2579 TRACE("(%s, %d, %d, %d, %d, %p, %p)\n", debugstr_w(ServerName
),
2580 Level
, Index
, EntriesRequested
, PreferredMaximumLength
,
2581 ReturnedEntryCount
, SortedBuffer
);
2583 if(!NETAPI_IsLocalComputer(ServerName
))
2585 FIXME("Only implemented on local computer, but requested for "
2586 "remote server %s\n", debugstr_w(ServerName
));
2587 return ERROR_ACCESS_DENIED
;
2594 /* current record */
2595 PNET_DISPLAY_USER inf
;
2596 /* current available strings buffer */
2598 PNET_DISPLAY_USER admin
, guest
;
2599 DWORD admin_size
, guest_size
;
2603 /* sizes of the field buffers in WCHARS */
2604 int name_sz
, comment_sz
, full_name_sz
;
2606 /* number of the records, returned in SortedBuffer
2607 3 - for current user, Administrator and Guest users
2611 FIXME("Level %d partially implemented\n", Level
);
2612 *ReturnedEntryCount
= records
;
2618 NetApiBufferAllocate(dwSize
* sizeof(WCHAR
), (LPVOID
*) &name
);
2619 if (!GetUserNameW(name
, &dwSize
))
2621 NetApiBufferFree(name
);
2622 return ERROR_ACCESS_DENIED
;
2625 ACCESS_QueryAdminDisplayInformation(&admin
, &admin_size
);
2626 ACCESS_QueryGuestDisplayInformation(&guest
, &guest_size
);
2629 dwSize
= sizeof(NET_DISPLAY_USER
) * records
;
2630 dwSize
+= (name_sz
+ comment_sz
+ full_name_sz
) * sizeof(WCHAR
);
2632 NetApiBufferAllocate(dwSize
+
2633 admin_size
- sizeof(NET_DISPLAY_USER
) +
2634 guest_size
- sizeof(NET_DISPLAY_USER
),
2636 inf
= *SortedBuffer
;
2637 str
= (LPWSTR
) ((PBYTE
) inf
+ sizeof(NET_DISPLAY_USER
) * records
);
2638 inf
->usri1_name
= str
;
2640 ((PBYTE
) str
) + name_sz
* sizeof(WCHAR
));
2641 inf
->usri1_comment
= str
;
2643 ((PBYTE
) str
) + comment_sz
* sizeof(WCHAR
));
2644 inf
->usri1_full_name
= str
;
2646 ((PBYTE
) str
) + full_name_sz
* sizeof(WCHAR
));
2649 lstrcpyW(inf
->usri1_name
, name
);
2650 NetApiBufferFree(name
);
2651 inf
->usri1_comment
[0] = 0;
2653 UF_SCRIPT
| UF_NORMAL_ACCOUNT
| UF_DONT_EXPIRE_PASSWD
;
2654 inf
->usri1_full_name
[0] = 0;
2655 inf
->usri1_user_id
= 0;
2656 inf
->usri1_next_index
= 0;
2659 ACCESS_CopyDisplayUser(admin
, &str
, inf
);
2660 NetApiBufferFree(admin
);
2663 ACCESS_CopyDisplayUser(guest
, &str
, inf
);
2664 NetApiBufferFree(guest
);
2671 FIXME("Level %d is not implemented\n", Level
);
2676 TRACE("Invalid level %d is specified\n", Level
);
2677 return ERROR_INVALID_LEVEL
;
2679 return NERR_Success
;
2682 /************************************************************
2683 * NetGetDCName (NETAPI32.@)
2685 * Return the name of the primary domain controller (PDC)
2688 NET_API_STATUS WINAPI
2689 NetGetDCName(LPCWSTR servername
, LPCWSTR domainname
, LPBYTE
*bufptr
)
2691 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername
),
2692 debugstr_w(domainname
), bufptr
);
2693 return NERR_DCNotFound
; /* say we can't find a domain controller */
2696 /************************************************************
2697 * NetGetAnyDCName (NETAPI32.@)
2699 * Return the name of any domain controller (DC) for a
2700 * domain that is directly trusted by the specified server
2703 NET_API_STATUS WINAPI
NetGetAnyDCName(LPCWSTR servername
, LPCWSTR domainname
, LPBYTE
*bufptr
)
2705 FIXME("(%s, %s, %p) stub!\n", debugstr_w(servername
),
2706 debugstr_w(domainname
), bufptr
);
2707 return ERROR_NO_SUCH_DOMAIN
;
2710 /************************************************************
2711 * NetGroupAddUser (NETAPI32.@)
2713 NET_API_STATUS WINAPI
2714 NetGroupAddUser(LPCWSTR servername
, LPCWSTR groupname
, LPCWSTR username
)
2716 FIXME("(%s, %s, %s) stub!\n", debugstr_w(servername
),
2717 debugstr_w(groupname
), debugstr_w(username
));
2718 return NERR_Success
;
2721 /************************************************************
2722 * NetGroupEnum (NETAPI32.@)
2725 NET_API_STATUS WINAPI
2726 NetGroupEnum(LPCWSTR servername
, DWORD level
, LPBYTE
*bufptr
, DWORD prefmaxlen
,
2727 LPDWORD entriesread
, LPDWORD totalentries
, LPDWORD resume_handle
)
2729 FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername
),
2730 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
2731 return ERROR_ACCESS_DENIED
;
2734 /************************************************************
2735 * NetGroupGetInfo (NETAPI32.@)
2738 NET_API_STATUS WINAPI
NetGroupGetInfo(LPCWSTR servername
, LPCWSTR groupname
, DWORD level
, LPBYTE
*bufptr
)
2740 FIXME("(%s, %s, %d, %p) stub!\n", debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
);
2741 return ERROR_ACCESS_DENIED
;
2744 /******************************************************************************
2745 * NetUserModalsGet (NETAPI32.@)
2747 * Retrieves global information for all users and global groups in the security
2751 * szServer [I] Specifies the DNS or the NetBIOS name of the remote server
2752 * on which the function is to execute.
2753 * level [I] Information level of the data.
2754 * 0 Return global passwords parameters. bufptr points to a
2755 * USER_MODALS_INFO_0 struct.
2756 * 1 Return logon server and domain controller information. bufptr
2757 * points to a USER_MODALS_INFO_1 struct.
2758 * 2 Return domain name and identifier. bufptr points to a
2759 * USER_MODALS_INFO_2 struct.
2760 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
2762 * pbuffer [I] Buffer that receives the data.
2765 * Success: NERR_Success.
2767 * ERROR_ACCESS_DENIED - the user does not have access to the info.
2768 * NERR_InvalidComputer - computer name is invalid.
2770 NET_API_STATUS WINAPI
NetUserModalsGet(
2771 LPCWSTR szServer
, DWORD level
, LPBYTE
*pbuffer
)
2773 TRACE("(%s %d %p)\n", debugstr_w(szServer
), level
, pbuffer
);
2778 /* return global passwords parameters */
2779 FIXME("level 0 not implemented!\n");
2781 return NERR_InternalError
;
2783 /* return logon server and domain controller info */
2784 FIXME("level 1 not implemented!\n");
2786 return NERR_InternalError
;
2789 /* return domain name and identifier */
2790 PUSER_MODALS_INFO_2 umi
;
2791 LSA_HANDLE policyHandle
;
2792 LSA_OBJECT_ATTRIBUTES objectAttributes
;
2793 PPOLICY_ACCOUNT_DOMAIN_INFO domainInfo
;
2795 PSID domainIdentifier
= NULL
;
2798 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
2799 objectAttributes
.Length
= sizeof(objectAttributes
);
2801 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
2802 POLICY_VIEW_LOCAL_INFORMATION
,
2804 if (ntStatus
!= STATUS_SUCCESS
)
2806 WARN("LsaOpenPolicy failed with NT status %x\n",
2807 LsaNtStatusToWinError(ntStatus
));
2811 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
2812 PolicyAccountDomainInformation
,
2813 (PVOID
*)&domainInfo
);
2814 if (ntStatus
!= STATUS_SUCCESS
)
2816 WARN("LsaQueryInformationPolicy failed with NT status %x\n",
2817 LsaNtStatusToWinError(ntStatus
));
2818 LsaClose(policyHandle
);
2822 domainIdentifier
= domainInfo
->DomainSid
;
2823 domainNameLen
= lstrlenW(domainInfo
->DomainName
.Buffer
) + 1;
2824 LsaClose(policyHandle
);
2826 ntStatus
= NetApiBufferAllocate(sizeof(USER_MODALS_INFO_2
) +
2827 GetLengthSid(domainIdentifier
) +
2828 domainNameLen
* sizeof(WCHAR
),
2831 if (ntStatus
!= NERR_Success
)
2833 WARN("NetApiBufferAllocate() failed\n");
2834 LsaFreeMemory(domainInfo
);
2838 umi
= (USER_MODALS_INFO_2
*) *pbuffer
;
2839 umi
->usrmod2_domain_id
= *pbuffer
+ sizeof(USER_MODALS_INFO_2
);
2840 umi
->usrmod2_domain_name
= (LPWSTR
)(*pbuffer
+
2841 sizeof(USER_MODALS_INFO_2
) + GetLengthSid(domainIdentifier
));
2843 lstrcpynW(umi
->usrmod2_domain_name
,
2844 domainInfo
->DomainName
.Buffer
,
2846 CopySid(GetLengthSid(domainIdentifier
), umi
->usrmod2_domain_id
,
2849 LsaFreeMemory(domainInfo
);
2854 /* return lockout information */
2855 FIXME("level 3 not implemented!\n");
2857 return NERR_InternalError
;
2859 TRACE("Invalid level %d is specified\n", level
);
2861 return ERROR_INVALID_LEVEL
;
2864 return NERR_Success
;
2867 static NET_API_STATUS
change_password_smb( LPCWSTR domainname
, LPCWSTR username
,
2868 LPCWSTR oldpassword
, LPCWSTR newpassword
)
2871 NET_API_STATUS ret
= NERR_Success
;
2872 static char option_silent
[] = "-s";
2873 static char option_user
[] = "-U";
2874 static char option_remote
[] = "-r";
2875 static char smbpasswd
[] = "smbpasswd";
2879 char *server
= NULL
, *user
, *argv
[7], *old
= NULL
, *new = NULL
;
2881 if (domainname
&& !(server
= strdup_unixcp( domainname
))) return ERROR_OUTOFMEMORY
;
2882 if (!(user
= strdup_unixcp( username
)))
2884 ret
= ERROR_OUTOFMEMORY
;
2887 if (!(old
= strdup_unixcp( oldpassword
)))
2889 ret
= ERROR_OUTOFMEMORY
;
2892 if (!(new = strdup_unixcp( newpassword
)))
2894 ret
= ERROR_OUTOFMEMORY
;
2897 argv
[0] = smbpasswd
;
2898 argv
[1] = option_silent
;
2899 argv
[2] = option_user
;
2903 argv
[4] = option_remote
;
2907 else argv
[4] = NULL
;
2909 if (pipe( pipe_out
) == -1)
2911 ret
= NERR_InternalError
;
2914 fcntl( pipe_out
[0], F_SETFD
, FD_CLOEXEC
);
2915 fcntl( pipe_out
[1], F_SETFD
, FD_CLOEXEC
);
2917 switch ((pid
= fork()))
2920 close( pipe_out
[0] );
2921 close( pipe_out
[1] );
2922 ret
= NERR_InternalError
;
2925 dup2( pipe_out
[0], 0 );
2926 close( pipe_out
[0] );
2927 close( pipe_out
[1] );
2928 execvp( "smbpasswd", argv
);
2929 ERR( "can't execute smbpasswd, is it installed?\n" );
2932 close( pipe_out
[0] );
2935 write( pipe_out
[1], old
, strlen( old
) );
2936 write( pipe_out
[1], "\n", 1 );
2937 write( pipe_out
[1], new, strlen( new ) );
2938 write( pipe_out
[1], "\n", 1 );
2939 write( pipe_out
[1], new, strlen( new ) );
2940 write( pipe_out
[1], "\n", 1 );
2941 close( pipe_out
[1] );
2944 wret
= waitpid(pid
, &status
, 0);
2945 } while (wret
< 0 && errno
== EINTR
);
2947 if (ret
== NERR_Success
&& (wret
< 0 || !WIFEXITED(status
) || WEXITSTATUS(status
)))
2948 ret
= NERR_InternalError
;
2951 HeapFree( GetProcessHeap(), 0, server
);
2952 HeapFree( GetProcessHeap(), 0, user
);
2953 HeapFree( GetProcessHeap(), 0, old
);
2954 HeapFree( GetProcessHeap(), 0, new );
2957 ERR( "no fork support on this platform\n" );
2958 return NERR_InternalError
;
2962 /******************************************************************************
2963 * NetUserChangePassword (NETAPI32.@)
2965 * domainname [I] Optional. Domain on which the user resides or the logon
2966 * domain of the current user if NULL.
2967 * username [I] Optional. Username to change the password for or the name
2968 * of the current user if NULL.
2969 * oldpassword [I] The user's current password.
2970 * newpassword [I] The password that the user will be changed to using.
2973 * Success: NERR_Success.
2974 * Failure: NERR_* failure code or win error code.
2977 NET_API_STATUS WINAPI
NetUserChangePassword(LPCWSTR domainname
, LPCWSTR username
,
2978 LPCWSTR oldpassword
, LPCWSTR newpassword
)
2980 struct sam_user
*user
;
2982 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname
), debugstr_w(username
));
2984 if (!change_password_smb( domainname
, username
, oldpassword
, newpassword
))
2985 return NERR_Success
;
2988 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname
));
2990 if((user
= NETAPI_FindUser(username
)) == NULL
)
2991 return NERR_UserNotFound
;
2993 if(lstrcmpW(user
->user_password
, oldpassword
) != 0)
2994 return ERROR_INVALID_PASSWORD
;
2996 if(lstrlenW(newpassword
) > PWLEN
)
2997 return ERROR_PASSWORD_RESTRICTION
;
2999 lstrcpyW(user
->user_password
, newpassword
);
3001 return NERR_Success
;
3004 NET_API_STATUS WINAPI
NetUseAdd(LMSTR servername
, DWORD level
, LPBYTE bufptr
, LPDWORD parm_err
)
3006 FIXME("%s %d %p %p stub\n", debugstr_w(servername
), level
, bufptr
, parm_err
);
3007 return NERR_Success
;
3010 NET_API_STATUS WINAPI
NetUseDel(LMSTR servername
, LMSTR usename
, DWORD forcecond
)
3012 FIXME("%s %s %d stub\n", debugstr_w(servername
), debugstr_w(usename
), forcecond
);
3013 return NERR_Success
;
3016 /************************************************************
3017 * I_BrowserSetNetlogonState (NETAPI32.@)
3019 NET_API_STATUS WINAPI
I_BrowserSetNetlogonState(
3020 LPWSTR ServerName
, LPWSTR DomainName
, LPWSTR EmulatedServerName
,
3023 return ERROR_NOT_SUPPORTED
;
3026 /************************************************************
3027 * I_BrowserQueryEmulatedDomains (NETAPI32.@)
3029 NET_API_STATUS WINAPI
I_BrowserQueryEmulatedDomains(
3030 LPWSTR ServerName
, PBROWSER_EMULATED_DOMAIN
*EmulatedDomains
,
3031 LPDWORD EntriesRead
)
3033 return ERROR_NOT_SUPPORTED
;
3036 DWORD WINAPI
DsGetDcNameW(LPCWSTR ComputerName
, LPCWSTR AvoidDCName
,
3037 GUID
* DomainGuid
, LPCWSTR SiteName
, ULONG Flags
,
3038 PDOMAIN_CONTROLLER_INFOW
*DomainControllerInfo
)
3040 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_w(ComputerName
),
3041 debugstr_w(AvoidDCName
), debugstr_guid(DomainGuid
),
3042 debugstr_w(SiteName
), Flags
, DomainControllerInfo
);
3043 return ERROR_CALL_NOT_IMPLEMENTED
;
3046 DWORD WINAPI
DsGetDcNameA(LPCSTR ComputerName
, LPCSTR AvoidDCName
,
3047 GUID
* DomainGuid
, LPCSTR SiteName
, ULONG Flags
,
3048 PDOMAIN_CONTROLLER_INFOA
*DomainControllerInfo
)
3050 FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_a(ComputerName
),
3051 debugstr_a(AvoidDCName
), debugstr_guid(DomainGuid
),
3052 debugstr_a(SiteName
), Flags
, DomainControllerInfo
);
3053 return ERROR_CALL_NOT_IMPLEMENTED
;
3056 DWORD WINAPI
DsGetSiteNameW(LPCWSTR ComputerName
, LPWSTR
*SiteName
)
3058 FIXME("(%s, %p): stub\n", debugstr_w(ComputerName
), SiteName
);
3059 return ERROR_CALL_NOT_IMPLEMENTED
;
3062 DWORD WINAPI
DsGetSiteNameA(LPCSTR ComputerName
, LPSTR
*SiteName
)
3064 FIXME("(%s, %p): stub\n", debugstr_a(ComputerName
), SiteName
);
3065 return ERROR_CALL_NOT_IMPLEMENTED
;
3068 /************************************************************
3069 * DsRoleFreeMemory (NETAPI32.@)
3072 * Buffer [I] Pointer to the to-be-freed buffer.
3077 VOID WINAPI
DsRoleFreeMemory(PVOID Buffer
)
3079 TRACE("(%p)\n", Buffer
);
3080 HeapFree(GetProcessHeap(), 0, Buffer
);
3083 /************************************************************
3084 * DsRoleGetPrimaryDomainInformation (NETAPI32.@)
3087 * lpServer [I] Pointer to UNICODE string with ComputerName
3088 * InfoLevel [I] Type of data to retrieve
3089 * Buffer [O] Pointer to to the requested data
3094 * When lpServer is NULL, use the local computer
3096 DWORD WINAPI
DsRoleGetPrimaryDomainInformation(
3097 LPCWSTR lpServer
, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel
,
3102 FIXME("(%p, %d, %p) stub\n", lpServer
, InfoLevel
, Buffer
);
3104 /* Check some input parameters */
3106 if (!Buffer
) return ERROR_INVALID_PARAMETER
;
3107 if ((InfoLevel
< DsRolePrimaryDomainInfoBasic
) || (InfoLevel
> DsRoleOperationState
)) return ERROR_INVALID_PARAMETER
;
3112 case DsRolePrimaryDomainInfoBasic
:
3114 LSA_OBJECT_ATTRIBUTES ObjectAttributes
;
3115 LSA_HANDLE PolicyHandle
;
3116 PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo
;
3118 int logon_domain_sz
;
3120 PDSROLE_PRIMARY_DOMAIN_INFO_BASIC basic
;
3122 ZeroMemory(&ObjectAttributes
, sizeof(ObjectAttributes
));
3123 NtStatus
= LsaOpenPolicy(NULL
, &ObjectAttributes
,
3124 POLICY_VIEW_LOCAL_INFORMATION
, &PolicyHandle
);
3125 if (NtStatus
!= STATUS_SUCCESS
)
3127 TRACE("LsaOpenPolicyFailed with NT status %x\n",
3128 LsaNtStatusToWinError(NtStatus
));
3129 return ERROR_OUTOFMEMORY
;
3131 LsaQueryInformationPolicy(PolicyHandle
,
3132 PolicyAccountDomainInformation
, (PVOID
*)&DomainInfo
);
3133 logon_domain_sz
= lstrlenW(DomainInfo
->DomainName
.Buffer
) + 1;
3134 LsaClose(PolicyHandle
);
3136 size
= sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC
) +
3137 logon_domain_sz
* sizeof(WCHAR
);
3138 basic
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
3141 basic
->MachineRole
= DsRole_RoleStandaloneWorkstation
;
3142 basic
->DomainNameFlat
= (LPWSTR
)((LPBYTE
)basic
+
3143 sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC
));
3144 lstrcpyW(basic
->DomainNameFlat
, DomainInfo
->DomainName
.Buffer
);
3145 ret
= ERROR_SUCCESS
;
3148 ret
= ERROR_OUTOFMEMORY
;
3149 *Buffer
= (PBYTE
)basic
;
3150 LsaFreeMemory(DomainInfo
);
3154 ret
= ERROR_CALL_NOT_IMPLEMENTED
;
3159 /************************************************************
3160 * NetLocalGroupAdd (NETAPI32.@)
3162 NET_API_STATUS WINAPI
NetLocalGroupAdd(
3168 FIXME("(%s %d %p %p) stub!\n", debugstr_w(servername
), level
, buf
,
3170 return NERR_Success
;
3173 /************************************************************
3174 * NetLocalGroupAddMember (NETAPI32.@)
3176 NET_API_STATUS WINAPI
NetLocalGroupAddMember(
3181 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
3182 debugstr_w(groupname
), membersid
);
3183 return NERR_Success
;
3186 /************************************************************
3187 * NetLocalGroupAddMembers (NETAPI32.@)
3189 NET_API_STATUS WINAPI
NetLocalGroupAddMembers(
3196 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
3197 debugstr_w(groupname
), level
, buf
, totalentries
);
3198 return NERR_Success
;
3201 /************************************************************
3202 * NetLocalGroupDel (NETAPI32.@)
3204 NET_API_STATUS WINAPI
NetLocalGroupDel(
3208 FIXME("(%s %s) stub!\n", debugstr_w(servername
), debugstr_w(groupname
));
3209 return NERR_Success
;
3212 /************************************************************
3213 * NetLocalGroupDelMember (NETAPI32.@)
3215 NET_API_STATUS WINAPI
NetLocalGroupDelMember(
3220 FIXME("(%s %s %p) stub!\n", debugstr_w(servername
),
3221 debugstr_w(groupname
), membersid
);
3222 return NERR_Success
;
3225 /************************************************************
3226 * NetLocalGroupDelMembers (NETAPI32.@)
3228 NET_API_STATUS WINAPI
NetLocalGroupDelMembers(
3235 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
3236 debugstr_w(groupname
), level
, buf
, totalentries
);
3237 return NERR_Success
;
3240 /************************************************************
3241 * NetLocalGroupEnum (NETAPI32.@)
3243 NET_API_STATUS WINAPI
NetLocalGroupEnum(
3248 LPDWORD entriesread
,
3249 LPDWORD totalentries
,
3250 PDWORD_PTR resumehandle
)
3252 FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername
),
3253 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resumehandle
);
3256 return NERR_Success
;
3259 /************************************************************
3260 * NetLocalGroupGetInfo (NETAPI32.@)
3262 NET_API_STATUS WINAPI
NetLocalGroupGetInfo(
3268 static const WCHAR commentW
[]={'N','o',' ','c','o','m','m','e','n','t',0};
3269 LOCALGROUP_INFO_1
* info
;
3272 FIXME("(%s %s %d %p) semi-stub!\n", debugstr_w(servername
),
3273 debugstr_w(groupname
), level
, bufptr
);
3275 size
= sizeof(*info
) + sizeof(WCHAR
) * (lstrlenW(groupname
)+1) + sizeof(commentW
);
3276 NetApiBufferAllocate(size
, (LPVOID
*)&info
);
3278 info
->lgrpi1_name
= (LPWSTR
)(info
+ 1);
3279 lstrcpyW(info
->lgrpi1_name
, groupname
);
3281 info
->lgrpi1_comment
= info
->lgrpi1_name
+ lstrlenW(groupname
) + 1;
3282 lstrcpyW(info
->lgrpi1_comment
, commentW
);
3284 *bufptr
= (LPBYTE
)info
;
3286 return NERR_Success
;
3289 /************************************************************
3290 * NetLocalGroupGetMembers (NETAPI32.@)
3292 NET_API_STATUS WINAPI
NetLocalGroupGetMembers(
3294 LPCWSTR localgroupname
,
3298 LPDWORD entriesread
,
3299 LPDWORD totalentries
,
3300 PDWORD_PTR resumehandle
)
3302 FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername
),
3303 debugstr_w(localgroupname
), level
, bufptr
, prefmaxlen
, entriesread
,
3304 totalentries
, resumehandle
);
3308 WCHAR userName
[MAX_COMPUTERNAME_LENGTH
+ 1];
3311 PLOCALGROUP_MEMBERS_INFO_3 ptr
;
3313 /* still a stub, current user is belonging to all groups */
3318 userNameLen
= MAX_COMPUTERNAME_LENGTH
+ 1;
3319 if (!GetUserNameW(userName
,&userNameLen
))
3320 return ERROR_NOT_ENOUGH_MEMORY
;
3322 needlen
= sizeof(LOCALGROUP_MEMBERS_INFO_3
) +
3323 (userNameLen
+2) * sizeof(WCHAR
);
3324 if (prefmaxlen
!= MAX_PREFERRED_LENGTH
)
3325 len
= min(prefmaxlen
,needlen
);
3329 NetApiBufferAllocate(len
, (LPVOID
*) bufptr
);
3331 return ERROR_MORE_DATA
;
3333 ptr
= (PLOCALGROUP_MEMBERS_INFO_3
)*bufptr
;
3334 ptr
->lgrmi3_domainandname
= (LPWSTR
)(*bufptr
+sizeof(LOCALGROUP_MEMBERS_INFO_3
));
3335 lstrcpyW(ptr
->lgrmi3_domainandname
,userName
);
3340 return NERR_Success
;
3343 /************************************************************
3344 * NetLocalGroupSetInfo (NETAPI32.@)
3346 NET_API_STATUS WINAPI
NetLocalGroupSetInfo(
3353 FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername
),
3354 debugstr_w(groupname
), level
, buf
, parm_err
);
3355 return NERR_Success
;
3358 /************************************************************
3359 * NetLocalGroupSetMember (NETAPI32.@)
3361 NET_API_STATUS WINAPI
NetLocalGroupSetMembers(
3368 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername
),
3369 debugstr_w(groupname
), level
, buf
, totalentries
);
3370 return NERR_Success
;
3373 /************************************************************
3374 * DavGetHTTPFromUNCPath (NETAPI32.@)
3376 DWORD WINAPI
DavGetHTTPFromUNCPath(const WCHAR
*unc_path
, WCHAR
*buf
, DWORD
*buflen
)
3378 static const WCHAR httpW
[] = {'h','t','t','p',':','/','/',0};
3379 static const WCHAR httpsW
[] = {'h','t','t','p','s',':','/','/',0};
3380 static const WCHAR sslW
[] = {'S','S','L',0};
3381 static const WCHAR fmtW
[] = {':','%','u',0};
3382 const WCHAR
*p
= unc_path
, *q
, *server
, *path
, *scheme
= httpW
;
3383 UINT i
, len_server
, len_path
= 0, len_port
= 0, len
, port
= 0;
3384 WCHAR
*end
, portbuf
[12];
3386 TRACE("(%s %p %p)\n", debugstr_w(unc_path
), buf
, buflen
);
3388 if (p
[0] != '\\' || p
[1] != '\\' || !p
[2]) return ERROR_INVALID_PARAMETER
;
3390 while (*q
&& *q
!= '\\' && *q
!= '/' && *q
!= '@') q
++;
3396 while (*p
&& (*p
!= '\\' && *p
!= '/' && *p
!= '@')) p
++;
3397 if (p
- q
== 3 && !memicmpW( q
, sslW
, 3 ))
3402 else if ((port
= strtolW( q
, &end
, 10 ))) q
= end
;
3403 else return ERROR_INVALID_PARAMETER
;
3407 if (!(port
= strtolW( ++q
, &end
, 10 ))) return ERROR_INVALID_PARAMETER
;
3410 if (*q
== '\\' || *q
== '/') q
++;
3412 while (*q
++) len_path
++;
3413 if (len_path
&& (path
[len_path
- 1] == '\\' || path
[len_path
- 1] == '/'))
3414 len_path
--; /* remove trailing slash */
3416 sprintfW( portbuf
, fmtW
, port
);
3417 if (scheme
== httpsW
)
3419 len
= strlenW( httpsW
);
3420 if (port
&& port
!= 443) len_port
= strlenW( portbuf
);
3424 len
= strlenW( httpW
);
3425 if (port
&& port
!= 80) len_port
= strlenW( portbuf
);
3429 if (len_path
) len
+= len_path
+ 1; /* leading '/' */
3435 return ERROR_INSUFFICIENT_BUFFER
;
3438 memcpy( buf
, scheme
, strlenW(scheme
) * sizeof(WCHAR
) );
3439 buf
+= strlenW( scheme
);
3440 memcpy( buf
, server
, len_server
* sizeof(WCHAR
) );
3444 memcpy( buf
, portbuf
, len_port
* sizeof(WCHAR
) );
3450 for (i
= 0; i
< len_path
; i
++)
3452 if (path
[i
] == '\\') *buf
++ = '/';
3453 else *buf
++ = path
[i
];
3459 return ERROR_SUCCESS
;
3462 /************************************************************
3463 * DavGetUNCFromHTTPPath (NETAPI32.@)
3465 DWORD WINAPI
DavGetUNCFromHTTPPath(const WCHAR
*http_path
, WCHAR
*buf
, DWORD
*buflen
)
3467 static const WCHAR httpW
[] = {'h','t','t','p'};
3468 static const WCHAR httpsW
[] = {'h','t','t','p','s'};
3469 static const WCHAR davrootW
[] = {'\\','D','a','v','W','W','W','R','o','o','t'};
3470 static const WCHAR sslW
[] = {'@','S','S','L'};
3471 static const WCHAR port80W
[] = {'8','0'};
3472 static const WCHAR port443W
[] = {'4','4','3'};
3473 const WCHAR
*p
= http_path
, *server
, *port
= NULL
, *path
= NULL
;
3474 DWORD i
, len
= 0, len_server
= 0, len_port
= 0, len_path
= 0;
3477 TRACE("(%s %p %p)\n", debugstr_w(http_path
), buf
, buflen
);
3479 while (*p
&& *p
!= ':') { p
++; len
++; };
3480 if (len
== sizeof(httpW
)/sizeof(httpW
[0]) && !memicmpW( http_path
, httpW
, len
)) ssl
= FALSE
;
3481 else if (len
== sizeof(httpsW
)/sizeof(httpsW
[0]) && !memicmpW( http_path
, httpsW
, len
)) ssl
= TRUE
;
3482 else return ERROR_INVALID_PARAMETER
;
3484 if (p
[0] != ':' || p
[1] != '/' || p
[2] != '/') return ERROR_INVALID_PARAMETER
;
3487 while (*p
&& *p
!= ':' && *p
!= '/') { p
++; len_server
++; };
3488 if (!len_server
) return ERROR_BAD_NET_NAME
;
3492 while (*p
&& isdigitW(*p
)) { p
++; len_port
++; };
3493 if (len_port
== 2 && !ssl
&& !memcmp( port
, port80W
, sizeof(port80W
) )) port
= NULL
;
3494 else if (len_port
== 3 && ssl
&& !memcmp( port
, port443W
, sizeof(port443W
) )) port
= NULL
;
3497 else if (*p
== '/') path
= p
;
3501 if (p
[0] == '/' && p
[1] == '/') return ERROR_BAD_NET_NAME
;
3504 if (len_path
&& path
[len_path
- 1] == '/') len_path
--;
3506 len
= len_server
+ 2; /* \\ */
3507 if (ssl
) len
+= 4; /* @SSL */
3508 if (port
) len
+= len_port
+ 1 /* @ */;
3509 len
+= sizeof(davrootW
)/sizeof(davrootW
[0]);
3510 len
+= len_path
+ 1; /* nul */
3515 return ERROR_INSUFFICIENT_BUFFER
;
3518 buf
[0] = buf
[1] = '\\';
3520 memcpy( buf
, server
, len_server
* sizeof(WCHAR
) );
3524 memcpy( buf
, sslW
, sizeof(sslW
) );
3530 memcpy( buf
, port
, len_port
* sizeof(WCHAR
) );
3533 memcpy( buf
, davrootW
, sizeof(davrootW
) );
3534 buf
+= sizeof(davrootW
)/sizeof(davrootW
[0]);
3535 for (i
= 0; i
< len_path
; i
++)
3537 if (path
[i
] == '/') *buf
++ = '\\';
3538 else *buf
++ = path
[i
];
3544 return ERROR_SUCCESS
;
3547 /************************************************************
3548 * DsEnumerateDomainTrustsA (NETAPI32.@)
3550 DWORD WINAPI
DsEnumerateDomainTrustsA(LPSTR server
, ULONG flags
, PDS_DOMAIN_TRUSTSA
* domains
, PULONG count
)
3552 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_a(server
), flags
, domains
, count
);
3553 return ERROR_NO_LOGON_SERVERS
;
3556 /************************************************************
3557 * DsEnumerateDomainTrustsW (NETAPI32.@)
3559 DWORD WINAPI
DsEnumerateDomainTrustsW(LPWSTR server
, ULONG flags
, PDS_DOMAIN_TRUSTSW
* domains
, PULONG count
)
3561 FIXME("(%s, 0x%04x, %p, %p): stub\n", debugstr_w(server
), flags
, domains
, count
);
3562 return ERROR_NO_LOGON_SERVERS
;
3565 DECLSPEC_HIDDEN
void __RPC_FAR
*__RPC_USER
MIDL_user_allocate(SIZE_T n
)
3567 return HeapAlloc(GetProcessHeap(), 0, n
);
3570 DECLSPEC_HIDDEN
void __RPC_USER
MIDL_user_free(void __RPC_FAR
*p
)
3572 HeapFree(GetProcessHeap(), 0, p
);
3575 DECLSPEC_HIDDEN handle_t __RPC_USER
ATSVC_HANDLE_bind(ATSVC_HANDLE str
)
3577 static unsigned char ncalrpc
[] = "ncalrpc";
3578 unsigned char *binding_str
;
3579 handle_t rpc_handle
= 0;
3581 if (RpcStringBindingComposeA(NULL
, ncalrpc
, NULL
, NULL
, NULL
, &binding_str
) == RPC_S_OK
)
3583 RpcBindingFromStringBindingA(binding_str
, &rpc_handle
);
3584 RpcStringFreeA(&binding_str
);
3589 DECLSPEC_HIDDEN
void __RPC_USER
ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName
, handle_t rpc_handle
)
3591 RpcBindingFree(&rpc_handle
);