Source code of Windows XP (NT5)
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.

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