OUT unsigned long *RelativeId)
{
SAM_DOMAIN_FIXED_DATA FixedDomainData;
+ SAM_USER_FIXED_DATA FixedUserData;
PSAM_DB_OBJECT DomainObject;
PSAM_DB_OBJECT UserObject;
ULONG ulSize;
return Status;
}
+ /* Initialize fixed user data */
+ memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
+ FixedUserData.Version = 1;
+
+ FixedUserData.UserId = ulRid;
+
+ /* 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",
return STATUS_NOT_IMPLEMENTED;
}
+
static
NTSTATUS
SampQueryUserName(PSAM_DB_OBJECT UserObject,
PSAMPR_USER_INFO_BUFFER *Buffer)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-/* Function 36 */
-NTSTATUS
-NTAPI
-SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
- IN USER_INFORMATION_CLASS UserInformationClass,
- OUT PSAMPR_USER_INFO_BUFFER *Buffer)
-{
- PSAM_DB_OBJECT UserObject;
- ACCESS_MASK DesiredAccess;
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
NTSTATUS Status;
- TRACE("SamrQueryInformationUser(%p %lu %p)\n",
- UserHandle, UserInformationClass, Buffer);
+ *Buffer = NULL;
- switch (UserInformationClass)
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = SampGetObjectAttribute(UserObject,
+ L"Name",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
{
- case UserGeneralInformation:
- case UserNameInformation:
- case UserAccountNameInformation:
- case UserFullNameInformation:
- case UserPrimaryGroupInformation:
- case UserAdminCommentInformation:
- DesiredAccess = USER_READ_GENERAL;
- break;
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+ InfoBuffer->Name.UserName.Length = Length - sizeof(WCHAR);
+ InfoBuffer->Name.UserName.MaximumLength = Length;
+ InfoBuffer->Name.UserName.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->Name.UserName.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
- default:
- return STATUS_INVALID_INFO_CLASS;
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"Name",
+ NULL,
+ (PVOID)InfoBuffer->Name.UserName.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
}
- /* Validate the domain handle */
- Status = SampValidateDbObject(UserHandle,
- SamDbUserObject,
- DesiredAccess,
- &UserObject);
+ Length = 0;
+ Status = SampGetObjectAttribute(UserObject,
+ L"FullName",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->Name.FullName.Length = Length - sizeof(WCHAR);
+ InfoBuffer->Name.FullName.MaximumLength = Length;
+ InfoBuffer->Name.FullName.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->Name.FullName.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"FullName",
+ NULL,
+ (PVOID)InfoBuffer->Name.FullName.Buffer,
+ &Length);
if (!NT_SUCCESS(Status))
{
- TRACE("failed with status 0x%08lx\n", Status);
- return Status;
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
}
- switch (UserInformationClass)
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
{
- case UserNameInformation:
- Status = SampQueryUserName(UserObject,
- Buffer);
- break;
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->Name.UserName.Buffer != NULL)
+ midl_user_free(InfoBuffer->Name.UserName.Buffer);
- default:
- Status = STATUS_INVALID_INFO_CLASS;
+ if (InfoBuffer->Name.FullName.Buffer != NULL)
+ midl_user_free(InfoBuffer->Name.FullName.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
}
return Status;
}
-/* Function 37 */
-NTSTATUS
-NTAPI
-SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
- IN USER_INFORMATION_CLASS UserInformationClass,
- IN PSAMPR_USER_INFO_BUFFER Buffer)
+
+static NTSTATUS
+SampQueryUserAccountName(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
{
- PSAM_DB_OBJECT UserObject;
- ACCESS_MASK DesiredAccess;
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
NTSTATUS Status;
- TRACE("SamrSetInformationUser(%p %lu %p)\n",
- UserHandle, UserInformationClass, Buffer);
+ *Buffer = NULL;
- switch (UserInformationClass)
- {
- case UserNameInformation:
- case UserAccountNameInformation:
- case UserFullNameInformation:
- case UserPrimaryGroupInformation:
- case UserHomeInformation:
- case UserScriptInformation:
- case UserProfileInformation:
- case UserAdminCommentInformation:
- case UserWorkStationsInformation:
- case UserControlInformation:
- case UserExpiresInformation:
- DesiredAccess = USER_WRITE_ACCOUNT;
- break;
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
- case UserSetPasswordInformation:
- DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
- break;
+ Status = SampGetObjectAttribute(UserObject,
+ L"Name",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
- default:
- return STATUS_INVALID_INFO_CLASS;
+ InfoBuffer->AccountName.UserName.Length = Length - sizeof(WCHAR);
+ InfoBuffer->AccountName.UserName.MaximumLength = Length;
+ InfoBuffer->AccountName.UserName.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->AccountName.UserName.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
}
- /* Validate the domain handle */
- Status = SampValidateDbObject(UserHandle,
- SamDbUserObject,
- DesiredAccess,
- &UserObject);
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"Name",
+ NULL,
+ (PVOID)InfoBuffer->AccountName.UserName.Buffer,
+ &Length);
if (!NT_SUCCESS(Status))
{
- TRACE("failed with status 0x%08lx\n", Status);
- return Status;
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
}
- switch (UserInformationClass)
- {
-// case UserGeneralInformation:
-// case UserPreferencesInformation:
-// case UserLogonHoursInformation:
+ *Buffer = InfoBuffer;
- case UserNameInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"Name",
- REG_SZ,
- Buffer->Name.UserName.Buffer,
- Buffer->Name.UserName.MaximumLength);
- if (!NT_SUCCESS(Status))
- break;
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->AccountName.UserName.Buffer != NULL)
+ midl_user_free(InfoBuffer->AccountName.UserName.Buffer);
- Status = SampSetObjectAttribute(UserObject,
- L"FullName",
- REG_SZ,
- Buffer->Name.FullName.Buffer,
- Buffer->Name.FullName.MaximumLength);
- break;
+ midl_user_free(InfoBuffer);
+ }
+ }
- case UserAccountNameInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"Name",
- REG_SZ,
- Buffer->AccountName.UserName.Buffer,
- Buffer->AccountName.UserName.MaximumLength);
- break;
+ return Status;
+}
- case UserFullNameInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"FullName",
- REG_SZ,
- Buffer->FullName.FullName.Buffer,
- Buffer->FullName.FullName.MaximumLength);
- break;
- case UserPrimaryGroupInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"PrimaryGroupId",
- REG_DWORD,
- &Buffer->PrimaryGroup.PrimaryGroupId,
- sizeof(ULONG));
- break;
+static NTSTATUS
+SampQueryUserFullName(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status;
- case UserHomeInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"HomeDirectory",
- REG_SZ,
- Buffer->Home.HomeDirectory.Buffer,
- Buffer->Home.HomeDirectory.MaximumLength);
- if (!NT_SUCCESS(Status))
- break;
+ *Buffer = NULL;
- Status = SampSetObjectAttribute(UserObject,
- L"HomeDirectoryDrive",
- REG_SZ,
- Buffer->Home.HomeDirectoryDrive.Buffer,
- Buffer->Home.HomeDirectoryDrive.MaximumLength);
- break;
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
- case UserScriptInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"ScriptPath",
- REG_SZ,
- Buffer->Script.ScriptPath.Buffer,
- Buffer->Script.ScriptPath.MaximumLength);
- break;
+ Status = SampGetObjectAttribute(UserObject,
+ L"FullName",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
- case UserProfileInformation:
- Status = SampSetObjectAttribute(UserObject,
+ InfoBuffer->FullName.FullName.Length = Length - sizeof(WCHAR);
+ InfoBuffer->FullName.FullName.MaximumLength = Length;
+ InfoBuffer->FullName.FullName.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->FullName.FullName.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"FullName",
+ NULL,
+ (PVOID)InfoBuffer->FullName.FullName.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->FullName.FullName.Buffer != NULL)
+ midl_user_free(InfoBuffer->FullName.FullName.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ SAM_USER_FIXED_DATA FixedData;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ (PVOID)&FixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId;
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
+SampQueryUserHome(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = SampGetObjectAttribute(UserObject,
+ L"HomeDirectory",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->Home.HomeDirectory.Length = Length - sizeof(WCHAR);
+ InfoBuffer->Home.HomeDirectory.MaximumLength = Length;
+ InfoBuffer->Home.HomeDirectory.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->Home.HomeDirectory.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"HomeDirectory",
+ NULL,
+ (PVOID)InfoBuffer->Home.HomeDirectory.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ Length = 0;
+ Status = SampGetObjectAttribute(UserObject,
+ L"HomeDirectoryDrive",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->Home.HomeDirectoryDrive.Length = Length - sizeof(WCHAR);
+ InfoBuffer->Home.HomeDirectoryDrive.MaximumLength = Length;
+ InfoBuffer->Home.HomeDirectoryDrive.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->Home.HomeDirectoryDrive.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"HomeDirectoryDrive",
+ NULL,
+ (PVOID)InfoBuffer->Home.HomeDirectoryDrive.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->Home.HomeDirectory.Buffer != NULL)
+ midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer);
+
+ if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL)
+ midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
+SampQueryUserScript(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = SampGetObjectAttribute(UserObject,
+ L"ScriptPath",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->Script.ScriptPath.Length = Length - sizeof(WCHAR);
+ InfoBuffer->Script.ScriptPath.MaximumLength = Length;
+ InfoBuffer->Script.ScriptPath.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->Script.ScriptPath.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"ScriptPath",
+ NULL,
+ (PVOID)InfoBuffer->Script.ScriptPath.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->Script.ScriptPath.Buffer != NULL)
+ midl_user_free(InfoBuffer->Script.ScriptPath.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
+SampQueryUserProfile(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = SampGetObjectAttribute(UserObject,
+ L"ProfilePath",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->Profile.ProfilePath.Length = Length - sizeof(WCHAR);
+ InfoBuffer->Profile.ProfilePath.MaximumLength = Length;
+ InfoBuffer->Profile.ProfilePath.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->Profile.ProfilePath.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"ProfilePath",
+ NULL,
+ (PVOID)InfoBuffer->Profile.ProfilePath.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->Profile.ProfilePath.Buffer != NULL)
+ midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
+SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = SampGetObjectAttribute(UserObject,
+ L"AdminComment",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->AdminComment.AdminComment.Length = Length - sizeof(WCHAR);
+ InfoBuffer->AdminComment.AdminComment.MaximumLength = Length;
+ InfoBuffer->AdminComment.AdminComment.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->AdminComment.AdminComment.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"AdminComment",
+ NULL,
+ (PVOID)InfoBuffer->AdminComment.AdminComment.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
+ midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+
+static NTSTATUS
+SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = SampGetObjectAttribute(UserObject,
+ L"WorkStations",
+ NULL,
+ NULL,
+ &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->WorkStations.WorkStations.Length = Length - sizeof(WCHAR);
+ InfoBuffer->WorkStations.WorkStations.MaximumLength = Length;
+ InfoBuffer->WorkStations.WorkStations.Buffer = midl_user_allocate(Length);
+ if (InfoBuffer->WorkStations.WorkStations.Buffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ TRACE("Length: %lu\n", Length);
+ Status = SampGetObjectAttribute(UserObject,
+ L"WorkStations",
+ NULL,
+ (PVOID)InfoBuffer->WorkStations.WorkStations.Buffer,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL)
+ midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+SampQueryUserControl(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ SAM_USER_FIXED_DATA FixedData;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ (PVOID)&FixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl;
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+SampQueryUserExpires(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ SAM_USER_FIXED_DATA FixedData;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ (PVOID)&FixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
+ InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+/* Function 36 */
+NTSTATUS
+NTAPI
+SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
+ IN USER_INFORMATION_CLASS UserInformationClass,
+ OUT PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAM_DB_OBJECT UserObject;
+ ACCESS_MASK DesiredAccess;
+ NTSTATUS Status;
+
+ TRACE("SamrQueryInformationUser(%p %lu %p)\n",
+ UserHandle, UserInformationClass, Buffer);
+
+ switch (UserInformationClass)
+ {
+ case UserGeneralInformation:
+ case UserNameInformation:
+ case UserAccountNameInformation:
+ case UserFullNameInformation:
+ case UserPrimaryGroupInformation:
+ case UserAdminCommentInformation:
+ DesiredAccess = USER_READ_GENERAL;
+ break;
+
+ case UserLogonHoursInformation:
+ case UserHomeInformation:
+ case UserScriptInformation:
+ case UserProfileInformation:
+ case UserWorkStationsInformation:
+ DesiredAccess = USER_READ_LOGON;
+ break;
+
+ case UserControlInformation:
+ case UserExpiresInformation:
+ DesiredAccess = USER_READ_ACCOUNT;
+ break;
+
+ case UserPreferencesInformation:
+ DesiredAccess = USER_READ_GENERAL |
+ USER_READ_PREFERENCES;
+ break;
+
+ case UserLogonInformation:
+ case UserAccountInformation:
+ DesiredAccess = USER_READ_GENERAL |
+ USER_READ_PREFERENCES |
+ USER_READ_LOGON |
+ USER_READ_ACCOUNT;
+ break;
+
+ default:
+ return STATUS_INVALID_INFO_CLASS;
+ }
+
+ /* Validate the domain handle */
+ Status = SampValidateDbObject(UserHandle,
+ SamDbUserObject,
+ DesiredAccess,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ switch (UserInformationClass)
+ {
+// case UserGeneralInformation:
+// case UserPreferencesInformation:
+// case UserLogonInformation:
+// case UserLogonHoursInformation:
+// case UserAccountInformation:
+
+ case UserNameInformation:
+ Status = SampQueryUserName(UserObject,
+ Buffer);
+ break;
+
+ case UserAccountNameInformation:
+ Status = SampQueryUserAccountName(UserObject,
+ Buffer);
+ break;
+
+ case UserFullNameInformation:
+ Status = SampQueryUserFullName(UserObject,
+ Buffer);
+ break;
+
+ case UserPrimaryGroupInformation:
+ Status = SampQueryUserPrimaryGroup(UserObject,
+ Buffer);
+ break;
+
+ case UserHomeInformation:
+ Status = SampQueryUserHome(UserObject,
+ Buffer);
+
+ case UserScriptInformation:
+ Status = SampQueryUserScript(UserObject,
+ Buffer);
+ break;
+
+ case UserProfileInformation:
+ Status = SampQueryUserProfile(UserObject,
+ Buffer);
+ break;
+
+ case UserAdminCommentInformation:
+ Status = SampQueryUserAdminComment(UserObject,
+ Buffer);
+ break;
+
+ case UserWorkStationsInformation:
+ Status = SampQueryUserWorkStations(UserObject,
+ Buffer);
+ break;
+
+ case UserControlInformation:
+ Status = SampQueryUserControl(UserObject,
+ Buffer);
+ break;
+
+ case UserExpiresInformation:
+ Status = SampQueryUserExpires(UserObject,
+ Buffer);
+ break;
+
+ default:
+ Status = STATUS_INVALID_INFO_CLASS;
+ }
+
+ return Status;
+}
+
+/* Function 37 */
+NTSTATUS
+NTAPI
+SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
+ IN USER_INFORMATION_CLASS UserInformationClass,
+ IN PSAMPR_USER_INFO_BUFFER Buffer)
+{
+ PSAM_DB_OBJECT UserObject;
+ ACCESS_MASK DesiredAccess;
+ NTSTATUS Status;
+
+ TRACE("SamrSetInformationUser(%p %lu %p)\n",
+ UserHandle, UserInformationClass, Buffer);
+
+ switch (UserInformationClass)
+ {
+ case UserNameInformation:
+ case UserAccountNameInformation:
+ case UserFullNameInformation:
+ case UserPrimaryGroupInformation:
+ case UserHomeInformation:
+ case UserScriptInformation:
+ case UserProfileInformation:
+ case UserAdminCommentInformation:
+ case UserWorkStationsInformation:
+ case UserControlInformation:
+ case UserExpiresInformation:
+ DesiredAccess = USER_WRITE_ACCOUNT;
+ break;
+
+ case UserSetPasswordInformation:
+ DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
+ break;
+
+ default:
+ return STATUS_INVALID_INFO_CLASS;
+ }
+
+ /* Validate the domain handle */
+ Status = SampValidateDbObject(UserHandle,
+ SamDbUserObject,
+ DesiredAccess,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ switch (UserInformationClass)
+ {
+// case UserGeneralInformation:
+// case UserPreferencesInformation:
+// case UserLogonHoursInformation:
+
+ case UserNameInformation:
+ Status = SampSetObjectAttribute(UserObject,
+ L"Name",
+ REG_SZ,
+ Buffer->Name.UserName.Buffer,
+ Buffer->Name.UserName.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ break;
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"FullName",
+ REG_SZ,
+ Buffer->Name.FullName.Buffer,
+ Buffer->Name.FullName.MaximumLength);
+ break;
+
+ case UserAccountNameInformation:
+ Status = SampSetObjectAttribute(UserObject,
+ L"Name",
+ REG_SZ,
+ Buffer->AccountName.UserName.Buffer,
+ Buffer->AccountName.UserName.MaximumLength);
+ break;
+
+ case UserFullNameInformation:
+ Status = SampSetObjectAttribute(UserObject,
+ L"FullName",
+ REG_SZ,
+ Buffer->FullName.FullName.Buffer,
+ Buffer->FullName.FullName.MaximumLength);
+ break;
+
+/*
+ case UserPrimaryGroupInformation:
+ Status = SampSetObjectAttribute(UserObject,
+ L"PrimaryGroupId",
+ REG_DWORD,
+ &Buffer->PrimaryGroup.PrimaryGroupId,
+ sizeof(ULONG));
+ break;
+*/
+
+ case UserHomeInformation:
+ Status = SampSetObjectAttribute(UserObject,
+ L"HomeDirectory",
+ REG_SZ,
+ Buffer->Home.HomeDirectory.Buffer,
+ Buffer->Home.HomeDirectory.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ break;
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"HomeDirectoryDrive",
+ REG_SZ,
+ Buffer->Home.HomeDirectoryDrive.Buffer,
+ Buffer->Home.HomeDirectoryDrive.MaximumLength);
+ break;
+
+ case UserScriptInformation:
+ Status = SampSetObjectAttribute(UserObject,
+ L"ScriptPath",
+ REG_SZ,
+ Buffer->Script.ScriptPath.Buffer,
+ Buffer->Script.ScriptPath.MaximumLength);
+ break;
+
+ case UserProfileInformation:
+ Status = SampSetObjectAttribute(UserObject,
L"ProfilePath",
REG_SZ,
Buffer->Profile.ProfilePath.Buffer,
Buffer->SetPassword.Password.MaximumLength);
break;
+/*
case UserControlInformation:
Status = SampSetObjectAttribute(UserObject,
L"UserAccountControl",
&Buffer->Control.UserAccountControl,
sizeof(ULONG));
break;
-
+*/
+/*
case UserExpiresInformation:
Status = SampSetObjectAttribute(UserObject,
L"AccountExpires",
&Buffer->Expires.AccountExpires,
sizeof(OLD_LARGE_INTEGER));
break;
+*/
// case UserInternal1Information:
// case UserParametersInformation: