[PATCH 2/4] netapi32: Move libnetapi support to a new Unix library.
Zebediah Figura
z.figura12 at gmail.com
Mon Apr 12 22:35:41 CDT 2021
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/netapi32/Makefile.in | 3 +-
dlls/netapi32/netapi32.c | 875 +---------------------------------
dlls/netapi32/unixlib.c | 967 ++++++++++++++++++++++++++++++++++++++
dlls/netapi32/unixlib.h | 27 ++
4 files changed, 1011 insertions(+), 861 deletions(-)
create mode 100644 dlls/netapi32/unixlib.c
create mode 100644 dlls/netapi32/unixlib.h
diff --git a/dlls/netapi32/Makefile.in b/dlls/netapi32/Makefile.in
index 13065578efe..70c5f117381 100644
--- a/dlls/netapi32/Makefile.in
+++ b/dlls/netapi32/Makefile.in
@@ -8,7 +8,8 @@ C_SRCS = \
nbnamecache.c \
nbt.c \
netapi32.c \
- netbios.c
+ netbios.c \
+ unixlib.c
IDL_SRCS = \
atsvc.idl
diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c
index ad115e26257..62c4ba138ac 100644
--- a/dlls/netapi32/netapi32.c
+++ b/dlls/netapi32/netapi32.c
@@ -60,10 +60,14 @@
#include "wine/unicode.h"
#include "initguid.h"
+#include "unixlib.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+static HINSTANCE netapi32_instance;
+
static CPTABLEINFO unix_cptable;
static ULONG unix_cp;
@@ -108,26 +112,6 @@ static DWORD netapi_wcstoumbs( const WCHAR *src, char *dst, DWORD dstlen )
}
}
-static DWORD netapi_umbstowcs( const char *src, WCHAR *dst, DWORD dstlen )
-{
- DWORD srclen = strlen( src ) + 1;
- DWORD len;
-
- get_unix_codepage();
-
- if (unix_cp == CP_UTF8)
- {
- RtlUTF8ToUnicodeN( dst, dstlen, &len, src, srclen );
- return len;
- }
- else
- {
- len = srclen * sizeof(WCHAR);
- if (dst) RtlCustomCPToUnicodeN( &unix_cptable, dst, dstlen, &len, src, srclen );
- return len;
- }
-}
-
static char *strdup_unixcp( const WCHAR *str )
{
char *ret;
@@ -138,851 +122,21 @@ static char *strdup_unixcp( const WCHAR *str )
return ret;
}
-#ifdef SONAME_LIBNETAPI
+static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-static void *libnetapi_handle;
-static void *libnetapi_ctx;
+static const struct samba_funcs *samba_funcs;
-static DWORD (*plibnetapi_init)(void **);
-static DWORD (*plibnetapi_free)(void *);
-static DWORD (*plibnetapi_set_debuglevel)(void *, const char *);
-static DWORD (*plibnetapi_set_username)(void *, const char *);
-static DWORD (*plibnetapi_set_password)(void *, const char *);
-
-static NET_API_STATUS (*pNetApiBufferAllocate)(unsigned int, void **);
-static NET_API_STATUS (*pNetApiBufferFree)(void *);
-static NET_API_STATUS (*pNetServerGetInfo)(const char *, unsigned int, unsigned char **);
-static NET_API_STATUS (*pNetShareAdd)(const char *, unsigned int, unsigned char *, unsigned int *);
-static NET_API_STATUS (*pNetShareDel)(const char *, const char *, unsigned int);
-static NET_API_STATUS (*pNetWkstaGetInfo)(const char *, unsigned int, unsigned char **);
-
-static void destroy_context(void)
+static BOOL WINAPI load_samba( INIT_ONCE *once, void *param, void **context )
{
- TRACE( "destroying %p\n", libnetapi_ctx );
- plibnetapi_free( libnetapi_ctx );
- libnetapi_ctx = NULL;
-}
-
-static BOOL init_context(void)
-{
- DWORD status;
-
- if ((status = plibnetapi_init( &libnetapi_ctx )))
- {
- ERR( "Failed to initialize context %u\n", status );
- return FALSE;
- }
- if (TRACE_ON( netapi32 ) && (status = plibnetapi_set_debuglevel( libnetapi_ctx, "10" )))
- {
- ERR( "Failed to set debug level %u\n", status );
- destroy_context();
- return FALSE;
- }
- /* perform an anonymous login by default (avoids a password prompt) */
- if ((status = plibnetapi_set_username( libnetapi_ctx, "Guest" )))
- {
- ERR( "Failed to set username %u\n", status );
- destroy_context();
- return FALSE;
- }
- if ((status = plibnetapi_set_password( libnetapi_ctx, "" )))
- {
- ERR( "Failed to set password %u\n", status );
- destroy_context();
- return FALSE;
- }
- TRACE( "using %p\n", libnetapi_ctx );
+ __wine_init_unix_lib( netapi32_instance, DLL_PROCESS_ATTACH, NULL, &samba_funcs );
return TRUE;
}
-static BOOL libnetapi_init(void)
+static BOOL samba_init(void)
{
- if (libnetapi_handle) return TRUE;
- if (!(libnetapi_handle = dlopen( SONAME_LIBNETAPI, RTLD_NOW )))
- {
- WARN( "Failed to load libnetapi: %s\n", dlerror() );
- return FALSE;
- }
-
-#define LOAD_FUNCPTR(f) \
- if (!(p##f = dlsym( libnetapi_handle, #f ))) \
- { \
- ERR( "Failed to load %s: %s\n", #f, dlerror() ); \
- goto error; \
- }
-
- LOAD_FUNCPTR(libnetapi_init)
- LOAD_FUNCPTR(libnetapi_free)
- LOAD_FUNCPTR(libnetapi_set_debuglevel)
- LOAD_FUNCPTR(libnetapi_set_username)
- LOAD_FUNCPTR(libnetapi_set_password)
-
- LOAD_FUNCPTR(NetApiBufferAllocate)
- LOAD_FUNCPTR(NetApiBufferFree)
- LOAD_FUNCPTR(NetServerGetInfo)
- LOAD_FUNCPTR(NetShareAdd)
- LOAD_FUNCPTR(NetShareDel)
- LOAD_FUNCPTR(NetWkstaGetInfo)
-#undef LOAD_FUNCPTR
-
- if (init_context()) return TRUE;
-
-error:
- dlclose( libnetapi_handle );
- libnetapi_handle = NULL;
- return FALSE;
+ return InitOnceExecuteOnce( &init_once, load_samba, NULL, NULL ) && samba_funcs;
}
-struct server_info_101
-{
- unsigned int sv101_platform_id;
- const char *sv101_name;
- unsigned int sv101_version_major;
- unsigned int sv101_version_minor;
- unsigned int sv101_type;
- const char *sv101_comment;
-};
-
-static NET_API_STATUS server_info_101_from_samba( const unsigned char *buf, BYTE **bufptr )
-{
- SERVER_INFO_101 *ret;
- struct server_info_101 *info = (struct server_info_101 *)buf;
- DWORD len = 0;
- WCHAR *ptr;
-
- if (info->sv101_name) len += netapi_umbstowcs( info->sv101_name, NULL, 0 );
- if (info->sv101_comment) len += netapi_umbstowcs( info->sv101_comment, NULL, 0 );
- if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
- return ERROR_OUTOFMEMORY;
-
- ptr = (WCHAR *)(ret + 1);
- ret->sv101_platform_id = info->sv101_platform_id;
- if (!info->sv101_name) ret->sv101_name = NULL;
- else
- {
- ret->sv101_name = ptr;
- ptr += netapi_umbstowcs( info->sv101_name, ptr, len );
- }
- ret->sv101_version_major = info->sv101_version_major;
- ret->sv101_version_minor = info->sv101_version_minor;
- ret->sv101_type = info->sv101_type;
- if (!info->sv101_comment) ret->sv101_comment = NULL;
- else
- {
- ret->sv101_comment = ptr;
- netapi_umbstowcs( info->sv101_comment, ptr, len );
- }
- *bufptr = (BYTE *)ret;
- return NERR_Success;
-}
-
-static NET_API_STATUS server_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
-{
- switch (level)
- {
- case 101: return server_info_101_from_samba( buf, bufptr );
- default:
- FIXME( "level %u not supported\n", level );
- return ERROR_NOT_SUPPORTED;
- }
-}
-
-static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
-{
- NET_API_STATUS status;
- char *server = NULL;
- unsigned char *buf = NULL;
-
- if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
- status = pNetServerGetInfo( server, level, &buf );
- HeapFree( GetProcessHeap(), 0, server );
- if (!status)
- {
- status = server_info_from_samba( level, buf, bufptr );
- pNetApiBufferFree( buf );
- }
- return status;
-}
-
-struct share_info_2
-{
- const char *shi2_netname;
- unsigned int shi2_type;
- const char *shi2_remark;
- unsigned int shi2_permissions;
- unsigned int shi2_max_uses;
- unsigned int shi2_current_uses;
- const char *shi2_path;
- const char *shi2_passwd;
-};
-
-static NET_API_STATUS share_info_2_to_samba( const BYTE *buf, unsigned char **bufptr )
-{
- struct share_info_2 *ret;
- SHARE_INFO_2 *info = (SHARE_INFO_2 *)buf;
- DWORD len = 0;
- char *ptr;
-
- if (info->shi2_netname)
- len += netapi_wcstoumbs( info->shi2_netname, NULL, 0 );
- if (info->shi2_remark)
- len += netapi_wcstoumbs( info->shi2_remark, NULL, 0 );
- if (info->shi2_path)
- len += netapi_wcstoumbs( info->shi2_path, NULL, 0 );
- if (info->shi2_passwd)
- len += netapi_wcstoumbs( info->shi2_passwd, NULL, 0 );
- if (!(ret = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) + len )))
- return ERROR_OUTOFMEMORY;
-
- ptr = (char *)(ret + 1);
- if (!info->shi2_netname) ret->shi2_netname = NULL;
- else
- {
- ret->shi2_netname = ptr;
- ptr += netapi_wcstoumbs( info->shi2_netname, ptr, len );
- }
- ret->shi2_type = info->shi2_type;
- if (!info->shi2_remark) ret->shi2_remark = NULL;
- else
- {
- ret->shi2_remark = ptr;
- ptr += netapi_wcstoumbs( info->shi2_remark, ptr, len );
- }
- ret->shi2_permissions = info->shi2_permissions;
- ret->shi2_max_uses = info->shi2_max_uses;
- ret->shi2_current_uses = info->shi2_current_uses;
- if (!info->shi2_path) ret->shi2_path = NULL;
- else
- {
- ret->shi2_path = ptr;
- ptr += netapi_wcstoumbs( info->shi2_path, ptr, len );
- }
- if (!info->shi2_passwd) ret->shi2_passwd = NULL;
- else
- {
- ret->shi2_passwd = ptr;
- netapi_wcstoumbs( info->shi2_passwd, ptr, len );
- }
- *bufptr = (unsigned char *)ret;
- return NERR_Success;
-}
-
-struct sid
-{
- unsigned char sid_rev_num;
- unsigned char num_auths;
- unsigned char id_auth[6];
- unsigned int sub_auths[15];
-};
-
-enum ace_type
-{
- ACE_TYPE_ACCESS_ALLOWED,
- ACE_TYPE_ACCESS_DENIED,
- ACE_TYPE_SYSTEM_AUDIT,
- ACE_TYPE_SYSTEM_ALARM,
- ACE_TYPE_ALLOWED_COMPOUND,
- ACE_TYPE_ACCESS_ALLOWED_OBJECT,
- ACE_TYPE_ACCESS_DENIED_OBJECT,
- ACE_TYPE_SYSTEM_AUDIT_OBJECT,
- ACE_TYPE_SYSTEM_ALARM_OBJECT
-};
-
-#define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
-#define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
-#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
-#define SEC_ACE_FLAG_INHERIT_ONLY 0x08
-#define SEC_ACE_FLAG_INHERITED_ACE 0x10
-#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
-#define SEC_ACE_FLAG_FAILED_ACCESS 0x80
-
-struct guid
-{
- unsigned int time_low;
- unsigned short time_mid;
- unsigned short time_hi_and_version;
- unsigned char clock_seq[2];
- unsigned char node[6];
-};
-
-union ace_object_type
-{
- struct guid type;
-};
-
-union ace_object_inherited_type
-{
- struct guid inherited_type;
-};
-
-struct ace_object
-{
- unsigned int flags;
- union ace_object_type type;
- union ace_object_inherited_type inherited_type;
-};
-
-union ace_object_ctr
-{
- struct ace_object object;
-};
-
-struct ace
-{
- enum ace_type type;
- unsigned char flags;
- unsigned short size;
- unsigned int access_mask;
- union ace_object_ctr object;
- struct sid trustee;
-};
-
-enum acl_revision
-{
- ACL_REVISION_NT4 = 2,
- ACL_REVISION_ADS = 4
-};
-
-struct acl
-{
- enum acl_revision revision;
- unsigned short size;
- unsigned int num_aces;
- struct ace *aces;
-};
-
-enum security_descriptor_revision
-{
- SECURITY_DESCRIPTOR_REVISION_1 = 1
-};
-
-#define SEC_DESC_OWNER_DEFAULTED 0x0001
-#define SEC_DESC_GROUP_DEFAULTED 0x0002
-#define SEC_DESC_DACL_PRESENT 0x0004
-#define SEC_DESC_DACL_DEFAULTED 0x0008
-#define SEC_DESC_SACL_PRESENT 0x0010
-#define SEC_DESC_SACL_DEFAULTED 0x0020
-#define SEC_DESC_DACL_TRUSTED 0x0040
-#define SEC_DESC_SERVER_SECURITY 0x0080
-#define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
-#define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
-#define SEC_DESC_DACL_AUTO_INHERITED 0x0400
-#define SEC_DESC_SACL_AUTO_INHERITED 0x0800
-#define SEC_DESC_DACL_PROTECTED 0x1000
-#define SEC_DESC_SACL_PROTECTED 0x2000
-#define SEC_DESC_RM_CONTROL_VALID 0x4000
-#define SEC_DESC_SELF_RELATIVE 0x8000
-
-struct security_descriptor
-{
- enum security_descriptor_revision revision;
- unsigned short type;
- struct sid *owner_sid;
- struct sid *group_sid;
- struct acl *sacl;
- struct acl *dacl;
-};
-
-struct share_info_502
-{
- const char *shi502_netname;
- unsigned int shi502_type;
- const char *shi502_remark;
- unsigned int shi502_permissions;
- unsigned int shi502_max_uses;
- unsigned int shi502_current_uses;
- const char *shi502_path;
- const char *shi502_passwd;
- unsigned int shi502_reserved;
- struct security_descriptor *shi502_security_descriptor;
-};
-
-static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control )
-{
- unsigned short ret = 0;
-
- if (control & SE_OWNER_DEFAULTED) ret |= SEC_DESC_OWNER_DEFAULTED;
- if (control & SE_GROUP_DEFAULTED) ret |= SEC_DESC_GROUP_DEFAULTED;
- if (control & SE_DACL_PRESENT) ret |= SEC_DESC_DACL_PRESENT;
- if (control & SE_DACL_DEFAULTED) ret |= SEC_DESC_DACL_DEFAULTED;
- if (control & SE_SACL_PRESENT) ret |= SEC_DESC_SACL_PRESENT;
- if (control & SE_SACL_DEFAULTED) ret |= SEC_DESC_SACL_DEFAULTED;
- if (control & SE_DACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_DACL_AUTO_INHERIT_REQ;
- if (control & SE_SACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_SACL_AUTO_INHERIT_REQ;
- if (control & SE_DACL_AUTO_INHERITED) ret |= SEC_DESC_DACL_AUTO_INHERITED;
- if (control & SE_SACL_AUTO_INHERITED) ret |= SEC_DESC_SACL_AUTO_INHERITED;
- if (control & SE_DACL_PROTECTED) ret |= SEC_DESC_DACL_PROTECTED;
- if (control & SE_SACL_PROTECTED) ret |= SEC_DESC_SACL_PROTECTED;
- if (control & SE_RM_CONTROL_VALID) ret |= SEC_DESC_RM_CONTROL_VALID;
- return ret;
-}
-
-static NET_API_STATUS sid_to_samba( const SID *src, struct sid *dst )
-{
- unsigned int i;
-
- if (src->Revision != 1)
- {
- ERR( "unknown revision %u\n", src->Revision );
- return ERROR_UNKNOWN_REVISION;
- }
- if (src->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
- {
- WARN( "invalid subauthority count %u\n", src->SubAuthorityCount );
- return ERROR_INVALID_PARAMETER;
- }
- dst->sid_rev_num = SECURITY_DESCRIPTOR_REVISION_1;
- dst->num_auths = src->SubAuthorityCount;
- for (i = 0; i < 6; i++) dst->id_auth[i] = src->IdentifierAuthority.Value[i];
- for (i = 0; i < dst->num_auths; i++) dst->sub_auths[i] = src->SubAuthority[i];
- return NERR_Success;
-}
-
-static enum ace_type ace_type_to_samba( BYTE type )
-{
- switch (type)
- {
- case ACCESS_ALLOWED_ACE_TYPE: return ACE_TYPE_ACCESS_ALLOWED;
- case ACCESS_DENIED_ACE_TYPE: return ACE_TYPE_ACCESS_DENIED;
- case SYSTEM_AUDIT_ACE_TYPE: return ACE_TYPE_SYSTEM_AUDIT;
- case SYSTEM_ALARM_ACE_TYPE: return ACE_TYPE_SYSTEM_ALARM;
- default:
- ERR( "unhandled type %u\n", type );
- return 0;
- }
-}
-
-static unsigned char ace_flags_to_samba( BYTE flags )
-{
- static const BYTE known_flags =
- OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | NO_PROPAGATE_INHERIT_ACE |
- INHERIT_ONLY_ACE | INHERITED_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
- unsigned char ret = 0;
-
- if (flags & ~known_flags)
- {
- ERR( "unknown flags %x\n", flags & ~known_flags );
- return 0;
- }
- if (flags & OBJECT_INHERIT_ACE) ret |= SEC_ACE_FLAG_OBJECT_INHERIT;
- if (flags & CONTAINER_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
- if (flags & NO_PROPAGATE_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
- if (flags & INHERIT_ONLY_ACE) ret |= SEC_ACE_FLAG_INHERIT_ONLY;
- if (flags & INHERITED_ACE) ret |= SEC_ACE_FLAG_INHERITED_ACE;
- if (flags & SUCCESSFUL_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_SUCCESSFUL_ACCESS;
- if (flags & FAILED_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_FAILED_ACCESS;
- return ret;
-}
-
-#define GENERIC_ALL_ACCESS (1u << 28)
-#define GENERIC_EXECUTE_ACCESS (1u << 29)
-#define GENERIC_WRITE_ACCESS (1u << 30)
-#define GENERIC_READ_ACCESS (1u << 31)
-
-static unsigned int access_mask_to_samba( DWORD mask )
-{
- static const DWORD known_rights =
- GENERIC_ALL | GENERIC_EXECUTE | GENERIC_WRITE | GENERIC_READ;
- unsigned int ret = 0;
-
- if (mask & ~known_rights)
- {
- ERR( "unknown rights %x\n", mask & ~known_rights );
- return 0;
- }
- if (mask & GENERIC_ALL) ret |= GENERIC_ALL_ACCESS;
- if (mask & GENERIC_EXECUTE) ret |= GENERIC_EXECUTE_ACCESS;
- if (mask & GENERIC_WRITE) ret |= GENERIC_WRITE_ACCESS;
- if (mask & GENERIC_READ) ret |= GENERIC_READ_ACCESS;
- return ret;
-}
-
-static NET_API_STATUS ace_to_samba( const ACE_HEADER *src, struct ace *dst )
-{
- dst->type = ace_type_to_samba( src->AceType );
- dst->flags = ace_flags_to_samba( src->AceFlags );
- dst->size = sizeof(*dst);
- switch (src->AceType)
- {
- case ACCESS_ALLOWED_ACE_TYPE:
- {
- ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *)src;
- dst->access_mask = access_mask_to_samba( ace->Mask );
- memset( &dst->object, 0, sizeof(dst->object) );
- sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
- break;
- }
- case ACCESS_DENIED_ACE_TYPE:
- {
- ACCESS_DENIED_ACE *ace = (ACCESS_DENIED_ACE *)src;
- dst->access_mask = access_mask_to_samba( ace->Mask );
- memset( &dst->object, 0, sizeof(dst->object) );
- sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
- break;
- }
- case SYSTEM_AUDIT_ACE_TYPE:
- {
- SYSTEM_AUDIT_ACE *ace = (SYSTEM_AUDIT_ACE *)src;
- dst->access_mask = access_mask_to_samba( ace->Mask );
- memset( &dst->object, 0, sizeof(dst->object) );
- sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
- break;
- }
- case SYSTEM_ALARM_ACE_TYPE:
- {
- SYSTEM_ALARM_ACE *ace = (SYSTEM_ALARM_ACE *)src;
- dst->access_mask = access_mask_to_samba( ace->Mask );
- memset( &dst->object, 0, sizeof(dst->object) );
- sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
- break;
- }
- default:
- ERR( "unhandled type %u\n", src->AceType );
- return ERROR_INVALID_PARAMETER;
- }
- return NERR_Success;
-}
-
-static NET_API_STATUS acl_to_samba( const ACL *src, struct acl *dst )
-{
- NET_API_STATUS status;
- ACE_HEADER *src_ace;
- unsigned int i;
-
- switch (src->AclRevision)
- {
- case ACL_REVISION4:
- dst->revision = ACL_REVISION_ADS;
- break;
- default:
- ERR( "unkhandled revision %u\n", src->AclRevision );
- return ERROR_UNKNOWN_REVISION;
- }
- dst->size = sizeof(*dst);
- src_ace = (ACE_HEADER *)(src + 1);
- dst->aces = (struct ace *)(dst + 1);
- for (i = 0; i < src->AceCount; i++)
- {
- if ((status = ace_to_samba( src_ace, &dst->aces[i] ))) return status;
- src_ace = (ACE_HEADER *)((char *)src_ace + src_ace->AceSize);
- dst->size += dst->aces[i].size;
- }
- return NERR_Success;
-}
-
-#define SELF_RELATIVE_FIELD(sd,field)\
- ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
-
-static NET_API_STATUS sd_to_samba( const SECURITY_DESCRIPTOR *src, struct security_descriptor *dst )
-{
- NET_API_STATUS status;
- const SID *owner, *group;
- const ACL *dacl, *sacl;
- unsigned int offset = sizeof(*dst);
-
- if (src->Revision != SECURITY_DESCRIPTOR_REVISION1)
- return ERROR_UNKNOWN_REVISION;
-
- dst->revision = SECURITY_DESCRIPTOR_REVISION_1;
- dst->type = sd_control_to_samba( src->Control );
-
- if (src->Control & SE_SELF_RELATIVE)
- {
- if (!src->Owner) dst->owner_sid = NULL;
- else
- {
- dst->owner_sid = (struct sid *)((char *)dst + offset);
- owner = (const SID *)SELF_RELATIVE_FIELD( src, Owner );
- if ((status = sid_to_samba( owner, dst->owner_sid ))) return status;
- offset += sizeof(struct sid);
- }
- if (!src->Group) dst->group_sid = NULL;
- else
- {
- dst->group_sid = (struct sid *)((char *)dst + offset);
- group = (const SID *)SELF_RELATIVE_FIELD( src, Group );
- if ((status = sid_to_samba( group, dst->group_sid ))) return status;
- offset += sizeof(struct sid);
- }
- if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
- else
- {
- dst->sacl = (struct acl *)((char *)dst + offset);
- sacl = (const ACL *)SELF_RELATIVE_FIELD( src, Sacl );
- if ((status = acl_to_samba( sacl, dst->sacl ))) return status;
- offset += dst->sacl->size;
- }
- if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
- else
- {
- dst->dacl = (struct acl *)((char *)dst + offset);
- dacl = (const ACL *)SELF_RELATIVE_FIELD( src, Dacl );
- if ((status = acl_to_samba( dacl, dst->dacl ))) return status;
- }
- }
- else
- {
- if (!src->Owner) dst->owner_sid = NULL;
- else
- {
- dst->owner_sid = (struct sid *)((char *)dst + offset);
- if ((status = sid_to_samba( src->Owner, dst->owner_sid ))) return status;
- offset += sizeof(struct sid);
- }
- if (!src->Group) dst->group_sid = NULL;
- else
- {
- dst->group_sid = (struct sid *)((char *)dst + offset);
- if ((status = sid_to_samba( src->Group, dst->group_sid ))) return status;
- offset += sizeof(struct sid);
- }
- if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
- else
- {
- dst->sacl = (struct acl *)((char *)dst + offset);
- if ((status = acl_to_samba( src->Sacl, dst->sacl ))) return status;
- offset += dst->sacl->size;
- }
- if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
- else
- {
- dst->dacl = (struct acl *)((char *)dst + offset);
- if ((status = acl_to_samba( src->Dacl, dst->dacl ))) return status;
- }
- }
- return NERR_Success;
-}
-
-static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR *sd )
-{
- unsigned int ret = sizeof(struct security_descriptor);
-
- if (sd->Owner) ret += sizeof(struct sid);
- if (sd->Group) ret += sizeof(struct sid);
- if (sd->Control & SE_SACL_PRESENT)
- ret += sizeof(struct acl) + sd->Sacl->AceCount * sizeof(struct ace);
- if (sd->Control & SE_DACL_PRESENT)
- ret += sizeof(struct acl) + sd->Dacl->AceCount * sizeof(struct ace);
- return ret;
-}
-
-static NET_API_STATUS share_info_502_to_samba( const BYTE *buf, unsigned char **bufptr )
-{
- NET_API_STATUS status;
- struct share_info_502 *ret;
- SHARE_INFO_502 *info = (SHARE_INFO_502 *)buf;
- DWORD len = 0, size = 0;
- char *ptr;
-
- *bufptr = NULL;
- if (info->shi502_netname)
- len += netapi_wcstoumbs( info->shi502_netname, NULL, 0 );
- if (info->shi502_remark)
- len += netapi_wcstoumbs( info->shi502_remark, NULL, 0 );
- if (info->shi502_path)
- len += netapi_wcstoumbs( info->shi502_path, NULL, 0 );
- if (info->shi502_passwd)
- len += netapi_wcstoumbs( info->shi502_passwd, NULL, 0 );
- if (info->shi502_security_descriptor)
- size = sd_to_samba_size( info->shi502_security_descriptor );
- if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR)) + size )))
- return ERROR_OUTOFMEMORY;
-
- ptr = (char *)(ret + 1);
- if (!info->shi502_netname) ret->shi502_netname = NULL;
- else
- {
- ret->shi502_netname = ptr;
- ptr += netapi_wcstoumbs( info->shi502_netname, ptr, len );
- }
- ret->shi502_type = info->shi502_type;
- if (!info->shi502_remark) ret->shi502_remark = NULL;
- else
- {
- ret->shi502_remark = ptr;
- ptr += netapi_wcstoumbs( info->shi502_remark, ptr, len );
- }
- ret->shi502_permissions = info->shi502_permissions;
- ret->shi502_max_uses = info->shi502_max_uses;
- ret->shi502_current_uses = info->shi502_current_uses;
- if (!info->shi502_path) ret->shi502_path = NULL;
- else
- {
- ret->shi502_path = ptr;
- ptr += netapi_wcstoumbs( info->shi502_path, ptr, len );
- }
- if (!info->shi502_passwd) ret->shi502_passwd = NULL;
- else
- {
- ret->shi502_passwd = ptr;
- ptr += netapi_wcstoumbs( info->shi502_passwd, ptr, len );
- }
- ret->shi502_reserved = info->shi502_reserved;
- if (!info->shi502_security_descriptor) ret->shi502_security_descriptor = NULL;
- else
- {
- status = sd_to_samba( info->shi502_security_descriptor, (struct security_descriptor *)ptr );
- if (status)
- {
- HeapFree( GetProcessHeap(), 0, ret );
- return status;
- }
- ret->shi502_security_descriptor = (struct security_descriptor *)ptr;
- }
- *bufptr = (unsigned char *)ret;
- return NERR_Success;
-}
-
-static NET_API_STATUS share_info_to_samba( DWORD level, const BYTE *buf, unsigned char **bufptr )
-{
- switch (level)
- {
- case 2: return share_info_2_to_samba( buf, bufptr );
- case 502: return share_info_502_to_samba( buf, bufptr );
- default:
- FIXME( "level %u not supported\n", level );
- return ERROR_NOT_SUPPORTED;
- }
-}
-
-static NET_API_STATUS share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
-{
- char *server = NULL;
- unsigned char *info;
- NET_API_STATUS status;
-
- if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
- status = share_info_to_samba( level, buf, &info );
- if (!status)
- {
- unsigned int err;
-
- status = pNetShareAdd( server, level, info, &err );
- HeapFree( GetProcessHeap(), 0, info );
- if (parm_err) *parm_err = err;
- }
- HeapFree( GetProcessHeap(), 0, server );
- return status;
-}
-
-static NET_API_STATUS share_del( LMSTR servername, LMSTR netname, DWORD reserved )
-{
- char *server = NULL, *share;
- NET_API_STATUS status;
-
- if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
- if (!(share = strdup_unixcp( netname )))
- {
- HeapFree( GetProcessHeap(), 0, server );
- return ERROR_OUTOFMEMORY;
- }
- status = pNetShareDel( server, share, reserved );
- HeapFree( GetProcessHeap(), 0, server );
- HeapFree( GetProcessHeap(), 0, share );
- return status;
-}
-
-struct wksta_info_100
-{
- unsigned int wki100_platform_id;
- const char *wki100_computername;
- const char *wki100_langroup;
- unsigned int wki100_ver_major;
- unsigned int wki100_ver_minor;
-};
-
-static NET_API_STATUS wksta_info_100_from_samba( const unsigned char *buf, BYTE **bufptr )
-{
- WKSTA_INFO_100 *ret;
- struct wksta_info_100 *info = (struct wksta_info_100 *)buf;
- DWORD len = 0;
- WCHAR *ptr;
-
- if (info->wki100_computername)
- len += netapi_umbstowcs( info->wki100_computername, NULL, 0 );
- if (info->wki100_langroup)
- len += netapi_umbstowcs( info->wki100_langroup, NULL, 0 );
- if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
- return ERROR_OUTOFMEMORY;
-
- ptr = (WCHAR *)(ret + 1);
- ret->wki100_platform_id = info->wki100_platform_id;
- if (!info->wki100_computername) ret->wki100_computername = NULL;
- else
- {
- ret->wki100_computername = ptr;
- ptr += netapi_umbstowcs( info->wki100_computername, ptr, len );
- }
- if (!info->wki100_langroup) ret->wki100_langroup = NULL;
- else
- {
- ret->wki100_langroup = ptr;
- netapi_umbstowcs( info->wki100_langroup, ptr, len );
- }
- ret->wki100_ver_major = info->wki100_ver_major;
- ret->wki100_ver_minor = info->wki100_ver_minor;
- *bufptr = (BYTE *)ret;
- return NERR_Success;
-}
-
-static NET_API_STATUS wksta_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
-{
- switch (level)
- {
- case 100: return wksta_info_100_from_samba( buf, bufptr );
- default:
- FIXME( "level %u not supported\n", level );
- return ERROR_NOT_SUPPORTED;
- }
-}
-
-static NET_API_STATUS wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
-{
- NET_API_STATUS status;
- char *wksta = NULL;
- unsigned char *buf = NULL;
-
- if (servername && !(wksta = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
- status = pNetWkstaGetInfo( wksta, level, &buf );
- HeapFree( GetProcessHeap(), 0, wksta );
- if (!status)
- {
- status = wksta_info_from_samba( level, buf, bufptr );
- pNetApiBufferFree( buf );
- }
- return status;
-}
-
-#else
-
-static BOOL libnetapi_init(void)
-{
- return FALSE;
-}
-
-static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
-{
- ERR( "\n" );
- return ERROR_NOT_SUPPORTED;
-}
-static NET_API_STATUS share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
-{
- ERR( "\n" );
- return ERROR_NOT_SUPPORTED;
-}
-static NET_API_STATUS share_del( LMSTR servername, LMSTR netname, DWORD reserved )
-{
- ERR( "\n" );
- return ERROR_NOT_SUPPORTED;
-}
-static NET_API_STATUS wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
-{
- ERR( "\n" );
- return ERROR_NOT_SUPPORTED;
-}
-
-#endif /* SONAME_LIBNETAPI */
-
/************************************************************
* NETAPI_IsLocalComputer
*
@@ -1007,6 +161,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
+ netapi32_instance = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
NetBIOSInit();
NetBTInit();
@@ -1093,7 +248,7 @@ NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bu
if (!local)
{
- if (libnetapi_init()) return server_getinfo( servername, level, bufptr );
+ if (samba_init()) return samba_funcs->server_getinfo( servername, level, bufptr );
FIXME( "remote computers not supported\n" );
return ERROR_INVALID_LEVEL;
}
@@ -1393,7 +548,7 @@ NET_API_STATUS WINAPI NetShareDel(LMSTR servername, LMSTR netname, DWORD reserve
if (!local)
{
- if (libnetapi_init()) return share_del( servername, netname, reserved );
+ if (samba_init()) return samba_funcs->share_del( servername, netname, reserved );
FIXME( "remote computers not supported\n" );
}
@@ -1424,7 +579,7 @@ NET_API_STATUS WINAPI NetShareAdd(LMSTR servername,
if (!local)
{
- if (libnetapi_init()) return share_add( servername, level, buf, parm_err );
+ if (samba_init()) return samba_funcs->share_add( servername, level, buf, parm_err );
FIXME( "remote computers not supported\n" );
}
@@ -1880,7 +1035,7 @@ NET_API_STATUS WINAPI NetWkstaGetInfo( LMSTR servername, DWORD level,
if (!local)
{
- if (libnetapi_init()) return wksta_getinfo( servername, level, bufptr );
+ if (samba_init()) return samba_funcs->wksta_getinfo( servername, level, bufptr );
FIXME( "remote computers not supported\n" );
return ERROR_INVALID_LEVEL;
}
diff --git a/dlls/netapi32/unixlib.c b/dlls/netapi32/unixlib.c
new file mode 100644
index 00000000000..3610abe2bde
--- /dev/null
+++ b/dlls/netapi32/unixlib.c
@@ -0,0 +1,967 @@
+/*
+ * Unix library for libnetapi functions
+ *
+ * Copyright 2013 Hans Leidekker for CodeWeavers
+ * Copyright 2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "lm.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#include "unixlib.h"
+
+#ifdef SONAME_LIBNETAPI
+
+WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+static void *libnetapi_handle;
+static void *libnetapi_ctx;
+
+static DWORD (*plibnetapi_init)( void ** );
+static DWORD (*plibnetapi_free)( void * );
+static DWORD (*plibnetapi_set_debuglevel)( void *, const char * );
+static DWORD (*plibnetapi_set_username)( void *, const char * );
+static DWORD (*plibnetapi_set_password)( void *, const char * );
+
+static NET_API_STATUS (*pNetApiBufferAllocate)( unsigned int, void ** );
+static NET_API_STATUS (*pNetApiBufferFree)( void * );
+static NET_API_STATUS (*pNetServerGetInfo)( const char *, unsigned int, unsigned char ** );
+static NET_API_STATUS (*pNetShareAdd)( const char *, unsigned int, unsigned char *, unsigned int * );
+static NET_API_STATUS (*pNetShareDel)( const char *, const char *, unsigned int );
+static NET_API_STATUS (*pNetWkstaGetInfo)( const char *, unsigned int, unsigned char ** );
+
+static CPTABLEINFO unix_cptable;
+static ULONG unix_cp;
+
+static BOOL get_unix_codepage(void)
+{
+ static const WCHAR wineunixcpW[] = {'W','I','N','E','U','N','I','X','C','P',0};
+ UNICODE_STRING name, value;
+ WCHAR value_buffer[13];
+ SIZE_T size;
+ void *ptr;
+
+ if (unix_cp) return TRUE;
+
+ RtlInitUnicodeString( &name, wineunixcpW );
+ value.Buffer = value_buffer;
+ value.MaximumLength = sizeof(value_buffer);
+ if (!RtlQueryEnvironmentVariable_U( NULL, &name, &value ))
+ RtlUnicodeStringToInteger( &value, 10, &unix_cp );
+ if (NtGetNlsSectionPtr( 11, unix_cp, NULL, &ptr, &size ))
+ return FALSE;
+ RtlInitCodePageTable( ptr, &unix_cptable );
+ return TRUE;
+}
+
+static DWORD netapi_wcstoumbs( const WCHAR *src, char *dst, DWORD dstlen )
+{
+ DWORD srclen = (strlenW( src ) + 1) * sizeof(WCHAR);
+ DWORD len;
+
+ get_unix_codepage();
+
+ if (unix_cp == CP_UTF8)
+ {
+ RtlUnicodeToUTF8N( dst, dstlen, &len, src, srclen );
+ return len;
+ }
+ else
+ {
+ len = (strlenW( src ) * 2) + 1;
+ if (dst) RtlUnicodeToCustomCPN( &unix_cptable, dst, dstlen, &len, src, srclen );
+ return len;
+ }
+}
+
+static DWORD netapi_umbstowcs( const char *src, WCHAR *dst, DWORD dstlen )
+{
+ DWORD srclen = strlen( src ) + 1;
+ DWORD len;
+
+ get_unix_codepage();
+
+ if (unix_cp == CP_UTF8)
+ {
+ RtlUTF8ToUnicodeN( dst, dstlen, &len, src, srclen );
+ return len;
+ }
+ else
+ {
+ len = srclen * sizeof(WCHAR);
+ if (dst) RtlCustomCPToUnicodeN( &unix_cptable, dst, dstlen, &len, src, srclen );
+ return len;
+ }
+}
+
+static char *strdup_unixcp( const WCHAR *str )
+{
+ char *ret;
+
+ int len = netapi_wcstoumbs( str, NULL, 0 );
+ if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, len )))
+ netapi_wcstoumbs( str, ret, len );
+ return ret;
+}
+
+struct server_info_101
+{
+ unsigned int sv101_platform_id;
+ const char *sv101_name;
+ unsigned int sv101_version_major;
+ unsigned int sv101_version_minor;
+ unsigned int sv101_type;
+ const char *sv101_comment;
+};
+
+static NET_API_STATUS server_info_101_from_samba( const unsigned char *buf, BYTE **bufptr )
+{
+ SERVER_INFO_101 *ret;
+ struct server_info_101 *info = (struct server_info_101 *)buf;
+ DWORD len = 0;
+ WCHAR *ptr;
+
+ if (info->sv101_name) len += netapi_umbstowcs( info->sv101_name, NULL, 0 );
+ if (info->sv101_comment) len += netapi_umbstowcs( info->sv101_comment, NULL, 0 );
+ if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
+ return ERROR_OUTOFMEMORY;
+
+ ptr = (WCHAR *)(ret + 1);
+ ret->sv101_platform_id = info->sv101_platform_id;
+ if (!info->sv101_name) ret->sv101_name = NULL;
+ else
+ {
+ ret->sv101_name = ptr;
+ ptr += netapi_umbstowcs( info->sv101_name, ptr, len );
+ }
+ ret->sv101_version_major = info->sv101_version_major;
+ ret->sv101_version_minor = info->sv101_version_minor;
+ ret->sv101_type = info->sv101_type;
+ if (!info->sv101_comment) ret->sv101_comment = NULL;
+ else
+ {
+ ret->sv101_comment = ptr;
+ netapi_umbstowcs( info->sv101_comment, ptr, len );
+ }
+ *bufptr = (BYTE *)ret;
+ return NERR_Success;
+}
+
+static NET_API_STATUS server_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
+{
+ switch (level)
+ {
+ case 101: return server_info_101_from_samba( buf, bufptr );
+ default:
+ FIXME( "level %u not supported\n", level );
+ return ERROR_NOT_SUPPORTED;
+ }
+}
+
+static NET_API_STATUS WINAPI server_getinfo( const WCHAR *server, DWORD level, BYTE **buffer )
+{
+ NET_API_STATUS status;
+ char *samba_server = NULL;
+ unsigned char *samba_buffer = NULL;
+
+ if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
+
+ if (server && !(samba_server = strdup_unixcp( server ))) return ERROR_OUTOFMEMORY;
+ status = pNetServerGetInfo( samba_server, level, &samba_buffer );
+ RtlFreeHeap( GetProcessHeap(), 0, samba_server );
+ if (!status)
+ {
+ status = server_info_from_samba( level, samba_buffer, buffer );
+ pNetApiBufferFree( samba_buffer );
+ }
+ return status;
+}
+
+struct share_info_2
+{
+ const char *shi2_netname;
+ unsigned int shi2_type;
+ const char *shi2_remark;
+ unsigned int shi2_permissions;
+ unsigned int shi2_max_uses;
+ unsigned int shi2_current_uses;
+ const char *shi2_path;
+ const char *shi2_passwd;
+};
+
+static NET_API_STATUS share_info_2_to_samba( const BYTE *buf, unsigned char **bufptr )
+{
+ struct share_info_2 *ret;
+ SHARE_INFO_2 *info = (SHARE_INFO_2 *)buf;
+ DWORD len = 0;
+ char *ptr;
+
+ if (info->shi2_netname)
+ len += netapi_wcstoumbs( info->shi2_netname, NULL, 0 );
+ if (info->shi2_remark)
+ len += netapi_wcstoumbs( info->shi2_remark, NULL, 0 );
+ if (info->shi2_path)
+ len += netapi_wcstoumbs( info->shi2_path, NULL, 0 );
+ if (info->shi2_passwd)
+ len += netapi_wcstoumbs( info->shi2_passwd, NULL, 0 );
+ if (!(ret = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) + len )))
+ return ERROR_OUTOFMEMORY;
+
+ ptr = (char *)(ret + 1);
+ if (!info->shi2_netname) ret->shi2_netname = NULL;
+ else
+ {
+ ret->shi2_netname = ptr;
+ ptr += netapi_wcstoumbs( info->shi2_netname, ptr, len );
+ }
+ ret->shi2_type = info->shi2_type;
+ if (!info->shi2_remark) ret->shi2_remark = NULL;
+ else
+ {
+ ret->shi2_remark = ptr;
+ ptr += netapi_wcstoumbs( info->shi2_remark, ptr, len );
+ }
+ ret->shi2_permissions = info->shi2_permissions;
+ ret->shi2_max_uses = info->shi2_max_uses;
+ ret->shi2_current_uses = info->shi2_current_uses;
+ if (!info->shi2_path) ret->shi2_path = NULL;
+ else
+ {
+ ret->shi2_path = ptr;
+ ptr += netapi_wcstoumbs( info->shi2_path, ptr, len );
+ }
+ if (!info->shi2_passwd) ret->shi2_passwd = NULL;
+ else
+ {
+ ret->shi2_passwd = ptr;
+ netapi_wcstoumbs( info->shi2_passwd, ptr, len );
+ }
+ *bufptr = (unsigned char *)ret;
+ return NERR_Success;
+}
+
+struct sid
+{
+ unsigned char sid_rev_num;
+ unsigned char num_auths;
+ unsigned char id_auth[6];
+ unsigned int sub_auths[15];
+};
+
+enum ace_type
+{
+ ACE_TYPE_ACCESS_ALLOWED,
+ ACE_TYPE_ACCESS_DENIED,
+ ACE_TYPE_SYSTEM_AUDIT,
+ ACE_TYPE_SYSTEM_ALARM,
+ ACE_TYPE_ALLOWED_COMPOUND,
+ ACE_TYPE_ACCESS_ALLOWED_OBJECT,
+ ACE_TYPE_ACCESS_DENIED_OBJECT,
+ ACE_TYPE_SYSTEM_AUDIT_OBJECT,
+ ACE_TYPE_SYSTEM_ALARM_OBJECT
+};
+
+#define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
+#define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
+#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
+#define SEC_ACE_FLAG_INHERIT_ONLY 0x08
+#define SEC_ACE_FLAG_INHERITED_ACE 0x10
+#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
+#define SEC_ACE_FLAG_FAILED_ACCESS 0x80
+
+struct guid
+{
+ unsigned int time_low;
+ unsigned short time_mid;
+ unsigned short time_hi_and_version;
+ unsigned char clock_seq[2];
+ unsigned char node[6];
+};
+
+union ace_object_type
+{
+ struct guid type;
+};
+
+union ace_object_inherited_type
+{
+ struct guid inherited_type;
+};
+
+struct ace_object
+{
+ unsigned int flags;
+ union ace_object_type type;
+ union ace_object_inherited_type inherited_type;
+};
+
+union ace_object_ctr
+{
+ struct ace_object object;
+};
+
+struct ace
+{
+ enum ace_type type;
+ unsigned char flags;
+ unsigned short size;
+ unsigned int access_mask;
+ union ace_object_ctr object;
+ struct sid trustee;
+};
+
+enum acl_revision
+{
+ ACL_REVISION_NT4 = 2,
+ ACL_REVISION_ADS = 4
+};
+
+struct acl
+{
+ enum acl_revision revision;
+ unsigned short size;
+ unsigned int num_aces;
+ struct ace *aces;
+};
+
+enum security_descriptor_revision
+{
+ SECURITY_DESCRIPTOR_REVISION_1 = 1
+};
+
+#define SEC_DESC_OWNER_DEFAULTED 0x0001
+#define SEC_DESC_GROUP_DEFAULTED 0x0002
+#define SEC_DESC_DACL_PRESENT 0x0004
+#define SEC_DESC_DACL_DEFAULTED 0x0008
+#define SEC_DESC_SACL_PRESENT 0x0010
+#define SEC_DESC_SACL_DEFAULTED 0x0020
+#define SEC_DESC_DACL_TRUSTED 0x0040
+#define SEC_DESC_SERVER_SECURITY 0x0080
+#define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
+#define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
+#define SEC_DESC_DACL_AUTO_INHERITED 0x0400
+#define SEC_DESC_SACL_AUTO_INHERITED 0x0800
+#define SEC_DESC_DACL_PROTECTED 0x1000
+#define SEC_DESC_SACL_PROTECTED 0x2000
+#define SEC_DESC_RM_CONTROL_VALID 0x4000
+#define SEC_DESC_SELF_RELATIVE 0x8000
+
+struct security_descriptor
+{
+ enum security_descriptor_revision revision;
+ unsigned short type;
+ struct sid *owner_sid;
+ struct sid *group_sid;
+ struct acl *sacl;
+ struct acl *dacl;
+};
+
+struct share_info_502
+{
+ const char *shi502_netname;
+ unsigned int shi502_type;
+ const char *shi502_remark;
+ unsigned int shi502_permissions;
+ unsigned int shi502_max_uses;
+ unsigned int shi502_current_uses;
+ const char *shi502_path;
+ const char *shi502_passwd;
+ unsigned int shi502_reserved;
+ struct security_descriptor *shi502_security_descriptor;
+};
+
+static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control )
+{
+ unsigned short ret = 0;
+
+ if (control & SE_OWNER_DEFAULTED) ret |= SEC_DESC_OWNER_DEFAULTED;
+ if (control & SE_GROUP_DEFAULTED) ret |= SEC_DESC_GROUP_DEFAULTED;
+ if (control & SE_DACL_PRESENT) ret |= SEC_DESC_DACL_PRESENT;
+ if (control & SE_DACL_DEFAULTED) ret |= SEC_DESC_DACL_DEFAULTED;
+ if (control & SE_SACL_PRESENT) ret |= SEC_DESC_SACL_PRESENT;
+ if (control & SE_SACL_DEFAULTED) ret |= SEC_DESC_SACL_DEFAULTED;
+ if (control & SE_DACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_DACL_AUTO_INHERIT_REQ;
+ if (control & SE_SACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_SACL_AUTO_INHERIT_REQ;
+ if (control & SE_DACL_AUTO_INHERITED) ret |= SEC_DESC_DACL_AUTO_INHERITED;
+ if (control & SE_SACL_AUTO_INHERITED) ret |= SEC_DESC_SACL_AUTO_INHERITED;
+ if (control & SE_DACL_PROTECTED) ret |= SEC_DESC_DACL_PROTECTED;
+ if (control & SE_SACL_PROTECTED) ret |= SEC_DESC_SACL_PROTECTED;
+ if (control & SE_RM_CONTROL_VALID) ret |= SEC_DESC_RM_CONTROL_VALID;
+ return ret;
+}
+
+static NET_API_STATUS sid_to_samba( const SID *src, struct sid *dst )
+{
+ unsigned int i;
+
+ if (src->Revision != 1)
+ {
+ ERR( "unknown revision %u\n", src->Revision );
+ return ERROR_UNKNOWN_REVISION;
+ }
+ if (src->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
+ {
+ WARN( "invalid subauthority count %u\n", src->SubAuthorityCount );
+ return ERROR_INVALID_PARAMETER;
+ }
+ dst->sid_rev_num = SECURITY_DESCRIPTOR_REVISION_1;
+ dst->num_auths = src->SubAuthorityCount;
+ for (i = 0; i < 6; i++) dst->id_auth[i] = src->IdentifierAuthority.Value[i];
+ for (i = 0; i < dst->num_auths; i++) dst->sub_auths[i] = src->SubAuthority[i];
+ return NERR_Success;
+}
+
+static enum ace_type ace_type_to_samba( BYTE type )
+{
+ switch (type)
+ {
+ case ACCESS_ALLOWED_ACE_TYPE: return ACE_TYPE_ACCESS_ALLOWED;
+ case ACCESS_DENIED_ACE_TYPE: return ACE_TYPE_ACCESS_DENIED;
+ case SYSTEM_AUDIT_ACE_TYPE: return ACE_TYPE_SYSTEM_AUDIT;
+ case SYSTEM_ALARM_ACE_TYPE: return ACE_TYPE_SYSTEM_ALARM;
+ default:
+ ERR( "unhandled type %u\n", type );
+ return 0;
+ }
+}
+
+static unsigned char ace_flags_to_samba( BYTE flags )
+{
+ static const BYTE known_flags =
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | NO_PROPAGATE_INHERIT_ACE |
+ INHERIT_ONLY_ACE | INHERITED_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
+ unsigned char ret = 0;
+
+ if (flags & ~known_flags)
+ {
+ ERR( "unknown flags %x\n", flags & ~known_flags );
+ return 0;
+ }
+ if (flags & OBJECT_INHERIT_ACE) ret |= SEC_ACE_FLAG_OBJECT_INHERIT;
+ if (flags & CONTAINER_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
+ if (flags & NO_PROPAGATE_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
+ if (flags & INHERIT_ONLY_ACE) ret |= SEC_ACE_FLAG_INHERIT_ONLY;
+ if (flags & INHERITED_ACE) ret |= SEC_ACE_FLAG_INHERITED_ACE;
+ if (flags & SUCCESSFUL_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_SUCCESSFUL_ACCESS;
+ if (flags & FAILED_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_FAILED_ACCESS;
+ return ret;
+}
+
+#define GENERIC_ALL_ACCESS (1u << 28)
+#define GENERIC_EXECUTE_ACCESS (1u << 29)
+#define GENERIC_WRITE_ACCESS (1u << 30)
+#define GENERIC_READ_ACCESS (1u << 31)
+
+static unsigned int access_mask_to_samba( DWORD mask )
+{
+ static const DWORD known_rights =
+ GENERIC_ALL | GENERIC_EXECUTE | GENERIC_WRITE | GENERIC_READ;
+ unsigned int ret = 0;
+
+ if (mask & ~known_rights)
+ {
+ ERR( "unknown rights %x\n", mask & ~known_rights );
+ return 0;
+ }
+ if (mask & GENERIC_ALL) ret |= GENERIC_ALL_ACCESS;
+ if (mask & GENERIC_EXECUTE) ret |= GENERIC_EXECUTE_ACCESS;
+ if (mask & GENERIC_WRITE) ret |= GENERIC_WRITE_ACCESS;
+ if (mask & GENERIC_READ) ret |= GENERIC_READ_ACCESS;
+ return ret;
+}
+
+static NET_API_STATUS ace_to_samba( const ACE_HEADER *src, struct ace *dst )
+{
+ dst->type = ace_type_to_samba( src->AceType );
+ dst->flags = ace_flags_to_samba( src->AceFlags );
+ dst->size = sizeof(*dst);
+ switch (src->AceType)
+ {
+ case ACCESS_ALLOWED_ACE_TYPE:
+ {
+ ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ break;
+ }
+ case ACCESS_DENIED_ACE_TYPE:
+ {
+ ACCESS_DENIED_ACE *ace = (ACCESS_DENIED_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ break;
+ }
+ case SYSTEM_AUDIT_ACE_TYPE:
+ {
+ SYSTEM_AUDIT_ACE *ace = (SYSTEM_AUDIT_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ break;
+ }
+ case SYSTEM_ALARM_ACE_TYPE:
+ {
+ SYSTEM_ALARM_ACE *ace = (SYSTEM_ALARM_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ break;
+ }
+ default:
+ ERR( "unhandled type %u\n", src->AceType );
+ return ERROR_INVALID_PARAMETER;
+ }
+ return NERR_Success;
+}
+
+static NET_API_STATUS acl_to_samba( const ACL *src, struct acl *dst )
+{
+ NET_API_STATUS status;
+ ACE_HEADER *src_ace;
+ unsigned int i;
+
+ switch (src->AclRevision)
+ {
+ case ACL_REVISION4:
+ dst->revision = ACL_REVISION_ADS;
+ break;
+ default:
+ ERR( "unkhandled revision %u\n", src->AclRevision );
+ return ERROR_UNKNOWN_REVISION;
+ }
+ dst->size = sizeof(*dst);
+ src_ace = (ACE_HEADER *)(src + 1);
+ dst->aces = (struct ace *)(dst + 1);
+ for (i = 0; i < src->AceCount; i++)
+ {
+ if ((status = ace_to_samba( src_ace, &dst->aces[i] ))) return status;
+ src_ace = (ACE_HEADER *)((char *)src_ace + src_ace->AceSize);
+ dst->size += dst->aces[i].size;
+ }
+ return NERR_Success;
+}
+
+#define SELF_RELATIVE_FIELD(sd,field)\
+ ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
+
+static NET_API_STATUS sd_to_samba( const SECURITY_DESCRIPTOR *src, struct security_descriptor *dst )
+{
+ NET_API_STATUS status;
+ const SID *owner, *group;
+ const ACL *dacl, *sacl;
+ unsigned int offset = sizeof(*dst);
+
+ if (src->Revision != SECURITY_DESCRIPTOR_REVISION1)
+ return ERROR_UNKNOWN_REVISION;
+
+ dst->revision = SECURITY_DESCRIPTOR_REVISION_1;
+ dst->type = sd_control_to_samba( src->Control );
+
+ if (src->Control & SE_SELF_RELATIVE)
+ {
+ if (!src->Owner) dst->owner_sid = NULL;
+ else
+ {
+ dst->owner_sid = (struct sid *)((char *)dst + offset);
+ owner = (const SID *)SELF_RELATIVE_FIELD( src, Owner );
+ if ((status = sid_to_samba( owner, dst->owner_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!src->Group) dst->group_sid = NULL;
+ else
+ {
+ dst->group_sid = (struct sid *)((char *)dst + offset);
+ group = (const SID *)SELF_RELATIVE_FIELD( src, Group );
+ if ((status = sid_to_samba( group, dst->group_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
+ else
+ {
+ dst->sacl = (struct acl *)((char *)dst + offset);
+ sacl = (const ACL *)SELF_RELATIVE_FIELD( src, Sacl );
+ if ((status = acl_to_samba( sacl, dst->sacl ))) return status;
+ offset += dst->sacl->size;
+ }
+ if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
+ else
+ {
+ dst->dacl = (struct acl *)((char *)dst + offset);
+ dacl = (const ACL *)SELF_RELATIVE_FIELD( src, Dacl );
+ if ((status = acl_to_samba( dacl, dst->dacl ))) return status;
+ }
+ }
+ else
+ {
+ if (!src->Owner) dst->owner_sid = NULL;
+ else
+ {
+ dst->owner_sid = (struct sid *)((char *)dst + offset);
+ if ((status = sid_to_samba( src->Owner, dst->owner_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!src->Group) dst->group_sid = NULL;
+ else
+ {
+ dst->group_sid = (struct sid *)((char *)dst + offset);
+ if ((status = sid_to_samba( src->Group, dst->group_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
+ else
+ {
+ dst->sacl = (struct acl *)((char *)dst + offset);
+ if ((status = acl_to_samba( src->Sacl, dst->sacl ))) return status;
+ offset += dst->sacl->size;
+ }
+ if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
+ else
+ {
+ dst->dacl = (struct acl *)((char *)dst + offset);
+ if ((status = acl_to_samba( src->Dacl, dst->dacl ))) return status;
+ }
+ }
+ return NERR_Success;
+}
+
+static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR *sd )
+{
+ unsigned int ret = sizeof(struct security_descriptor);
+
+ if (sd->Owner) ret += sizeof(struct sid);
+ if (sd->Group) ret += sizeof(struct sid);
+ if (sd->Control & SE_SACL_PRESENT)
+ ret += sizeof(struct acl) + sd->Sacl->AceCount * sizeof(struct ace);
+ if (sd->Control & SE_DACL_PRESENT)
+ ret += sizeof(struct acl) + sd->Dacl->AceCount * sizeof(struct ace);
+ return ret;
+}
+
+static NET_API_STATUS share_info_502_to_samba( const BYTE *buf, unsigned char **bufptr )
+{
+ NET_API_STATUS status;
+ struct share_info_502 *ret;
+ SHARE_INFO_502 *info = (SHARE_INFO_502 *)buf;
+ DWORD len = 0, size = 0;
+ char *ptr;
+
+ *bufptr = NULL;
+ if (info->shi502_netname)
+ len += netapi_wcstoumbs( info->shi502_netname, NULL, 0 );
+ if (info->shi502_remark)
+ len += netapi_wcstoumbs( info->shi502_remark, NULL, 0 );
+ if (info->shi502_path)
+ len += netapi_wcstoumbs( info->shi502_path, NULL, 0 );
+ if (info->shi502_passwd)
+ len += netapi_wcstoumbs( info->shi502_passwd, NULL, 0 );
+ if (info->shi502_security_descriptor)
+ size = sd_to_samba_size( info->shi502_security_descriptor );
+ if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR)) + size )))
+ return ERROR_OUTOFMEMORY;
+
+ ptr = (char *)(ret + 1);
+ if (!info->shi502_netname) ret->shi502_netname = NULL;
+ else
+ {
+ ret->shi502_netname = ptr;
+ ptr += netapi_wcstoumbs( info->shi502_netname, ptr, len );
+ }
+ ret->shi502_type = info->shi502_type;
+ if (!info->shi502_remark) ret->shi502_remark = NULL;
+ else
+ {
+ ret->shi502_remark = ptr;
+ ptr += netapi_wcstoumbs( info->shi502_remark, ptr, len );
+ }
+ ret->shi502_permissions = info->shi502_permissions;
+ ret->shi502_max_uses = info->shi502_max_uses;
+ ret->shi502_current_uses = info->shi502_current_uses;
+ if (!info->shi502_path) ret->shi502_path = NULL;
+ else
+ {
+ ret->shi502_path = ptr;
+ ptr += netapi_wcstoumbs( info->shi502_path, ptr, len );
+ }
+ if (!info->shi502_passwd) ret->shi502_passwd = NULL;
+ else
+ {
+ ret->shi502_passwd = ptr;
+ ptr += netapi_wcstoumbs( info->shi502_passwd, ptr, len );
+ }
+ ret->shi502_reserved = info->shi502_reserved;
+ if (!info->shi502_security_descriptor) ret->shi502_security_descriptor = NULL;
+ else
+ {
+ status = sd_to_samba( info->shi502_security_descriptor, (struct security_descriptor *)ptr );
+ if (status)
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, ret );
+ return status;
+ }
+ ret->shi502_security_descriptor = (struct security_descriptor *)ptr;
+ }
+ *bufptr = (unsigned char *)ret;
+ return NERR_Success;
+}
+
+static NET_API_STATUS share_info_to_samba( DWORD level, const BYTE *buf, unsigned char **bufptr )
+{
+ switch (level)
+ {
+ case 2: return share_info_2_to_samba( buf, bufptr );
+ case 502: return share_info_502_to_samba( buf, bufptr );
+ default:
+ FIXME( "level %u not supported\n", level );
+ return ERROR_NOT_SUPPORTED;
+ }
+}
+
+static NET_API_STATUS WINAPI share_add( const WCHAR *server, DWORD level, const BYTE *info, DWORD *err )
+{
+ char *samba_server = NULL;
+ unsigned char *samba_info;
+ NET_API_STATUS status;
+
+ if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
+
+ if (server && !(samba_server = strdup_unixcp( server ))) return ERROR_OUTOFMEMORY;
+ status = share_info_to_samba( level, info, &samba_info );
+ if (!status)
+ {
+ unsigned int samba_err;
+
+ status = pNetShareAdd( samba_server, level, samba_info, &samba_err );
+ RtlFreeHeap( GetProcessHeap(), 0, samba_info );
+ if (err) *err = samba_err;
+ }
+ RtlFreeHeap( GetProcessHeap(), 0, samba_server );
+ return status;
+}
+
+static NET_API_STATUS WINAPI share_del( const WCHAR *server, const WCHAR *share, DWORD reserved )
+{
+ char *samba_server = NULL, *samba_share;
+ NET_API_STATUS status;
+
+ if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
+
+ if (server && !(samba_server = strdup_unixcp( server ))) return ERROR_OUTOFMEMORY;
+ if (!(samba_share = strdup_unixcp( share )))
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, samba_server );
+ return ERROR_OUTOFMEMORY;
+ }
+ status = pNetShareDel( samba_server, samba_share, reserved );
+ RtlFreeHeap( GetProcessHeap(), 0, samba_server );
+ RtlFreeHeap( GetProcessHeap(), 0, samba_share );
+ return status;
+}
+
+struct wksta_info_100
+{
+ unsigned int wki100_platform_id;
+ const char *wki100_computername;
+ const char *wki100_langroup;
+ unsigned int wki100_ver_major;
+ unsigned int wki100_ver_minor;
+};
+
+static NET_API_STATUS wksta_info_100_from_samba( const unsigned char *buf, BYTE **bufptr )
+{
+ WKSTA_INFO_100 *ret;
+ struct wksta_info_100 *info = (struct wksta_info_100 *)buf;
+ DWORD len = 0;
+ WCHAR *ptr;
+
+ if (info->wki100_computername)
+ len += netapi_umbstowcs( info->wki100_computername, NULL, 0 );
+ if (info->wki100_langroup)
+ len += netapi_umbstowcs( info->wki100_langroup, NULL, 0 );
+ if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) ))))
+ return ERROR_OUTOFMEMORY;
+
+ ptr = (WCHAR *)(ret + 1);
+ ret->wki100_platform_id = info->wki100_platform_id;
+ if (!info->wki100_computername) ret->wki100_computername = NULL;
+ else
+ {
+ ret->wki100_computername = ptr;
+ ptr += netapi_umbstowcs( info->wki100_computername, ptr, len );
+ }
+ if (!info->wki100_langroup) ret->wki100_langroup = NULL;
+ else
+ {
+ ret->wki100_langroup = ptr;
+ netapi_umbstowcs( info->wki100_langroup, ptr, len );
+ }
+ ret->wki100_ver_major = info->wki100_ver_major;
+ ret->wki100_ver_minor = info->wki100_ver_minor;
+ *bufptr = (BYTE *)ret;
+ return NERR_Success;
+}
+
+static NET_API_STATUS wksta_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr )
+{
+ switch (level)
+ {
+ case 100: return wksta_info_100_from_samba( buf, bufptr );
+ default:
+ FIXME( "level %u not supported\n", level );
+ return ERROR_NOT_SUPPORTED;
+ }
+}
+
+static NET_API_STATUS WINAPI wksta_getinfo( const WCHAR *server, DWORD level, BYTE **buffer )
+{
+ unsigned char *samba_buffer = NULL;
+ char *samba_server = NULL;
+ NET_API_STATUS status;
+
+ if (!libnetapi_ctx) return ERROR_NOT_SUPPORTED;
+
+ if (server && !(samba_server = strdup_unixcp( server ))) return ERROR_OUTOFMEMORY;
+ status = pNetWkstaGetInfo( samba_server, level, &samba_buffer );
+ RtlFreeHeap( GetProcessHeap(), 0, samba_server );
+ if (!status)
+ {
+ status = wksta_info_from_samba( level, samba_buffer, buffer );
+ pNetApiBufferFree( samba_buffer );
+ }
+ return status;
+}
+
+static void libnetapi_init(void)
+{
+ DWORD status;
+ void *ctx;
+
+ if (!(libnetapi_handle = dlopen( SONAME_LIBNETAPI, RTLD_NOW )))
+ {
+ ERR_(winediag)( "failed to load %s\n", SONAME_LIBNETAPI );
+ return;
+ }
+
+#define LOAD_FUNCPTR(f) \
+ if (!(p##f = dlsym( libnetapi_handle, #f ))) \
+ { \
+ ERR_(winediag)( "%s not found in %s\n", #f, SONAME_LIBNETAPI ); \
+ return; \
+ }
+
+ LOAD_FUNCPTR(libnetapi_init)
+ LOAD_FUNCPTR(libnetapi_free)
+ LOAD_FUNCPTR(libnetapi_set_debuglevel)
+ LOAD_FUNCPTR(libnetapi_set_username)
+ LOAD_FUNCPTR(libnetapi_set_password)
+
+ LOAD_FUNCPTR(NetApiBufferAllocate)
+ LOAD_FUNCPTR(NetApiBufferFree)
+ LOAD_FUNCPTR(NetServerGetInfo)
+ LOAD_FUNCPTR(NetShareAdd)
+ LOAD_FUNCPTR(NetShareDel)
+ LOAD_FUNCPTR(NetWkstaGetInfo)
+#undef LOAD_FUNCPTR
+
+ if ((status = plibnetapi_init( &ctx )))
+ {
+ ERR( "Failed to initialize context, status %u\n", status );
+ return;
+ }
+ if (TRACE_ON(netapi32) && (status = plibnetapi_set_debuglevel( ctx, "10" )))
+ {
+ ERR( "Failed to set debug level, status %u\n", status );
+ plibnetapi_free( ctx );
+ return;
+ }
+ /* perform an anonymous login by default (avoids a password prompt) */
+ if ((status = plibnetapi_set_username( ctx, "Guest" )))
+ {
+ ERR( "Failed to set username, status %u\n", status );
+ plibnetapi_free( ctx );
+ return;
+ }
+ if ((status = plibnetapi_set_password( ctx, "" )))
+ {
+ ERR( "Failed to set password, status %u\n", status );
+ plibnetapi_free( ctx );
+ return;
+ }
+
+ libnetapi_ctx = ctx;
+}
+
+#else
+
+static NET_API_STATUS WINAPI server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+static NET_API_STATUS WINAPI share_add( LMSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err )
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+static NET_API_STATUS WINAPI share_del( LMSTR servername, LMSTR netname, DWORD reserved )
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+static NET_API_STATUS WINAPI wksta_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr )
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+static void libnetapi_init(void)
+{
+}
+
+#endif /* SONAME_LIBNETAPI */
+
+static const struct samba_funcs samba_funcs =
+{
+ server_getinfo,
+ share_add,
+ share_del,
+ wksta_getinfo,
+};
+
+NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+{
+ if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
+
+ libnetapi_init();
+ *(const struct samba_funcs **)ptr_out = &samba_funcs;
+ return STATUS_SUCCESS;
+}
diff --git a/dlls/netapi32/unixlib.h b/dlls/netapi32/unixlib.h
new file mode 100644
index 00000000000..9e84c035965
--- /dev/null
+++ b/dlls/netapi32/unixlib.h
@@ -0,0 +1,27 @@
+/*
+ * Unix library interface
+ *
+ * Copyright 2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+struct samba_funcs
+{
+ NET_API_STATUS (WINAPI *server_getinfo)( const WCHAR *server, DWORD level, BYTE **buffer );
+ NET_API_STATUS (WINAPI *share_add)( const WCHAR *server, DWORD level, const BYTE *buffer, DWORD *err );
+ NET_API_STATUS (WINAPI *share_del)( const WCHAR *server, const WCHAR *share, DWORD reserved );
+ NET_API_STATUS (WINAPI *wksta_getinfo)( const WCHAR *server, DWORD level, BYTE **buffer );
+};
--
2.30.2
More information about the wine-devel
mailing list