- Implement SamOpenUser and SamSetInformationUser.
- Add SamQueryInformationUser stub.

[SAMSRV]
- Implement SamrOpenUser.
- Add a hack to SamrSetInformationUser that enables us to store a users password (as plain-text) in the registry.
- SamrCreateUserInDomain: Fix the creation of user account key names and start counting user RIDs at 1000.
- Clean-up the SAM registry setup code.
- Assingn SIDs to the BUILTIN and Account domains.
- Create the Administrator and Guest accounts in the SAM setup.

svn path=/trunk/; revision=56679
This commit is contained in:
Eric Kohl 2012-05-31 11:07:51 +00:00
parent ecff0e52a3
commit fb25b9f54f
7 changed files with 482 additions and 251 deletions

View file

@ -404,6 +404,7 @@ SamCloseHandle(IN SAM_HANDLE SamHandle)
return Status; return Status;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
SamConnect(IN OUT PUNICODE_STRING ServerName, SamConnect(IN OUT PUNICODE_STRING ServerName,
@ -431,6 +432,7 @@ SamConnect(IN OUT PUNICODE_STRING ServerName,
return Status; return Status;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
SamCreateUserInDomain(IN SAM_HANDLE DomainHandle, SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
@ -461,6 +463,7 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
return Status; return Status;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
SamOpenDomain(IN SAM_HANDLE ServerHandle, SamOpenDomain(IN SAM_HANDLE ServerHandle,
@ -489,6 +492,74 @@ SamOpenDomain(IN SAM_HANDLE ServerHandle,
return Status; return Status;
} }
NTSTATUS
NTAPI
SamOpenUser(IN SAM_HANDLE DomainHandle,
IN ACCESS_MASK DesiredAccess,
IN ULONG UserId,
OUT PSAM_HANDLE UserHandle)
{
NTSTATUS Status;
TRACE("SamOpenUser(%p,0x%08x,%lx,%p)\n",
DomainHandle, DesiredAccess, UserId, UserHandle);
RpcTryExcept
{
Status = SamrOpenUser((SAMPR_HANDLE)DomainHandle,
DesiredAccess,
UserId,
(SAMPR_HANDLE *)UserHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamQueryInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
OUT PVOID *Buffer)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
SamSetInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
IN PVOID Buffer)
{
NTSTATUS Status;
TRACE("SamSetInformationUser(%p %lu %p)\n",
UserHandle, UserInformationClass, Buffer);
RpcTryExcept
{
Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
UserInformationClass,
Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
SamShutdownSamServer(IN SAM_HANDLE ServerHandle) SamShutdownSamServer(IN SAM_HANDLE ServerHandle)

View file

@ -31,12 +31,12 @@
@ stub SamOpenAlias @ stub SamOpenAlias
@ stdcall SamOpenDomain(ptr long ptr ptr) @ stdcall SamOpenDomain(ptr long ptr ptr)
@ stub SamOpenGroup @ stub SamOpenGroup
@ stub SamOpenUser @ stdcall SamOpenUser(ptr long long ptr)
@ stub SamQueryDisplayInformation @ stub SamQueryDisplayInformation
@ stub SamQueryInformationAlias @ stub SamQueryInformationAlias
@ stub SamQueryInformationDomain @ stub SamQueryInformationDomain
@ stub SamQueryInformationGroup @ stub SamQueryInformationGroup
@ stub SamQueryInformationUser @ stdcall SamQueryInformationUser(ptr long ptr)
@ stub SamQuerySecurityObject @ stub SamQuerySecurityObject
@ stub SamRemoveMemberFromAlias @ stub SamRemoveMemberFromAlias
@ stub SamRemoveMemberFromForeignDomain @ stub SamRemoveMemberFromForeignDomain
@ -46,7 +46,7 @@
@ stub SamSetInformationAlias @ stub SamSetInformationAlias
@ stub SamSetInformationDomain @ stub SamSetInformationDomain
@ stub SamSetInformationGroup @ stub SamSetInformationGroup
@ stub SamSetInformationUser @ stdcall SamSetInformationUser(ptr long ptr)
@ stub SamSetMemberAttributesOfGroup @ stub SamSetMemberAttributesOfGroup
@ stub SamSetSecurityObject @ stub SamSetSecurityObject
@ stdcall SamShutdownSamServer(ptr) @ stdcall SamShutdownSamServer(ptr)

View file

@ -337,12 +337,12 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
(LPVOID)&ulRid, (LPVOID)&ulRid,
&ulSize); &ulSize);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
ulRid = DOMAIN_USER_RID_MAX; ulRid = DOMAIN_USER_RID_MAX + 1;
TRACE("RID: %lx\n", ulRid); TRACE("RID: %lx\n", ulRid);
/* Convert the RID into a string (hex) */ /* Convert the RID into a string (hex) */
_ultow(ulRid, szRid, 16); swprintf(szRid, L"%08lX", ulRid);
/* Check whether the user name is already in use */ /* Check whether the user name is already in use */
Status = SampCheckDbObjectNameAlias(DomainObject, Status = SampCheckDbObjectNameAlias(DomainObject,
@ -385,9 +385,9 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
return Status; return Status;
} }
/* Set the account name attribute */ /* Set the name attribute */
Status = SampSetObjectAttribute(UserObject, Status = SampSetObjectAttribute(UserObject,
L"AccountName", L"Name",
REG_SZ, REG_SZ,
(LPVOID)Name->Buffer, (LPVOID)Name->Buffer,
Name->MaximumLength); Name->MaximumLength);
@ -658,12 +658,48 @@ SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
NTSTATUS NTSTATUS
NTAPI NTAPI
SamrOpenUser(IN SAMPR_HANDLE DomainHandle, SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
IN unsigned long DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN unsigned long UserId, IN unsigned long UserId,
OUT SAMPR_HANDLE *UserHandle) OUT SAMPR_HANDLE *UserHandle)
{ {
UNIMPLEMENTED; PSAM_DB_OBJECT DomainObject;
return STATUS_NOT_IMPLEMENTED; PSAM_DB_OBJECT UserObject;
WCHAR szRid[9];
NTSTATUS Status;
TRACE("SamrOpenUser(%p %lx %lx %p)\n",
DomainHandle, DesiredAccess, UserId, UserHandle);
/* 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;
}
/* Convert the RID into a string (hex) */
swprintf(szRid, L"%08lX", UserId);
/* Create the user object */
Status = SampOpenDbObject(DomainObject,
L"Users",
szRid,
SamDbUserObject,
DesiredAccess,
&UserObject);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
*UserHandle = (SAMPR_HANDLE)UserObject;
return STATUS_SUCCESS;
} }
/* Function 35 */ /* Function 35 */
@ -686,6 +722,27 @@ SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
static
NTSTATUS
SampSetPasswordInformation(PSAM_DB_OBJECT UserObject,
PSAMPR_USER_SET_PASSWORD_INFORMATION PasswordInfo)
{
NTSTATUS Status;
TRACE("Password: %S\n", PasswordInfo->Password.Buffer);
TRACE("PasswordExpired: %d\n", PasswordInfo->PasswordExpired);
Status = SampSetObjectAttribute(UserObject,
L"Password",
REG_SZ,
PasswordInfo->Password.Buffer,
PasswordInfo->Password.MaximumLength);
return Status;
}
/* Function 37 */ /* Function 37 */
NTSTATUS NTSTATUS
NTAPI NTAPI
@ -693,8 +750,36 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass, IN USER_INFORMATION_CLASS UserInformationClass,
IN PSAMPR_USER_INFO_BUFFER Buffer) IN PSAMPR_USER_INFO_BUFFER Buffer)
{ {
UNIMPLEMENTED; PSAM_DB_OBJECT UserObject;
return STATUS_NOT_IMPLEMENTED; NTSTATUS Status;
TRACE("SamrSetInformationUser(%p %lu %p)\n",
UserHandle, UserInformationClass, Buffer);
/* Validate the domain handle */
Status = SampValidateDbObject(UserHandle,
SamDbUserObject,
USER_FORCE_PASSWORD_CHANGE,
&UserObject);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
switch (UserInformationClass)
{
case UserSetPasswordInformation:
Status = SampSetPasswordInformation(UserObject,
(PSAMPR_USER_SET_PASSWORD_INFORMATION)Buffer);
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
break;
}
return Status;
} }
/* Function 38 */ /* Function 38 */
@ -848,7 +933,7 @@ NTAPI
SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle, SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
IN PRPC_UNICODE_STRING Name, IN PRPC_UNICODE_STRING Name,
IN unsigned long AccountType, IN unsigned long AccountType,
IN unsigned long DesiredAccess, IN ACCESS_MASK DesiredAccess,
OUT SAMPR_HANDLE *UserHandle, OUT SAMPR_HANDLE *UserHandle,
OUT unsigned long *GrantedAccess, OUT unsigned long *GrantedAccess,
OUT unsigned long *RelativeId) OUT unsigned long *RelativeId)

View file

@ -7,7 +7,7 @@
* PROGRAMMERS: Eric Kohl * PROGRAMMERS: Eric Kohl
*/ */
#include <stdlib.h> #include <stdio.h>
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
#include <windows.h> #include <windows.h>
#define NTOS_MODE_USER #define NTOS_MODE_USER
@ -16,6 +16,7 @@
#include <ndk/rtlfuncs.h> #include <ndk/rtlfuncs.h>
#include <ndk/umtypes.h> #include <ndk/umtypes.h>
#include <ddk/ntsam.h> #include <ddk/ntsam.h>
#include <ntsecapi.h>
#include <samsrv/samsrv.h> #include <samsrv/samsrv.h>

View file

@ -13,6 +13,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(samsrv); WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
/* GLOBALS *****************************************************************/
SID_IDENTIFIER_AUTHORITY SecurityNtAuthority = {SECURITY_NT_AUTHORITY};
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
@ -56,60 +59,220 @@ SampIsSetupRunning(VOID)
static BOOL static BOOL
CreateNamesKey(HKEY hParentKey) SampCreateUserAccount(HKEY hDomainKey,
LPCWSTR lpAccountName,
ULONG ulRelativeId)
{ {
DWORD dwDisposition; DWORD dwDisposition;
HKEY hNamesKey; WCHAR szUserKeyName[32];
HKEY hUserKey = NULL;
HKEY hNamesKey = NULL;
if (RegCreateKeyExW(hParentKey, swprintf(szUserKeyName, L"Users\\%08lX", ulRelativeId);
L"Names",
if (!RegCreateKeyExW(hDomainKey,
szUserKeyName,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hUserKey,
&dwDisposition))
{
RegSetValueEx(hUserKey,
L"Name",
0,
REG_SZ,
(LPVOID)lpAccountName,
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
RegCloseKey(hUserKey);
}
if (!RegOpenKeyExW(hDomainKey,
L"Users\\Names",
0,
KEY_ALL_ACCESS,
&hNamesKey))
{
RegSetValueEx(hNamesKey,
lpAccountName,
0,
REG_DWORD,
(LPVOID)&ulRelativeId,
sizeof(ULONG));
RegCloseKey(hNamesKey);
}
return TRUE;
}
static BOOL
SampCreateDomain(IN HKEY hDomainsKey,
IN LPCWSTR lpDomainName,
IN PSID lpDomainSid,
OUT PHKEY lpDomainKey)
{
DWORD dwDisposition;
HKEY hDomainKey = NULL;
HKEY hAliasKey = NULL;
HKEY hGroupsKey = NULL;
HKEY hUsersKey = NULL;
HKEY hNamesKey = NULL;
if (lpDomainKey != NULL)
*lpDomainKey = NULL;
if (RegCreateKeyExW(hDomainsKey,
lpDomainName,
0, 0,
NULL, NULL,
REG_OPTION_NON_VOLATILE, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, KEY_ALL_ACCESS,
NULL, NULL,
&hNamesKey, &hDomainKey,
&dwDisposition)) &dwDisposition))
return FALSE; return FALSE;
RegCloseKey(hNamesKey); if (lpDomainSid != NULL)
{
RegSetValueEx(hDomainKey,
L"SID",
0,
REG_BINARY,
(LPVOID)lpDomainSid,
RtlLengthSid(lpDomainSid));
}
/* Create the Alias container */
if (!RegCreateKeyExW(hDomainKey,
L"Alias",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hAliasKey,
&dwDisposition))
{
if (!RegCreateKeyExW(hAliasKey,
L"Names",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hNamesKey,
&dwDisposition))
RegCloseKey(hNamesKey);
RegCloseKey(hAliasKey);
}
/* Create the Groups container */
if (!RegCreateKeyExW(hDomainKey,
L"Groups",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hGroupsKey,
&dwDisposition))
{
if (!RegCreateKeyExW(hGroupsKey,
L"Names",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hNamesKey,
&dwDisposition))
RegCloseKey(hNamesKey);
RegCloseKey(hGroupsKey);
}
/* Create the Users container */
if (!RegCreateKeyExW(hDomainKey,
L"Users",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hUsersKey,
&dwDisposition))
{
if (!RegCreateKeyExW(hUsersKey,
L"Names",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hNamesKey,
&dwDisposition))
RegCloseKey(hNamesKey);
RegCloseKey(hUsersKey);
}
if (lpDomainKey != NULL)
*lpDomainKey = hDomainKey;
return TRUE; return TRUE;
} }
static BOOL NTSTATUS
CreateBuiltinAliases(HKEY hAliasesKey) SampGetAccountDomainInfo(PPOLICY_ACCOUNT_DOMAIN_INFO *AccountDomainInfo)
{ {
return TRUE; LSA_OBJECT_ATTRIBUTES ObjectAttributes;
} LSA_HANDLE PolicyHandle;
NTSTATUS Status;
TRACE("SampGetAccountDomainInfo\n");
static BOOL memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
CreateBuiltinGroups(HKEY hGroupsKey) ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
{
return TRUE;
}
Status = LsaOpenPolicy(NULL,
&ObjectAttributes,
POLICY_TRUST_ADMIN,
&PolicyHandle);
if (Status != STATUS_SUCCESS)
{
ERR("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status);
return Status;
}
static BOOL Status = LsaQueryInformationPolicy(PolicyHandle,
CreateBuiltinUsers(HKEY hUsersKey) PolicyAccountDomainInformation,
{ (PVOID *)AccountDomainInfo);
return TRUE;
LsaClose(PolicyHandle);
return Status;
} }
BOOL BOOL
SampInitializeSAM(VOID) SampInitializeSAM(VOID)
{ {
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
DWORD dwDisposition; DWORD dwDisposition;
HKEY hSamKey = NULL; HKEY hSamKey = NULL;
HKEY hDomainsKey = NULL; HKEY hDomainsKey = NULL;
HKEY hAccountKey = NULL; HKEY hDomainKey = NULL;
HKEY hBuiltinKey = NULL; PSID pBuiltinSid = NULL;
HKEY hAliasesKey = NULL;
HKEY hGroupsKey = NULL;
HKEY hUsersKey = NULL;
BOOL bResult = TRUE; BOOL bResult = TRUE;
NTSTATUS Status;
TRACE("SampInitializeSAM() called\n"); TRACE("SampInitializeSAM() called\n");
@ -145,237 +308,60 @@ SampInitializeSAM(VOID)
RegCloseKey(hSamKey); RegCloseKey(hSamKey);
hSamKey = NULL; hSamKey = NULL;
/* Create the 'Domains\\Account' key */ /* Create and initialize the Builtin Domain SID */
if (RegCreateKeyExW(hDomainsKey, pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
L"Account", if (pBuiltinSid == NULL)
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hAccountKey,
&dwDisposition))
{ {
ERR("Failed to create 'Domains\\Account' key! (Error %lu)\n", GetLastError()); ERR("Failed to alloacte the Builtin Domain SID\n");
bResult = FALSE; bResult = FALSE;
goto done; goto done;
} }
RtlInitializeSid(pBuiltinSid, &SecurityNtAuthority, 1);
*(RtlSubAuthoritySid(pBuiltinSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
/* Create the 'Account\Aliases' key */ /* Get account domain information */
if (RegCreateKeyExW(hAccountKey, Status = SampGetAccountDomainInfo(&AccountDomainInfo);
L"Aliases", if (!NT_SUCCESS(Status))
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hAliasesKey,
&dwDisposition))
{ {
ERR("Failed to create 'Account\\Aliases' key! (Error %lu)\n", GetLastError()); ERR("SampGetAccountDomainInfo failed (Status %08lx)\n", Status);
bResult = FALSE; bResult = FALSE;
goto done; goto done;
} }
if (!CreateNamesKey(hAliasesKey)) /* Create the Builtin domain */
if (SampCreateDomain(hDomainsKey,
L"Builtin",
pBuiltinSid,
&hDomainKey))
{ {
ERR("Failed to create 'Account\\Aliases\\Names' key! (Error %lu)\n", GetLastError());
bResult = FALSE; RegCloseKey(hDomainKey);
goto done;
} }
RegCloseKey(hAliasesKey); /* Create the Account domain */
hAliasesKey = NULL; if (SampCreateDomain(hDomainsKey,
L"Account",
/* Create the 'Account\Groups' key */ AccountDomainInfo->DomainSid, //NULL,
if (RegCreateKeyExW(hAccountKey, &hDomainKey))
L"Groups",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hGroupsKey,
&dwDisposition))
{ {
ERR("Failed to create 'Account\\Groups' key! (Error %lu)\n", GetLastError()); SampCreateUserAccount(hDomainKey,
bResult = FALSE; L"Administrator",
goto done; DOMAIN_USER_RID_ADMIN);
}
if (!CreateNamesKey(hGroupsKey)) SampCreateUserAccount(hDomainKey,
{ L"Guest",
ERR("Failed to create 'Account\\Groups\\Names' key! (Error %lu)\n", GetLastError()); DOMAIN_USER_RID_GUEST);
bResult = FALSE;
goto done;
}
RegCloseKey(hGroupsKey); RegCloseKey(hDomainKey);
hGroupsKey = NULL;
/* Create the 'Account\Users' key */
if (RegCreateKeyExW(hAccountKey,
L"Users",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hUsersKey,
&dwDisposition))
{
ERR("Failed to create 'Account\\Users' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
if (!CreateNamesKey(hUsersKey))
{
ERR("Failed to create 'Account\\Aliases\\Users' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
RegCloseKey(hUsersKey);
hUsersKey = NULL;
RegCloseKey(hAccountKey);
hAccountKey = NULL;
/* Create the 'Domains\\Builtin' */
if (RegCreateKeyExW(hDomainsKey,
L"Builtin",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hBuiltinKey,
&dwDisposition))
{
ERR("Failed to create Builtin key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
/* Create the 'Builtin\Aliases' key */
if (RegCreateKeyExW(hBuiltinKey,
L"Aliases",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hAliasesKey,
&dwDisposition))
{
ERR("Failed to create 'Builtin\\Aliases' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
if (!CreateNamesKey(hAliasesKey))
{
ERR("Failed to create 'Builtin\\Aliases\\Names' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
/* Create builtin aliases */
if (!CreateBuiltinAliases(hAliasesKey))
{
ERR("Failed to create builtin aliases!\n");
bResult = FALSE;
goto done;
}
RegCloseKey(hAliasesKey);
hAliasesKey = NULL;
/* Create the 'Builtin\Groups' key */
if (RegCreateKeyExW(hBuiltinKey,
L"Groups",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hGroupsKey,
&dwDisposition))
{
ERR("Failed to create 'Builtin\\Groups' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
if (!CreateNamesKey(hGroupsKey))
{
ERR("Failed to create 'Builtin\\Groups\\Names' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
/* Create builtin groups */
if (!CreateBuiltinGroups(hGroupsKey))
{
ERR("Failed to create builtin groups!\n");
bResult = FALSE;
goto done;
}
RegCloseKey(hGroupsKey);
hGroupsKey = NULL;
/* Create the 'Builtin\Users' key */
if (RegCreateKeyExW(hBuiltinKey,
L"Users",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hUsersKey,
&dwDisposition))
{
ERR("Failed to create 'Builtin\\Users' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
if (!CreateNamesKey(hUsersKey))
{
ERR("Failed to create 'Builtin\\Users\\Names' key! (Error %lu)\n", GetLastError());
bResult = FALSE;
goto done;
}
/* Create builtin users */
if (!CreateBuiltinUsers(hUsersKey))
{
ERR("Failed to create builtin users!\n");
bResult = FALSE;
goto done;
} }
done: done:
if (hAliasesKey) if (AccountDomainInfo)
RegCloseKey(hAliasesKey); LsaFreeMemory(AccountDomainInfo);
if (hGroupsKey) if (pBuiltinSid)
RegCloseKey(hGroupsKey); RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
if (hUsersKey)
RegCloseKey(hUsersKey);
if (hAccountKey)
RegCloseKey(hAccountKey);
if (hBuiltinKey)
RegCloseKey(hBuiltinKey);
if (hDomainsKey) if (hDomainsKey)
RegCloseKey(hDomainsKey); RegCloseKey(hDomainsKey);

View file

@ -25,9 +25,60 @@ extern "C" {
#define SAM_SERVER_ENUMERATE_DOMAINS 16 #define SAM_SERVER_ENUMERATE_DOMAINS 16
#define SAM_SERVER_LOOKUP_DOMAIN 32 #define SAM_SERVER_LOOKUP_DOMAIN 32
#define USER_READ_GENERAL 1
#define USER_READ_PREFERENCES 2
#define USER_WRITE_PREFERENCES 4
#define USER_READ_LOGON 8
#define USER_READ_ACCOUNT 16
#define USER_WRITE_ACCOUNT 32
#define USER_CHANGE_PASSWORD 64
#define USER_FORCE_PASSWORD_CHANGE 128
#define USER_LIST_GROUPS 256
#define USER_READ_GROUP_INFORMATION 512
#define USER_WRITE_GROUP_INFORMATION 1024
typedef PVOID SAM_HANDLE, *PSAM_HANDLE; typedef PVOID SAM_HANDLE, *PSAM_HANDLE;
typedef enum _USER_INFORMATION_CLASS
{
UserGeneralInformation = 1,
UserPreferencesInformation,
UserLogonInformation,
UserLogonHoursInformation,
UserAccountInformation,
UserNameInformation,
UserAccountNameInformation,
UserFullNameInformation,
UserPrimaryGroupInformation,
UserHomeInformation,
UserScriptInformation,
UserProfileInformation,
UserAdminCommentInformation,
UserWorkStationsInformation,
UserSetPasswordInformation,
UserControlInformation,
UserExpiresInformation,
UserInternal1Information,
UserInternal2Information,
UserParametersInformation,
UserAllInformation,
UserInternal3Information,
UserInternal4Information,
UserInternal5Information,
UserInternal4InformationNew,
UserInternal5InformationNew,
UserInternal6Information,
UserExtendedInformation,
UserLogonUIInformation,
} USER_INFORMATION_CLASS, *PUSER_INFORMATION_CLASS;
typedef struct _USER_SET_PASSWORD_INFORMATION
{
UNICODE_STRING Password;
BOOLEAN PasswordExpired;
} USER_SET_PASSWORD_INFORMATION, *PUSER_SET_PASSWORD_INFORMATION;
NTSTATUS NTSTATUS
NTAPI NTAPI
SamCloseHandle(IN SAM_HANDLE SamHandle); SamCloseHandle(IN SAM_HANDLE SamHandle);
@ -54,6 +105,25 @@ SamOpenDomain(IN SAM_HANDLE ServerHandle,
IN PSID DomainId, IN PSID DomainId,
OUT PSAM_HANDLE DomainHandle); OUT PSAM_HANDLE DomainHandle);
NTSTATUS
NTAPI
SamOpenUser(IN SAM_HANDLE DomainHandle,
IN ACCESS_MASK DesiredAccess,
IN ULONG UserId,
OUT PSAM_HANDLE UserHandle);
NTSTATUS
NTAPI
SamQueryInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
OUT PVOID *Buffer);
NTSTATUS
NTAPI
SamSetInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
IN PVOID Buffer);
NTSTATUS NTSTATUS
NTAPI NTAPI
SamShutdownSamServer(IN SAM_HANDLE ServerHandle); SamShutdownSamServer(IN SAM_HANDLE ServerHandle);

View file

@ -152,6 +152,7 @@ typedef enum _DOMAIN_SERVER_ROLE
DomainServerRolePrimary = 3 DomainServerRolePrimary = 3
} DOMAIN_SERVER_ROLE, *PDOMAIN_SERVER_ROLE; } DOMAIN_SERVER_ROLE, *PDOMAIN_SERVER_ROLE;
cpp_quote("#ifndef _NTSECAPI_H")
typedef struct _DOMAIN_PASSWORD_INFORMATION typedef struct _DOMAIN_PASSWORD_INFORMATION
{ {
unsigned short MinPasswordLength; unsigned short MinPasswordLength;
@ -160,6 +161,7 @@ typedef struct _DOMAIN_PASSWORD_INFORMATION
OLD_LARGE_INTEGER MaxPasswordAge; OLD_LARGE_INTEGER MaxPasswordAge;
OLD_LARGE_INTEGER MinPasswordAge; OLD_LARGE_INTEGER MinPasswordAge;
} DOMAIN_PASSWORD_INFORMATION, *PDOMAIN_PASSWORD_INFORMATION; } DOMAIN_PASSWORD_INFORMATION, *PDOMAIN_PASSWORD_INFORMATION;
cpp_quote("#endif")
typedef struct _DOMAIN_LOGOFF_INFORMATION typedef struct _DOMAIN_LOGOFF_INFORMATION
{ {
@ -600,6 +602,13 @@ typedef struct _SAMPR_USER_WORKSTATIONS_INFORMATION
RPC_UNICODE_STRING WorkStations; RPC_UNICODE_STRING WorkStations;
} SAMPR_USER_WORKSTATIONS_INFORMATION, *PSAMPR_USER_WORKSTATIONS_INFORMATION; } SAMPR_USER_WORKSTATIONS_INFORMATION, *PSAMPR_USER_WORKSTATIONS_INFORMATION;
typedef struct _SAMPR_USER_SET_PASSWORD_INFORMATION
{
// SAMPR_ENCRYPTED_USER_PASSWORD Password;
RPC_UNICODE_STRING Password;
BOOLEAN PasswordExpired;
} SAMPR_USER_SET_PASSWORD_INFORMATION, *PSAMPR_USER_SET_PASSWORD_INFORMATION;
typedef struct _SAMPR_USER_LOGON_HOURS_INFORMATION typedef struct _SAMPR_USER_LOGON_HOURS_INFORMATION
{ {
SAMPR_LOGON_HOURS LogonHours; SAMPR_LOGON_HOURS LogonHours;
@ -638,6 +647,7 @@ typedef struct _SAMPR_USER_INTERNAL5_INFORMATION_NEW
unsigned char PasswordExpired; unsigned char PasswordExpired;
} SAMPR_USER_INTERNAL5_INFORMATION_NEW, *PSAMPR_USER_INTERNAL5_INFORMATION_NEW; } SAMPR_USER_INTERNAL5_INFORMATION_NEW, *PSAMPR_USER_INTERNAL5_INFORMATION_NEW;
cpp_quote("#ifndef _NTSAM_")
typedef enum _USER_INFORMATION_CLASS typedef enum _USER_INFORMATION_CLASS
{ {
UserGeneralInformation = 1, UserGeneralInformation = 1,
@ -654,16 +664,23 @@ typedef enum _USER_INFORMATION_CLASS
UserProfileInformation = 12, UserProfileInformation = 12,
UserAdminCommentInformation = 13, UserAdminCommentInformation = 13,
UserWorkStationsInformation = 14, UserWorkStationsInformation = 14,
UserSetPasswordInformation = 15, /* This is missing from the SAM RPC documentation */
UserControlInformation = 16, UserControlInformation = 16,
UserExpiresInformation = 17, UserExpiresInformation = 17,
UserInternal1Information = 18, UserInternal1Information = 18,
UserInternal2Information = 19, /* This is missing from the SAM RPC documentation */
UserParametersInformation = 20, UserParametersInformation = 20,
UserAllInformation = 21, UserAllInformation = 21,
UserInternal3Information = 22, /* This is missing from the SAM RPC documentation */
UserInternal4Information = 23, UserInternal4Information = 23,
UserInternal5Information = 24, UserInternal5Information = 24,
UserInternal4InformationNew = 25, UserInternal4InformationNew = 25,
UserInternal5InformationNew = 26, UserInternal5InformationNew = 26,
UserInternal6Information, /* This is missing from the SAM RPC documentation */
UserExtendedInformation, /* This is missing from the SAM RPC documentation */
UserLogonUIInformation, /* This is missing from the SAM RPC documentation */
} USER_INFORMATION_CLASS, *PUSER_INFORMATION_CLASS; } USER_INFORMATION_CLASS, *PUSER_INFORMATION_CLASS;
cpp_quote("#endif")
typedef [switch_type(USER_INFORMATION_CLASS)] union _SAMPR_USER_INFO_BUFFER typedef [switch_type(USER_INFORMATION_CLASS)] union _SAMPR_USER_INFO_BUFFER
{ {
@ -681,6 +698,7 @@ typedef [switch_type(USER_INFORMATION_CLASS)] union _SAMPR_USER_INFO_BUFFER
[case(UserProfileInformation)] SAMPR_USER_PROFILE_INFORMATION Profile; [case(UserProfileInformation)] SAMPR_USER_PROFILE_INFORMATION Profile;
[case(UserAdminCommentInformation)] SAMPR_USER_ADMIN_COMMENT_INFORMATION AdminComment; [case(UserAdminCommentInformation)] SAMPR_USER_ADMIN_COMMENT_INFORMATION AdminComment;
[case(UserWorkStationsInformation)] SAMPR_USER_WORKSTATIONS_INFORMATION WorkStations; [case(UserWorkStationsInformation)] SAMPR_USER_WORKSTATIONS_INFORMATION WorkStations;
[case(UserSetPasswordInformation)] SAMPR_USER_SET_PASSWORD_INFORMATION SetPassword;
[case(UserControlInformation)] USER_CONTROL_INFORMATION Control; [case(UserControlInformation)] USER_CONTROL_INFORMATION Control;
[case(UserExpiresInformation)] USER_EXPIRES_INFORMATION Expires; [case(UserExpiresInformation)] USER_EXPIRES_INFORMATION Expires;
[case(UserInternal1Information)] SAMPR_USER_INTERNAL1_INFORMATION Internal1; [case(UserInternal1Information)] SAMPR_USER_INTERNAL1_INFORMATION Internal1;
@ -1015,7 +1033,7 @@ interface samr
__stdcall __stdcall
SamrOpenAlias( SamrOpenAlias(
[in] SAMPR_HANDLE DomainHandle, [in] SAMPR_HANDLE DomainHandle,
[in] unsigned long DesiredAccess, [in] ACCESS_MASK DesiredAccess,
[in] unsigned long AliasId, [in] unsigned long AliasId,
[out] SAMPR_HANDLE *AliasHandle); [out] SAMPR_HANDLE *AliasHandle);
@ -1067,7 +1085,7 @@ interface samr
__stdcall __stdcall
SamrOpenUser( SamrOpenUser(
[in] SAMPR_HANDLE DomainHandle, [in] SAMPR_HANDLE DomainHandle,
[in] unsigned long DesiredAccess, [in] ACCESS_MASK DesiredAccess,
[in] unsigned long UserId, [in] unsigned long UserId,
[out] SAMPR_HANDLE *UserHandle); [out] SAMPR_HANDLE *UserHandle);
@ -1209,7 +1227,7 @@ interface samr
[in] SAMPR_HANDLE DomainHandle, [in] SAMPR_HANDLE DomainHandle,
[in] PRPC_UNICODE_STRING Name, [in] PRPC_UNICODE_STRING Name,
[in] unsigned long AccountType, [in] unsigned long AccountType,
[in] unsigned long DesiredAccess, [in] ACCESS_MASK DesiredAccess,
[out] SAMPR_HANDLE *UserHandle, [out] SAMPR_HANDLE *UserHandle,
[out] unsigned long *GrantedAccess, [out] unsigned long *GrantedAccess,
[out] unsigned long *RelativeId); [out] unsigned long *RelativeId);