Leaked source code of windows server 2003
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

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * srpasswd.cpp
  7. *
  8. * Abstract:
  9. * password filter routines to restore user's latest passwords
  10. *
  11. * Revision History:
  12. * Henry Lee (henrylee) 06/27/2000 created
  13. *
  14. *****************************************************************************/
  15. #include "stdwin.h"
  16. #include <ntlsa.h>
  17. #include <ntsam.h>
  18. extern "C"
  19. {
  20. #include <ntsamp.h>
  21. #include <recovery.h>
  22. }
  23. #include "rstrcore.h"
  24. extern CSRClientLoader g_CSRClientLoader;
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Function: RegisterNotificationDLL
  28. //
  29. // Synopsis: registers/unregisters this DLL
  30. //
  31. // Arguments: [fRegister] -- TRUE to register, FALSE to unregister
  32. // [hKeyLM] -- key for HKEY_LOCAL_MACHINE or System
  33. //
  34. // History: 12-Apr-2000 HenryLee Created
  35. //
  36. //----------------------------------------------------------------------------
  37. DWORD RegisterNotificationDLL (HKEY hKeyLM, BOOL fRegister)
  38. {
  39. HKEY hKey = NULL;
  40. DWORD dwErr = ERROR_SUCCESS;
  41. ULONG ulType;
  42. ULONG ulSize = MAX_PATH * sizeof(WCHAR);
  43. WCHAR wcsBuffer[MAX_PATH];
  44. WCHAR wcsFileName[MAX_PATH];
  45. GetModuleFileNameW (g_hInst, wcsFileName, MAX_PATH);
  46. const ULONG ccFileName = lstrlenW (wcsFileName) + 1;
  47. if (hKeyLM == HKEY_LOCAL_MACHINE)
  48. {
  49. lstrcpy (wcsBuffer, L"System\\CurrentControlSet\\Control\\Lsa");
  50. }
  51. else
  52. {
  53. lstrcpy(wcsBuffer, L"CurrentControlSet\\Control\\Lsa");
  54. ChangeCCS(hKeyLM, wcsBuffer);
  55. }
  56. dwErr = RegOpenKeyExW (hKeyLM, wcsBuffer,
  57. 0, KEY_READ | KEY_WRITE, &hKey);
  58. if (dwErr != ERROR_SUCCESS)
  59. goto Err;
  60. dwErr = RegQueryValueEx (hKey, L"Notification Packages",
  61. 0, &ulType, (BYTE *) wcsBuffer, &ulSize);
  62. if (dwErr != ERROR_SUCCESS)
  63. goto Err;
  64. for (ULONG i=0; i < ulSize/sizeof(WCHAR); i += lstrlenW(&wcsBuffer[i])+1)
  65. {
  66. if (fRegister) // append at end
  67. {
  68. if (lstrcmpi (&wcsBuffer[i], wcsFileName) == 0)
  69. goto Err; // it's already registered
  70. if (wcsBuffer[i] == L'\0') // end of list
  71. {
  72. lstrcpy (&wcsBuffer[i], wcsFileName);
  73. wcsBuffer[ i + ccFileName ] = L'\0'; // add double NULL
  74. ulSize += ccFileName * sizeof(WCHAR);
  75. break;
  76. }
  77. }
  78. else // remove from the end
  79. {
  80. if (lstrcmpi (&wcsBuffer[i], wcsFileName) == 0)
  81. {
  82. wcsBuffer[i] = L'\0';
  83. ulSize -= ccFileName * sizeof(WCHAR);
  84. break;
  85. }
  86. }
  87. }
  88. dwErr = RegSetValueExW (hKey, L"Notification Packages",
  89. 0, ulType, (BYTE *) wcsBuffer, ulSize);
  90. Err:
  91. if (hKey != NULL)
  92. RegCloseKey (hKey);
  93. return dwErr;
  94. }
  95. //+---------------------------------------------------------------------------
  96. //
  97. // Function: GetDomainId
  98. //
  99. // Synopsis: stolen from setup, get the local domain ID
  100. //
  101. // Arguments: [ServerHandle] -- handle to the local SAM server
  102. // [pDomainId] -- output domain ID
  103. //
  104. // History: 12-Apr-2000 HenryLee Created
  105. //
  106. //----------------------------------------------------------------------------
  107. NTSTATUS GetDomainId (SAM_HANDLE ServerHandle, PSID * pDomainId )
  108. {
  109. NTSTATUS status = STATUS_SUCCESS;
  110. SAM_ENUMERATE_HANDLE EnumContext;
  111. PSAM_RID_ENUMERATION EnumBuffer = NULL;
  112. DWORD CountReturned = 0;
  113. PSID LocalDomainId = NULL;
  114. DWORD LocalBuiltinDomainSid[sizeof(SID) / sizeof(DWORD) +
  115. SID_MAX_SUB_AUTHORITIES];
  116. SID_IDENTIFIER_AUTHORITY BuiltinAuthority = SECURITY_NT_AUTHORITY;
  117. BOOL bExit = FALSE;
  118. //
  119. // Compute the builtin domain sid.
  120. //
  121. RtlInitializeSid((PSID) LocalBuiltinDomainSid, &BuiltinAuthority, 1);
  122. *(RtlSubAuthoritySid((PSID)LocalBuiltinDomainSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
  123. //
  124. // Loop getting the list of domain ids from SAM
  125. //
  126. EnumContext = 0;
  127. do
  128. {
  129. //
  130. // Get several domain names.
  131. //
  132. status = SamEnumerateDomainsInSamServer (
  133. ServerHandle,
  134. &EnumContext,
  135. (PVOID *) &EnumBuffer,
  136. 8192,
  137. &CountReturned );
  138. if (!NT_SUCCESS (status))
  139. {
  140. goto exit;
  141. }
  142. if (status != STATUS_MORE_ENTRIES)
  143. {
  144. bExit = TRUE;
  145. }
  146. //
  147. // Lookup the domain ids for the domains
  148. //
  149. for (ULONG i = 0; i < CountReturned; i++)
  150. {
  151. //
  152. // Free the sid from the previous iteration.
  153. //
  154. if (LocalDomainId != NULL)
  155. {
  156. SamFreeMemory (LocalDomainId);
  157. LocalDomainId = NULL;
  158. }
  159. //
  160. // Lookup the domain id
  161. //
  162. status = SamLookupDomainInSamServer (
  163. ServerHandle,
  164. &EnumBuffer[i].Name,
  165. &LocalDomainId );
  166. if (!NT_SUCCESS (status))
  167. {
  168. goto exit;
  169. }
  170. if (RtlEqualSid ((PSID)LocalBuiltinDomainSid, LocalDomainId))
  171. {
  172. continue;
  173. }
  174. *pDomainId = LocalDomainId;
  175. LocalDomainId = NULL;
  176. status = STATUS_SUCCESS;
  177. goto exit;
  178. }
  179. SamFreeMemory(EnumBuffer);
  180. EnumBuffer = NULL;
  181. }
  182. while (!bExit);
  183. status = STATUS_NO_SUCH_DOMAIN;
  184. exit:
  185. if (EnumBuffer != NULL)
  186. SamFreeMemory(EnumBuffer);
  187. return status;
  188. }
  189. //+---------------------------------------------------------------------------
  190. //
  191. // Function: ForAllUsers
  192. //
  193. // Synopsis: iterate password changing for all local users
  194. //
  195. // Arguments: [hSam] -- handle to open SAM hive
  196. // [hSecurity] -- handle to open SECURITY hive
  197. // [hSystem] -- handle to open SYSTEM hive
  198. //
  199. // History: 12-Apr-2000 HenryLee Created
  200. //
  201. //----------------------------------------------------------------------------
  202. NTSTATUS ForAllUsers (HKEY hSam, HKEY hSecurity, HKEY hSystem)
  203. {
  204. NTSTATUS nts = STATUS_SUCCESS;
  205. NTSTATUS ntsEnum = STATUS_SUCCESS;
  206. BOOLEAN bPresent;
  207. BOOLEAN bNonNull;
  208. SAM_HANDLE ServerHandle = NULL;
  209. SAM_HANDLE DomainHandle = NULL;
  210. SAM_HANDLE UserHandle;
  211. SAM_ENUMERATE_HANDLE EnumerationContext = NULL;
  212. SAM_RID_ENUMERATION *SamRidEnumeration;
  213. ULONG CountOfEntries;
  214. ULONG UserRid;
  215. UNICODE_STRING us;
  216. PSID LocalDomainId = NULL;
  217. USER_INTERNAL1_INFORMATION UserPasswordInfo;
  218. RtlInitUnicodeString (&us, L""); // this machine
  219. nts = SamConnect (&us, &ServerHandle,
  220. SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN |
  221. SAM_SERVER_ENUMERATE_DOMAINS,
  222. NULL);
  223. if (!NT_SUCCESS(nts))
  224. goto Err;
  225. nts = GetDomainId (ServerHandle, &LocalDomainId);
  226. if (!NT_SUCCESS(nts))
  227. goto Err;
  228. nts = SamOpenDomain( ServerHandle,
  229. DOMAIN_READ | DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP |
  230. DOMAIN_READ_PASSWORD_PARAMETERS,
  231. LocalDomainId,
  232. &DomainHandle );
  233. if (!NT_SUCCESS(nts))
  234. goto Err;
  235. do
  236. {
  237. ntsEnum = nts = SamEnumerateUsersInDomain (
  238. DomainHandle,
  239. &EnumerationContext,
  240. 0,
  241. (PVOID *) &SamRidEnumeration,
  242. 0,
  243. &CountOfEntries);
  244. if (nts != STATUS_MORE_ENTRIES && !NT_SUCCESS(nts))
  245. {
  246. goto Err;
  247. }
  248. for (UINT i=0; i < CountOfEntries; i++)
  249. {
  250. ULONG UserRid = SamRidEnumeration[i].RelativeId;
  251. nts = SamRetrieveOwfPasswordUser( UserRid,
  252. hSecurity,
  253. hSam,
  254. hSystem,
  255. NULL, /* boot key not supported */
  256. 0, /* boot key not supported */
  257. &UserPasswordInfo.NtOwfPassword,
  258. &bPresent,
  259. &bNonNull);
  260. if (!NT_SUCCESS(nts))
  261. continue;
  262. nts = SamOpenUser (DomainHandle,
  263. USER_READ_ACCOUNT | USER_WRITE_ACCOUNT |
  264. USER_CHANGE_PASSWORD |
  265. USER_FORCE_PASSWORD_CHANGE,
  266. UserRid,
  267. &UserHandle);
  268. if (NT_SUCCESS(nts))
  269. {
  270. UserPasswordInfo.NtPasswordPresent = bPresent;
  271. UserPasswordInfo.LmPasswordPresent = FALSE;
  272. UserPasswordInfo.PasswordExpired = FALSE;
  273. nts = SamSetInformationUser(UserHandle,
  274. UserInternal1Information,
  275. &UserPasswordInfo);
  276. SamCloseHandle (UserHandle);
  277. }
  278. }
  279. SamFreeMemory (SamRidEnumeration);
  280. }
  281. while (ntsEnum == STATUS_MORE_ENTRIES);
  282. Err:
  283. if (ServerHandle != NULL)
  284. SamCloseHandle (ServerHandle);
  285. if (DomainHandle != NULL)
  286. SamCloseHandle (DomainHandle);
  287. if (LocalDomainId != NULL)
  288. SamFreeMemory (LocalDomainId);
  289. return nts;
  290. }
  291. //+---------------------------------------------------------------------------
  292. //
  293. // Function: RestoreLsaSecrets
  294. //
  295. // Synopsis: restore machine account and autologon passwords
  296. //
  297. // Arguments:
  298. //
  299. // History: 12-Apr-2000 HenryLee Created
  300. //
  301. //----------------------------------------------------------------------------
  302. DWORD RestoreLsaSecrets ()
  303. {
  304. HKEY hKey = NULL;
  305. LSA_OBJECT_ATTRIBUTES loa;
  306. LSA_HANDLE hLsa = NULL;
  307. DWORD dwErr = ERROR_SUCCESS;
  308. ULONG ulSize = 0;
  309. ULONG ulType = 0;
  310. WCHAR wcsBuffer [MAX_PATH];
  311. loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
  312. loa.RootDirectory = NULL;
  313. loa.ObjectName = NULL;
  314. loa.Attributes = 0;
  315. loa.SecurityDescriptor = NULL;
  316. loa.SecurityQualityOfService = NULL;
  317. if (LSA_SUCCESS (LsaOpenPolicy(NULL, &loa,
  318. POLICY_VIEW_LOCAL_INFORMATION, &hLsa)))
  319. {
  320. dwErr = RegOpenKeyExW (HKEY_LOCAL_MACHINE, s_cszSRRegKey,
  321. 0, KEY_READ | KEY_WRITE, &hKey);
  322. if (dwErr != ERROR_SUCCESS)
  323. goto Err;
  324. ulSize = MAX_PATH * sizeof(WCHAR);
  325. if (ERROR_SUCCESS == RegQueryValueEx (hKey, s_cszMachineSecret,
  326. 0, &ulType, (BYTE *) wcsBuffer, &ulSize))
  327. {
  328. wcsBuffer [ulSize / 2] = L'\0';
  329. dwErr = SetLsaSecret (hLsa, s_cszMachineSecret, wcsBuffer);
  330. if (ERROR_SUCCESS != dwErr)
  331. goto Err;
  332. RegDeleteValueW (hKey, s_cszMachineSecret);
  333. }
  334. ulSize = MAX_PATH * sizeof(WCHAR);
  335. if (ERROR_SUCCESS == RegQueryValueEx (hKey, s_cszAutologonSecret,
  336. 0, &ulType, (BYTE *) wcsBuffer, &ulSize))
  337. {
  338. wcsBuffer [ulSize / 2] = L'\0';
  339. dwErr = SetLsaSecret (hLsa, s_cszAutologonSecret, wcsBuffer);
  340. if (ERROR_SUCCESS != dwErr)
  341. goto Err;
  342. RegDeleteValueW (hKey, s_cszAutologonSecret);
  343. }
  344. }
  345. Err:
  346. if (hKey != NULL)
  347. RegCloseKey (hKey);
  348. return dwErr;
  349. }
  350. //+---------------------------------------------------------------------------
  351. //
  352. // Function: RestoreRIDs
  353. //
  354. // Synopsis: restore next availble RID and password
  355. //
  356. // Arguments:
  357. //
  358. // History: 12-Apr-2000 HenryLee Created
  359. //
  360. //----------------------------------------------------------------------------
  361. DWORD RestoreRIDs (WCHAR *pszSamPath)
  362. {
  363. HKEY hKeySam = NULL;
  364. DWORD dwErr = ERROR_SUCCESS;
  365. ULONG ulNextRid = 0;
  366. ULONG ulOldRid = 0;
  367. TENTER("RestoreRIDs");
  368. dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName,
  369. pszSamPath);
  370. if (dwErr != ERROR_SUCCESS)
  371. {
  372. trace(0, "! RegLoadKeyW : %ld", dwErr);
  373. goto Err;
  374. }
  375. dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszSamHiveName, &hKeySam);
  376. if (dwErr != ERROR_SUCCESS)
  377. {
  378. trace(0, "! RegOpenKeyW on %S: %ld", s_cszSamHiveName, dwErr);
  379. goto Err;
  380. }
  381. dwErr = RtlNtStatusToDosError(SamGetNextAvailableRid (hKeySam, &ulNextRid));
  382. if (dwErr != ERROR_SUCCESS)
  383. {
  384. trace(0, "! SamGetNextAvailableRid : %ld", dwErr);
  385. goto Err;
  386. }
  387. RegCloseKey (hKeySam);
  388. hKeySam = NULL;
  389. dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName, &hKeySam);
  390. if (dwErr != ERROR_SUCCESS)
  391. {
  392. trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSAMHiveName, dwErr);
  393. goto Err;
  394. }
  395. // as an optimization we don't set the RID if it didn't change
  396. if (NT_SUCCESS(SamGetNextAvailableRid (hKeySam, &ulOldRid)) &&
  397. ulNextRid > ulOldRid)
  398. {
  399. dwErr = RtlNtStatusToDosError(SamSetNextAvailableRid (hKeySam,
  400. ulNextRid));
  401. if (dwErr != ERROR_SUCCESS)
  402. {
  403. trace(0, "! SamSetNextAvailableRid : %ld", dwErr);
  404. }
  405. }
  406. Err:
  407. if (hKeySam != NULL)
  408. {
  409. RegCloseKey (hKeySam);
  410. }
  411. RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName);
  412. TLEAVE();
  413. return dwErr;
  414. }
  415. DWORD RestorePasswords ()
  416. {
  417. HKEY hKeySam = NULL, hKeySecurity = NULL, hKeySystem = NULL;
  418. DWORD dwErr = ERROR_SUCCESS;
  419. WCHAR wcsSystem [MAX_PATH];
  420. WCHAR wcsPath [MAX_PATH];
  421. BOOLEAN OldPriv;
  422. CRestorePoint rp;
  423. DWORD dwTemp;
  424. InitAsyncTrace();
  425. TENTER("RestorePasswords");
  426. // Attempt to get restore privilege
  427. dwErr = RtlNtStatusToDosError (RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
  428. TRUE,
  429. FALSE,
  430. &OldPriv));
  431. if (dwErr != ERROR_SUCCESS)
  432. {
  433. trace(0, "! RtlAdjustPrivilege : %ld", dwErr);
  434. goto Err0;
  435. }
  436. if (FALSE == GetSystemDrive (wcsSystem))
  437. {
  438. dwErr = GetLastError();
  439. trace(0, "! GetSystemDrive : %ld", dwErr);
  440. goto Err;
  441. }
  442. dwErr = GetCurrentRestorePoint(rp);
  443. if (dwErr != ERROR_SUCCESS)
  444. {
  445. trace(0, "! GetCurrentRestorePoint : %ld", dwErr);
  446. goto Err;
  447. }
  448. MakeRestorePath (wcsPath, wcsSystem, rp.GetDir());
  449. lstrcatW (wcsPath, SNAPSHOT_DIR_NAME);
  450. lstrcatW (wcsPath, L"\\");
  451. lstrcatW (wcsPath, s_cszHKLMFilePrefix);
  452. lstrcatW (wcsPath, s_cszSamHiveName);
  453. dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName, wcsPath);
  454. if (dwErr != ERROR_SUCCESS)
  455. {
  456. trace(0, "! RegLoadKeyW on %S: %ld", s_cszRestoreSAMHiveName, dwErr);
  457. goto Err;
  458. }
  459. dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName, &hKeySam);
  460. if (dwErr != ERROR_SUCCESS)
  461. {
  462. trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSAMHiveName, dwErr);
  463. goto Err;
  464. }
  465. MakeRestorePath (wcsPath, wcsSystem, rp.GetDir());
  466. lstrcatW (wcsPath, SNAPSHOT_DIR_NAME);
  467. lstrcatW (wcsPath, L"\\");
  468. lstrcatW (wcsPath, s_cszHKLMFilePrefix);
  469. lstrcatW (wcsPath, s_cszSecurityHiveName);
  470. dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSECURITYHiveName, wcsPath);
  471. if (dwErr != ERROR_SUCCESS)
  472. {
  473. trace(0, "! RegLoadKeyW on %S: %ld", s_cszRestoreSECURITYHiveName, dwErr);
  474. goto Err;
  475. }
  476. dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSECURITYHiveName,&hKeySecurity);
  477. if (dwErr != ERROR_SUCCESS)
  478. {
  479. trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSECURITYHiveName, dwErr);
  480. goto Err;
  481. }
  482. MakeRestorePath (wcsPath, wcsSystem, rp.GetDir());
  483. lstrcatW (wcsPath, SNAPSHOT_DIR_NAME);
  484. lstrcatW (wcsPath, L"\\");
  485. lstrcatW (wcsPath, s_cszHKLMFilePrefix);
  486. lstrcatW (wcsPath, s_cszSystemHiveName);
  487. dwErr = RegLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSYSTEMHiveName, wcsPath);
  488. if (dwErr != ERROR_SUCCESS)
  489. {
  490. trace(0, "! RegLoadKeyW on %S: %ld", s_cszRestoreSYSTEMHiveName, dwErr);
  491. goto Err;
  492. }
  493. dwErr = RegOpenKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSYSTEMHiveName, &hKeySystem);
  494. if (dwErr != ERROR_SUCCESS)
  495. {
  496. trace(0, "! RegOpenKeyW on %S: %ld", s_cszRestoreSYSTEMHiveName, dwErr);
  497. goto Err;
  498. }
  499. dwErr = RtlNtStatusToDosError(ForAllUsers(hKeySam,hKeySecurity,hKeySystem));
  500. if (dwErr != ERROR_SUCCESS)
  501. {
  502. trace(0, "! ForAllUsers : %ld", dwErr);
  503. goto Err;
  504. }
  505. dwErr = RestoreLsaSecrets ();
  506. if (dwErr != ERROR_SUCCESS)
  507. {
  508. trace(0, "! RestoreLsaSecrets : %ld", dwErr);
  509. }
  510. Err:
  511. if (hKeySam != NULL)
  512. {
  513. RegCloseKey (hKeySam);
  514. }
  515. dwTemp = RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSAMHiveName);
  516. if (ERROR_SUCCESS != dwTemp)
  517. {
  518. trace(0, "! RegUnLoadKeyW 0n %S : %ld", s_cszRestoreSAMHiveName, dwTemp);
  519. }
  520. if (hKeySecurity != NULL)
  521. {
  522. RegCloseKey (hKeySecurity);
  523. }
  524. dwTemp = RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSECURITYHiveName);
  525. if (ERROR_SUCCESS != dwTemp)
  526. {
  527. trace(0, "! RegUnLoadKeyW 0n %S : %ld", s_cszRestoreSECURITYHiveName, dwTemp);
  528. }
  529. if (hKeySystem != NULL)
  530. {
  531. RegCloseKey (hKeySystem);
  532. }
  533. dwTemp = RegUnLoadKeyW (HKEY_LOCAL_MACHINE, s_cszRestoreSYSTEMHiveName);
  534. if (ERROR_SUCCESS != dwTemp)
  535. {
  536. trace(0, "! RegUnLoadKeyW 0n %S : %ld", s_cszRestoreSYSTEMHiveName, dwTemp);
  537. }
  538. // restore the old privilege
  539. RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, OldPriv, FALSE, &OldPriv);
  540. Err0:
  541. // unregister this notification package
  542. RegisterNotificationDLL (HKEY_LOCAL_MACHINE, FALSE);
  543. TermAsyncTrace();
  544. return dwErr;
  545. }
  546. //+---------------------------------------------------------------------------
  547. //
  548. // Function: WaitForSAM
  549. //
  550. // Synopsis: waits for SAM database to initialize
  551. //
  552. // Arguments:
  553. //
  554. // History: 12-Apr-2000 HenryLee Created
  555. //
  556. //----------------------------------------------------------------------------
  557. DWORD WINAPI WaitForSAM (VOID *pv)
  558. {
  559. NTSTATUS nts = STATUS_SUCCESS;
  560. DWORD dwErr = ERROR_SUCCESS;
  561. DWORD WaitStatus;
  562. UNICODE_STRING EventName;
  563. HANDLE EventHandle;
  564. OBJECT_ATTRIBUTES EventAttributes;
  565. // Load SRClient
  566. g_CSRClientLoader.LoadSrClient();
  567. //
  568. // open SAM event
  569. //
  570. RtlInitUnicodeString( &EventName, L"\\SAM_SERVICE_STARTED");
  571. InitializeObjectAttributes( &EventAttributes, &EventName, 0, 0, NULL );
  572. nts = NtOpenEvent( &EventHandle,
  573. SYNCHRONIZE|EVENT_MODIFY_STATE,
  574. &EventAttributes );
  575. if ( !NT_SUCCESS(nts))
  576. {
  577. if( nts == STATUS_OBJECT_NAME_NOT_FOUND )
  578. {
  579. //
  580. // SAM hasn't created this event yet, let us create it now.
  581. // SAM opens this event to set it.
  582. //
  583. nts = NtCreateEvent( &EventHandle,
  584. SYNCHRONIZE|EVENT_MODIFY_STATE,
  585. &EventAttributes,
  586. NotificationEvent,
  587. FALSE ); // The event is initially not signaled
  588. if( nts == STATUS_OBJECT_NAME_EXISTS ||
  589. nts == STATUS_OBJECT_NAME_COLLISION )
  590. {
  591. //
  592. // second chance, if the SAM created the event before we did
  593. //
  594. nts = NtOpenEvent( &EventHandle,
  595. SYNCHRONIZE|EVENT_MODIFY_STATE,
  596. &EventAttributes );
  597. }
  598. }
  599. }
  600. //
  601. // Loop waiting.
  602. //
  603. if (NT_SUCCESS(nts))
  604. {
  605. WaitStatus = WaitForSingleObject( EventHandle, 60*1000 ); // 60 Seconds
  606. if ( WaitStatus == WAIT_TIMEOUT )
  607. {
  608. nts = STATUS_TIMEOUT;
  609. }
  610. else if ( WaitStatus != WAIT_OBJECT_0 )
  611. {
  612. nts = STATUS_UNSUCCESSFUL;
  613. }
  614. }
  615. (VOID) NtClose( EventHandle );
  616. if (NT_SUCCESS(nts)) // Okay, SAM is available
  617. {
  618. dwErr = RestorePasswords();
  619. }
  620. else
  621. {
  622. dwErr = RtlNtStatusToDosError (nts);
  623. }
  624. return dwErr;
  625. }
  626. //+---------------------------------------------------------------------------
  627. //
  628. // Function: InitializeChangeNotify and PasswordChangeNotify
  629. //
  630. // Synopsis: callback functions from SAM
  631. //
  632. // Arguments:
  633. //
  634. // History: 12-Apr-2000 HenryLee Created
  635. //
  636. //----------------------------------------------------------------------------
  637. BOOLEAN NTAPI InitializeChangeNotify ()
  638. {
  639. // we will call LoadSRClient from WaitForSAM
  640. HANDLE hThread = CreateThread (NULL,
  641. 0,
  642. WaitForSAM,
  643. NULL,
  644. 0,
  645. NULL);
  646. return TRUE;
  647. }
  648. NTSTATUS NTAPI PasswordChangeNotify ( PUNICODE_STRING UserName,
  649. ULONG RelativeId,
  650. PUNICODE_STRING NewPassword )
  651. {
  652. return STATUS_SUCCESS;
  653. }