Author: ekohl
Date: Wed Aug 8 21:17:17 2012
New Revision: 57054
URL:
http://svn.reactos.org/svn/reactos?rev=57054&view=rev
Log:
[SAMLIB/SAMSRV]
Implement SamCreateUser2InDomain / SamrCreateUser2InDomain (untested) and
SamLookupNamesInDomain / SamrLookupNamesInDomain.
Modified:
trunk/reactos/dll/win32/samlib/samlib.c
trunk/reactos/dll/win32/samlib/samlib.spec
trunk/reactos/dll/win32/samsrv/samrpc.c
trunk/reactos/include/ddk/ntsam.h
Modified: trunk/reactos/dll/win32/samlib/samlib.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samlib/samlib.c?…
==============================================================================
--- trunk/reactos/dll/win32/samlib/samlib.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samlib/samlib.c [iso-8859-1] Wed Aug 8 21:17:17 2012
@@ -191,6 +191,9 @@
TRACE("SamCreateAliasInDomain(%p %p 0x%08x %p %p)\n",
DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
+ *AliasHandle = NULL;
+ *RelativeId = 0;
+
RpcTryExcept
{
Status = SamrCreateAliasInDomain((SAMPR_HANDLE)DomainHandle,
@@ -222,6 +225,9 @@
TRACE("SamCreateGroupInDomain(%p %p 0x%08x %p %p)\n",
DomainHandle, AccountName, DesiredAccess, GroupHandle, RelativeId);
+ *GroupHandle = NULL;
+ *RelativeId = 0;
+
RpcTryExcept
{
Status = SamrCreateGroupInDomain((SAMPR_HANDLE)DomainHandle,
@@ -242,6 +248,46 @@
NTSTATUS
NTAPI
+SamCreateUser2InDomain(IN SAM_HANDLE DomainHandle,
+ IN PUNICODE_STRING AccountName,
+ IN ULONG AccountType,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PSAM_HANDLE UserHandle,
+ OUT PULONG GrantedAccess,
+ OUT PULONG RelativeId)
+{
+ NTSTATUS Status;
+
+ TRACE("SamCreateUser2InDomain(%p %p %lu 0x%08x %p %p %p)\n",
+ DomainHandle, AccountName, AccountType, DesiredAccess,
+ UserHandle, GrantedAccess, RelativeId);
+
+ *UserHandle = NULL;
+ *RelativeId = 0;
+
+ RpcTryExcept
+ {
+ Status = SamrCreateUser2InDomain((SAMPR_HANDLE)DomainHandle,
+ (PRPC_UNICODE_STRING)AccountName,
+ AccountType,
+ DesiredAccess,
+ (SAMPR_HANDLE *)UserHandle,
+ GrantedAccess,
+ RelativeId);
+
+ }
+ RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = I_RpcMapWin32Status(RpcExceptionCode());
+ }
+ RpcEndExcept;
+
+ return Status;
+}
+
+
+NTSTATUS
+NTAPI
SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
IN PUNICODE_STRING AccountName,
IN ACCESS_MASK DesiredAccess,
@@ -252,6 +298,9 @@
TRACE("SamCreateUserInDomain(%p %p 0x%08x %p %p)\n",
DomainHandle, AccountName, DesiredAccess, UserHandle, RelativeId);
+
+ *UserHandle = NULL;
+ *RelativeId = 0;
RpcTryExcept
{
@@ -605,8 +654,75 @@
OUT PULONG *RelativeIds,
OUT PSID_NAME_USE *Use)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ SAMPR_ULONG_ARRAY RidBuffer = {0, NULL};
+ SAMPR_ULONG_ARRAY UseBuffer = {0, NULL};
+ NTSTATUS Status;
+
+ TRACE("SamLookupNamesInDomain(%p %lu %p %p %p)\n",
+ DomainHandle, Count, Names, RelativeIds, Use);
+
+ *RelativeIds = NULL;
+ *Use = NULL;
+
+ RidBuffer.Element = NULL;
+ UseBuffer.Element = NULL;
+
+ RpcTryExcept
+ {
+ Status = SamrLookupNamesInDomain((SAMPR_HANDLE)DomainHandle,
+ Count,
+ (PRPC_UNICODE_STRING)Names,
+ &RidBuffer,
+ &UseBuffer);
+ }
+ RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = I_RpcMapWin32Status(RpcExceptionCode());
+ }
+ RpcEndExcept;
+
+ if (NT_SUCCESS(Status))
+ {
+ *RelativeIds = midl_user_allocate(Count * sizeof(ULONG));
+ if (*RelativeIds == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ *Use = midl_user_allocate(Count * sizeof(SID_NAME_USE));
+ if (*Use == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ RtlCopyMemory(*RelativeIds,
+ RidBuffer.Element,
+ Count * sizeof(ULONG));
+
+ RtlCopyMemory(*Use,
+ UseBuffer.Element,
+ Count * sizeof(SID_NAME_USE));
+ }
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (*RelativeIds != NULL)
+ midl_user_free(*RelativeIds);
+
+ if (*Use != NULL)
+ midl_user_free(*Use);
+ }
+
+ if (RidBuffer.Element != NULL)
+ midl_user_free(RidBuffer.Element);
+
+ if (UseBuffer.Element != NULL)
+ midl_user_free(UseBuffer.Element);
+
+ return Status;
}
Modified: trunk/reactos/dll/win32/samlib/samlib.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samlib/samlib.sp…
==============================================================================
--- trunk/reactos/dll/win32/samlib/samlib.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samlib/samlib.spec [iso-8859-1] Wed Aug 8 21:17:17 2012
@@ -9,7 +9,7 @@
@ stub SamConnectWithCreds
@ stdcall SamCreateAliasInDomain(ptr ptr long ptr ptr)
@ stdcall SamCreateGroupInDomain(ptr ptr long ptr ptr)
-@ stub SamCreateUser2InDomain
+@ stdcall SamCreateUser2InDomain(ptr ptr long long ptr ptr ptr)
@ stdcall SamCreateUserInDomain(ptr ptr long ptr ptr)
@ stub SamDeleteAlias
@ stub SamDeleteGroup
Modified: trunk/reactos/dll/win32/samsrv/samrpc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/samrpc.c?…
==============================================================================
--- trunk/reactos/dll/win32/samsrv/samrpc.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samsrv/samrpc.c [iso-8859-1] Wed Aug 8 21:17:17 2012
@@ -2840,14 +2840,211 @@
NTSTATUS
NTAPI
SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
- IN unsigned long Count,
+ IN ULONG Count,
IN RPC_UNICODE_STRING Names[],
OUT PSAMPR_ULONG_ARRAY RelativeIds,
OUT PSAMPR_ULONG_ARRAY Use)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ PSAM_DB_OBJECT DomainObject;
+ HANDLE AccountsKeyHandle;
+ HANDLE NamesKeyHandle;
+ ULONG MappedCount = 0;
+ ULONG DataLength;
+ ULONG i;
+ ULONG RelativeId;
+ NTSTATUS Status;
+
+ TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n",
+ DomainHandle, Count, Names, RelativeIds, Use);
+
+ /* Validate the domain handle */
+ Status = SampValidateDbObject(DomainHandle,
+ SamDbDomainObject,
+ DOMAIN_LOOKUP,
+ &DomainObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ RelativeIds->Count = 0;
+ Use->Count = 0;
+
+ if (Count == 0)
+ return STATUS_SUCCESS;
+
+ /* Allocate the relative IDs array */
+ RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG));
+ if (RelativeIds->Element == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ /* Allocate the use array */
+ Use->Element = midl_user_allocate(Count * sizeof(ULONG));
+ if (Use->Element == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ RelativeIds->Count = Count;
+ Use->Count = Count;
+
+ for (i = 0; i < Count; i++)
+ {
+ TRACE("Name: %S\n", Names[i].Buffer);
+
+ RelativeId = 0;
+
+ /* Lookup aliases */
+ Status = SampRegOpenKey(DomainObject->KeyHandle,
+ L"Aliases",
+ KEY_READ,
+ &AccountsKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ Status = SampRegOpenKey(AccountsKeyHandle,
+ L"Names",
+ KEY_READ,
+ &NamesKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ DataLength = sizeof(ULONG);
+ Status = SampRegQueryValue(NamesKeyHandle,
+ Names[i].Buffer,
+ NULL,
+ &RelativeId,
+ &DataLength);
+
+ SampRegCloseKey(NamesKeyHandle);
+ }
+
+ SampRegCloseKey(AccountsKeyHandle);
+ }
+
+ /* Return alias account */
+ if (NT_SUCCESS(Status) && RelativeId != 0)
+ {
+ TRACE("Rid: %lu\n", RelativeId);
+ RelativeIds->Element[i] = RelativeId;
+ Use->Element[i] = SidTypeAlias;
+ MappedCount++;
+ continue;
+ }
+
+ /* Lookup groups */
+ Status = SampRegOpenKey(DomainObject->KeyHandle,
+ L"Groups",
+ KEY_READ,
+ &AccountsKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ Status = SampRegOpenKey(AccountsKeyHandle,
+ L"Names",
+ KEY_READ,
+ &NamesKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ DataLength = sizeof(ULONG);
+ Status = SampRegQueryValue(NamesKeyHandle,
+ Names[i].Buffer,
+ NULL,
+ &RelativeId,
+ &DataLength);
+
+ SampRegCloseKey(NamesKeyHandle);
+ }
+
+ SampRegCloseKey(AccountsKeyHandle);
+ }
+
+ /* Return group account */
+ if (NT_SUCCESS(Status) && RelativeId != 0)
+ {
+ TRACE("Rid: %lu\n", RelativeId);
+ RelativeIds->Element[i] = RelativeId;
+ Use->Element[i] = SidTypeGroup;
+ MappedCount++;
+ continue;
+ }
+
+ /* Lookup users */
+ Status = SampRegOpenKey(DomainObject->KeyHandle,
+ L"Users",
+ KEY_READ,
+ &AccountsKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ Status = SampRegOpenKey(AccountsKeyHandle,
+ L"Names",
+ KEY_READ,
+ &NamesKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ DataLength = sizeof(ULONG);
+ Status = SampRegQueryValue(NamesKeyHandle,
+ Names[i].Buffer,
+ NULL,
+ &RelativeId,
+ &DataLength);
+
+ SampRegCloseKey(NamesKeyHandle);
+ }
+
+ SampRegCloseKey(AccountsKeyHandle);
+ }
+
+ /* Return user account */
+ if (NT_SUCCESS(Status) && RelativeId != 0)
+ {
+ TRACE("Rid: %lu\n", RelativeId);
+ RelativeIds->Element[i] = RelativeId;
+ Use->Element[i] = SidTypeUser;
+ MappedCount++;
+ continue;
+ }
+
+ /* Return unknown account */
+ RelativeIds->Element[i] = 0;
+ Use->Element[i] = SidTypeUnknown;
+ }
+
+done:
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ Status = STATUS_SUCCESS;
+
+ if (NT_SUCCESS(Status))
+ {
+ if (MappedCount == 0)
+ Status = STATUS_NONE_MAPPED;
+ else if (MappedCount < Count)
+ Status = STATUS_SOME_NOT_MAPPED;
+ }
+ else
+ {
+ if (RelativeIds->Element != NULL)
+ {
+ midl_user_free(RelativeIds->Element);
+ RelativeIds->Element = NULL;
+ }
+
+ RelativeIds->Count = 0;
+
+ if (Use->Element != NULL)
+ {
+ midl_user_free(Use->Element);
+ Use->Element = NULL;
+ }
+
+ Use->Count = 0;
+ }
+
+ return Status;
+}
+
/* Function 18 */
NTSTATUS
@@ -5546,6 +5743,7 @@
return STATUS_NOT_IMPLEMENTED;
}
+
/* Function 50 */
NTSTATUS
NTAPI
@@ -5557,8 +5755,260 @@
OUT unsigned long *GrantedAccess,
OUT unsigned long *RelativeId)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
+ SAM_DOMAIN_FIXED_DATA FixedDomainData;
+ SAM_USER_FIXED_DATA FixedUserData;
+ PSAM_DB_OBJECT DomainObject;
+ PSAM_DB_OBJECT UserObject;
+ ULONG ulSize;
+ ULONG ulRid;
+ WCHAR szRid[9];
+ NTSTATUS Status;
+
+ TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
+ DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
+
+ if (Name == NULL ||
+ Name->Length == 0 ||
+ Name->Buffer == NULL ||
+ UserHandle == NULL ||
+ RelativeId == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Check for valid account type */
+ if (AccountType != USER_NORMAL_ACCOUNT &&
+ AccountType != USER_WORKSTATION_TRUST_ACCOUNT &&
+ AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT &&
+ AccountType != USER_SERVER_TRUST_ACCOUNT &&
+ AccountType != USER_TEMP_DUPLICATE_ACCOUNT)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Validate the domain handle */
+ Status = SampValidateDbObject(DomainHandle,
+ SamDbDomainObject,
+ DOMAIN_CREATE_USER,
+ &DomainObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Check if the user name already exists in the domain */
+ Status = SampCheckAccountNameInDomain(DomainObject,
+ Name->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("User name \'%S\' already exists in domain (Status
0x%08lx)\n",
+ Name->Buffer, Status);
+ return Status;
+ }
+
+ /* Get the fixed domain attributes */
+ ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
+ Status = SampGetObjectAttribute(DomainObject,
+ L"F",
+ NULL,
+ (PVOID)&FixedDomainData,
+ &ulSize);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Increment the NextRid attribute */
+ ulRid = FixedDomainData.NextRid;
+ FixedDomainData.NextRid++;
+
+ /* Store the fixed domain attributes */
+ Status = SampSetObjectAttribute(DomainObject,
+ L"F",
+ REG_BINARY,
+ &FixedDomainData,
+ ulSize);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ TRACE("RID: %lx\n", ulRid);
+
+ /* Convert the RID into a string (hex) */
+ swprintf(szRid, L"%08lX", ulRid);
+
+ /* Create the user object */
+ Status = SampCreateDbObject(DomainObject,
+ L"Users",
+ szRid,
+ SamDbUserObject,
+ DesiredAccess,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Add the account name for the user object */
+ Status = SampSetAccountNameInDomain(DomainObject,
+ L"Users",
+ Name->Buffer,
+ ulRid);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Initialize fixed user data */
+ memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
+ FixedUserData.Version = 1;
+ FixedUserData.LastLogon.QuadPart = 0;
+ FixedUserData.LastLogoff.QuadPart = 0;
+ FixedUserData.PasswordLastSet.QuadPart = 0;
+ FixedUserData.AccountExpires.LowPart = MAXULONG;
+ FixedUserData.AccountExpires.HighPart = MAXLONG;
+ FixedUserData.LastBadPasswordTime.QuadPart = 0;
+ FixedUserData.UserId = ulRid;
+ FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
+ FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
+ USER_PASSWORD_NOT_REQUIRED |
+ AccountType;
+
+ /* Set fixed user data attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"F",
+ REG_BINARY,
+ (LPVOID)&FixedUserData,
+ sizeof(SAM_USER_FIXED_DATA));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the Name attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"Name",
+ REG_SZ,
+ (LPVOID)Name->Buffer,
+ Name->MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the FullName attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"FullName",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the HomeDirectory attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"HomeDirectory",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the HomeDirectoryDrive attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"HomeDirectoryDrive",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the ScriptPath attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"ScriptPath",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the ProfilePath attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"ProfilePath",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the AdminComment attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"AdminComment",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the UserComment attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"UserComment",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set the WorkStations attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"WorkStations",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* FIXME: Set default user attributes */
+
+ if (NT_SUCCESS(Status))
+ {
+ *UserHandle = (SAMPR_HANDLE)UserObject;
+ *RelativeId = ulRid;
+ *GrantedAccess = UserObject->Access;
+ }
+
+ TRACE("returns with status 0x%08lx\n", Status);
+
+ return Status;
}
/* Function 51 */
Modified: trunk/reactos/include/ddk/ntsam.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/ntsam.h?rev=57…
==============================================================================
--- trunk/reactos/include/ddk/ntsam.h [iso-8859-1] (original)
+++ trunk/reactos/include/ddk/ntsam.h [iso-8859-1] Wed Aug 8 21:17:17 2012
@@ -351,6 +351,16 @@
NTSTATUS
NTAPI
+SamCreateUser2InDomain(IN SAM_HANDLE DomainHandle,
+ IN PUNICODE_STRING AccountName,
+ IN ULONG AccountType,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PSAM_HANDLE UserHandle,
+ OUT PULONG GrantedAccess,
+ OUT PULONG RelativeId);
+
+NTSTATUS
+NTAPI
SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
IN PUNICODE_STRING AccountName,
IN ACCESS_MASK DesiredAccess,