reactos/dll/win32/samlib/samlib.c

2292 lines
63 KiB
C

/*
* ReactOS kernel
* Copyright (C) 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: SAM interface library
* FILE: lib/samlib/samlib.c
* PROGRAMER: Eric Kohl
*/
#include "precomp.h"
#define NTOS_MODE_USER
#include <ndk/rtlfuncs.h>
#include <ntsam.h>
#include <sam_c.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(samlib);
NTSTATUS
WINAPI
SystemFunction006(LPCSTR password,
LPSTR hash);
NTSTATUS
WINAPI
SystemFunction007(PUNICODE_STRING string,
LPBYTE hash);
NTSTATUS
WINAPI
SystemFunction012(const BYTE *in,
const BYTE *key,
LPBYTE out);
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
}
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
handle_t __RPC_USER
PSAMPR_SERVER_NAME_bind(PSAMPR_SERVER_NAME pszSystemName)
{
handle_t hBinding = NULL;
LPWSTR pszStringBinding;
RPC_STATUS status;
TRACE("PSAMPR_SERVER_NAME_bind() called\n");
status = RpcStringBindingComposeW(NULL,
L"ncacn_np",
pszSystemName,
L"\\pipe\\samr",
NULL,
&pszStringBinding);
if (status)
{
TRACE("RpcStringBindingCompose returned 0x%x\n", status);
return NULL;
}
/* Set the binding handle that will be used to bind to the server. */
status = RpcBindingFromStringBindingW(pszStringBinding,
&hBinding);
if (status)
{
TRACE("RpcBindingFromStringBinding returned 0x%x\n", status);
}
status = RpcStringFreeW(&pszStringBinding);
if (status)
{
// TRACE("RpcStringFree returned 0x%x\n", status);
}
return hBinding;
}
void __RPC_USER
PSAMPR_SERVER_NAME_unbind(PSAMPR_SERVER_NAME pszSystemName,
handle_t hBinding)
{
RPC_STATUS status;
TRACE("PSAMPR_SERVER_NAME_unbind() called\n");
status = RpcBindingFree(&hBinding);
if (status)
{
TRACE("RpcBindingFree returned 0x%x\n", status);
}
}
NTSTATUS
SampCheckPassword(IN SAMPR_HANDLE UserHandle,
IN PUNICODE_STRING Password)
{
USER_DOMAIN_PASSWORD_INFORMATION DomainPasswordInformation;
LPWORD CharTypeBuffer = NULL;
ULONG PasswordLength;
ULONG i;
ULONG Upper = 0, Lower = 0, Digit = 0, Punct = 0, Alpha = 0;
NTSTATUS Status = STATUS_SUCCESS;
TRACE("(%p %p)\n", UserHandle, Password);
/* Get the domain password information */
Status = SamrGetUserDomainPasswordInformation(UserHandle,
&DomainPasswordInformation);
if (!NT_SUCCESS(Status))
{
TRACE("SamrGetUserDomainPasswordInformation failed (Status 0x%08lx)\n", Status);
return Status;
}
PasswordLength = (ULONG)(Password->Length / sizeof(WCHAR));
/* Fail if the password is too short or too long */
if ((PasswordLength < DomainPasswordInformation.MinPasswordLength) ||
(PasswordLength > 256))
return STATUS_PASSWORD_RESTRICTION;
/* Check the password complexity */
if (DomainPasswordInformation.PasswordProperties & DOMAIN_PASSWORD_COMPLEX)
{
CharTypeBuffer = midl_user_allocate(PasswordLength * sizeof(WORD));
if (CharTypeBuffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
GetStringTypeW(CT_CTYPE1,
Password->Buffer,
PasswordLength,
CharTypeBuffer);
for (i = 0; i < PasswordLength; i++)
{
TRACE("%lu: %C %s %s %s %s\n", i, Password->Buffer[i],
(CharTypeBuffer[i] & C1_UPPER) ? "C1_UPPER" : " ",
(CharTypeBuffer[i] & C1_LOWER) ? "C1_LOWER" : " ",
(CharTypeBuffer[i] & C1_DIGIT) ? "C1_DIGIT" : " ",
(CharTypeBuffer[i] & C1_PUNCT) ? "C1_PUNCT" : " ",
(CharTypeBuffer[i] & C1_ALPHA) ? "C1_ALPHA" : " ");
if (CharTypeBuffer[i] & C1_UPPER)
Upper = 1;
if (CharTypeBuffer[i] & C1_LOWER)
Lower = 1;
if (CharTypeBuffer[i] & C1_DIGIT)
Digit = 1;
if (CharTypeBuffer[i] & C1_PUNCT)
Punct = 1;
if ((CharTypeBuffer[i] & C1_ALPHA) &&
!(CharTypeBuffer[i] & C1_UPPER) &&
!(CharTypeBuffer[i] & C1_LOWER))
Alpha = 1;
}
TRACE("Upper: %lu\n", Upper);
TRACE("Lower: %lu\n", Lower);
TRACE("Digit: %lu\n", Digit);
TRACE("Punct: %lu\n", Punct);
TRACE("Alpha: %lu\n", Alpha);
TRACE("Total: %lu\n", Upper + Lower + Digit + Punct + Alpha);
if (Upper + Lower + Digit + Punct + Alpha < 3)
Status = STATUS_PASSWORD_RESTRICTION;
}
if (CharTypeBuffer != NULL)
midl_user_free(CharTypeBuffer);
return Status;
}
NTSTATUS
NTAPI
SamAddMemberToAlias(IN SAM_HANDLE AliasHandle,
IN PSID MemberId)
{
NTSTATUS Status;
TRACE("SamAddMemberToAlias(%p %p)\n",
AliasHandle, MemberId);
RpcTryExcept
{
Status = SamrAddMemberToAlias((SAMPR_HANDLE)AliasHandle,
(PRPC_SID)MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes)
{
NTSTATUS Status;
TRACE("SamAddMemberToGroup(%p %lu %lx)\n",
GroupHandle, MemberId, Attributes);
RpcTryExcept
{
Status = SamrAddMemberToGroup((SAMPR_HANDLE)GroupHandle,
MemberId,
Attributes);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamAddMultipleMembersToAlias(IN SAM_HANDLE AliasHandle,
IN PSID *MemberIds,
IN ULONG MemberCount)
{
SAMPR_PSID_ARRAY Buffer;
NTSTATUS Status;
TRACE("SamAddMultipleMembersToAlias(%p %p %lu)\n",
AliasHandle, MemberIds, MemberCount);
if (MemberIds == NULL)
return STATUS_INVALID_PARAMETER_2;
Buffer.Count = MemberCount;
Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
RpcTryExcept
{
Status = SamrAddMultipleMembersToAlias((SAMPR_HANDLE)AliasHandle,
&Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamChangePasswordUser(IN SAM_HANDLE UserHandle,
IN PUNICODE_STRING OldPassword,
IN PUNICODE_STRING NewPassword)
{
NT_OWF_PASSWORD OldNtPassword;
NT_OWF_PASSWORD NewNtPassword;
LM_OWF_PASSWORD OldLmPassword;
LM_OWF_PASSWORD NewLmPassword;
OEM_STRING LmPwdString;
CHAR LmPwdBuffer[15];
BOOLEAN OldLmPasswordPresent = FALSE;
BOOLEAN NewLmPasswordPresent = FALSE;
NTSTATUS Status;
ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
ENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt;
ENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt;
PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
/* Calculate the NT hash for the old password */
Status = SystemFunction007(OldPassword,
(LPBYTE)&OldNtPassword);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Calculate the NT hash for the new password */
Status = SystemFunction007(NewPassword,
(LPBYTE)&NewNtPassword);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Calculate the LM password and hash for the old password */
LmPwdString.Length = 15;
LmPwdString.MaximumLength = 15;
LmPwdString.Buffer = LmPwdBuffer;
ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
OldPassword,
FALSE);
if (NT_SUCCESS(Status))
{
/* Calculate the LM hash value of the password */
Status = SystemFunction006(LmPwdString.Buffer,
(LPSTR)&OldLmPassword);
if (NT_SUCCESS(Status))
{
OldLmPasswordPresent = TRUE;
}
}
/* Calculate the LM password and hash for the new password */
LmPwdString.Length = 15;
LmPwdString.MaximumLength = 15;
LmPwdString.Buffer = LmPwdBuffer;
ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
NewPassword,
FALSE);
if (NT_SUCCESS(Status))
{
/* Calculate the LM hash value of the password */
Status = SystemFunction006(LmPwdString.Buffer,
(LPSTR)&NewLmPassword);
if (NT_SUCCESS(Status))
{
NewLmPasswordPresent = TRUE;
}
}
if (OldLmPasswordPresent && NewLmPasswordPresent)
{
/* Encrypt the old LM hash with the new LM hash */
Status = SystemFunction012((const BYTE *)&OldLmPassword,
(const BYTE *)&NewLmPassword,
(LPBYTE)&OldLmEncryptedWithNewLm);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Encrypt the new LM hash with the old LM hash */
Status = SystemFunction012((const BYTE *)&NewLmPassword,
(const BYTE *)&OldLmPassword,
(LPBYTE)&NewLmEncryptedWithOldLm);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
return Status;
}
pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
}
/* Encrypt the old NT hash with the new NT hash */
Status = SystemFunction012((const BYTE *)&OldNtPassword,
(const BYTE *)&NewNtPassword,
(LPBYTE)&OldNtEncryptedWithNewNt);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Encrypt the new NT hash with the old NT hash */
Status = SystemFunction012((const BYTE *)&NewNtPassword,
(const BYTE *)&OldNtPassword,
(LPBYTE)&NewNtEncryptedWithOldNt);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
return Status;
}
RpcTryExcept
{
Status = SamrChangePasswordUser((SAMPR_HANDLE)UserHandle,
OldLmPasswordPresent && NewLmPasswordPresent,
pOldLmEncryptedWithNewLm,
pNewLmEncryptedWithOldLm,
TRUE,
&OldNtEncryptedWithNewNt,
&NewNtEncryptedWithOldNt,
FALSE,
NULL,
FALSE,
NULL);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamChangePasswordUser2(IN PUNICODE_STRING ServerName,
IN PUNICODE_STRING UserName,
IN PUNICODE_STRING OldPassword,
IN PUNICODE_STRING NewPassword)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
SamChangePasswordUser3(IN PUNICODE_STRING ServerName,
IN PUNICODE_STRING UserName,
IN PUNICODE_STRING OldPassword,
IN PUNICODE_STRING NewPassword,
OUT PDOMAIN_PASSWORD_INFORMATION *EffectivePasswordPolicy,
OUT PUSER_PWD_CHANGE_FAILURE_INFORMATION *PasswordChangeFailureInfo)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
SamCloseHandle(IN SAM_HANDLE SamHandle)
{
NTSTATUS Status;
TRACE("SamCloseHandle(%p)\n", SamHandle);
RpcTryExcept
{
Status = SamrCloseHandle((SAMPR_HANDLE *)&SamHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamConnect(IN OUT PUNICODE_STRING ServerName OPTIONAL,
OUT PSAM_HANDLE ServerHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
NTSTATUS Status;
TRACE("SamConnect(%p %p 0x%08x %p)\n",
ServerName, ServerHandle, DesiredAccess, ObjectAttributes);
RpcTryExcept
{
Status = SamrConnect((PSAMPR_SERVER_NAME)ServerName,
(SAMPR_HANDLE *)ServerHandle,
DesiredAccess);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamCreateAliasInDomain(IN SAM_HANDLE DomainHandle,
IN PUNICODE_STRING AccountName,
IN ACCESS_MASK DesiredAccess,
OUT PSAM_HANDLE AliasHandle,
OUT PULONG RelativeId)
{
NTSTATUS Status;
TRACE("SamCreateAliasInDomain(%p %p 0x%08x %p %p)\n",
DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
*AliasHandle = NULL;
*RelativeId = 0;
RpcTryExcept
{
Status = SamrCreateAliasInDomain((SAMPR_HANDLE)DomainHandle,
(PRPC_UNICODE_STRING)AccountName,
DesiredAccess,
(SAMPR_HANDLE *)AliasHandle,
RelativeId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamCreateGroupInDomain(IN SAM_HANDLE DomainHandle,
IN PUNICODE_STRING AccountName,
IN ACCESS_MASK DesiredAccess,
OUT PSAM_HANDLE GroupHandle,
OUT PULONG RelativeId)
{
NTSTATUS Status;
TRACE("SamCreateGroupInDomain(%p %p 0x%08x %p %p)\n",
DomainHandle, AccountName, DesiredAccess, GroupHandle, RelativeId);
*GroupHandle = NULL;
*RelativeId = 0;
RpcTryExcept
{
Status = SamrCreateGroupInDomain((SAMPR_HANDLE)DomainHandle,
(PRPC_UNICODE_STRING)AccountName,
DesiredAccess,
(SAMPR_HANDLE *)GroupHandle,
RelativeId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
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,
OUT PSAM_HANDLE UserHandle,
OUT PULONG RelativeId)
{
NTSTATUS Status;
TRACE("SamCreateUserInDomain(%p %p 0x%08x %p %p)\n",
DomainHandle, AccountName, DesiredAccess, UserHandle, RelativeId);
*UserHandle = NULL;
*RelativeId = 0;
RpcTryExcept
{
Status = SamrCreateUserInDomain((SAMPR_HANDLE)DomainHandle,
(PRPC_UNICODE_STRING)AccountName,
DesiredAccess,
(SAMPR_HANDLE *)UserHandle,
RelativeId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamDeleteAlias(IN SAM_HANDLE AliasHandle)
{
SAMPR_HANDLE LocalAliasHandle;
NTSTATUS Status;
TRACE("SamDeleteAlias(%p)\n", AliasHandle);
LocalAliasHandle = (SAMPR_HANDLE)AliasHandle;
if (LocalAliasHandle == NULL)
return STATUS_INVALID_HANDLE;
RpcTryExcept
{
Status = SamrDeleteAlias(&LocalAliasHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamDeleteGroup(IN SAM_HANDLE GroupHandle)
{
SAMPR_HANDLE LocalGroupHandle;
NTSTATUS Status;
TRACE("SamDeleteGroup(%p)\n", GroupHandle);
LocalGroupHandle = (SAMPR_HANDLE)GroupHandle;
if (LocalGroupHandle == NULL)
return STATUS_INVALID_HANDLE;
RpcTryExcept
{
Status = SamrDeleteGroup(&LocalGroupHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamDeleteUser(IN SAM_HANDLE UserHandle)
{
SAMPR_HANDLE LocalUserHandle;
NTSTATUS Status;
TRACE("SamDeleteUser(%p)\n", UserHandle);
LocalUserHandle = (SAMPR_HANDLE)UserHandle;
if (LocalUserHandle == NULL)
return STATUS_INVALID_HANDLE;
RpcTryExcept
{
Status = SamrDeleteUser(&LocalUserHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamEnumerateAliasesInDomain(IN SAM_HANDLE DomainHandle,
IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
OUT PVOID *Buffer,
IN ULONG PreferedMaximumLength,
OUT PULONG CountReturned)
{
PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
NTSTATUS Status;
TRACE("SamEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
DomainHandle, EnumerationContext, Buffer, PreferedMaximumLength,
CountReturned);
if ((EnumerationContext == NULL) ||
(Buffer == NULL) ||
(CountReturned == NULL))
return STATUS_INVALID_PARAMETER;
*Buffer = NULL;
RpcTryExcept
{
Status = SamrEnumerateAliasesInDomain((SAMPR_HANDLE)DomainHandle,
EnumerationContext,
&EnumBuffer,
PreferedMaximumLength,
CountReturned);
if (EnumBuffer != NULL)
{
if (EnumBuffer->Buffer != NULL)
{
*Buffer = EnumBuffer->Buffer;
}
midl_user_free(EnumBuffer);
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamEnumerateDomainsInSamServer(IN SAM_HANDLE ServerHandle,
IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
OUT PVOID *Buffer,
IN ULONG PreferedMaximumLength,
OUT PULONG CountReturned)
{
PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
NTSTATUS Status;
TRACE("SamEnumerateDomainsInSamServer(%p %p %p %lu %p)\n",
ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
CountReturned);
if ((EnumerationContext == NULL) ||
(Buffer == NULL) ||
(CountReturned == NULL))
return STATUS_INVALID_PARAMETER;
*Buffer = NULL;
RpcTryExcept
{
Status = SamrEnumerateDomainsInSamServer((SAMPR_HANDLE)ServerHandle,
EnumerationContext,
&EnumBuffer,
PreferedMaximumLength,
CountReturned);
if (EnumBuffer != NULL)
{
if (EnumBuffer->Buffer != NULL)
{
*Buffer = EnumBuffer->Buffer;
}
midl_user_free(EnumBuffer);
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamEnumerateGroupsInDomain(IN SAM_HANDLE DomainHandle,
IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
IN PVOID *Buffer,
IN ULONG PreferedMaximumLength,
OUT PULONG CountReturned)
{
PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
NTSTATUS Status;
TRACE("SamEnumerateGroupsInDomain(%p %p %p %lu %p)\n",
DomainHandle, EnumerationContext, Buffer,
PreferedMaximumLength, CountReturned);
if (EnumerationContext == NULL || Buffer == NULL || CountReturned == NULL)
return STATUS_INVALID_PARAMETER;
*Buffer = NULL;
RpcTryExcept
{
Status = SamrEnumerateGroupsInDomain((SAMPR_HANDLE)DomainHandle,
EnumerationContext,
&EnumBuffer,
PreferedMaximumLength,
CountReturned);
if (EnumBuffer != NULL)
{
if (EnumBuffer->Buffer != NULL)
*Buffer = EnumBuffer->Buffer;
midl_user_free(EnumBuffer);
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamEnumerateUsersInDomain(IN SAM_HANDLE DomainHandle,
IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
IN ULONG UserAccountControl,
OUT PVOID *Buffer,
IN ULONG PreferedMaximumLength,
OUT PULONG CountReturned)
{
PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
NTSTATUS Status;
TRACE("SamEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n",
DomainHandle, EnumerationContext, UserAccountControl, Buffer,
PreferedMaximumLength, CountReturned);
if (EnumerationContext == NULL || Buffer == NULL || CountReturned == NULL)
return STATUS_INVALID_PARAMETER;
*Buffer = NULL;
RpcTryExcept
{
Status = SamrEnumerateUsersInDomain((SAMPR_HANDLE)DomainHandle,
EnumerationContext,
UserAccountControl,
&EnumBuffer,
PreferedMaximumLength,
CountReturned);
if (EnumBuffer != NULL)
{
if (EnumBuffer->Buffer != NULL)
{
*Buffer = EnumBuffer->Buffer;
}
midl_user_free(EnumBuffer);
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamFreeMemory(IN PVOID Buffer)
{
if (Buffer != NULL)
midl_user_free(Buffer);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
SamGetAliasMembership(IN SAM_HANDLE DomainHandle,
IN ULONG PassedCount,
IN PSID *Sids,
OUT PULONG MembershipCount,
OUT PULONG *Aliases)
{
SAMPR_PSID_ARRAY SidArray;
SAMPR_ULONG_ARRAY Membership;
NTSTATUS Status;
TRACE("SamAliasMembership(%p %lu %p %p %p)\n",
DomainHandle, PassedCount, Sids, MembershipCount, Aliases);
if (Sids == NULL ||
MembershipCount == NULL ||
Aliases == NULL)
return STATUS_INVALID_PARAMETER;
Membership.Element = NULL;
RpcTryExcept
{
SidArray.Count = PassedCount;
SidArray.Sids = (PSAMPR_SID_INFORMATION)Sids;
Status = SamrGetAliasMembership((SAMPR_HANDLE)DomainHandle,
&SidArray,
&Membership);
if (NT_SUCCESS(Status))
{
*MembershipCount = Membership.Count;
*Aliases = Membership.Element;
}
else
{
if (Membership.Element != NULL)
midl_user_free(Membership.Element);
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamGetCompatibilityMode(IN SAM_HANDLE ObjectHandle,
OUT PULONG Mode)
{
TRACE("(%p %p)\n", ObjectHandle, Mode);
if (Mode == NULL)
return STATUS_INVALID_PARAMETER;
*Mode = SAM_SID_COMPATIBILITY_ALL;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
SamGetDisplayEnumerationIndex(IN SAM_HANDLE DomainHandle,
IN DOMAIN_DISPLAY_INFORMATION DisplayInformation,
IN PUNICODE_STRING Prefix,
OUT PULONG Index)
{
NTSTATUS Status;
TRACE("(%p %lu %wZ %p)\n",
DomainHandle, DisplayInformation, Prefix, Index);
if ((Prefix == NULL) ||
(Index == NULL))
return STATUS_INVALID_PARAMETER;
RpcTryExcept
{
Status = SamrGetDisplayEnumerationIndex2((SAMPR_HANDLE)DomainHandle,
DisplayInformation,
(PRPC_UNICODE_STRING)Prefix,
Index);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamGetGroupsForUser(IN SAM_HANDLE UserHandle,
OUT PGROUP_MEMBERSHIP *Groups,
OUT PULONG MembershipCount)
{
PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
NTSTATUS Status;
TRACE("SamGetGroupsForUser(%p %p %p)\n",
UserHandle, Groups, MembershipCount);
RpcTryExcept
{
Status = SamrGetGroupsForUser((SAMPR_HANDLE)UserHandle,
&GroupsBuffer);
if (NT_SUCCESS(Status))
{
*Groups = GroupsBuffer->Groups;
*MembershipCount = GroupsBuffer->MembershipCount;
MIDL_user_free(GroupsBuffer);
}
else
{
if (GroupsBuffer != NULL)
{
if (GroupsBuffer->Groups != NULL)
MIDL_user_free(GroupsBuffer->Groups);
MIDL_user_free(GroupsBuffer);
}
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
OUT PSID **MemberIds,
OUT PULONG MemberCount)
{
SAMPR_PSID_ARRAY_OUT SidArray;
NTSTATUS Status;
TRACE("SamGetMembersInAlias(%p %p %p)\n",
AliasHandle, MemberIds, MemberCount);
if ((MemberIds == NULL) ||
(MemberCount == NULL))
return STATUS_INVALID_PARAMETER;
*MemberIds = NULL;
*MemberCount = 0;
SidArray.Sids = NULL;
RpcTryExcept
{
Status = SamrGetMembersInAlias((SAMPR_HANDLE)AliasHandle,
&SidArray);
if (NT_SUCCESS(Status))
{
*MemberCount = SidArray.Count;
*MemberIds = (PSID *)SidArray.Sids;
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamGetMembersInGroup(IN SAM_HANDLE GroupHandle,
OUT PULONG *MemberIds,
OUT PULONG *Attributes,
OUT PULONG MemberCount)
{
PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
NTSTATUS Status;
TRACE("SamGetMembersInGroup(%p %p %p %p)\n",
GroupHandle, MemberIds, Attributes, MemberCount);
RpcTryExcept
{
Status = SamrGetMembersInGroup((SAMPR_HANDLE)GroupHandle,
&MembersBuffer);
if (NT_SUCCESS(Status))
{
*MemberIds = MembersBuffer->Members;
*Attributes = MembersBuffer->Attributes;
*MemberCount = MembersBuffer->MemberCount;
MIDL_user_free(MembersBuffer);
}
else
{
if (MembersBuffer != NULL)
{
if (MembersBuffer->Members != NULL)
MIDL_user_free(MembersBuffer->Members);
if (MembersBuffer->Attributes != NULL)
MIDL_user_free(MembersBuffer->Attributes);
MIDL_user_free(MembersBuffer);
}
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
IN PUNICODE_STRING Name,
OUT PSID *DomainId)
{
NTSTATUS Status;
TRACE("SamLookupDomainInSamServer(%p %p %p)\n",
ServerHandle, Name, DomainId);
RpcTryExcept
{
Status = SamrLookupDomainInSamServer((SAMPR_HANDLE)ServerHandle,
(PRPC_UNICODE_STRING)Name,
(PRPC_SID *)DomainId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamLookupIdsInDomain(IN SAM_HANDLE DomainHandle,
IN ULONG Count,
IN PULONG RelativeIds,
OUT PUNICODE_STRING *Names,
OUT PSID_NAME_USE *Use OPTIONAL)
{
SAMPR_RETURNED_USTRING_ARRAY NamesBuffer = {0, NULL};
SAMPR_ULONG_ARRAY UseBuffer = {0, NULL};
ULONG i;
NTSTATUS Status;
TRACE("SamLookupIdsInDomain(%p %lu %p %p %p)\n",
DomainHandle, Count, RelativeIds, Names, Use);
*Names = NULL;
if (Use != NULL)
*Use = NULL;
RpcTryExcept
{
Status = SamrLookupIdsInDomain((SAMPR_HANDLE)DomainHandle,
Count,
RelativeIds,
&NamesBuffer,
&UseBuffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
if (NT_SUCCESS(Status))
{
*Names = midl_user_allocate(Count * sizeof(RPC_UNICODE_STRING));
if (*Names == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
for (i = 0; i < Count; i++)
{
(*Names)[i].Buffer = midl_user_allocate(NamesBuffer.Element[i].MaximumLength);
if ((*Names)[i].Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
}
for (i = 0; i < Count; i++)
{
(*Names)[i].Length = NamesBuffer.Element[i].Length;
(*Names)[i].MaximumLength = NamesBuffer.Element[i].MaximumLength;
RtlCopyMemory((*Names)[i].Buffer,
NamesBuffer.Element[i].Buffer,
NamesBuffer.Element[i].Length);
}
if (Use != NULL)
{
*Use = midl_user_allocate(Count * sizeof(SID_NAME_USE));
if (*Use == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
RtlCopyMemory(*Use,
UseBuffer.Element,
Count * sizeof(SID_NAME_USE));
}
}
done:
if (!NT_SUCCESS(Status))
{
if (*Names != NULL)
{
for (i = 0; i < Count; i++)
{
if ((*Names)[i].Buffer != NULL)
midl_user_free((*Names)[i].Buffer);
}
midl_user_free(*Names);
}
if (Use != NULL && *Use != NULL)
midl_user_free(*Use);
}
if (NamesBuffer.Element != NULL)
{
for (i = 0; i < NamesBuffer.Count; i++)
{
if (NamesBuffer.Element[i].Buffer != NULL)
midl_user_free(NamesBuffer.Element[i].Buffer);
}
midl_user_free(NamesBuffer.Element);
}
if (UseBuffer.Element != NULL)
midl_user_free(UseBuffer.Element);
return 0;
}
NTSTATUS
NTAPI
SamLookupNamesInDomain(IN SAM_HANDLE DomainHandle,
IN ULONG Count,
IN PUNICODE_STRING Names,
OUT PULONG *RelativeIds,
OUT PSID_NAME_USE *Use)
{
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;
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;
}
NTSTATUS
NTAPI
SamOpenAlias(IN SAM_HANDLE DomainHandle,
IN ACCESS_MASK DesiredAccess,
IN ULONG AliasId,
OUT PSAM_HANDLE AliasHandle)
{
NTSTATUS Status;
TRACE("SamOpenAlias(%p 0x%08x %lx %p)\n",
DomainHandle, DesiredAccess, AliasId, AliasHandle);
RpcTryExcept
{
Status = SamrOpenAlias((SAMPR_HANDLE)DomainHandle,
DesiredAccess,
AliasId,
(SAMPR_HANDLE *)AliasHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamOpenDomain(IN SAM_HANDLE ServerHandle,
IN ACCESS_MASK DesiredAccess,
IN PSID DomainId,
OUT PSAM_HANDLE DomainHandle)
{
NTSTATUS Status;
TRACE("SamOpenDomain(%p 0x%08x %p %p)\n",
ServerHandle, DesiredAccess, DomainId, DomainHandle);
RpcTryExcept
{
Status = SamrOpenDomain((SAMPR_HANDLE)ServerHandle,
DesiredAccess,
(PRPC_SID)DomainId,
(SAMPR_HANDLE *)DomainHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamOpenGroup(IN SAM_HANDLE DomainHandle,
IN ACCESS_MASK DesiredAccess,
IN ULONG GroupId,
OUT PSAM_HANDLE GroupHandle)
{
NTSTATUS Status;
TRACE("SamOpenGroup(%p 0x%08x %p %p)\n",
DomainHandle, DesiredAccess, GroupId, GroupHandle);
RpcTryExcept
{
Status = SamrOpenGroup((SAMPR_HANDLE)DomainHandle,
DesiredAccess,
GroupId,
(SAMPR_HANDLE *)GroupHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
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
SamQueryDisplayInformation(IN SAM_HANDLE DomainHandle,
IN DOMAIN_DISPLAY_INFORMATION DisplayInformation,
IN ULONG Index,
IN ULONG EntryCount,
IN ULONG PreferredMaximumLength,
OUT PULONG TotalAvailable,
OUT PULONG TotalReturned,
OUT PULONG ReturnedEntryCount,
OUT PVOID *SortedBuffer)
{
SAMPR_DISPLAY_INFO_BUFFER LocalBuffer;
NTSTATUS Status;
TRACE("(%p %lu %lu %lu %lu %p %p %p %p)\n",
DomainHandle, DisplayInformation, Index, EntryCount,
PreferredMaximumLength, TotalAvailable, TotalReturned,
ReturnedEntryCount, SortedBuffer);
if ((TotalAvailable == NULL) ||
(TotalReturned == NULL) ||
(ReturnedEntryCount == NULL) ||
(SortedBuffer == NULL))
return STATUS_INVALID_PARAMETER;
RpcTryExcept
{
Status = SamrQueryDisplayInformation3((SAMPR_HANDLE)DomainHandle,
DisplayInformation,
Index,
EntryCount,
PreferredMaximumLength,
TotalAvailable,
TotalReturned,
&LocalBuffer);
if (NT_SUCCESS(Status))
{
switch (DisplayInformation)
{
case DomainDisplayUser:
*ReturnedEntryCount = LocalBuffer.UserInformation.EntriesRead;
*SortedBuffer = LocalBuffer.UserInformation.Buffer;
break;
case DomainDisplayMachine:
*ReturnedEntryCount = LocalBuffer.MachineInformation.EntriesRead;
*SortedBuffer = LocalBuffer.MachineInformation.Buffer;
break;
case DomainDisplayGroup:
*ReturnedEntryCount = LocalBuffer.GroupInformation.EntriesRead;
*SortedBuffer = LocalBuffer.GroupInformation.Buffer;
break;
case DomainDisplayOemUser:
*ReturnedEntryCount = LocalBuffer.OemUserInformation.EntriesRead;
*SortedBuffer = LocalBuffer.OemUserInformation.Buffer;
break;
case DomainDisplayOemGroup:
*ReturnedEntryCount = LocalBuffer.OemGroupInformation.EntriesRead;
*SortedBuffer = LocalBuffer.OemGroupInformation.Buffer;
break;
case DomainDisplayServer:
/* FIXME */
break;
}
}
else
{
*ReturnedEntryCount = 0;
*SortedBuffer = NULL;
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamQueryInformationAlias(IN SAM_HANDLE AliasHandle,
IN ALIAS_INFORMATION_CLASS AliasInformationClass,
OUT PVOID *Buffer)
{
NTSTATUS Status;
TRACE("SamQueryInformationAlias(%p %lu %p)\n",
AliasHandle, AliasInformationClass, Buffer);
RpcTryExcept
{
Status = SamrQueryInformationAlias((SAMPR_HANDLE)AliasHandle,
AliasInformationClass,
(PSAMPR_ALIAS_INFO_BUFFER *)Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamQueryInformationDomain(IN SAM_HANDLE DomainHandle,
IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
OUT PVOID *Buffer)
{
NTSTATUS Status;
TRACE("SamQueryInformationDomain(%p %lu %p)\n",
DomainHandle, DomainInformationClass, Buffer);
RpcTryExcept
{
Status = SamrQueryInformationDomain((SAMPR_HANDLE)DomainHandle,
DomainInformationClass,
(PSAMPR_DOMAIN_INFO_BUFFER *)Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamQueryInformationGroup(IN SAM_HANDLE GroupHandle,
IN GROUP_INFORMATION_CLASS GroupInformationClass,
OUT PVOID *Buffer)
{
NTSTATUS Status;
TRACE("SamQueryInformationGroup(%p %lu %p)\n",
GroupHandle, GroupInformationClass, Buffer);
RpcTryExcept
{
Status = SamrQueryInformationGroup((SAMPR_HANDLE)GroupHandle,
GroupInformationClass,
(PSAMPR_GROUP_INFO_BUFFER *)Buffer);
}
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)
{
NTSTATUS Status;
TRACE("SamQueryInformationUser(%p %lu %p)\n",
UserHandle, UserInformationClass, Buffer);
RpcTryExcept
{
Status = SamrQueryInformationUser((SAMPR_HANDLE)UserHandle,
UserInformationClass,
(PSAMPR_USER_INFO_BUFFER *)Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamQuerySecurityObject(IN SAM_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
PSAMPR_SR_SECURITY_DESCRIPTOR SamSecurityDescriptor = NULL;
NTSTATUS Status;
TRACE("SamQuerySecurityObject(%p %lu %p)\n",
ObjectHandle, SecurityInformation, SecurityDescriptor);
*SecurityDescriptor = NULL;
RpcTryExcept
{
Status = SamrQuerySecurityObject((SAMPR_HANDLE)ObjectHandle,
SecurityInformation,
&SamSecurityDescriptor);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
TRACE("SamSecurityDescriptor: %p\n", SamSecurityDescriptor);
if (SamSecurityDescriptor != NULL)
{
TRACE("SamSecurityDescriptor->Length: %lu\n", SamSecurityDescriptor->Length);
TRACE("SamSecurityDescriptor->SecurityDescriptor: %p\n", SamSecurityDescriptor->SecurityDescriptor);
*SecurityDescriptor = SamSecurityDescriptor->SecurityDescriptor;
midl_user_free(SamSecurityDescriptor);
}
return Status;
}
NTSTATUS
NTAPI
SamRemoveMemberFromAlias(IN SAM_HANDLE AliasHandle,
IN PSID MemberId)
{
NTSTATUS Status;
TRACE("SamRemoveMemberFromAlias(%p %ul)\n",
AliasHandle, MemberId);
RpcTryExcept
{
Status = SamrRemoveMemberFromAlias((SAMPR_HANDLE)AliasHandle,
MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMemberFromForeignDomain(IN SAM_HANDLE DomainHandle,
IN PSID MemberId)
{
NTSTATUS Status;
TRACE("SamRemoveMemberFromForeignDomain(%p %ul)\n",
DomainHandle, MemberId);
RpcTryExcept
{
Status = SamrRemoveMemberFromForeignDomain((SAMPR_HANDLE)DomainHandle,
MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMemberFromGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId)
{
NTSTATUS Status;
TRACE("SamRemoveMemberFromGroup(%p %ul)\n",
GroupHandle, MemberId);
RpcTryExcept
{
Status = SamrRemoveMemberFromGroup((SAMPR_HANDLE)GroupHandle,
MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMultipleMembersFromAlias(IN SAM_HANDLE AliasHandle,
IN PSID *MemberIds,
IN ULONG MemberCount)
{
SAMPR_PSID_ARRAY Buffer;
NTSTATUS Status;
TRACE("SamRemoveMultipleMembersFromAlias(%p %p %lu)\n",
AliasHandle, MemberIds, MemberCount);
if (MemberIds == NULL)
return STATUS_INVALID_PARAMETER_2;
Buffer.Count = MemberCount;
Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
RpcTryExcept
{
Status = SamrRemoveMultipleMembersFromAlias((SAMPR_HANDLE)AliasHandle,
&Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRidToSid(IN SAM_HANDLE ObjectHandle,
IN ULONG Rid,
OUT PSID *Sid)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
SamSetInformationAlias(IN SAM_HANDLE AliasHandle,
IN ALIAS_INFORMATION_CLASS AliasInformationClass,
IN PVOID Buffer)
{
NTSTATUS Status;
TRACE("SamSetInformationAlias(%p %lu %p)\n",
AliasHandle, AliasInformationClass, Buffer);
RpcTryExcept
{
Status = SamrSetInformationAlias((SAMPR_HANDLE)AliasHandle,
AliasInformationClass,
Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamSetInformationDomain(IN SAM_HANDLE DomainHandle,
IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
IN PVOID Buffer)
{
NTSTATUS Status;
TRACE("SamSetInformationDomain(%p %lu %p)\n",
DomainHandle, DomainInformationClass, Buffer);
RpcTryExcept
{
Status = SamrSetInformationDomain((SAMPR_HANDLE)DomainHandle,
DomainInformationClass,
Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamSetInformationGroup(IN SAM_HANDLE GroupHandle,
IN GROUP_INFORMATION_CLASS GroupInformationClass,
IN PVOID Buffer)
{
NTSTATUS Status;
TRACE("SamSetInformationGroup(%p %lu %p)\n",
GroupHandle, GroupInformationClass, Buffer);
RpcTryExcept
{
Status = SamrSetInformationGroup((SAMPR_HANDLE)GroupHandle,
GroupInformationClass,
Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamSetInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
IN PVOID Buffer)
{
PSAMPR_USER_SET_PASSWORD_INFORMATION PasswordBuffer;
SAMPR_USER_INTERNAL1_INFORMATION Internal1Buffer;
USER_ALL_INFORMATION InternalAllBuffer;
OEM_STRING LmPwdString;
CHAR LmPwdBuffer[15];
NTSTATUS Status;
TRACE("SamSetInformationUser(%p %lu %p)\n",
UserHandle, UserInformationClass, Buffer);
if (UserInformationClass == UserSetPasswordInformation)
{
PasswordBuffer = (PSAMPR_USER_SET_PASSWORD_INFORMATION)Buffer;
Status = SampCheckPassword(UserHandle,
(PUNICODE_STRING)&PasswordBuffer->Password);
if (!NT_SUCCESS(Status))
{
TRACE("SampCheckPassword failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Calculate the NT hash value of the password */
Status = SystemFunction007((PUNICODE_STRING)&PasswordBuffer->Password,
(LPBYTE)&Internal1Buffer.EncryptedNtOwfPassword);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
return Status;
}
Internal1Buffer.NtPasswordPresent = TRUE;
Internal1Buffer.LmPasswordPresent = FALSE;
/* Build the LM password */
LmPwdString.Length = 15;
LmPwdString.MaximumLength = 15;
LmPwdString.Buffer = LmPwdBuffer;
ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
(PUNICODE_STRING)&PasswordBuffer->Password,
FALSE);
if (NT_SUCCESS(Status))
{
/* Calculate the LM hash value of the password */
Status = SystemFunction006(LmPwdString.Buffer,
(LPSTR)&Internal1Buffer.EncryptedLmOwfPassword);
if (NT_SUCCESS(Status))
Internal1Buffer.LmPasswordPresent = TRUE;
}
Internal1Buffer.PasswordExpired = PasswordBuffer->PasswordExpired;
RpcTryExcept
{
Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
UserInternal1Information,
(PVOID)&Internal1Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
if (!NT_SUCCESS(Status))
{
TRACE("SamrSetInformation() failed (Status 0x%08lx)\n", Status);
}
return Status;
}
else if (UserInformationClass == UserAllInformation)
{
RtlCopyMemory(&InternalAllBuffer,
Buffer,
sizeof(USER_ALL_INFORMATION));
if (InternalAllBuffer.WhichFields & (USER_ALL_LMPASSWORDPRESENT | USER_ALL_NTPASSWORDPRESENT))
{
if (InternalAllBuffer.WhichFields & USER_ALL_OWFPASSWORD)
{
/* Check NT password hash */
if (InternalAllBuffer.WhichFields & USER_ALL_NTPASSWORDPRESENT)
{
if (InternalAllBuffer.NtPassword.Length != sizeof(ENCRYPTED_NT_OWF_PASSWORD))
return STATUS_INVALID_PARAMETER;
}
/* Check LM password hash */
if (InternalAllBuffer.WhichFields & USER_ALL_LMPASSWORDPRESENT)
{
if (InternalAllBuffer.LmPassword.Length != sizeof(ENCRYPTED_LM_OWF_PASSWORD))
return STATUS_INVALID_PARAMETER;
}
}
else
{
/*
* Only allow the NT password to be set.
* The LM password will be created here.
*/
if (InternalAllBuffer.WhichFields & USER_ALL_LMPASSWORDPRESENT)
{
TRACE("Do not try to set a clear text LM password!\n");
return STATUS_INVALID_PARAMETER;
}
if (InternalAllBuffer.WhichFields & USER_ALL_NTPASSWORDPRESENT)
{
Status = SampCheckPassword(UserHandle,
&InternalAllBuffer.NtPassword);
if (!NT_SUCCESS(Status))
{
TRACE("SampCheckPassword failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Calculate the NT password hash */
Status = SystemFunction007((PUNICODE_STRING)&InternalAllBuffer.NtPassword,
(LPBYTE)&Internal1Buffer.EncryptedNtOwfPassword);
if (!NT_SUCCESS(Status))
{
TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
return Status;
}
InternalAllBuffer.NtPasswordPresent = TRUE;
InternalAllBuffer.LmPasswordPresent = FALSE;
InternalAllBuffer.NtPassword.Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
InternalAllBuffer.NtPassword.MaximumLength = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
InternalAllBuffer.NtPassword.Buffer = (LPWSTR)&Internal1Buffer.EncryptedNtOwfPassword;
/* Build the LM password */
LmPwdString.Length = 15;
LmPwdString.MaximumLength = 15;
LmPwdString.Buffer = LmPwdBuffer;
ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
(PUNICODE_STRING)&InternalAllBuffer.NtPassword,
FALSE);
if (NT_SUCCESS(Status))
{
/* Calculate the LM password hash */
Status = SystemFunction006(LmPwdString.Buffer,
(LPSTR)&Internal1Buffer.EncryptedLmOwfPassword);
if (NT_SUCCESS(Status))
{
InternalAllBuffer.WhichFields |= USER_ALL_LMPASSWORDPRESENT;
InternalAllBuffer.LmPasswordPresent = TRUE;
InternalAllBuffer.LmPassword.Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
InternalAllBuffer.LmPassword.MaximumLength = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
InternalAllBuffer.LmPassword.Buffer = (LPWSTR)&Internal1Buffer.EncryptedLmOwfPassword;
}
}
}
}
}
RpcTryExcept
{
Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
UserAllInformation,
(PVOID)&InternalAllBuffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
if (!NT_SUCCESS(Status))
{
TRACE("SamrSetInformation() failed (Status 0x%08lx)\n", Status);
}
return Status;
}
RpcTryExcept
{
Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
UserInformationClass,
Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamSetMemberAttributesOfGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes)
{
NTSTATUS Status;
TRACE("SamSetMemberAttributesOfGroup(%p %lu 0x%lx)\n",
GroupHandle, MemberId, Attributes);
RpcTryExcept
{
Status = SamrSetMemberAttributesOfGroup((SAMPR_HANDLE)GroupHandle,
MemberId,
Attributes);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamSetSecurityObject(IN SAM_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
SAMPR_SR_SECURITY_DESCRIPTOR DescriptorToPass;
ULONG Length;
NTSTATUS Status;
TRACE("SamSetSecurityObject(%p %lu %p)\n",
ObjectHandle, SecurityInformation, SecurityDescriptor);
/* Retrieve the length of the relative security descriptor */
Length = 0;
Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
NULL,
&Length);
if (Status != STATUS_BUFFER_TOO_SMALL)
return STATUS_INVALID_PARAMETER;
/* Allocate a buffer for the security descriptor */
DescriptorToPass.Length = Length;
DescriptorToPass.SecurityDescriptor = MIDL_user_allocate(Length);
if (DescriptorToPass.SecurityDescriptor == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
/* Convert the given security descriptor to a relative security descriptor */
Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
(PSECURITY_DESCRIPTOR)DescriptorToPass.SecurityDescriptor,
&Length);
if (!NT_SUCCESS(Status))
goto done;
RpcTryExcept
{
Status = SamrSetSecurityObject((SAMPR_HANDLE)ObjectHandle,
SecurityInformation,
&DescriptorToPass);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
done:
if (DescriptorToPass.SecurityDescriptor != NULL)
MIDL_user_free(DescriptorToPass.SecurityDescriptor);
return Status;
}
NTSTATUS
NTAPI
SamShutdownSamServer(IN SAM_HANDLE ServerHandle)
{
NTSTATUS Status;
TRACE("(%p)\n", ServerHandle);
RpcTryExcept
{
Status = SamrShutdownSamServer((SAMPR_HANDLE)ServerHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamTestPrivateFunctionsDomain(
_In_ SAM_HANDLE DomainHandle)
{
TRACE("SamTestPrivateFunctionsDomain(%p)\n",
DomainHandle);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
SamTestPrivateFunctionsUser(
_In_ SAM_HANDLE UserHandle)
{
TRACE("SamTestPrivateFunctionsUser(%p)\n",
UserHandle);
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */