dmusic: Avoid swallowing collection Load failures.
[wine.git] / dlls / netapi32 / unixlib.c
blob4c5f1ba386edc5c3cd974bc5c4a28f53a2d090c4
1 /*
2 * Unix library for libnetapi functions
4 * Copyright 2013 Hans Leidekker for CodeWeavers
5 * Copyright 2021 Zebediah Figura for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #if 0
23 #pragma makedep unix
24 #endif
26 #include "config.h"
28 #ifdef SONAME_LIBNETAPI
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <unistd.h>
37 #include <dlfcn.h>
39 #include "ntstatus.h"
40 #define WIN32_NO_STATUS
41 #include "windef.h"
42 #include "winternl.h"
43 #include "lm.h"
44 #include "wine/debug.h"
46 #include "unixlib.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
49 WINE_DECLARE_DEBUG_CHANNEL(winediag);
51 static void *libnetapi_handle;
52 static void *libnetapi_ctx;
54 static DWORD (*plibnetapi_init)( void ** );
55 static DWORD (*plibnetapi_free)( void * );
56 static DWORD (*plibnetapi_set_debuglevel)( void *, const char * );
57 static DWORD (*plibnetapi_set_username)( void *, const char * );
58 static DWORD (*plibnetapi_set_password)( void *, const char * );
60 static NET_API_STATUS (*pNetApiBufferAllocate)( unsigned int, void ** );
61 static NET_API_STATUS (*pNetApiBufferFree)( void * );
62 static NET_API_STATUS (*pNetServerGetInfo)( const char *, unsigned int, unsigned char ** );
63 static NET_API_STATUS (*pNetShareAdd)( const char *, unsigned int, unsigned char *, unsigned int * );
64 static NET_API_STATUS (*pNetShareDel)( const char *, const char *, unsigned int );
65 static NET_API_STATUS (*pNetWkstaGetInfo)( const char *, unsigned int, unsigned char ** );
67 static DWORD netapi_wcstoumbs( const WCHAR *src, char *dst, DWORD dstlen )
69 if (!dst) return 3 * wcslen( src ) + 1;
70 return ntdll_wcstoumbs( src, wcslen( src ) + 1, dst, dstlen, FALSE );
73 static DWORD netapi_umbstowcs( const char *src, WCHAR *dst, DWORD dstlen )
75 if (!dst) return strlen( src ) + 1;
76 return ntdll_umbstowcs( src, strlen( src ) + 1, dst, dstlen );
79 static char *strdup_unixcp( const WCHAR *str )
81 char *ret;
83 int len = netapi_wcstoumbs( str, NULL, 0 );
84 if ((ret = malloc( len )))
85 netapi_wcstoumbs( str, ret, len );
86 return ret;
89 struct server_info_101
91 unsigned int sv101_platform_id;
92 const char *sv101_name;
93 unsigned int sv101_version_major;
94 unsigned int sv101_version_minor;
95 unsigned int sv101_type;
96 const char *sv101_comment;
99 static NET_API_STATUS server_info_101_from_samba( const unsigned char *buf, void *buffer, ULONG *size )
101 SERVER_INFO_101 *ret = (SERVER_INFO_101 *)buffer;
102 const struct server_info_101 *info = (const struct server_info_101 *)buf;
103 DWORD len = 0;
104 WCHAR *ptr;
106 if (info->sv101_name) len += netapi_umbstowcs( info->sv101_name, NULL, 0 );
107 if (info->sv101_comment) len += netapi_umbstowcs( info->sv101_comment, NULL, 0 );
108 if (*size < sizeof(*ret) + (len * sizeof(WCHAR) ))
110 *size = sizeof(*ret) + (len * sizeof(WCHAR) );
111 return ERROR_INSUFFICIENT_BUFFER;
114 ptr = (WCHAR *)(ret + 1);
115 ret->sv101_platform_id = info->sv101_platform_id;
116 if (!info->sv101_name) ret->sv101_name = NULL;
117 else
119 ret->sv101_name = ptr;
120 ptr += netapi_umbstowcs( info->sv101_name, ptr, len );
122 ret->sv101_version_major = info->sv101_version_major;
123 ret->sv101_version_minor = info->sv101_version_minor;
124 ret->sv101_type = info->sv101_type;
125 if (!info->sv101_comment) ret->sv101_comment = NULL;
126 else
128 ret->sv101_comment = ptr;
129 ptr += netapi_umbstowcs( info->sv101_comment, ptr, len );
131 *size = (char *)ptr - (char *)buffer;
132 return NERR_Success;
135 static NET_API_STATUS server_info_from_samba( unsigned int level, const unsigned char *buf, void *buffer, ULONG *size )
137 switch (level)
139 case 101: return server_info_101_from_samba( buf, buffer, size );
140 default:
141 FIXME( "level %u not supported\n", level );
142 return ERROR_NOT_SUPPORTED;
146 static NTSTATUS server_getinfo( void *args )
148 const struct server_getinfo_params *params = args;
149 NET_API_STATUS status;
150 char *samba_server = NULL;
151 unsigned char *samba_buffer = NULL;
153 if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
155 if (params->server && !(samba_server = strdup_unixcp( params->server ))) return ERROR_OUTOFMEMORY;
156 status = pNetServerGetInfo( samba_server, params->level, &samba_buffer );
157 free( samba_server );
158 if (!status)
160 status = server_info_from_samba( params->level, samba_buffer, params->buffer, params->size );
161 pNetApiBufferFree( samba_buffer );
163 return status;
166 struct share_info_2
168 const char *shi2_netname;
169 unsigned int shi2_type;
170 const char *shi2_remark;
171 unsigned int shi2_permissions;
172 unsigned int shi2_max_uses;
173 unsigned int shi2_current_uses;
174 const char *shi2_path;
175 const char *shi2_passwd;
178 static NET_API_STATUS share_info_2_to_samba( const BYTE *buf, unsigned char **bufptr )
180 struct share_info_2 *ret;
181 SHARE_INFO_2 *info = (SHARE_INFO_2 *)buf;
182 DWORD len = 0;
183 char *ptr;
185 if (info->shi2_netname)
186 len += netapi_wcstoumbs( info->shi2_netname, NULL, 0 );
187 if (info->shi2_remark)
188 len += netapi_wcstoumbs( info->shi2_remark, NULL, 0 );
189 if (info->shi2_path)
190 len += netapi_wcstoumbs( info->shi2_path, NULL, 0 );
191 if (info->shi2_passwd)
192 len += netapi_wcstoumbs( info->shi2_passwd, NULL, 0 );
193 if (!(ret = malloc( sizeof(*ret) + len )))
194 return ERROR_OUTOFMEMORY;
196 ptr = (char *)(ret + 1);
197 if (!info->shi2_netname) ret->shi2_netname = NULL;
198 else
200 ret->shi2_netname = ptr;
201 ptr += netapi_wcstoumbs( info->shi2_netname, ptr, len - (ptr - (char *)(ret + 1)) );
203 ret->shi2_type = info->shi2_type;
204 if (!info->shi2_remark) ret->shi2_remark = NULL;
205 else
207 ret->shi2_remark = ptr;
208 ptr += netapi_wcstoumbs( info->shi2_remark, ptr, len - (ptr - (char *)(ret + 1)) );
210 ret->shi2_permissions = info->shi2_permissions;
211 ret->shi2_max_uses = info->shi2_max_uses;
212 ret->shi2_current_uses = info->shi2_current_uses;
213 if (!info->shi2_path) ret->shi2_path = NULL;
214 else
216 ret->shi2_path = ptr;
217 ptr += netapi_wcstoumbs( info->shi2_path, ptr, len - (ptr - (char *)(ret + 1)) );
219 if (!info->shi2_passwd) ret->shi2_passwd = NULL;
220 else
222 ret->shi2_passwd = ptr;
223 netapi_wcstoumbs( info->shi2_passwd, ptr, len - (ptr - (char *)(ret + 1)) );
225 *bufptr = (unsigned char *)ret;
226 return NERR_Success;
229 struct sid
231 unsigned char sid_rev_num;
232 unsigned char num_auths;
233 unsigned char id_auth[6];
234 unsigned int sub_auths[15];
237 enum ace_type
239 ACE_TYPE_ACCESS_ALLOWED,
240 ACE_TYPE_ACCESS_DENIED,
241 ACE_TYPE_SYSTEM_AUDIT,
242 ACE_TYPE_SYSTEM_ALARM,
243 ACE_TYPE_ALLOWED_COMPOUND,
244 ACE_TYPE_ACCESS_ALLOWED_OBJECT,
245 ACE_TYPE_ACCESS_DENIED_OBJECT,
246 ACE_TYPE_SYSTEM_AUDIT_OBJECT,
247 ACE_TYPE_SYSTEM_ALARM_OBJECT
250 #define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
251 #define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
252 #define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
253 #define SEC_ACE_FLAG_INHERIT_ONLY 0x08
254 #define SEC_ACE_FLAG_INHERITED_ACE 0x10
255 #define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
256 #define SEC_ACE_FLAG_FAILED_ACCESS 0x80
258 struct guid
260 unsigned int time_low;
261 unsigned short time_mid;
262 unsigned short time_hi_and_version;
263 unsigned char clock_seq[2];
264 unsigned char node[6];
267 union ace_object_type
269 struct guid type;
272 union ace_object_inherited_type
274 struct guid inherited_type;
277 struct ace_object
279 unsigned int flags;
280 union ace_object_type type;
281 union ace_object_inherited_type inherited_type;
284 union ace_object_ctr
286 struct ace_object object;
289 struct ace
291 enum ace_type type;
292 unsigned char flags;
293 unsigned short size;
294 unsigned int access_mask;
295 union ace_object_ctr object;
296 struct sid trustee;
299 enum acl_revision
301 ACL_REVISION_NT4 = 2,
302 ACL_REVISION_ADS = 4
305 struct acl
307 enum acl_revision revision;
308 unsigned short size;
309 unsigned int num_aces;
310 struct ace *aces;
313 enum security_descriptor_revision
315 SECURITY_DESCRIPTOR_REVISION_1 = 1
318 #define SEC_DESC_OWNER_DEFAULTED 0x0001
319 #define SEC_DESC_GROUP_DEFAULTED 0x0002
320 #define SEC_DESC_DACL_PRESENT 0x0004
321 #define SEC_DESC_DACL_DEFAULTED 0x0008
322 #define SEC_DESC_SACL_PRESENT 0x0010
323 #define SEC_DESC_SACL_DEFAULTED 0x0020
324 #define SEC_DESC_DACL_TRUSTED 0x0040
325 #define SEC_DESC_SERVER_SECURITY 0x0080
326 #define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
327 #define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
328 #define SEC_DESC_DACL_AUTO_INHERITED 0x0400
329 #define SEC_DESC_SACL_AUTO_INHERITED 0x0800
330 #define SEC_DESC_DACL_PROTECTED 0x1000
331 #define SEC_DESC_SACL_PROTECTED 0x2000
332 #define SEC_DESC_RM_CONTROL_VALID 0x4000
333 #define SEC_DESC_SELF_RELATIVE 0x8000
335 struct security_descriptor
337 enum security_descriptor_revision revision;
338 unsigned short type;
339 struct sid *owner_sid;
340 struct sid *group_sid;
341 struct acl *sacl;
342 struct acl *dacl;
345 struct share_info_502
347 const char *shi502_netname;
348 unsigned int shi502_type;
349 const char *shi502_remark;
350 unsigned int shi502_permissions;
351 unsigned int shi502_max_uses;
352 unsigned int shi502_current_uses;
353 const char *shi502_path;
354 const char *shi502_passwd;
355 unsigned int shi502_reserved;
356 struct security_descriptor *shi502_security_descriptor;
359 static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control )
361 unsigned short ret = 0;
363 if (control & SE_OWNER_DEFAULTED) ret |= SEC_DESC_OWNER_DEFAULTED;
364 if (control & SE_GROUP_DEFAULTED) ret |= SEC_DESC_GROUP_DEFAULTED;
365 if (control & SE_DACL_PRESENT) ret |= SEC_DESC_DACL_PRESENT;
366 if (control & SE_DACL_DEFAULTED) ret |= SEC_DESC_DACL_DEFAULTED;
367 if (control & SE_SACL_PRESENT) ret |= SEC_DESC_SACL_PRESENT;
368 if (control & SE_SACL_DEFAULTED) ret |= SEC_DESC_SACL_DEFAULTED;
369 if (control & SE_DACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_DACL_AUTO_INHERIT_REQ;
370 if (control & SE_SACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_SACL_AUTO_INHERIT_REQ;
371 if (control & SE_DACL_AUTO_INHERITED) ret |= SEC_DESC_DACL_AUTO_INHERITED;
372 if (control & SE_SACL_AUTO_INHERITED) ret |= SEC_DESC_SACL_AUTO_INHERITED;
373 if (control & SE_DACL_PROTECTED) ret |= SEC_DESC_DACL_PROTECTED;
374 if (control & SE_SACL_PROTECTED) ret |= SEC_DESC_SACL_PROTECTED;
375 if (control & SE_RM_CONTROL_VALID) ret |= SEC_DESC_RM_CONTROL_VALID;
376 return ret;
379 static NET_API_STATUS sid_to_samba( const SID *src, struct sid *dst )
381 unsigned int i;
383 if (src->Revision != 1)
385 ERR( "unknown revision %u\n", src->Revision );
386 return ERROR_UNKNOWN_REVISION;
388 if (src->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
390 WARN( "invalid subauthority count %u\n", src->SubAuthorityCount );
391 return ERROR_INVALID_PARAMETER;
393 dst->sid_rev_num = SECURITY_DESCRIPTOR_REVISION_1;
394 dst->num_auths = src->SubAuthorityCount;
395 for (i = 0; i < 6; i++) dst->id_auth[i] = src->IdentifierAuthority.Value[i];
396 for (i = 0; i < dst->num_auths; i++) dst->sub_auths[i] = src->SubAuthority[i];
397 return NERR_Success;
400 static enum ace_type ace_type_to_samba( BYTE type )
402 switch (type)
404 case ACCESS_ALLOWED_ACE_TYPE: return ACE_TYPE_ACCESS_ALLOWED;
405 case ACCESS_DENIED_ACE_TYPE: return ACE_TYPE_ACCESS_DENIED;
406 case SYSTEM_AUDIT_ACE_TYPE: return ACE_TYPE_SYSTEM_AUDIT;
407 case SYSTEM_ALARM_ACE_TYPE: return ACE_TYPE_SYSTEM_ALARM;
408 default:
409 ERR( "unhandled type %u\n", type );
410 return 0;
414 static unsigned char ace_flags_to_samba( BYTE flags )
416 static const BYTE known_flags =
417 OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | NO_PROPAGATE_INHERIT_ACE |
418 INHERIT_ONLY_ACE | INHERITED_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
419 unsigned char ret = 0;
421 if (flags & ~known_flags)
423 ERR( "unknown flags %x\n", flags & ~known_flags );
424 return 0;
426 if (flags & OBJECT_INHERIT_ACE) ret |= SEC_ACE_FLAG_OBJECT_INHERIT;
427 if (flags & CONTAINER_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
428 if (flags & NO_PROPAGATE_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
429 if (flags & INHERIT_ONLY_ACE) ret |= SEC_ACE_FLAG_INHERIT_ONLY;
430 if (flags & INHERITED_ACE) ret |= SEC_ACE_FLAG_INHERITED_ACE;
431 if (flags & SUCCESSFUL_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_SUCCESSFUL_ACCESS;
432 if (flags & FAILED_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_FAILED_ACCESS;
433 return ret;
436 #define GENERIC_ALL_ACCESS (1u << 28)
437 #define GENERIC_EXECUTE_ACCESS (1u << 29)
438 #define GENERIC_WRITE_ACCESS (1u << 30)
439 #define GENERIC_READ_ACCESS (1u << 31)
441 static unsigned int access_mask_to_samba( unsigned int mask )
443 static const unsigned int known_rights =
444 GENERIC_ALL | GENERIC_EXECUTE | GENERIC_WRITE | GENERIC_READ;
445 unsigned int ret = 0;
447 if (mask & ~known_rights)
449 ERR( "unknown rights %x\n", mask & ~known_rights );
450 return 0;
452 if (mask & GENERIC_ALL) ret |= GENERIC_ALL_ACCESS;
453 if (mask & GENERIC_EXECUTE) ret |= GENERIC_EXECUTE_ACCESS;
454 if (mask & GENERIC_WRITE) ret |= GENERIC_WRITE_ACCESS;
455 if (mask & GENERIC_READ) ret |= GENERIC_READ_ACCESS;
456 return ret;
459 static NET_API_STATUS ace_to_samba( const ACE_HEADER *src, struct ace *dst )
461 dst->type = ace_type_to_samba( src->AceType );
462 dst->flags = ace_flags_to_samba( src->AceFlags );
463 dst->size = sizeof(*dst);
464 switch (src->AceType)
466 case ACCESS_ALLOWED_ACE_TYPE:
468 ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *)src;
469 dst->access_mask = access_mask_to_samba( ace->Mask );
470 memset( &dst->object, 0, sizeof(dst->object) );
471 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
472 break;
474 case ACCESS_DENIED_ACE_TYPE:
476 ACCESS_DENIED_ACE *ace = (ACCESS_DENIED_ACE *)src;
477 dst->access_mask = access_mask_to_samba( ace->Mask );
478 memset( &dst->object, 0, sizeof(dst->object) );
479 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
480 break;
482 case SYSTEM_AUDIT_ACE_TYPE:
484 SYSTEM_AUDIT_ACE *ace = (SYSTEM_AUDIT_ACE *)src;
485 dst->access_mask = access_mask_to_samba( ace->Mask );
486 memset( &dst->object, 0, sizeof(dst->object) );
487 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
488 break;
490 case SYSTEM_ALARM_ACE_TYPE:
492 SYSTEM_ALARM_ACE *ace = (SYSTEM_ALARM_ACE *)src;
493 dst->access_mask = access_mask_to_samba( ace->Mask );
494 memset( &dst->object, 0, sizeof(dst->object) );
495 sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
496 break;
498 default:
499 ERR( "unhandled type %u\n", src->AceType );
500 return ERROR_INVALID_PARAMETER;
502 return NERR_Success;
505 static NET_API_STATUS acl_to_samba( const ACL *src, struct acl *dst )
507 NET_API_STATUS status;
508 ACE_HEADER *src_ace;
509 unsigned int i;
511 switch (src->AclRevision)
513 case ACL_REVISION4:
514 dst->revision = ACL_REVISION_ADS;
515 break;
516 default:
517 ERR( "unkhandled revision %u\n", src->AclRevision );
518 return ERROR_UNKNOWN_REVISION;
520 dst->size = sizeof(*dst);
521 src_ace = (ACE_HEADER *)(src + 1);
522 dst->aces = (struct ace *)(dst + 1);
523 for (i = 0; i < src->AceCount; i++)
525 if ((status = ace_to_samba( src_ace, &dst->aces[i] ))) return status;
526 src_ace = (ACE_HEADER *)((char *)src_ace + src_ace->AceSize);
527 dst->size += dst->aces[i].size;
529 return NERR_Success;
532 #define SELF_RELATIVE_FIELD(sd,field)\
533 ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
535 static NET_API_STATUS sd_to_samba( const SECURITY_DESCRIPTOR *src, struct security_descriptor *dst )
537 NET_API_STATUS status;
538 const SID *owner, *group;
539 const ACL *dacl, *sacl;
540 unsigned int offset = sizeof(*dst);
542 if (src->Revision != SECURITY_DESCRIPTOR_REVISION1)
543 return ERROR_UNKNOWN_REVISION;
545 dst->revision = SECURITY_DESCRIPTOR_REVISION_1;
546 dst->type = sd_control_to_samba( src->Control );
548 if (src->Control & SE_SELF_RELATIVE)
550 if (!src->Owner) dst->owner_sid = NULL;
551 else
553 dst->owner_sid = (struct sid *)((char *)dst + offset);
554 owner = (const SID *)SELF_RELATIVE_FIELD( src, Owner );
555 if ((status = sid_to_samba( owner, dst->owner_sid ))) return status;
556 offset += sizeof(struct sid);
558 if (!src->Group) dst->group_sid = NULL;
559 else
561 dst->group_sid = (struct sid *)((char *)dst + offset);
562 group = (const SID *)SELF_RELATIVE_FIELD( src, Group );
563 if ((status = sid_to_samba( group, dst->group_sid ))) return status;
564 offset += sizeof(struct sid);
566 if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
567 else
569 dst->sacl = (struct acl *)((char *)dst + offset);
570 sacl = (const ACL *)SELF_RELATIVE_FIELD( src, Sacl );
571 if ((status = acl_to_samba( sacl, dst->sacl ))) return status;
572 offset += dst->sacl->size;
574 if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
575 else
577 dst->dacl = (struct acl *)((char *)dst + offset);
578 dacl = (const ACL *)SELF_RELATIVE_FIELD( src, Dacl );
579 if ((status = acl_to_samba( dacl, dst->dacl ))) return status;
582 else
584 if (!src->Owner) dst->owner_sid = NULL;
585 else
587 dst->owner_sid = (struct sid *)((char *)dst + offset);
588 if ((status = sid_to_samba( src->Owner, dst->owner_sid ))) return status;
589 offset += sizeof(struct sid);
591 if (!src->Group) dst->group_sid = NULL;
592 else
594 dst->group_sid = (struct sid *)((char *)dst + offset);
595 if ((status = sid_to_samba( src->Group, dst->group_sid ))) return status;
596 offset += sizeof(struct sid);
598 if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
599 else
601 dst->sacl = (struct acl *)((char *)dst + offset);
602 if ((status = acl_to_samba( src->Sacl, dst->sacl ))) return status;
603 offset += dst->sacl->size;
605 if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
606 else
608 dst->dacl = (struct acl *)((char *)dst + offset);
609 if ((status = acl_to_samba( src->Dacl, dst->dacl ))) return status;
612 return NERR_Success;
615 static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR *sd )
617 unsigned int ret = sizeof(struct security_descriptor);
619 if (sd->Owner) ret += sizeof(struct sid);
620 if (sd->Group) ret += sizeof(struct sid);
621 if (sd->Control & SE_SACL_PRESENT)
622 ret += sizeof(struct acl) + sd->Sacl->AceCount * sizeof(struct ace);
623 if (sd->Control & SE_DACL_PRESENT)
624 ret += sizeof(struct acl) + sd->Dacl->AceCount * sizeof(struct ace);
625 return ret;
628 static NET_API_STATUS share_info_502_to_samba( const BYTE *buf, unsigned char **bufptr )
630 NET_API_STATUS status;
631 struct share_info_502 *ret;
632 SHARE_INFO_502 *info = (SHARE_INFO_502 *)buf;
633 DWORD len = 0, size = 0;
634 char *ptr;
636 *bufptr = NULL;
637 if (info->shi502_netname)
638 len += netapi_wcstoumbs( info->shi502_netname, NULL, 0 );
639 if (info->shi502_remark)
640 len += netapi_wcstoumbs( info->shi502_remark, NULL, 0 );
641 if (info->shi502_path)
642 len += netapi_wcstoumbs( info->shi502_path, NULL, 0 );
643 if (info->shi502_passwd)
644 len += netapi_wcstoumbs( info->shi502_passwd, NULL, 0 );
645 if (info->shi502_security_descriptor)
646 size = sd_to_samba_size( info->shi502_security_descriptor );
647 if (!(ret = malloc( sizeof(*ret) + (len * sizeof(WCHAR)) + size )))
648 return ERROR_OUTOFMEMORY;
650 ptr = (char *)(ret + 1);
651 if (!info->shi502_netname) ret->shi502_netname = NULL;
652 else
654 ret->shi502_netname = ptr;
655 ptr += netapi_wcstoumbs( info->shi502_netname, ptr, len - (ptr - (char *)(ret + 1)) );
657 ret->shi502_type = info->shi502_type;
658 if (!info->shi502_remark) ret->shi502_remark = NULL;
659 else
661 ret->shi502_remark = ptr;
662 ptr += netapi_wcstoumbs( info->shi502_remark, ptr, len - (ptr - (char *)(ret + 1)) );
664 ret->shi502_permissions = info->shi502_permissions;
665 ret->shi502_max_uses = info->shi502_max_uses;
666 ret->shi502_current_uses = info->shi502_current_uses;
667 if (!info->shi502_path) ret->shi502_path = NULL;
668 else
670 ret->shi502_path = ptr;
671 ptr += netapi_wcstoumbs( info->shi502_path, ptr, len - (ptr - (char *)(ret + 1)) );
673 if (!info->shi502_passwd) ret->shi502_passwd = NULL;
674 else
676 ret->shi502_passwd = ptr;
677 ptr += netapi_wcstoumbs( info->shi502_passwd, ptr, len - (ptr - (char *)(ret + 1)) );
679 ret->shi502_reserved = info->shi502_reserved;
680 if (!info->shi502_security_descriptor) ret->shi502_security_descriptor = NULL;
681 else
683 status = sd_to_samba( info->shi502_security_descriptor, (struct security_descriptor *)ptr );
684 if (status)
686 free( ret );
687 return status;
689 ret->shi502_security_descriptor = (struct security_descriptor *)ptr;
691 *bufptr = (unsigned char *)ret;
692 return NERR_Success;
695 static NET_API_STATUS share_info_to_samba( unsigned int level, const BYTE *buf, unsigned char **bufptr )
697 switch (level)
699 case 2: return share_info_2_to_samba( buf, bufptr );
700 case 502: return share_info_502_to_samba( buf, bufptr );
701 default:
702 FIXME( "level %u not supported\n", level );
703 return ERROR_NOT_SUPPORTED;
707 static NTSTATUS share_add( void *args )
709 const struct share_add_params *params = args;
710 char *samba_server = NULL;
711 unsigned char *samba_info;
712 NET_API_STATUS status;
714 if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
716 if (params->server && !(samba_server = strdup_unixcp( params->server ))) return ERROR_OUTOFMEMORY;
717 status = share_info_to_samba( params->level, params->info, &samba_info );
718 if (!status)
720 unsigned int samba_err;
722 status = pNetShareAdd( samba_server, params->level, samba_info, &samba_err );
723 free( samba_info );
724 if (params->err) *params->err = samba_err;
726 free( samba_server );
727 return status;
730 static NTSTATUS share_del( void *args )
732 const struct share_del_params *params = args;
733 char *samba_server = NULL, *samba_share;
734 NET_API_STATUS status;
736 if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
738 if (params->server && !(samba_server = strdup_unixcp( params->server ))) return ERROR_OUTOFMEMORY;
739 if (!(samba_share = strdup_unixcp( params->share )))
741 free( samba_server );
742 return ERROR_OUTOFMEMORY;
744 status = pNetShareDel( samba_server, samba_share, params->reserved );
745 free( samba_server );
746 free( samba_share );
747 return status;
750 struct wksta_info_100
752 unsigned int wki100_platform_id;
753 const char *wki100_computername;
754 const char *wki100_langroup;
755 unsigned int wki100_ver_major;
756 unsigned int wki100_ver_minor;
759 static NET_API_STATUS wksta_info_100_from_samba( const unsigned char *buf, void *buffer, ULONG *size )
761 WKSTA_INFO_100 *ret = (WKSTA_INFO_100 *)buffer;
762 const struct wksta_info_100 *info = (const struct wksta_info_100 *)buf;
763 DWORD len = 0;
764 WCHAR *ptr;
766 if (info->wki100_computername)
767 len += netapi_umbstowcs( info->wki100_computername, NULL, 0 );
768 if (info->wki100_langroup)
769 len += netapi_umbstowcs( info->wki100_langroup, NULL, 0 );
770 if (*size < sizeof(*ret) + (len * sizeof(WCHAR) ))
772 *size = sizeof(*ret) + (len * sizeof(WCHAR) );
773 return ERROR_INSUFFICIENT_BUFFER;
776 ptr = (WCHAR *)(ret + 1);
777 ret->wki100_platform_id = info->wki100_platform_id;
778 if (!info->wki100_computername) ret->wki100_computername = NULL;
779 else
781 ret->wki100_computername = ptr;
782 ptr += netapi_umbstowcs( info->wki100_computername, ptr, len );
784 if (!info->wki100_langroup) ret->wki100_langroup = NULL;
785 else
787 ret->wki100_langroup = ptr;
788 ptr += netapi_umbstowcs( info->wki100_langroup, ptr, len );
790 ret->wki100_ver_major = info->wki100_ver_major;
791 ret->wki100_ver_minor = info->wki100_ver_minor;
792 *size = (char *)ptr - (char *)buffer;
793 return NERR_Success;
796 static NET_API_STATUS wksta_info_from_samba( unsigned int level, const unsigned char *buf, void *buffer, ULONG *size )
798 switch (level)
800 case 100: return wksta_info_100_from_samba( buf, buffer, size );
801 default:
802 FIXME( "level %u not supported\n", level );
803 return ERROR_NOT_SUPPORTED;
807 static NTSTATUS wksta_getinfo( void *args )
809 const struct wksta_getinfo_params *params = args;
810 unsigned char *samba_buffer = NULL;
811 char *samba_server = NULL;
812 NET_API_STATUS status;
814 if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
816 if (params->server && !(samba_server = strdup_unixcp( params->server ))) return ERROR_OUTOFMEMORY;
817 status = pNetWkstaGetInfo( samba_server, params->level, &samba_buffer );
818 free( samba_server );
819 if (!status)
821 status = wksta_info_from_samba( params->level, samba_buffer, params->buffer, params->size );
822 pNetApiBufferFree( samba_buffer );
824 return status;
827 static NTSTATUS netapi_init( void *args )
829 unsigned int status;
830 void *ctx;
832 if (!(libnetapi_handle = dlopen( SONAME_LIBNETAPI, RTLD_NOW )))
834 ERR_(winediag)( "failed to load %s\n", SONAME_LIBNETAPI );
835 return STATUS_DLL_NOT_FOUND;
838 #define LOAD_FUNCPTR(f) \
839 if (!(p##f = dlsym( libnetapi_handle, #f ))) \
841 ERR_(winediag)( "%s not found in %s\n", #f, SONAME_LIBNETAPI ); \
842 return STATUS_DLL_NOT_FOUND; \
845 LOAD_FUNCPTR(libnetapi_init)
846 LOAD_FUNCPTR(libnetapi_free)
847 LOAD_FUNCPTR(libnetapi_set_debuglevel)
848 LOAD_FUNCPTR(libnetapi_set_username)
849 LOAD_FUNCPTR(libnetapi_set_password)
851 LOAD_FUNCPTR(NetApiBufferAllocate)
852 LOAD_FUNCPTR(NetApiBufferFree)
853 LOAD_FUNCPTR(NetServerGetInfo)
854 LOAD_FUNCPTR(NetShareAdd)
855 LOAD_FUNCPTR(NetShareDel)
856 LOAD_FUNCPTR(NetWkstaGetInfo)
857 #undef LOAD_FUNCPTR
859 if ((status = plibnetapi_init( &ctx )))
861 ERR( "Failed to initialize context, status %u\n", status );
862 return STATUS_DLL_NOT_FOUND;
864 if (TRACE_ON(netapi32) && (status = plibnetapi_set_debuglevel( ctx, "10" )))
866 ERR( "Failed to set debug level, status %u\n", status );
867 plibnetapi_free( ctx );
868 return STATUS_DLL_NOT_FOUND;
870 /* perform an anonymous login by default (avoids a password prompt) */
871 if ((status = plibnetapi_set_username( ctx, "Guest" )))
873 ERR( "Failed to set username, status %u\n", status );
874 plibnetapi_free( ctx );
875 return STATUS_DLL_NOT_FOUND;
877 if ((status = plibnetapi_set_password( ctx, "" )))
879 ERR( "Failed to set password, status %u\n", status );
880 plibnetapi_free( ctx );
881 return STATUS_DLL_NOT_FOUND;
884 libnetapi_ctx = ctx;
885 return STATUS_SUCCESS;
888 static NTSTATUS change_password( void *args )
890 const struct change_password_params *params = args;
891 NET_API_STATUS ret = NERR_Success;
892 static char option_silent[] = "-s";
893 static char option_user[] = "-U";
894 static char option_remote[] = "-r";
895 static char smbpasswd[] = "smbpasswd";
896 int pipe_out[2];
897 pid_t pid, wret;
898 int status;
899 char *server = NULL, *user, *argv[7], *old = NULL, *new = NULL;
901 if (params->domain && !(server = strdup_unixcp( params->domain ))) return ERROR_OUTOFMEMORY;
902 if (!(user = strdup_unixcp( params->user )))
904 ret = ERROR_OUTOFMEMORY;
905 goto end;
907 if (!(old = strdup_unixcp( params->old )))
909 ret = ERROR_OUTOFMEMORY;
910 goto end;
912 if (!(new = strdup_unixcp( params->new )))
914 ret = ERROR_OUTOFMEMORY;
915 goto end;
917 argv[0] = smbpasswd;
918 argv[1] = option_silent;
919 argv[2] = option_user;
920 argv[3] = user;
921 if (server)
923 argv[4] = option_remote;
924 argv[5] = server;
925 argv[6] = NULL;
927 else argv[4] = NULL;
929 if (pipe( pipe_out ) == -1)
931 ret = NERR_InternalError;
932 goto end;
934 fcntl( pipe_out[0], F_SETFD, FD_CLOEXEC );
935 fcntl( pipe_out[1], F_SETFD, FD_CLOEXEC );
937 switch ((pid = fork()))
939 case -1:
940 close( pipe_out[0] );
941 close( pipe_out[1] );
942 ret = NERR_InternalError;
943 goto end;
944 case 0:
945 dup2( pipe_out[0], 0 );
946 close( pipe_out[0] );
947 close( pipe_out[1] );
948 execvp( "smbpasswd", argv );
949 ERR( "can't execute smbpasswd, is it installed?\n" );
950 _exit(1);
951 default:
952 close( pipe_out[0] );
953 break;
955 write( pipe_out[1], old, strlen( old ) );
956 write( pipe_out[1], "\n", 1 );
957 write( pipe_out[1], new, strlen( new ) );
958 write( pipe_out[1], "\n", 1 );
959 write( pipe_out[1], new, strlen( new ) );
960 write( pipe_out[1], "\n", 1 );
961 close( pipe_out[1] );
963 do {
964 wret = waitpid(pid, &status, 0);
965 } while (wret < 0 && errno == EINTR);
967 if (ret == NERR_Success && (wret < 0 || !WIFEXITED(status) || WEXITSTATUS(status)))
968 ret = NERR_InternalError;
970 end:
971 free( server );
972 free( user );
973 free( old );
974 free( new );
975 return ret;
978 const unixlib_entry_t __wine_unix_call_funcs[] =
980 netapi_init,
981 server_getinfo,
982 share_add,
983 share_del,
984 wksta_getinfo,
985 change_password,
988 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
990 #ifdef _WIN64
992 typedef ULONG PTR32;
994 static NTSTATUS wow64_server_getinfo( void *args )
996 struct
998 PTR32 server;
999 DWORD level;
1000 PTR32 buffer;
1001 PTR32 size;
1002 } const *params32 = args;
1004 struct server_getinfo_params params =
1006 ULongToPtr(params32->server),
1007 params32->level,
1008 ULongToPtr(params32->buffer),
1009 ULongToPtr(params32->size)
1012 return server_getinfo( &params );
1015 static NTSTATUS wow64_share_add( void *args )
1017 struct
1019 PTR32 server;
1020 DWORD level;
1021 PTR32 info;
1022 PTR32 err;
1023 } const *params32 = args;
1025 struct share_add_params params =
1027 ULongToPtr(params32->server),
1028 params32->level,
1029 ULongToPtr(params32->info),
1030 ULongToPtr(params32->err)
1033 return share_add( &params );
1036 static NTSTATUS wow64_share_del( void *args )
1038 struct
1040 PTR32 server;
1041 PTR32 share;
1042 DWORD reserved;
1043 } const *params32 = args;
1045 struct share_del_params params =
1047 ULongToPtr(params32->server),
1048 ULongToPtr(params32->share),
1049 params32->reserved
1052 return share_del( &params );
1055 static NTSTATUS wow64_wksta_getinfo( void *args )
1057 struct
1059 PTR32 server;
1060 DWORD level;
1061 PTR32 buffer;
1062 PTR32 size;
1063 } const *params32 = args;
1065 struct wksta_getinfo_params params =
1067 ULongToPtr(params32->server),
1068 params32->level,
1069 ULongToPtr(params32->buffer),
1070 ULongToPtr(params32->size)
1073 return wksta_getinfo( &params );
1076 static NTSTATUS wow64_change_password( void *args )
1078 struct
1080 PTR32 domain;
1081 PTR32 user;
1082 PTR32 old;
1083 PTR32 new;
1084 } const *params32 = args;
1086 struct change_password_params params =
1088 ULongToPtr(params32->domain),
1089 ULongToPtr(params32->user),
1090 ULongToPtr(params32->old),
1091 ULongToPtr(params32->new)
1094 return change_password( &params );
1097 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
1099 netapi_init,
1100 wow64_server_getinfo,
1101 wow64_share_add,
1102 wow64_share_del,
1103 wow64_wksta_getinfo,
1104 wow64_change_password,
1107 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
1109 #endif /* _WIN64 */
1111 #endif /* SONAME_LIBNETAPI */