You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
774 lines
22 KiB
774 lines
22 KiB
/******************************************************************************
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
*
|
|
* Module Name:
|
|
* srpasswd.cpp
|
|
*
|
|
* Abstract:
|
|
* password filter routines to restore user's latest passwords
|
|
*
|
|
* Revision History:
|
|
* Henry Lee (henrylee) 06/27/2000 created
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "stdwin.h"
|
|
#include <ntlsa.h>
|
|
#include <ntsam.h>
|
|
|
|
extern "C"
|
|
{
|
|
#include <ntsamp.h>
|
|
#include <recovery.h>
|
|
}
|
|
|
|
#include "rstrcore.h"
|
|
extern CSRClientLoader g_CSRClientLoader;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterNotificationDLL
|
|
//
|
|
// Synopsis: registers/unregisters this DLL
|
|
//
|
|
// Arguments: [fRegister] -- TRUE to register, FALSE to unregister
|
|
// [hKeyLM] -- key for HKEY_LOCAL_MACHINE or System
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD RegisterNotificationDLL (HKEY hKeyLM, BOOL fRegister)
|
|
{
|
|
HKEY hKey = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG ulType;
|
|
ULONG ulSize = MAX_PATH * sizeof(WCHAR);
|
|
WCHAR wcsBuffer[MAX_PATH];
|
|
WCHAR wcsFileName[MAX_PATH];
|
|
|
|
GetModuleFileNameW (g_hInst, wcsFileName, MAX_PATH);
|
|
const ULONG ccFileName = lstrlenW (wcsFileName) + 1;
|
|
|
|
if (hKeyLM == HKEY_LOCAL_MACHINE)
|
|
{
|
|
lstrcpy (wcsBuffer, L"System\\CurrentControlSet\\Control\\Lsa");
|
|
}
|
|
else
|
|
{
|
|
lstrcpy(wcsBuffer, L"CurrentControlSet\\Control\\Lsa");
|
|
ChangeCCS(hKeyLM, wcsBuffer);
|
|
}
|
|
|
|
dwErr = RegOpenKeyExW (hKeyLM, wcsBuffer,
|
|
0, KEY_READ | KEY_WRITE, &hKey);
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
dwErr = RegQueryValueEx (hKey, L"Notification Packages",
|
|
0, &ulType, (BYTE *) wcsBuffer, &ulSize);
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
for (ULONG i=0; i < ulSize/sizeof(WCHAR); i += lstrlenW(&wcsBuffer[i])+1)
|
|
{
|
|
if (fRegister) // append at end
|
|
{
|
|
if (lstrcmpi (&wcsBuffer[i], wcsFileName) == 0)
|
|
goto Err; // it's already registered
|
|
|
|
if (wcsBuffer[i] == L'\0') // end of list
|
|
{
|
|
lstrcpy (&wcsBuffer[i], wcsFileName);
|
|
wcsBuffer[ i + ccFileName ] = L'\0'; // add double NULL
|
|
ulSize += ccFileName * sizeof(WCHAR);
|
|
break;
|
|
}
|
|
}
|
|
else // remove from the end
|
|
{
|
|
if (lstrcmpi (&wcsBuffer[i], wcsFileName) == 0)
|
|
{
|
|
wcsBuffer[i] = L'\0';
|
|
ulSize -= ccFileName * sizeof(WCHAR);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
dwErr = RegSetValueExW (hKey, L"Notification Packages",
|
|
0, ulType, (BYTE *) wcsBuffer, ulSize);
|
|
Err:
|
|
if (hKey != NULL)
|
|
RegCloseKey (hKey);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDomainId
|
|
//
|
|
// Synopsis: stolen from setup, get the local domain ID
|
|
//
|
|
// Arguments: [ServerHandle] -- handle to the local SAM server
|
|
// [pDomainId] -- output domain ID
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
NTSTATUS GetDomainId (SAM_HANDLE ServerHandle, PSID * pDomainId )
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
SAM_ENUMERATE_HANDLE EnumContext;
|
|
PSAM_RID_ENUMERATION EnumBuffer = NULL;
|
|
DWORD CountReturned = 0;
|
|
PSID LocalDomainId = NULL;
|
|
DWORD LocalBuiltinDomainSid[sizeof(SID) / sizeof(DWORD) +
|
|
SID_MAX_SUB_AUTHORITIES];
|
|
SID_IDENTIFIER_AUTHORITY BuiltinAuthority = SECURITY_NT_AUTHORITY;
|
|
BOOL bExit = FALSE;
|
|
|
|
//
|
|
// Compute the builtin domain sid.
|
|
//
|
|
RtlInitializeSid((PSID) LocalBuiltinDomainSid, &BuiltinAuthority, 1);
|
|
*(RtlSubAuthoritySid((PSID)LocalBuiltinDomainSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
|
|
|
|
//
|
|
// Loop getting the list of domain ids from SAM
|
|
//
|
|
EnumContext = 0;
|
|
do
|
|
{
|
|
//
|
|
// Get several domain names.
|
|
//
|
|
status = SamEnumerateDomainsInSamServer (
|
|
ServerHandle,
|
|
&EnumContext,
|
|
(PVOID *) &EnumBuffer,
|
|
8192,
|
|
&CountReturned );
|
|
|
|
if (!NT_SUCCESS (status))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (status != STATUS_MORE_ENTRIES)
|
|
{
|
|
bExit = TRUE;
|
|
}
|
|
|
|
//
|
|
// Lookup the domain ids for the domains
|
|
//
|
|
for (ULONG i = 0; i < CountReturned; i++)
|
|
{
|
|
//
|
|
// Free the sid from the previous iteration.
|
|
//
|
|
if (LocalDomainId != NULL)
|
|
{
|
|
SamFreeMemory (LocalDomainId);
|
|
LocalDomainId = NULL;
|
|
}
|
|
|
|
//
|
|
// Lookup the domain id
|
|
//
|
|
status = SamLookupDomainInSamServer (
|
|
ServerHandle,
|
|
&EnumBuffer[i].Name,
|
|
&LocalDomainId );
|
|
|
|
if (!NT_SUCCESS (status))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (RtlEqualSid ((PSID)LocalBuiltinDomainSid, LocalDomainId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
*pDomainId = LocalDomainId;
|
|
LocalDomainId = NULL;
|
|
status = STATUS_SUCCESS;
|
|
goto exit;
|
|
}
|
|
|
|
SamFreeMemory(EnumBuffer);
|
|
EnumBuffer = NULL;
|
|
}
|
|
while (!bExit);
|
|
|
|
status = STATUS_NO_SUCH_DOMAIN;
|
|
|
|
exit:
|
|
if (EnumBuffer != NULL)
|
|
SamFreeMemory(EnumBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ForAllUsers
|
|
//
|
|
// Synopsis: iterate password changing for all local users
|
|
//
|
|
// Arguments: [hSam] -- handle to open SAM hive
|
|
// [hSecurity] -- handle to open SECURITY hive
|
|
// [hSystem] -- handle to open SYSTEM hive
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
NTSTATUS ForAllUsers (HKEY hSam, HKEY hSecurity, HKEY hSystem)
|
|
{
|
|
NTSTATUS nts = STATUS_SUCCESS;
|
|
NTSTATUS ntsEnum = STATUS_SUCCESS;
|
|
BOOLEAN bPresent;
|
|
BOOLEAN bNonNull;
|
|
SAM_HANDLE ServerHandle = NULL;
|
|
SAM_HANDLE DomainHandle = NULL;
|
|
SAM_HANDLE UserHandle;
|
|
SAM_ENUMERATE_HANDLE EnumerationContext = NULL;
|
|
SAM_RID_ENUMERATION *SamRidEnumeration;
|
|
ULONG CountOfEntries;
|
|
ULONG UserRid;
|
|
UNICODE_STRING us;
|
|
PSID LocalDomainId = NULL;
|
|
USER_INTERNAL1_INFORMATION UserPasswordInfo;
|
|
|
|
RtlInitUnicodeString (&us, L""); // this machine
|
|
nts = SamConnect (&us, &ServerHandle,
|
|
SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN |
|
|
SAM_SERVER_ENUMERATE_DOMAINS,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(nts))
|
|
goto Err;
|
|
|
|
nts = GetDomainId (ServerHandle, &LocalDomainId);
|
|
|
|
if (!NT_SUCCESS(nts))
|
|
goto Err;
|
|
|
|
nts = SamOpenDomain( ServerHandle,
|
|
DOMAIN_READ | DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP |
|
|
DOMAIN_READ_PASSWORD_PARAMETERS,
|
|
LocalDomainId,
|
|
&DomainHandle );
|
|
|
|
if (!NT_SUCCESS(nts))
|
|
goto Err;
|
|
|
|
do
|
|
{
|
|
ntsEnum = nts = SamEnumerateUsersInDomain (
|
|
DomainHandle,
|
|
&EnumerationContext,
|
|
0,
|
|
(PVOID *) &SamRidEnumeration,
|
|
0,
|
|
&CountOfEntries);
|
|
|
|
if (nts != STATUS_MORE_ENTRIES && !NT_SUCCESS(nts))
|
|
{
|
|
goto Err;
|
|
}
|
|
|
|
for (UINT i=0; i < CountOfEntries; i++)
|
|
{
|
|
ULONG UserRid = SamRidEnumeration[i].RelativeId;
|
|
|
|
nts = SamRetrieveOwfPasswordUser( UserRid,
|
|
hSecurity,
|
|
hSam,
|
|
hSystem,
|
|
NULL, /* boot key not supported */
|
|
0, /* boot key not supported */
|
|
&UserPasswordInfo.NtOwfPassword,
|
|
&bPresent,
|
|
&bNonNull);
|
|
|
|
if (!NT_SUCCESS(nts))
|
|
continue;
|
|
|
|
nts = SamOpenUser (DomainHandle,
|
|
USER_READ_ACCOUNT | USER_WRITE_ACCOUNT |
|
|
USER_CHANGE_PASSWORD |
|
|
USER_FORCE_PASSWORD_CHANGE,
|
|
UserRid,
|
|
&UserHandle);
|
|
|
|
if (NT_SUCCESS(nts))
|
|
{
|
|
UserPasswordInfo.NtPasswordPresent = bPresent;
|
|
UserPasswordInfo.LmPasswordPresent = FALSE;
|
|
UserPasswordInfo.PasswordExpired = FALSE;
|
|
|
|
nts = SamSetInformationUser(UserHandle,
|
|
UserInternal1Information,
|
|
&UserPasswordInfo);
|
|
|
|
SamCloseHandle (UserHandle);
|
|
}
|
|
}
|
|
|
|
SamFreeMemory (SamRidEnumeration);
|
|
}
|
|
while (ntsEnum == STATUS_MORE_ENTRIES);
|
|
|
|
|
|
Err:
|
|
if (ServerHandle != NULL)
|
|
SamCloseHandle (ServerHandle);
|
|
|
|
if (DomainHandle != NULL)
|
|
SamCloseHandle (DomainHandle);
|
|
|
|
if (LocalDomainId != NULL)
|
|
SamFreeMemory (LocalDomainId);
|
|
|
|
return nts;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RestoreLsaSecrets
|
|
//
|
|
// Synopsis: restore machine account and autologon passwords
|
|
//
|
|
// Arguments:
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD RestoreLsaSecrets ()
|
|
{
|
|
HKEY hKey = NULL;
|
|
LSA_OBJECT_ATTRIBUTES loa;
|
|
LSA_HANDLE hLsa = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG ulSize = 0;
|
|
ULONG ulType = 0;
|
|
WCHAR wcsBuffer [MAX_PATH];
|
|
|
|
loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
|
|
loa.RootDirectory = NULL;
|
|
loa.ObjectName = NULL;
|
|
loa.Attributes = 0;
|
|
loa.SecurityDescriptor = NULL;
|
|
loa.SecurityQualityOfService = NULL;
|
|
|
|
if (LSA_SUCCESS (LsaOpenPolicy(NULL, &loa,
|
|
POLICY_VIEW_LOCAL_INFORMATION, &hLsa)))
|
|
{
|
|
dwErr = RegOpenKeyExW (HKEY_LOCAL_MACHINE, s_cszSRRegKey,
|
|
0, KEY_READ | KEY_WRITE, &hKey);
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
ulSize = MAX_PATH * sizeof(WCHAR);
|
|
if (ERROR_SUCCESS == RegQueryValueEx (hKey, s_cszMachineSecret,
|
|
0, &ulType, (BYTE *) wcsBuffer, &ulSize))
|
|
{
|
|
wcsBuffer [ulSize / 2] = L'\0';
|
|
dwErr = SetLsaSecret (hLsa, s_cszMachineSecret, wcsBuffer);
|
|
if (ERROR_SUCCESS != dwErr)
|
|
goto Err;
|
|
|
|
RegDeleteValueW (hKey, s_cszMachineSecret);
|
|
}
|
|
|
|
ulSize = MAX_PATH * sizeof(WCHAR);
|
|
if (ERROR_SUCCESS == RegQueryValueEx (hKey, s_cszAutologonSecret,
|
|
0, &ulType, (BYTE *) wcsBuffer, &ulSize))
|
|
{
|
|
wcsBuffer [ulSize / 2] = L'\0';
|
|
dwErr = SetLsaSecret (hLsa, s_cszAutologonSecret, wcsBuffer);
|
|
if (ERROR_SUCCESS != dwErr)
|
|
goto Err;
|
|
|
|
RegDeleteValueW (hKey, s_cszAutologonSecret);
|
|
}
|
|
}
|
|
Err:
|
|
if (hKey != NULL)
|
|
RegCloseKey (hKey);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RestoreRIDs
|
|
//
|
|
// Synopsis: restore next availble RID and password
|
|
//
|
|
// Arguments:
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD RestoreRIDs (WCHAR *pszSamPath)
|
|
{
|
|
HKEY hKeySam = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG ulNextRid = 0;
|
|
ULONG ulOldRid = 0;
|
|
|
|
TENTER("RestoreRIDs");
|
|
|
|
dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName,
|
|
pszSamPath);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegLoadKeyW : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszSamHiveName, &hKeySam);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegOpenKeyW on %S: %ld", s_cszSamHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RtlNtStatusToDosError(SamGetNextAvailableRid (hKeySam, &ulNextRid));
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! SamGetNextAvailableRid : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
RegCloseKey (hKeySam);
|
|
hKeySam = NULL;
|
|
|
|
dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName, &hKeySam);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSAMHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
// as an optimization we don't set the RID if it didn't change
|
|
if (NT_SUCCESS(SamGetNextAvailableRid (hKeySam, &ulOldRid)) &&
|
|
ulNextRid > ulOldRid)
|
|
{
|
|
dwErr = RtlNtStatusToDosError(SamSetNextAvailableRid (hKeySam,
|
|
ulNextRid));
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! SamSetNextAvailableRid : %ld", dwErr);
|
|
}
|
|
}
|
|
|
|
Err:
|
|
if (hKeySam != NULL)
|
|
{
|
|
RegCloseKey (hKeySam);
|
|
}
|
|
RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName);
|
|
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD RestorePasswords ()
|
|
{
|
|
HKEY hKeySam = NULL, hKeySecurity = NULL, hKeySystem = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wcsSystem [MAX_PATH];
|
|
WCHAR wcsPath [MAX_PATH];
|
|
BOOLEAN OldPriv;
|
|
CRestorePoint rp;
|
|
DWORD dwTemp;
|
|
|
|
InitAsyncTrace();
|
|
|
|
TENTER("RestorePasswords");
|
|
|
|
// Attempt to get restore privilege
|
|
dwErr = RtlNtStatusToDosError (RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&OldPriv));
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RtlAdjustPrivilege : %ld", dwErr);
|
|
goto Err0;
|
|
}
|
|
|
|
if (FALSE == GetSystemDrive (wcsSystem))
|
|
{
|
|
dwErr = GetLastError();
|
|
trace(0, "! GetSystemDrive : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = GetCurrentRestorePoint(rp);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! GetCurrentRestorePoint : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
MakeRestorePath (wcsPath, wcsSystem, rp.GetDir());
|
|
lstrcatW (wcsPath, SNAPSHOT_DIR_NAME);
|
|
lstrcatW (wcsPath, L"\\");
|
|
lstrcatW (wcsPath, s_cszHKLMFilePrefix);
|
|
lstrcatW (wcsPath, s_cszSamHiveName);
|
|
|
|
dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName, wcsPath);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegLoadKeyW on %S: %ld", s_cszRestoreSAMHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName, &hKeySam);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSAMHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
MakeRestorePath (wcsPath, wcsSystem, rp.GetDir());
|
|
lstrcatW (wcsPath, SNAPSHOT_DIR_NAME);
|
|
lstrcatW (wcsPath, L"\\");
|
|
lstrcatW (wcsPath, s_cszHKLMFilePrefix);
|
|
lstrcatW (wcsPath, s_cszSecurityHiveName);
|
|
|
|
dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSECURITYHiveName, wcsPath);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegLoadKeyW on %S: %ld", s_cszRestoreSECURITYHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSECURITYHiveName,&hKeySecurity);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSECURITYHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
MakeRestorePath (wcsPath, wcsSystem, rp.GetDir());
|
|
lstrcatW (wcsPath, SNAPSHOT_DIR_NAME);
|
|
lstrcatW (wcsPath, L"\\");
|
|
lstrcatW (wcsPath, s_cszHKLMFilePrefix);
|
|
lstrcatW (wcsPath, s_cszSystemHiveName);
|
|
|
|
dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSYSTEMHiveName, wcsPath);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegLoadKeyW on %S: %ld", s_cszRestoreSYSTEMHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSYSTEMHiveName, &hKeySystem);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSYSTEMHiveName, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RtlNtStatusToDosError(ForAllUsers(hKeySam,hKeySecurity,hKeySystem));
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! ForAllUsers : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = RestoreLsaSecrets ();
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! RestoreLsaSecrets : %ld", dwErr);
|
|
}
|
|
|
|
|
|
Err:
|
|
if (hKeySam != NULL)
|
|
{
|
|
RegCloseKey (hKeySam);
|
|
}
|
|
|
|
dwTemp = RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName);
|
|
if (ERROR_SUCCESS != dwTemp)
|
|
{
|
|
trace(0, "! RegUnLoadKeyW 0n %S : %ld", s_cszRestoreSAMHiveName, dwTemp);
|
|
}
|
|
|
|
if (hKeySecurity != NULL)
|
|
{
|
|
RegCloseKey (hKeySecurity);
|
|
}
|
|
dwTemp = RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSECURITYHiveName);
|
|
if (ERROR_SUCCESS != dwTemp)
|
|
{
|
|
trace(0, "! RegUnLoadKeyW 0n %S : %ld", s_cszRestoreSECURITYHiveName, dwTemp);
|
|
}
|
|
|
|
if (hKeySystem != NULL)
|
|
{
|
|
RegCloseKey (hKeySystem);
|
|
}
|
|
dwTemp = RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSYSTEMHiveName);
|
|
if (ERROR_SUCCESS != dwTemp)
|
|
{
|
|
trace(0, "! RegUnLoadKeyW 0n %S : %ld", s_cszRestoreSYSTEMHiveName, dwTemp);
|
|
}
|
|
|
|
// restore the old privilege
|
|
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, OldPriv, FALSE, &OldPriv);
|
|
|
|
Err0:
|
|
// unregister this notification package
|
|
RegisterNotificationDLL (HKEY_LOCAL_MACHINE, FALSE);
|
|
|
|
TermAsyncTrace();
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: WaitForSAM
|
|
//
|
|
// Synopsis: waits for SAM database to initialize
|
|
//
|
|
// Arguments:
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI WaitForSAM (VOID *pv)
|
|
{
|
|
NTSTATUS nts = STATUS_SUCCESS;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
DWORD WaitStatus;
|
|
UNICODE_STRING EventName;
|
|
HANDLE EventHandle;
|
|
OBJECT_ATTRIBUTES EventAttributes;
|
|
|
|
// Load SRClient
|
|
g_CSRClientLoader.LoadSrClient();
|
|
|
|
//
|
|
// open SAM event
|
|
//
|
|
|
|
RtlInitUnicodeString( &EventName, L"\\SAM_SERVICE_STARTED");
|
|
InitializeObjectAttributes( &EventAttributes, &EventName, 0, 0, NULL );
|
|
|
|
nts = NtOpenEvent( &EventHandle,
|
|
SYNCHRONIZE|EVENT_MODIFY_STATE,
|
|
&EventAttributes );
|
|
|
|
if ( !NT_SUCCESS(nts))
|
|
{
|
|
if( nts == STATUS_OBJECT_NAME_NOT_FOUND )
|
|
{
|
|
//
|
|
// SAM hasn't created this event yet, let us create it now.
|
|
// SAM opens this event to set it.
|
|
//
|
|
|
|
nts = NtCreateEvent( &EventHandle,
|
|
SYNCHRONIZE|EVENT_MODIFY_STATE,
|
|
&EventAttributes,
|
|
NotificationEvent,
|
|
FALSE ); // The event is initially not signaled
|
|
|
|
if( nts == STATUS_OBJECT_NAME_EXISTS ||
|
|
nts == STATUS_OBJECT_NAME_COLLISION )
|
|
{
|
|
//
|
|
// second chance, if the SAM created the event before we did
|
|
//
|
|
|
|
nts = NtOpenEvent( &EventHandle,
|
|
SYNCHRONIZE|EVENT_MODIFY_STATE,
|
|
&EventAttributes );
|
|
}
|
|
}
|
|
|
|
}
|
|
//
|
|
// Loop waiting.
|
|
//
|
|
|
|
if (NT_SUCCESS(nts))
|
|
{
|
|
WaitStatus = WaitForSingleObject( EventHandle, 60*1000 ); // 60 Seconds
|
|
|
|
if ( WaitStatus == WAIT_TIMEOUT )
|
|
{
|
|
nts = STATUS_TIMEOUT;
|
|
}
|
|
else if ( WaitStatus != WAIT_OBJECT_0 )
|
|
{
|
|
nts = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
(VOID) NtClose( EventHandle );
|
|
|
|
if (NT_SUCCESS(nts)) // Okay, SAM is available
|
|
{
|
|
dwErr = RestorePasswords();
|
|
}
|
|
else
|
|
{
|
|
dwErr = RtlNtStatusToDosError (nts);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: InitializeChangeNotify and PasswordChangeNotify
|
|
//
|
|
// Synopsis: callback functions from SAM
|
|
//
|
|
// Arguments:
|
|
//
|
|
// History: 12-Apr-2000 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOLEAN NTAPI InitializeChangeNotify ()
|
|
{
|
|
// we will call LoadSRClient from WaitForSAM
|
|
|
|
HANDLE hThread = CreateThread (NULL,
|
|
0,
|
|
WaitForSAM,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
NTSTATUS NTAPI PasswordChangeNotify ( PUNICODE_STRING UserName,
|
|
ULONG RelativeId,
|
|
PUNICODE_STRING NewPassword )
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|