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.

933 lines
24 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: mpnotify.c
  3. *
  4. * Copyright (c) 1991, Microsoft Corporation
  5. *
  6. * MpNotify main module
  7. *
  8. * Mpnotify is an app executed by winlogon to notify network providers
  9. * of authentication events. Currently this means logon and password change.
  10. * This functionality is in a separate process to avoid network providers
  11. * having to handle the asynchronous events that winlogon receives.
  12. *
  13. * Winlogon initializes environment variables to describe the event
  14. * and then executes this process in system context on the winlogon
  15. * desktop. While this process executes, winlogon handls all screen-saver
  16. * and logoff notifications. Winlogon will terminate this process if required
  17. * to respond to events (e.g. remote shutdown).
  18. *
  19. * On completion this process signals winlogon by sending a buffer of
  20. * data to it in a WM_COPYDATA message and then quits.
  21. *
  22. * History:
  23. * 01-12-93 Davidc Created.
  24. \***************************************************************************/
  25. #include "mpnotify.h"
  26. #include <ntmsv1_0.h>
  27. #include <mpr.h>
  28. #include <npapi.h>
  29. #include <stdio.h>
  30. //
  31. // Define to enable verbose output for this module
  32. //
  33. // #define DEBUG_MPNOTIFY
  34. #ifdef DEBUG_MPNOTIFY
  35. #define VerbosePrint(s) MPPrint(s)
  36. #else
  37. #define VerbosePrint(s)
  38. #endif
  39. //
  40. // Define the environment variable names used to pass the
  41. // notification event data
  42. //
  43. #define MPR_STATION_NAME_VARIABLE TEXT("WlMprNotifyStationName")
  44. #define MPR_STATION_HANDLE_VARIABLE TEXT("WlMprNotifyStationHandle")
  45. #define MPR_WINLOGON_WINDOW_VARIABLE TEXT("WlMprNotifyWinlogonWindow")
  46. #define MPR_LOGON_FLAG_VARIABLE TEXT("WlMprNotifyLogonFlag")
  47. #define MPR_USERNAME_VARIABLE TEXT("WlMprNotifyUserName")
  48. #define MPR_DOMAIN_VARIABLE TEXT("WlMprNotifyDomain")
  49. #define MPR_PASSWORD_VARIABLE TEXT("WlMprNotifyPassword")
  50. #define MPR_OLD_PASSWORD_VARIABLE TEXT("WlMprNotifyOldPassword")
  51. #define MPR_OLD_PASSWORD_VALID_VARIABLE TEXT("WlMprNotifyOldPasswordValid")
  52. #define MPR_LOGONID_VARIABLE TEXT("WlMprNotifyLogonId")
  53. #define MPR_CHANGE_INFO_VARIABLE TEXT("WlMprNotifyChangeInfo")
  54. #define MPR_PASSTHROUGH_VARIABLE TEXT("WlMprNotifyPassThrough")
  55. #define MPR_PROVIDER_VARIABLE TEXT("WlMprNotifyProvider")
  56. #define MPR_DESKTOP_VARIABLE TEXT("WlMprNotifyDesktop")
  57. #define WINLOGON_DESKTOP_NAME TEXT("Winlogon")
  58. //
  59. // Define the authentication info type that we use
  60. // This lets the provider know that we're passing
  61. // an MSV1_0_INTERACTIVE_LOGON structure.
  62. //
  63. #define AUTHENTICATION_INFO_TYPE TEXT("MSV1_0:Interactive")
  64. //
  65. // Define the primary authenticator
  66. //
  67. #define PRIMARY_AUTHENTICATOR TEXT("Microsoft Windows Network")
  68. /***************************************************************************\
  69. * ScrubString
  70. *
  71. * Wipes out the content of the string.
  72. \***************************************************************************/
  73. void ScrubString(
  74. LPTSTR lpName
  75. )
  76. {
  77. while(*lpName)
  78. {
  79. *lpName++ = TEXT(' ');
  80. }
  81. }
  82. /***************************************************************************\
  83. * AllocAndGetEnvironmentVariable
  84. *
  85. * Version of GetEnvironmentVariable that allocates the return buffer.
  86. *
  87. * Returns pointer to environment variable or NULL on failure. This routine
  88. * will also return NULL if the environment variable is a 0 length string.
  89. *
  90. * The returned buffer should be free using Free()
  91. *
  92. * History:
  93. * 09-Dec-92 Davidc Created
  94. *
  95. \***************************************************************************/
  96. LPTSTR
  97. AllocAndGetEnvironmentVariable(
  98. LPTSTR lpName
  99. )
  100. {
  101. LPTSTR Buffer;
  102. DWORD LengthRequired;
  103. DWORD LengthUsed;
  104. DWORD BytesRequired;
  105. //
  106. // Go search for the variable and find its length
  107. //
  108. LengthRequired = GetEnvironmentVariable(lpName, NULL, 0);
  109. if (LengthRequired == 0) {
  110. VerbosePrint(("Environment variable <%ws> not found, error = %d", lpName, GetLastError()));
  111. return(NULL);
  112. }
  113. //
  114. // Allocate a buffer to hold the variable
  115. //
  116. BytesRequired = LengthRequired * sizeof(TCHAR);
  117. Buffer = Alloc(BytesRequired);
  118. if (Buffer == NULL) {
  119. MPPrint(("Failed to allocate %d bytes for environment variable", BytesRequired));
  120. return(NULL);
  121. }
  122. //
  123. // Go get the variable and pass a buffer this time
  124. //
  125. LengthUsed = GetEnvironmentVariable(lpName, Buffer, LengthRequired);
  126. // Now is a good time to cleanup the env variable
  127. if (LengthRequired > 1)
  128. {
  129. // There is a non empty password
  130. if (wcsstr(lpName, TEXT("Password"))) { // Matches WlMprNotifyOldPassword & WlMprNotifyPassword
  131. LPTSTR Stars, Cursor;
  132. Stars = Alloc(BytesRequired);
  133. if (Stars != NULL) {
  134. // Alloc inits to 0 and we can't have an empty value.
  135. // Get Cursor to point to the last char
  136. Cursor = Stars + LengthRequired - 1;
  137. // We need to wipe out from Cursor to Stars
  138. do {
  139. *(--Cursor) = TEXT('*');
  140. } while(Stars != Cursor);
  141. // That'll wipe out our env var...
  142. SetEnvironmentVariable(lpName, Stars);
  143. }
  144. }
  145. }
  146. if (LengthUsed != LengthRequired - 1) {
  147. MPPrint(("Unexpected result from GetEnvironmentVariable. Length passed = %d, length used = %d (expected %d)", LengthRequired, LengthUsed, LengthRequired - 1));
  148. Free(Buffer);
  149. return(NULL);
  150. }
  151. return(Buffer);
  152. }
  153. /***************************************************************************\
  154. * FUNCTION: GetEnvironmentULong
  155. *
  156. * PURPOSE: Gets the value of an environment variable and converts it back
  157. * to its normal form. The variable should have been written
  158. * using SetEnvironmentULong. (See winlogon)
  159. *
  160. * RETURNS: TRUE on success, FALSE on failure
  161. *
  162. * HISTORY:
  163. *
  164. * 01-12-93 Davidc Created.
  165. *
  166. \***************************************************************************/
  167. BOOL
  168. GetEnvironmentULong(
  169. LPTSTR Variable,
  170. PULONG Value
  171. )
  172. {
  173. LPTSTR String;
  174. UNICODE_STRING UnicodeString;
  175. ANSI_STRING AnsiString;
  176. NTSTATUS Status;
  177. String = AllocAndGetEnvironmentVariable(Variable);
  178. if (String == NULL) {
  179. return(FALSE);
  180. }
  181. //
  182. // Convert to ansi
  183. //
  184. RtlInitUnicodeString(&UnicodeString, String);
  185. Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
  186. Free(String);
  187. if (!NT_SUCCESS(Status)) {
  188. return(FALSE);
  189. }
  190. //
  191. // Convert to numeric value
  192. //
  193. if (1 != sscanf(AnsiString.Buffer, "%x", Value)) {
  194. Value = 0;
  195. }
  196. RtlFreeAnsiString(&AnsiString);
  197. return(TRUE);
  198. }
  199. /***************************************************************************\
  200. * FUNCTION: GetEnvironmentLargeInt
  201. *
  202. * PURPOSE: Gets the value of an environment variable and converts it back
  203. * to its normal form. The variable should have been written
  204. * using SetEnvironmentLargeInt. (See winlogon)
  205. *
  206. * RETURNS: TRUE on success, FALSE on failure
  207. *
  208. * HISTORY:
  209. *
  210. * 01-12-93 Davidc Created.
  211. *
  212. \***************************************************************************/
  213. BOOL
  214. GetEnvironmentLargeInt(
  215. LPTSTR Variable,
  216. PLARGE_INTEGER Value
  217. )
  218. {
  219. LPTSTR String;
  220. UNICODE_STRING UnicodeString;
  221. ANSI_STRING AnsiString;
  222. NTSTATUS Status;
  223. String = AllocAndGetEnvironmentVariable(Variable);
  224. if (String == NULL) {
  225. return(FALSE);
  226. }
  227. //
  228. // Convert to ansi
  229. //
  230. RtlInitUnicodeString(&UnicodeString, String);
  231. Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
  232. Free(String);
  233. if (!NT_SUCCESS(Status)) {
  234. return(FALSE);
  235. }
  236. //
  237. // Convert to numeric value
  238. //
  239. if (2 != sscanf(AnsiString.Buffer, "%x:%x", &Value->HighPart, &Value->LowPart)) {
  240. Value->LowPart = 0;
  241. Value->HighPart = 0;
  242. }
  243. RtlFreeAnsiString(&AnsiString);
  244. return(TRUE);
  245. }
  246. /***************************************************************************\
  247. * FUNCTION: GetCommonNotifyVariables
  248. *
  249. * PURPOSE: Gets environment variables describing values common to all
  250. * notification events
  251. *
  252. * On successful return, all values should be free using Free()
  253. *
  254. * RETURNS: TRUE on success, FALSE on failure
  255. *
  256. * HISTORY:
  257. *
  258. * 01-12-93 Davidc Created.
  259. *
  260. \***************************************************************************/
  261. BOOL
  262. GetCommonNotifyVariables(
  263. PULONG LogonFlag,
  264. PHWND hwndWinlogon,
  265. PLPTSTR StationName,
  266. PHWND StationHandle,
  267. PLPTSTR Name,
  268. PLPTSTR Domain,
  269. PLPTSTR Password,
  270. PLPTSTR OldPassword
  271. )
  272. {
  273. BOOL Result = TRUE;
  274. ULONG OldPasswordValid;
  275. //
  276. // Prepare for failure
  277. //
  278. *hwndWinlogon = NULL;
  279. *StationName = NULL;
  280. *StationHandle = NULL;
  281. *Name = NULL;
  282. *Domain = NULL;
  283. *Password = NULL;
  284. *OldPassword = NULL;
  285. Result = GetEnvironmentULong(MPR_WINLOGON_WINDOW_VARIABLE, (PULONG)hwndWinlogon);
  286. if (Result) {
  287. *StationName = AllocAndGetEnvironmentVariable(MPR_STATION_NAME_VARIABLE);
  288. Result = (*StationName != NULL);
  289. }
  290. if (Result) {
  291. Result = GetEnvironmentULong(MPR_STATION_HANDLE_VARIABLE, (PULONG)StationHandle);
  292. }
  293. if (Result) {
  294. *Name = AllocAndGetEnvironmentVariable(MPR_USERNAME_VARIABLE);
  295. // Result = (*Name != NULL);
  296. }
  297. if (Result) {
  298. *Domain = AllocAndGetEnvironmentVariable(MPR_DOMAIN_VARIABLE);
  299. // Result = (*Domain != NULL);
  300. }
  301. if (Result) {
  302. *Password = AllocAndGetEnvironmentVariable(MPR_PASSWORD_VARIABLE);
  303. // If the password is NULL that's ok
  304. }
  305. if (Result) {
  306. Result = GetEnvironmentULong(MPR_OLD_PASSWORD_VALID_VARIABLE, &OldPasswordValid);
  307. }
  308. if (Result && OldPasswordValid) {
  309. *OldPassword = AllocAndGetEnvironmentVariable(MPR_OLD_PASSWORD_VARIABLE);
  310. // If the old password is NULL that's ok
  311. }
  312. if (Result) {
  313. Result = GetEnvironmentULong(MPR_LOGON_FLAG_VARIABLE, LogonFlag);
  314. }
  315. if (!Result) {
  316. MPPrint(("GetCommonNotifyVariables: Failed to get a variable, error = %d", GetLastError()));
  317. //
  318. // Free up any memory we allocated
  319. //
  320. if (*StationName != NULL) {
  321. Free(*StationName);
  322. }
  323. if (*Name != NULL) {
  324. Free(*Name);
  325. }
  326. if (*Domain != NULL) {
  327. Free(*Domain);
  328. }
  329. if (*Password != NULL) {
  330. ScrubString(*Password);
  331. Free(*Password);
  332. }
  333. if (*OldPassword != NULL) {
  334. ScrubString(*OldPassword);
  335. Free(*OldPassword);
  336. }
  337. }
  338. return(Result);
  339. }
  340. /***************************************************************************\
  341. * FUNCTION: GetLogonNotifyVariables
  342. *
  343. * PURPOSE: Get logon specific notify data
  344. *
  345. * RETURNS: TRUE on success, FALSE on failure
  346. *
  347. * HISTORY:
  348. *
  349. * 01-12-93 Davidc Created.
  350. *
  351. \***************************************************************************/
  352. BOOL
  353. GetLogonNotifyVariables(
  354. PLUID LogonId
  355. )
  356. {
  357. BOOL Result;
  358. Result = GetEnvironmentLargeInt(MPR_LOGONID_VARIABLE, (PLARGE_INTEGER) LogonId);
  359. if (!Result) {
  360. MPPrint(("GetLogonNotifyVariables: Failed to get variable, error = %d", GetLastError()));
  361. }
  362. return(Result);
  363. }
  364. /***************************************************************************\
  365. * FUNCTION: GetChangePasswordNotifyVariables
  366. *
  367. * PURPOSE: Gets change-password specific notify data
  368. *
  369. * RETURNS: TRUE on success, FALSE on failure
  370. *
  371. * HISTORY:
  372. *
  373. * 01-12-93 Davidc Created.
  374. *
  375. \***************************************************************************/
  376. BOOL
  377. GetChangePasswordNotifyVariables(
  378. PDWORD ChangeInfo,
  379. PBOOL PassThrough,
  380. PWSTR * ProviderName
  381. )
  382. {
  383. BOOL Result;
  384. Result = GetEnvironmentULong(MPR_CHANGE_INFO_VARIABLE, ChangeInfo);
  385. if (Result) {
  386. Result = GetEnvironmentULong(MPR_PASSTHROUGH_VARIABLE, PassThrough);
  387. }
  388. if (Result)
  389. {
  390. *ProviderName = AllocAndGetEnvironmentVariable( MPR_PROVIDER_VARIABLE );
  391. }
  392. if (!Result) {
  393. MPPrint(("GetChangePasswordNotifyVariables: Failed to get variable, error = %d", GetLastError()));
  394. }
  395. return(Result);
  396. }
  397. /***************************************************************************\
  398. * FUNCTION: NotifyWinlogon
  399. *
  400. * PURPOSE: Informs winlogon that credential provider notification
  401. * has completed and passes the logon scripts buffer back.
  402. *
  403. * RETURNS: TRUE on success, FALSE on failure
  404. *
  405. * HISTORY:
  406. *
  407. * 01-12-93 Davidc Created.
  408. *
  409. \***************************************************************************/
  410. BOOL
  411. NotifyWinlogon(
  412. HWND hwndWinlogon,
  413. DWORD Error,
  414. LPTSTR MultiSz OPTIONAL
  415. )
  416. {
  417. DWORD MultiSzSize = 0;
  418. COPYDATASTRUCT CopyData;
  419. if (MultiSz != NULL) {
  420. LPTSTR StringPointer = MultiSz;
  421. DWORD Length;
  422. VerbosePrint(("NotifyWinlogon : logon scripts strings start"));
  423. do {
  424. Length = lstrlen(StringPointer);
  425. if (Length != 0) {
  426. VerbosePrint(("<%ws>", StringPointer));
  427. }
  428. MultiSzSize += ((Length + 1) * sizeof(TCHAR));
  429. StringPointer += Length + 1;
  430. } while (Length != 0);
  431. VerbosePrint(("NotifyWinlogon : logon scripts strings end"));
  432. }
  433. CopyData.dwData = Error;
  434. CopyData.cbData = MultiSzSize;
  435. CopyData.lpData = MultiSz;
  436. SendMessage(hwndWinlogon, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&CopyData);
  437. return(TRUE);
  438. }
  439. DWORD
  440. NotifySpecificProvider(
  441. PWSTR Provider,
  442. LPCWSTR lpAuthentInfoType,
  443. LPVOID lpAuthentInfo,
  444. LPCWSTR lpPreviousAuthentInfoType,
  445. LPVOID lpPreviousAuthentInfo,
  446. LPWSTR lpStationName,
  447. LPVOID StationHandle,
  448. DWORD dwChangeInfo
  449. )
  450. {
  451. HMODULE hDll;
  452. HKEY hKey;
  453. WCHAR szText[MAX_PATH];
  454. WCHAR szPath[128];
  455. PWSTR pszPath;
  456. DWORD dwType;
  457. DWORD dwLen;
  458. int err;
  459. PF_NPPasswordChangeNotify pFunc;
  460. wcscpy(szText, TEXT("System\\CurrentControlSet\\Services\\") );
  461. wcscat(szText, Provider );
  462. wcscat(szText, TEXT("\\networkprovider") );
  463. err = RegOpenKey( HKEY_LOCAL_MACHINE,
  464. szText,
  465. &hKey );
  466. if ( err )
  467. {
  468. return( err );
  469. }
  470. dwLen = sizeof( szPath );
  471. pszPath = szPath;
  472. err = RegQueryValueEx( hKey,
  473. TEXT("ProviderPath"),
  474. NULL,
  475. &dwType,
  476. (PUCHAR) pszPath,
  477. &dwLen );
  478. if ( err )
  479. {
  480. if ( err == ERROR_BUFFER_OVERFLOW )
  481. {
  482. pszPath = LocalAlloc( LMEM_FIXED, dwLen );
  483. if (pszPath)
  484. {
  485. err = RegQueryValueEx( hKey,
  486. TEXT("ProviderPath"),
  487. NULL,
  488. &dwType,
  489. (PUCHAR) pszPath,
  490. &dwLen );
  491. }
  492. }
  493. if ( err )
  494. {
  495. RegCloseKey( hKey );
  496. if ( pszPath != szPath )
  497. {
  498. LocalFree( pszPath );
  499. }
  500. return( err );
  501. }
  502. }
  503. RegCloseKey( hKey );
  504. if ( dwType == REG_EXPAND_SZ )
  505. {
  506. ExpandEnvironmentStrings( pszPath, szText, MAX_PATH );
  507. }
  508. else if (dwType == REG_SZ )
  509. {
  510. wcscpy( szText, pszPath );
  511. }
  512. else
  513. {
  514. if (pszPath != szPath)
  515. {
  516. LocalFree( pszPath );
  517. }
  518. return( err );
  519. }
  520. //
  521. // Ok, now we have expanded the DLL where the NP code lives, and it
  522. // is in szText. Load it, call it.
  523. //
  524. if ( pszPath != szPath )
  525. {
  526. LocalFree( pszPath );
  527. pszPath = NULL;
  528. }
  529. hDll = LoadLibrary( szText );
  530. if ( hDll )
  531. {
  532. pFunc = (PF_NPPasswordChangeNotify) GetProcAddress( hDll,
  533. "NPPasswordChangeNotify" );
  534. if ( pFunc )
  535. {
  536. err = pFunc(lpAuthentInfoType,
  537. lpAuthentInfo,
  538. lpPreviousAuthentInfoType,
  539. lpPreviousAuthentInfo,
  540. lpStationName,
  541. StationHandle,
  542. dwChangeInfo);
  543. }
  544. FreeLibrary( hDll );
  545. }
  546. return( err );
  547. }
  548. /***************************************************************************\
  549. * WinMain
  550. *
  551. * History:
  552. * 01-12-93 Davidc Created.
  553. \***************************************************************************/
  554. int
  555. WINAPI
  556. WinMain(
  557. HINSTANCE hInstance,
  558. HINSTANCE hPrevInstance,
  559. LPSTR lpszCmdParam,
  560. int nCmdShow
  561. )
  562. {
  563. DWORD Error;
  564. BOOL Result;
  565. ULONG LogonFlag;
  566. HWND hwndWinlogon;
  567. LPTSTR StationName;
  568. HWND StationHandle;
  569. LPTSTR Name;
  570. LPTSTR Domain;
  571. LPTSTR Password;
  572. LPTSTR OldPassword;
  573. LPTSTR LogonScripts;
  574. LPTSTR Desktop;
  575. PWSTR Provider;
  576. LUID LogonId;
  577. DWORD ChangeInfo;
  578. MSV1_0_INTERACTIVE_LOGON AuthenticationInfo;
  579. MSV1_0_INTERACTIVE_LOGON OldAuthenticationInfo;
  580. HDESK hDesk = NULL ;
  581. HDESK hWinlogon ;
  582. BOOL PassThrough = FALSE;
  583. //
  584. // Get information describing event from environment variables
  585. //
  586. Result = GetCommonNotifyVariables(
  587. &LogonFlag,
  588. &hwndWinlogon,
  589. &StationName,
  590. &StationHandle,
  591. &Name,
  592. &Domain,
  593. &Password,
  594. &OldPassword);
  595. if (!Result) {
  596. MPPrint(("Failed to get common notify variables"));
  597. return(0);
  598. }
  599. //
  600. // Debug info
  601. //
  602. VerbosePrint(("LogonFlag = 0x%x", LogonFlag));
  603. VerbosePrint(("hwndWinlogon = 0x%x", hwndWinlogon));
  604. VerbosePrint(("Station Name = <%ws>", StationName));
  605. VerbosePrint(("Station Handle = 0x%x", StationHandle));
  606. VerbosePrint(("Name = <%ws>", Name));
  607. VerbosePrint(("Domain = <%ws>", Domain));
  608. VerbosePrint(("Password = <%ws>", Password));
  609. VerbosePrint(("Old Password = <%ws>", OldPassword));
  610. //
  611. // Get the notify type specific data
  612. //
  613. if (LogonFlag != 0) {
  614. Result = GetLogonNotifyVariables(&LogonId);
  615. } else {
  616. Result = GetChangePasswordNotifyVariables(&ChangeInfo, &PassThrough, &Provider);
  617. }
  618. if (!Result) {
  619. MPPrint(("Failed to get notify event type-specific variables"));
  620. return(0);
  621. }
  622. //
  623. // Debug info
  624. //
  625. if (LogonFlag != 0) {
  626. VerbosePrint(("LogonId = 0x%x:%x", LogonId.HighPart, LogonId.LowPart));
  627. } else {
  628. VerbosePrint(("ChangeInfo = 0x%x", ChangeInfo));
  629. VerbosePrint(("PassThrough = 0x%x", PassThrough));
  630. }
  631. Desktop = AllocAndGetEnvironmentVariable( MPR_DESKTOP_VARIABLE );
  632. if ( wcscmp( Desktop, WINLOGON_DESKTOP_NAME ) )
  633. {
  634. //
  635. // Not supposed to use winlogon desktop. Switch ourselves to the
  636. // current one:
  637. //
  638. hWinlogon = GetThreadDesktop( GetCurrentThreadId() );
  639. if ( hWinlogon )
  640. {
  641. hDesk = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
  642. if ( hDesk )
  643. {
  644. SetThreadDesktop( hDesk );
  645. }
  646. }
  647. }
  648. //
  649. // Fill in the authentication info structures
  650. //
  651. RtlInitUnicodeString(&AuthenticationInfo.UserName, Name);
  652. RtlInitUnicodeString(&AuthenticationInfo.LogonDomainName, Domain);
  653. RtlInitUnicodeString(&AuthenticationInfo.Password, Password);
  654. RtlInitUnicodeString(&OldAuthenticationInfo.UserName, Name);
  655. RtlInitUnicodeString(&OldAuthenticationInfo.LogonDomainName, Domain);
  656. RtlInitUnicodeString(&OldAuthenticationInfo.Password, OldPassword);
  657. //
  658. // Call the appropriate notify api
  659. //
  660. if (LogonFlag != 0) {
  661. Error = WNetLogonNotify(
  662. PRIMARY_AUTHENTICATOR,
  663. &LogonId,
  664. AUTHENTICATION_INFO_TYPE,
  665. &AuthenticationInfo,
  666. (OldPassword != NULL) ? AUTHENTICATION_INFO_TYPE : NULL,
  667. (OldPassword != NULL) ? &OldAuthenticationInfo : NULL,
  668. StationName,
  669. StationHandle,
  670. &LogonScripts
  671. );
  672. if (Error != ERROR_SUCCESS) {
  673. LogonScripts = NULL;
  674. }
  675. } else {
  676. if (!PassThrough) {
  677. ChangeInfo |= WN_NT_PASSWORD_CHANGED;
  678. }
  679. if (Provider)
  680. {
  681. Error = NotifySpecificProvider(
  682. Provider,
  683. AUTHENTICATION_INFO_TYPE,
  684. &AuthenticationInfo,
  685. AUTHENTICATION_INFO_TYPE,
  686. &OldAuthenticationInfo,
  687. StationName,
  688. StationHandle,
  689. ChangeInfo
  690. );
  691. }
  692. else
  693. {
  694. Error = WNetPasswordChangeNotify(
  695. PRIMARY_AUTHENTICATOR,
  696. AUTHENTICATION_INFO_TYPE,
  697. &AuthenticationInfo,
  698. AUTHENTICATION_INFO_TYPE,
  699. &OldAuthenticationInfo,
  700. StationName,
  701. StationHandle,
  702. ChangeInfo
  703. );
  704. }
  705. LogonScripts = NULL;
  706. }
  707. if (Error != ERROR_SUCCESS) {
  708. MPPrint(("WNet%sNotify failed, error = %d", LogonFlag ? "Logon" : "PasswordChange", Error));
  709. }
  710. //
  711. // Switch back if necessary
  712. //
  713. if ( hDesk )
  714. {
  715. SetThreadDesktop( hWinlogon );
  716. CloseDesktop( hWinlogon );
  717. CloseDesktop( hDesk );
  718. }
  719. //
  720. // Scrub the passwords before calling NotifyWinlogon
  721. // because we can be killed before the cleanup below
  722. if (Password != NULL) {
  723. ScrubString(Password);
  724. }
  725. if (OldPassword != NULL) {
  726. ScrubString(OldPassword);
  727. }
  728. //
  729. // Notify winlogon we completed and pass the logon script data
  730. //
  731. NotifyWinlogon(hwndWinlogon, Error, LogonScripts);
  732. //
  733. // Free up allocated data
  734. //
  735. if (LogonScripts != NULL) {
  736. LocalFree(LogonScripts);
  737. }
  738. if (StationName != NULL) {
  739. Free(StationName);
  740. }
  741. if (Name != NULL) {
  742. Free(Name);
  743. }
  744. if (Domain != NULL) {
  745. Free(Domain);
  746. }
  747. if (Password != NULL) {
  748. Free(Password);
  749. }
  750. if (OldPassword != NULL) {
  751. Free(OldPassword);
  752. }
  753. //
  754. // We're finished
  755. //
  756. return(0);
  757. }