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.

4133 lines
120 KiB

  1. /*++
  2. Copyright (c) 1993, 1994 Microsoft Corporation
  3. Module Name:
  4. nwdlg.c
  5. Abstract:
  6. This module contains NetWare Network Provider Dialog code.
  7. It contains all functions used in handling the dialogs
  8. shown by the provider.
  9. Author:
  10. Yi-Hsin Sung (yihsins) 5-July-1993
  11. Split from provider.c
  12. Revision History:
  13. Rita Wong (ritaw) 10-Apr-1994
  14. Added change password functionality.
  15. --*/
  16. #include <nwclient.h>
  17. #include <nwsnames.h>
  18. #include <nwcanon.h>
  19. #include <validc.h>
  20. #include <nwevent.h>
  21. #include <ntmsv1_0.h>
  22. #include <nwdlg.h>
  23. #include <tstr.h>
  24. #include <align.h>
  25. #include <nwpkstr.h>
  26. #include <nwreg.h>
  27. #include <nwlsa.h>
  28. #include <nwmisc.h>
  29. #include <nwauth.h>
  30. #include <nwutil.h>
  31. #include <ntddnwfs.h>
  32. #include <nds.h>
  33. #define NW_ENUM_EXTRA_BYTES 256
  34. #define IS_TREE(p) (*p == TREE_CHAR)
  35. //-------------------------------------------------------------------//
  36. // //
  37. // Local Function Prototypes //
  38. // //
  39. //-------------------------------------------------------------------//
  40. VOID
  41. NwpAddToComboBox(
  42. IN HWND DialogHandle,
  43. IN INT ControlId,
  44. IN LPWSTR pszNone OPTIONAL,
  45. IN BOOL AllowNone
  46. );
  47. BOOL
  48. WINAPI
  49. NwpConnectDlgProc(
  50. HWND DialogHandle,
  51. UINT Message,
  52. WPARAM WParam,
  53. LPARAM LParam
  54. );
  55. VOID
  56. NwpCenterDialog(
  57. IN HWND hwnd
  58. );
  59. HWND
  60. NwpGetParentHwnd(
  61. VOID
  62. );
  63. VOID
  64. NwpGetNoneString(
  65. LPWSTR pszNone,
  66. DWORD cBufferSize
  67. );
  68. VOID
  69. NwpAddNetWareTreeConnectionsToList(
  70. IN HWND DialogHandle,
  71. IN LPWSTR NtUserName,
  72. IN LPDWORD lpdwUserLuid,
  73. IN INT ControlId
  74. );
  75. VOID
  76. NwpAddServersToControl(
  77. IN HWND DialogHandle,
  78. IN INT ControlId,
  79. IN UINT Message,
  80. IN INT ControlIdMatch OPTIONAL,
  81. IN UINT FindMessage
  82. );
  83. VOID
  84. NwpAddTreeNamesToControl(
  85. IN HWND DialogHandle,
  86. IN INT ControlId,
  87. IN UINT Message,
  88. IN INT ControlIdMatch OPTIONAL,
  89. IN UINT FindMessage
  90. );
  91. DWORD
  92. NwpGetTreesAndChangePw(
  93. IN HWND DialogHandle,
  94. IN LPWSTR ServerBuf,
  95. IN DWORD UserLuid,
  96. IN PCHANGE_PW_DLG_PARAM Credential
  97. );
  98. BOOL
  99. WINAPI
  100. NwpOldPasswordDlgProc(
  101. HWND DialogHandle,
  102. UINT Message,
  103. WPARAM WParam,
  104. LPARAM LParam
  105. );
  106. BOOL
  107. WINAPI
  108. NwpAltUserNameDlgProc(
  109. HWND DialogHandle,
  110. UINT Message,
  111. WPARAM WParam,
  112. LPARAM LParam
  113. );
  114. VOID
  115. EnableAddRemove(
  116. IN HWND DialogHandle
  117. );
  118. BOOL
  119. WINAPI
  120. NwpLoginDlgProc(
  121. HWND DialogHandle,
  122. UINT Message,
  123. WPARAM WParam,
  124. LPARAM LParam
  125. )
  126. /*++
  127. Routine Description:
  128. This function is the window management message handler which
  129. initializes, and reads user input from the login dialog. It also
  130. checks that the preferred server name is valid, notifies the user
  131. if not, and dismisses the dialog when done.
  132. Arguments:
  133. DialogHandle - Supplies a handle to the login dialog.
  134. Message - Supplies the window management message.
  135. Return Value:
  136. TRUE - the message was processed.
  137. FALSE - the message was not processed.
  138. --*/
  139. {
  140. static PLOGINDLGPARAM pLoginParam;
  141. static WCHAR OrigPassword[NW_MAX_SERVER_LEN + 1];
  142. static WCHAR pszNone[64];
  143. DWORD status = NO_ERROR;
  144. LPARAM dwNoneIndex = 0;
  145. BOOL enableServer = TRUE ;
  146. switch (Message)
  147. {
  148. case WM_QUERYENDSESSION:
  149. //
  150. // Clear the password buffer
  151. //
  152. RtlZeroMemory( OrigPassword, sizeof( OrigPassword));
  153. EndDialog(DialogHandle, 0);
  154. return FALSE;
  155. case WM_INITDIALOG:
  156. pLoginParam = (PLOGINDLGPARAM) LParam;
  157. //
  158. // Store the original password
  159. //
  160. wcscpy( OrigPassword, pLoginParam->Password );
  161. //
  162. // Position dialog
  163. //
  164. NwpCenterDialog(DialogHandle);
  165. //
  166. // Handle logon script button
  167. //
  168. if ( pLoginParam->LogonScriptOptions & NW_LOGONSCRIPT_ENABLED )
  169. CheckDlgButton( DialogHandle, ID_LOGONSCRIPT, 1 );
  170. else
  171. CheckDlgButton( DialogHandle, ID_LOGONSCRIPT, 0 );
  172. //
  173. // Username. Just display the original.
  174. //
  175. SetDlgItemTextW(DialogHandle, ID_USERNAME, pLoginParam->UserName);
  176. //
  177. // Initialize the <None> string.
  178. //
  179. NwpGetNoneString( pszNone, sizeof( pszNone) );
  180. //
  181. // Set the values in combo-box list.
  182. //
  183. NwpAddToComboBox(DialogHandle, ID_SERVER, pszNone, TRUE);
  184. //
  185. // Initially, select the last entry in server list, which should
  186. // be the <None> entry.
  187. //
  188. dwNoneIndex = SendDlgItemMessageW(
  189. DialogHandle,
  190. ID_SERVER,
  191. CB_GETCOUNT,
  192. 0,
  193. 0 );
  194. if ( dwNoneIndex != CB_ERR && dwNoneIndex > 0 )
  195. dwNoneIndex -= 1;
  196. (void) SendDlgItemMessageW(
  197. DialogHandle,
  198. ID_SERVER,
  199. CB_SETCURSEL,
  200. dwNoneIndex == CB_ERR ? 0 : dwNoneIndex,
  201. 0 );
  202. //
  203. // Display the previously saved preferred server or context.
  204. // Also set appropriate radio button
  205. //
  206. if ( *(pLoginParam->ServerName) != NW_INVALID_SERVER_CHAR )
  207. {
  208. if ( !IS_TREE(pLoginParam->ServerName) )
  209. {
  210. //
  211. // regular server
  212. //
  213. if (SendDlgItemMessageW(
  214. DialogHandle,
  215. ID_SERVER,
  216. CB_SELECTSTRING,
  217. 0,
  218. (LPARAM) pLoginParam->ServerName
  219. ) == CB_ERR) {
  220. //
  221. // Did not find preferred server in the combo-box,
  222. // just set the old value in the edit item.
  223. //
  224. SetDlgItemTextW( DialogHandle, ID_SERVER,
  225. pLoginParam->ServerName);
  226. }
  227. }
  228. else
  229. {
  230. //
  231. // we are dealing with *tree\context. break it into
  232. // tree and context
  233. //
  234. WCHAR *pszTmp = wcschr(pLoginParam->ServerName + 1, L'\\') ;
  235. if (pszTmp)
  236. *pszTmp = 0 ;
  237. SetDlgItemTextW( DialogHandle, ID_DEFAULTTREE,
  238. pLoginParam->ServerName + 1);
  239. SetDlgItemTextW( DialogHandle, ID_DEFAULTCONTEXT,
  240. pszTmp ? (pszTmp + 1) : L"");
  241. if (pszTmp)
  242. *pszTmp = L'\\' ; // restore the '\'
  243. enableServer = FALSE ;
  244. }
  245. }
  246. //
  247. // enable appropriate buttons
  248. //
  249. CheckRadioButton( DialogHandle,
  250. ID_PREFERREDSERVER_RB,
  251. ID_DEFAULTCONTEXT_RB,
  252. enableServer ?
  253. ID_PREFERREDSERVER_RB :
  254. ID_DEFAULTCONTEXT_RB) ;
  255. EnableWindow ( GetDlgItem ( DialogHandle,
  256. ID_SERVER ),
  257. enableServer ) ;
  258. EnableWindow ( GetDlgItem ( DialogHandle,
  259. ID_DEFAULTTREE ),
  260. !enableServer ) ;
  261. EnableWindow ( GetDlgItem ( DialogHandle,
  262. ID_DEFAULTCONTEXT ),
  263. !enableServer ) ;
  264. SetFocus ( GetDlgItem ( DialogHandle,
  265. enableServer ? ID_SERVER : ID_DEFAULTTREE ) ) ;
  266. //
  267. // Preferred server name is limited to 48 characters.
  268. // Tree is limited to 32. We limit context to 256 - MAXTREE - 3
  269. //
  270. SendDlgItemMessageW(
  271. DialogHandle,
  272. ID_SERVER,
  273. CB_LIMITTEXT,
  274. NW_MAX_SERVER_LEN - 1,
  275. 0
  276. );
  277. SendDlgItemMessageW(
  278. DialogHandle,
  279. ID_DEFAULTTREE,
  280. EM_LIMITTEXT,
  281. NW_MAX_TREE_LEN - 1,
  282. 0
  283. );
  284. SendDlgItemMessageW(
  285. DialogHandle,
  286. ID_DEFAULTCONTEXT,
  287. EM_LIMITTEXT,
  288. (256 - NW_MAX_TREE_LEN) - 4, // -4 for backslashes unc style
  289. 0
  290. );
  291. return TRUE;
  292. case WM_COMMAND:
  293. switch (LOWORD(WParam)) {
  294. case ID_DEFAULTCONTEXT_RB :
  295. if ( (HIWORD(WParam) == BN_CLICKED )
  296. || (HIWORD(WParam) == BN_DOUBLECLICKED )
  297. )
  298. {
  299. CheckRadioButton( DialogHandle,
  300. ID_PREFERREDSERVER_RB,
  301. ID_DEFAULTCONTEXT_RB,
  302. ID_DEFAULTCONTEXT_RB) ;
  303. EnableWindow ( GetDlgItem ( DialogHandle,
  304. ID_SERVER ),
  305. FALSE ) ;
  306. EnableWindow ( GetDlgItem ( DialogHandle,
  307. ID_DEFAULTTREE ),
  308. TRUE ) ;
  309. EnableWindow ( GetDlgItem ( DialogHandle,
  310. ID_DEFAULTCONTEXT ),
  311. TRUE ) ;
  312. SetFocus ( GetDlgItem ( DialogHandle,
  313. ID_DEFAULTTREE ) ) ;
  314. }
  315. break ;
  316. case ID_PREFERREDSERVER_RB :
  317. if ( (HIWORD(WParam) == BN_CLICKED )
  318. || (HIWORD(WParam) == BN_DOUBLECLICKED )
  319. )
  320. {
  321. CheckRadioButton( DialogHandle,
  322. ID_PREFERREDSERVER_RB,
  323. ID_DEFAULTCONTEXT_RB,
  324. ID_PREFERREDSERVER_RB) ;
  325. EnableWindow ( GetDlgItem ( DialogHandle,
  326. ID_SERVER ),
  327. TRUE ) ;
  328. EnableWindow ( GetDlgItem ( DialogHandle,
  329. ID_DEFAULTTREE ),
  330. FALSE ) ;
  331. EnableWindow ( GetDlgItem ( DialogHandle,
  332. ID_DEFAULTCONTEXT ),
  333. FALSE ) ;
  334. SetFocus ( GetDlgItem ( DialogHandle, ID_SERVER ) ) ;
  335. }
  336. break ;
  337. //
  338. // Use the user's original password when
  339. // the user types in or selects a new server or context
  340. //
  341. case ID_DEFAULTTREE:
  342. case ID_DEFAULTCONTEXT:
  343. if ( HIWORD(WParam) == EN_CHANGE )
  344. {
  345. wcscpy( pLoginParam->Password, OrigPassword );
  346. }
  347. break;
  348. case ID_SERVER:
  349. if ( (HIWORD(WParam) == CBN_EDITCHANGE )
  350. || (HIWORD(WParam) == CBN_SELCHANGE )
  351. )
  352. {
  353. wcscpy( pLoginParam->Password, OrigPassword );
  354. }
  355. break;
  356. case IDOK: {
  357. LPWSTR pszLocation = NULL;
  358. ASSERT(pLoginParam->ServerNameSize >= MAX_PATH) ;
  359. //
  360. // Allocate a buffer big enough to hold the Preferred
  361. // Server name or the NDS Tree and context in the form:
  362. // *Tree(Context). Therefore we allocate twice the space
  363. // needed for a UNICODE Server name.
  364. //
  365. if ((pszLocation =
  366. LocalAlloc(LMEM_ZEROINIT,
  367. (pLoginParam->ServerNameSize * sizeof(WCHAR) * 2))
  368. ) == NULL )
  369. {
  370. break;
  371. }
  372. //
  373. // Read the server or tree/context and validate its value.
  374. //
  375. //Handle extra buttons for Multi-User
  376. if ( (BOOL)(IsDlgButtonChecked (DialogHandle,
  377. ID_LOGONSCRIPT) ) )
  378. {
  379. pLoginParam->LogonScriptOptions =
  380. NW_LOGONSCRIPT_ENABLED | NW_LOGONSCRIPT_4X_ENABLED;
  381. }
  382. else
  383. {
  384. pLoginParam->LogonScriptOptions =
  385. NW_LOGONSCRIPT_DISABLED;
  386. }
  387. if ( !enableServer ||
  388. (IsDlgButtonChecked(DialogHandle, ID_DEFAULTCONTEXT_RB)))
  389. {
  390. //
  391. // We are dealing with TREE/CONTEXT. Synthesize string
  392. // in "*TREE\CONTEXT" format.
  393. //
  394. WCHAR *pTmp ;
  395. *pszLocation = TREE_CHAR ;
  396. if (!GetDlgItemTextW(
  397. DialogHandle,
  398. ID_DEFAULTTREE,
  399. pszLocation + 1,
  400. pLoginParam->ServerNameSize - 1
  401. ))
  402. {
  403. //
  404. // The tree name field was blank!
  405. // Prompt user to provide a NDS tree name.
  406. //
  407. LocalFree( pszLocation );
  408. (void) NwpMessageBoxError(
  409. DialogHandle,
  410. IDS_AUTH_FAILURE_TITLE,
  411. IDS_TREE_NAME_MISSING,
  412. 0,
  413. NULL,
  414. MB_OK | MB_ICONSTOP
  415. );
  416. //
  417. // Put the focus where the user can fix the
  418. // invalid tree name.
  419. //
  420. SetFocus(GetDlgItem(DialogHandle,ID_DEFAULTTREE));
  421. SendDlgItemMessageW(
  422. DialogHandle,
  423. ID_DEFAULTTREE,
  424. EM_SETSEL,
  425. 0,
  426. MAKELPARAM(0, -1)
  427. );
  428. return TRUE;
  429. }
  430. pTmp = pszLocation + wcslen( pszLocation );
  431. *pTmp++ = L'\\' ;
  432. if (!GetDlgItemTextW(
  433. DialogHandle,
  434. ID_DEFAULTCONTEXT,
  435. pTmp,
  436. pLoginParam->ServerNameSize - (DWORD)(pTmp-pszLocation)
  437. ))
  438. {
  439. //
  440. // The context name field was blank!
  441. // Prompt user to provide a NDS context name.
  442. //
  443. LocalFree( pszLocation );
  444. (void) NwpMessageBoxError(
  445. DialogHandle,
  446. IDS_AUTH_FAILURE_TITLE,
  447. IDS_CONTEXT_MISSING,
  448. 0,
  449. NULL,
  450. MB_OK | MB_ICONSTOP
  451. );
  452. //
  453. // Put the focus where the user can fix the
  454. // invalid context name.
  455. //
  456. SetFocus(GetDlgItem(DialogHandle,ID_DEFAULTCONTEXT));
  457. SendDlgItemMessageW(
  458. DialogHandle,
  459. ID_DEFAULTCONTEXT,
  460. EM_SETSEL,
  461. 0,
  462. MAKELPARAM(0, -1)
  463. );
  464. return TRUE;
  465. }
  466. }
  467. else
  468. {
  469. //
  470. // Straight server. Just read it in. If we cant get it
  471. // or is empty, use <None>.
  472. //
  473. if (GetDlgItemTextW(
  474. DialogHandle,
  475. ID_SERVER,
  476. pszLocation,
  477. pLoginParam->ServerNameSize
  478. ) == 0)
  479. {
  480. wcscpy( pszLocation, pszNone );
  481. goto CANCEL_PREFERRED_SERVER;
  482. }
  483. }
  484. if (( lstrcmpi( pszLocation, pszNone ) != 0) &&
  485. ( !IS_TREE( pszLocation )) &&
  486. ( !IS_VALID_TOKEN( pszLocation,wcslen( pszLocation ))))
  487. {
  488. //
  489. // Put up message box complaining about the bad
  490. // server name.
  491. //
  492. LocalFree( pszLocation );
  493. (void) NwpMessageBoxError(
  494. DialogHandle,
  495. IDS_AUTH_FAILURE_TITLE,
  496. IDS_INVALID_SERVER,
  497. 0,
  498. NULL,
  499. MB_OK | MB_ICONSTOP
  500. );
  501. //
  502. // Put the focus where the user can fix the
  503. // invalid name.
  504. //
  505. SetFocus(GetDlgItem(DialogHandle, ID_SERVER));
  506. SendDlgItemMessageW(
  507. DialogHandle,
  508. ID_SERVER,
  509. EM_SETSEL,
  510. 0,
  511. MAKELPARAM(0, -1)
  512. );
  513. return TRUE;
  514. }
  515. //
  516. // If the user select <NONE>,
  517. // change it to empty string.
  518. //
  519. if (lstrcmpi( pszLocation, pszNone) == 0) {
  520. wcscpy( pszLocation, L"" );
  521. }
  522. #if DBG
  523. IF_DEBUG(LOGON) {
  524. KdPrint(("\n\t[OK] was pressed\n"));
  525. KdPrint(("\tNwrLogonUser\n"));
  526. KdPrint(("\tPassword : %ws\n",pLoginParam->Password));
  527. KdPrint(("\tServer : %ws\n",pszLocation ));
  528. }
  529. #endif
  530. while(1)
  531. {
  532. PROMPTDLGPARAM PasswdPromptParam;
  533. INT_PTR Result ;
  534. //
  535. // make sure this user is logged off
  536. //
  537. (void) NwrLogoffUser(
  538. NULL,
  539. pLoginParam->pLogonId
  540. );
  541. status = NwrLogonUser(
  542. NULL,
  543. pLoginParam->pLogonId,
  544. pLoginParam->UserName,
  545. pLoginParam->Password,
  546. pszLocation,
  547. NULL,
  548. NULL,
  549. 0,
  550. pLoginParam->PrintOption
  551. );
  552. //
  553. // tommye
  554. //
  555. // If the error is NO_SUCH_USER, see if the user name has any
  556. // periods in it - if so, then we need to escape them (\.) and
  557. // try the login again.
  558. //
  559. if (status == ERROR_NO_SUCH_USER) {
  560. WCHAR EscapedName[NW_MAX_USERNAME_LEN * 2];
  561. PWSTR pChar = pLoginParam->UserName;
  562. int i = 0;
  563. BOOL bEscaped = FALSE;
  564. RtlZeroMemory(EscapedName, sizeof(EscapedName));
  565. do {
  566. if (*pChar == L'.') {
  567. EscapedName[i++] = '\\';
  568. bEscaped = TRUE;
  569. }
  570. EscapedName[i++] = *pChar;
  571. } while (*pChar++);
  572. // Try the login again
  573. if (bEscaped) {
  574. status = NwrLogonUser(
  575. NULL,
  576. pLoginParam->pLogonId,
  577. EscapedName,
  578. pLoginParam->Password,
  579. pszLocation,
  580. NULL,
  581. NULL,
  582. 0,
  583. pLoginParam->PrintOption
  584. );
  585. if (status != ERROR_NO_SUCH_USER) { // if we matched a username, copy that name into buffer
  586. //
  587. // check for max length to avoid overflowing.
  588. //
  589. if (i < (sizeof(pLoginParam->UserName))) {
  590. wcsncpy(
  591. pLoginParam->UserName,
  592. EscapedName,
  593. i
  594. );
  595. }
  596. }
  597. }
  598. }
  599. if (status != ERROR_INVALID_PASSWORD)
  600. break ;
  601. PasswdPromptParam.UserName =
  602. pLoginParam->UserName,
  603. PasswdPromptParam.ServerName =
  604. pszLocation;
  605. PasswdPromptParam.Password =
  606. pLoginParam->Password;
  607. PasswdPromptParam.PasswordSize =
  608. pLoginParam->PasswordSize ;
  609. Result = DialogBoxParamW(
  610. hmodNW,
  611. MAKEINTRESOURCEW(DLG_PASSWORD_PROMPT),
  612. (HWND) DialogHandle,
  613. (DLGPROC) NwpPasswdPromptDlgProc,
  614. (LPARAM) &PasswdPromptParam
  615. );
  616. if (Result == -1 || Result == IDCANCEL)
  617. {
  618. status = ERROR_INVALID_PASSWORD ;
  619. break ;
  620. }
  621. }
  622. if (status == NW_PASSWORD_HAS_EXPIRED)
  623. {
  624. WCHAR szNumber[16] ;
  625. DWORD dwMsgId, dwGraceLogins = 0 ;
  626. LPWSTR apszInsertStrings[3] ;
  627. //
  628. // get the grace login count
  629. //
  630. if (!IS_TREE(pszLocation))
  631. {
  632. DWORD status1 ;
  633. status1 = NwGetGraceLoginCount(
  634. pszLocation,
  635. pLoginParam->UserName,
  636. &dwGraceLogins) ;
  637. //
  638. // if hit error, just dont use the number
  639. //
  640. if (status1 == NO_ERROR)
  641. {
  642. //
  643. // tommye - MCS bug 251 - changed from SETPASS
  644. // message (IDS_PASSWORD_EXPIRED) to
  645. // Ctrl+Alt+Del message.
  646. //
  647. dwMsgId = IDS_PASSWORD_HAS_EXPIRED0 ;
  648. wsprintfW(szNumber, L"%ld", dwGraceLogins) ;
  649. }
  650. else
  651. {
  652. //
  653. // tommye - MCS bug 251 - changed from SETPASS
  654. // message (IDS_PASSWORD_EXPIRED1) to
  655. // Ctrl+Alt+Del message.
  656. //
  657. dwMsgId = IDS_PASSWORD_HAS_EXPIRED2 ;
  658. }
  659. }
  660. else
  661. {
  662. dwMsgId = IDS_PASSWORD_HAS_EXPIRED2 ;
  663. }
  664. apszInsertStrings[0] = pszLocation ;
  665. apszInsertStrings[1] = szNumber ;
  666. apszInsertStrings[2] = NULL ;
  667. //
  668. // put up message on password expiry
  669. //
  670. (void) NwpMessageBoxIns(
  671. (HWND) DialogHandle,
  672. IDS_NETWARE_TITLE,
  673. dwMsgId,
  674. apszInsertStrings,
  675. MB_OK | MB_SETFOREGROUND |
  676. MB_ICONINFORMATION );
  677. status = NO_ERROR ;
  678. }
  679. //
  680. // Check the LogonScript check box.
  681. //
  682. if (IsDlgButtonChecked(DialogHandle, ID_LOGONSCRIPT))
  683. {
  684. pLoginParam->LogonScriptOptions =
  685. NW_LOGONSCRIPT_ENABLED | NW_LOGONSCRIPT_4X_ENABLED ;
  686. }
  687. else
  688. {
  689. pLoginParam->LogonScriptOptions =
  690. NW_LOGONSCRIPT_DISABLED ;
  691. }
  692. if (status == NO_ERROR)
  693. {
  694. //
  695. // Save the logon credential to the registry
  696. //
  697. NwpSaveLogonCredential(
  698. pLoginParam->NewUserSid,
  699. pLoginParam->pLogonId,
  700. pLoginParam->UserName,
  701. pLoginParam->Password,
  702. pszLocation
  703. );
  704. // Clear the password buffer
  705. RtlZeroMemory( OrigPassword, sizeof( OrigPassword));
  706. NwpSaveLogonScriptOptions( pLoginParam->NewUserSid, pLoginParam->LogonScriptOptions );
  707. EndDialog(DialogHandle, 0);
  708. }
  709. else
  710. {
  711. INT nResult;
  712. DWORD dwMsgId = IDS_AUTH_FAILURE_WARNING;
  713. WCHAR *pszErrorLocation = pszLocation ;
  714. if (status == ERROR_ACCOUNT_RESTRICTION)
  715. {
  716. dwMsgId = IDS_AUTH_ACC_RESTRICTION;
  717. }
  718. if (status == ERROR_SHARING_PAUSED)
  719. {
  720. status = IDS_LOGIN_DISABLED;
  721. }
  722. if (IS_TREE(pszLocation))
  723. {
  724. //
  725. // Format into nicer string for user
  726. //
  727. WCHAR *pszTmp = LocalAlloc(LMEM_ZEROINIT,
  728. (wcslen(pszLocation)+2) *
  729. sizeof(WCHAR)) ;
  730. if (pszTmp)
  731. {
  732. pszErrorLocation = pszTmp ;
  733. //
  734. // This code formats the NDS
  735. // tree UNC to: Tree(Context)
  736. //
  737. wcscpy(pszErrorLocation, pszLocation+1) ;
  738. if (pszTmp = wcschr(pszErrorLocation, L'\\'))
  739. {
  740. *pszTmp = L'(' ;
  741. wcscat(pszErrorLocation, L")") ;
  742. }
  743. }
  744. }
  745. nResult = NwpMessageBoxError(
  746. DialogHandle,
  747. IDS_AUTH_FAILURE_TITLE,
  748. dwMsgId,
  749. status,
  750. pszErrorLocation,
  751. MB_YESNO | MB_DEFBUTTON2
  752. | MB_ICONEXCLAMATION
  753. );
  754. if (pszErrorLocation != pszLocation)
  755. {
  756. (void) LocalFree(pszErrorLocation) ;
  757. }
  758. if ( nResult == IDYES )
  759. {
  760. //
  761. // Save the logon credential to the registry
  762. //
  763. NwpSaveLogonCredential(
  764. pLoginParam->NewUserSid,
  765. pLoginParam->pLogonId,
  766. pLoginParam->UserName,
  767. pLoginParam->Password,
  768. pszLocation
  769. );
  770. // Clear the password buffer
  771. RtlZeroMemory( OrigPassword, sizeof( OrigPassword));
  772. NwpSaveLogonScriptOptions( pLoginParam->NewUserSid, pLoginParam->LogonScriptOptions );
  773. EndDialog(DialogHandle, 0);
  774. }
  775. else
  776. {
  777. //
  778. // Put the focus where the user can fix the
  779. // invalid name.
  780. //
  781. DWORD controlId =
  782. IsDlgButtonChecked(DialogHandle,
  783. ID_DEFAULTCONTEXT_RB) ?
  784. ID_DEFAULTTREE :
  785. ID_SERVER ;
  786. SetFocus(GetDlgItem(DialogHandle, controlId));
  787. SendDlgItemMessageW(
  788. DialogHandle,
  789. controlId,
  790. EM_SETSEL,
  791. 0,
  792. MAKELPARAM(0, -1)
  793. );
  794. }
  795. }
  796. LocalFree( pszLocation );
  797. return TRUE;
  798. }
  799. case IDCANCEL:
  800. CANCEL_PREFERRED_SERVER:
  801. #if DBG
  802. IF_DEBUG(LOGON) {
  803. KdPrint(("\n\t[CANCEL] was pressed\n"));
  804. KdPrint(("\tLast Preferred Server: %ws\n",
  805. pLoginParam->ServerName));
  806. KdPrint(("\tLast Password: %ws\n",
  807. pLoginParam->Password ));
  808. }
  809. #endif
  810. if ( *(pLoginParam->ServerName) == NW_INVALID_SERVER_CHAR )
  811. {
  812. // No preferred server has been set.
  813. // Pop up a warning to the user.
  814. INT nResult = NwpMessageBoxError(
  815. DialogHandle,
  816. IDS_NETWARE_TITLE,
  817. IDS_NO_PREFERRED,
  818. 0,
  819. NULL,
  820. MB_YESNO | MB_ICONEXCLAMATION
  821. );
  822. //
  823. // The user chose NO, return to the dialog.
  824. //
  825. if ( nResult == IDNO )
  826. {
  827. //
  828. // Put the focus where the user can fix the
  829. // invalid name.
  830. //
  831. DWORD controlId =
  832. IsDlgButtonChecked(DialogHandle,
  833. ID_DEFAULTCONTEXT_RB) ?
  834. ID_DEFAULTTREE :
  835. ID_SERVER ;
  836. SetFocus(GetDlgItem(DialogHandle, controlId));
  837. SendDlgItemMessageW(
  838. DialogHandle,
  839. controlId,
  840. EM_SETSEL,
  841. 0,
  842. MAKELPARAM(0, -1)
  843. );
  844. return TRUE;
  845. }
  846. //
  847. // Save the preferred server as empty string
  848. //
  849. NwpSaveLogonCredential(
  850. pLoginParam->NewUserSid,
  851. pLoginParam->pLogonId,
  852. pLoginParam->UserName,
  853. pLoginParam->Password,
  854. L""
  855. );
  856. pLoginParam->LogonScriptOptions = NW_LOGONSCRIPT_DISABLED;
  857. NwpSaveLogonScriptOptions( pLoginParam->NewUserSid, pLoginParam->LogonScriptOptions );
  858. }
  859. // The user has not logged on to any server.
  860. // Logged the user on using NULL as preferred server.
  861. NwrLogonUser(
  862. NULL,
  863. pLoginParam->pLogonId,
  864. pLoginParam->UserName,
  865. pLoginParam->Password,
  866. NULL,
  867. NULL,
  868. NULL,
  869. 0,
  870. pLoginParam->PrintOption
  871. );
  872. //
  873. // Clear the password buffer
  874. RtlZeroMemory( OrigPassword, sizeof( OrigPassword));
  875. EndDialog(DialogHandle, 0);
  876. return TRUE;
  877. case IDHELP:
  878. {
  879. INT_PTR Result ;
  880. Result = DialogBoxParamW(
  881. hmodNW,
  882. MAKEINTRESOURCEW(DLG_PREFERRED_SERVER_HELP),
  883. (HWND) DialogHandle,
  884. (DLGPROC) NwpHelpDlgProc,
  885. (LPARAM) 0
  886. );
  887. // ignore any errors. should not fail, and if does,
  888. // nothing we can do.
  889. return TRUE ;
  890. }
  891. }
  892. }
  893. //
  894. // We didn't process this message
  895. //
  896. return FALSE;
  897. }
  898. INT
  899. NwpMessageBoxError(
  900. IN HWND hwndParent,
  901. IN DWORD TitleId,
  902. IN DWORD BodyId,
  903. IN DWORD Error,
  904. IN LPWSTR pszParameter,
  905. IN UINT Style
  906. )
  907. /*++
  908. Routine Description:
  909. This routine puts up a message box error.
  910. Arguments:
  911. hwndParent - Supplies the handle of the parent window.
  912. TitleId - Supplies the ID of the title. ( LoadString )
  913. BodyId - Supplies the ID of the message. ( LoadString )
  914. Error - If BodyId != 0, then this supplies the ID of the
  915. substitution string that will be substituted into
  916. the string indicated by BodyId.
  917. If BodyId == 0, then this will be the error message.
  918. This id is a system error that we will get from FormatMessage
  919. using FORMAT_MESSAGE_FROM_SYSTEM.
  920. pszParameter - A substitution string that will be used as %2 or if
  921. Error == 0, this string will be substituted as %1 into
  922. the string indicated by BodyId.
  923. Style - Supplies the style of the MessageBox.
  924. Return Value:
  925. The return value from the MessageBox, 0 if any error is encountered.
  926. --*/
  927. {
  928. DWORD nResult = 0;
  929. DWORD nLength;
  930. WCHAR szTitle[MAX_PATH];
  931. WCHAR szBody[MAX_PATH];
  932. LPWSTR pszError = NULL;
  933. LPWSTR pszBuffer = NULL;
  934. szTitle[0] = 0;
  935. szBody[0] = 0;
  936. //
  937. // Get the Title string
  938. //
  939. nLength = LoadStringW(
  940. hmodNW,
  941. TitleId,
  942. szTitle,
  943. sizeof(szTitle) / sizeof(WCHAR)
  944. );
  945. if ( nLength == 0) {
  946. KdPrint(("NWPROVAU: LoadStringW of Title failed with %lu\n",
  947. GetLastError()));
  948. return 0;
  949. }
  950. //
  951. // Get the body string, if BodyId != 0
  952. //
  953. if ( BodyId != 0 )
  954. {
  955. nLength = LoadStringW(
  956. hmodNW,
  957. BodyId,
  958. szBody,
  959. sizeof(szBody) / sizeof(WCHAR)
  960. );
  961. if ( nLength == 0) {
  962. KdPrint(("NWPROVAU: LoadStringW of Body failed with %lu\n",
  963. GetLastError()));
  964. return 0;
  965. }
  966. }
  967. if ( (Error >= IDS_START) && (Error <= IDS_END) ) {
  968. pszError = (WCHAR *) LocalAlloc(
  969. LPTR,
  970. 256 * sizeof(WCHAR)) ;
  971. if (!pszError)
  972. return 0 ;
  973. nLength = LoadStringW(
  974. hmodNW,
  975. Error,
  976. pszError,
  977. 256
  978. );
  979. if ( nLength == 0 ) {
  980. KdPrint(("NWPROVAU: LoadStringW of Error failed with %lu\n",
  981. GetLastError()));
  982. (void) LocalFree( (HLOCAL)pszError) ;
  983. return 0;
  984. }
  985. }
  986. else if ( Error != 0 ) {
  987. if ( ( Error == WN_NO_MORE_ENTRIES )
  988. || ( Error == ERROR_MR_MID_NOT_FOUND )) {
  989. //
  990. // Handle bogus error from the redirector
  991. //
  992. KdPrint(("NWPROVAU: The NetwareRedirector returned a bogus error as the reason for failure to authenticate. (See Kernel Debugger)\n"));
  993. }
  994. nLength = FormatMessageW(
  995. FORMAT_MESSAGE_FROM_SYSTEM
  996. | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  997. NULL,
  998. Error,
  999. 0,
  1000. (LPWSTR) &pszError,
  1001. MAX_PATH,
  1002. NULL
  1003. );
  1004. if ( nLength == 0 ) {
  1005. KdPrint(("NWPROVAU: FormatMessageW of Error failed with %lu\n",
  1006. GetLastError()));
  1007. return 0;
  1008. }
  1009. }
  1010. if ( ( *szBody != 0 )
  1011. && ( ( pszError != NULL ) || ( pszParameter != NULL) )) {
  1012. LPWSTR aInsertStrings[2];
  1013. aInsertStrings[0] = pszError? pszError : pszParameter;
  1014. aInsertStrings[1] = pszError? pszParameter : NULL;
  1015. nLength = FormatMessageW(
  1016. FORMAT_MESSAGE_FROM_STRING
  1017. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  1018. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1019. szBody,
  1020. 0, // Ignored
  1021. 0, // Ignored
  1022. (LPWSTR) &pszBuffer,
  1023. MAX_PATH,
  1024. (va_list *) aInsertStrings
  1025. );
  1026. if ( nLength == 0 ) {
  1027. KdPrint(("NWPROVAU:FormatMessageW(insertstring) failed with %lu\n",
  1028. GetLastError()));
  1029. if ( pszError != NULL )
  1030. (void) LocalFree( (HLOCAL) pszError );
  1031. return 0;
  1032. }
  1033. }
  1034. else if ( *szBody != 0 ) {
  1035. pszBuffer = szBody;
  1036. }
  1037. else if ( pszError != NULL ) {
  1038. pszBuffer = pszError;
  1039. }
  1040. else {
  1041. // We have neither the body nor the error string.
  1042. // Hence, don't popup the messagebox
  1043. return 0;
  1044. }
  1045. if ( pszBuffer != NULL )
  1046. {
  1047. nResult = MessageBoxW(
  1048. hwndParent,
  1049. pszBuffer,
  1050. szTitle,
  1051. Style
  1052. );
  1053. }
  1054. if ( ( pszBuffer != NULL )
  1055. && ( pszBuffer != szBody )
  1056. && ( pszBuffer != pszError ))
  1057. {
  1058. (void) LocalFree( (HLOCAL) pszBuffer );
  1059. }
  1060. if ( pszError != NULL )
  1061. (void) LocalFree( (HLOCAL) pszError );
  1062. return nResult;
  1063. }
  1064. INT
  1065. NwpMessageBoxIns(
  1066. IN HWND hwndParent,
  1067. IN DWORD TitleId,
  1068. IN DWORD MessageId,
  1069. IN LPWSTR *InsertStrings,
  1070. IN UINT Style
  1071. )
  1072. /*++
  1073. Routine Description:
  1074. This routine puts up a message box error with array of insert strings
  1075. Arguments:
  1076. hwndParent - Supplies the handle of the parent window.
  1077. TitleId - Supplies the ID of the title. ( LoadString )
  1078. MessageId - Supplies the ID of the message. ( LoadString )
  1079. InsertStrings - Array of insert strings for FormatMessage.
  1080. Style - Supplies the style of the MessageBox.
  1081. Return Value:
  1082. The return value from the MessageBox, 0 if any error is encountered.
  1083. --*/
  1084. {
  1085. DWORD nResult = 0;
  1086. DWORD nLength;
  1087. WCHAR szTitle[MAX_PATH];
  1088. WCHAR szBody[MAX_PATH];
  1089. LPWSTR pszBuffer = NULL;
  1090. szTitle[0] = 0;
  1091. szBody[0] = 0;
  1092. //
  1093. // Get the Title string
  1094. //
  1095. nLength = LoadStringW(
  1096. hmodNW,
  1097. TitleId,
  1098. szTitle,
  1099. sizeof(szTitle) / sizeof(szTitle[0])
  1100. );
  1101. if ( nLength == 0) {
  1102. return 0;
  1103. }
  1104. //
  1105. // Get the message string
  1106. //
  1107. nLength = LoadStringW(
  1108. hmodNW,
  1109. MessageId,
  1110. szBody,
  1111. sizeof(szBody) / sizeof(szBody[0])
  1112. );
  1113. if ( nLength == 0) {
  1114. return 0;
  1115. }
  1116. nLength = FormatMessageW(
  1117. FORMAT_MESSAGE_FROM_STRING
  1118. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  1119. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1120. szBody,
  1121. 0, // Ignored
  1122. 0, // Ignored
  1123. (LPWSTR) &pszBuffer,
  1124. MAX_PATH,
  1125. (va_list *) InsertStrings
  1126. );
  1127. if ( nLength == 0 ) {
  1128. return 0;
  1129. }
  1130. if ( pszBuffer != NULL )
  1131. {
  1132. nResult = MessageBoxW(
  1133. hwndParent,
  1134. pszBuffer,
  1135. szTitle,
  1136. Style
  1137. );
  1138. (void) LocalFree( (HLOCAL) pszBuffer );
  1139. }
  1140. return nResult;
  1141. }
  1142. VOID
  1143. NwpAddServersToControl(
  1144. IN HWND DialogHandle,
  1145. IN INT ControlId,
  1146. IN UINT Message,
  1147. IN INT ControlIdMatch OPTIONAL,
  1148. IN UINT FindMessage
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. This function enumerates the servers on the network and adds each
  1153. server name to the specified Windows control.
  1154. If ControlIdMatch is specified (i.e. non 0), only servers that are
  1155. not found in ControlIdMatch list are added to the list specified
  1156. by ControlId.
  1157. Arguments:
  1158. DialogHandle - Supplies a handle to the Windows dialog.
  1159. ControlId - Supplies id which specifies the control.
  1160. Message - Supplies the window management message to add string.
  1161. ControlIdMatch - Supplies the control ID which contains server
  1162. names that should not be in ControlId.
  1163. FindMessage - Supplies the window management message to find
  1164. string.
  1165. Return Value:
  1166. TRUE - the message was processed.
  1167. FALSE - the message was not processed.
  1168. --*/
  1169. {
  1170. DWORD status = ERROR_NO_NETWORK;
  1171. HANDLE EnumHandle = (HANDLE) NULL;
  1172. LPNETRESOURCE NetR = NULL;
  1173. LPNETRESOURCEW SavePtr;
  1174. WCHAR FormattedNameBuf[MAX_NDS_NAME_CHARS];
  1175. LPWSTR lpFormattedName;
  1176. DWORD dwLength;
  1177. DWORD BytesNeeded = 512;
  1178. DWORD EntriesRead;
  1179. DWORD i;
  1180. //
  1181. // Retrieve the list of servers on the network
  1182. //
  1183. status = NPOpenEnum(
  1184. RESOURCE_GLOBALNET,
  1185. 0,
  1186. 0,
  1187. NULL,
  1188. &EnumHandle
  1189. );
  1190. if (status != NO_ERROR) {
  1191. EnumHandle = (HANDLE) NULL;
  1192. goto CleanExit;
  1193. }
  1194. //
  1195. // Allocate buffer to get servers on the net.
  1196. //
  1197. if ((NetR = (LPVOID) LocalAlloc(
  1198. 0,
  1199. BytesNeeded
  1200. )) == NULL) {
  1201. status = ERROR_NOT_ENOUGH_MEMORY;
  1202. goto CleanExit;
  1203. }
  1204. do {
  1205. EntriesRead = 0xFFFFFFFF; // Read as many as possible
  1206. status = NPEnumResource(
  1207. EnumHandle,
  1208. &EntriesRead,
  1209. (LPVOID) NetR,
  1210. &BytesNeeded
  1211. );
  1212. if (status == WN_SUCCESS) {
  1213. SavePtr = NetR;
  1214. for (i = 0; i < EntriesRead; i++, NetR++)
  1215. {
  1216. if ( NetR->dwDisplayType == RESOURCEDISPLAYTYPE_TREE)
  1217. {
  1218. continue;
  1219. }
  1220. else
  1221. {
  1222. lpFormattedName = FormattedNameBuf;
  1223. }
  1224. dwLength = NW_MAX_SERVER_LEN + 1;
  1225. status = NPFormatNetworkName( NetR->lpRemoteName,
  1226. lpFormattedName,
  1227. &dwLength,
  1228. WNFMT_INENUM,
  1229. 0 );
  1230. lpFormattedName = FormattedNameBuf;
  1231. if ( status != WN_SUCCESS )
  1232. {
  1233. continue;
  1234. }
  1235. if ( dwLength > NW_MAX_SERVER_LEN + 1 )
  1236. {
  1237. continue;
  1238. }
  1239. if (ControlIdMatch != 0) {
  1240. LRESULT Result;
  1241. //
  1242. // Add the server to list only if it's not found
  1243. // in the alternate list specified by ControlIdMatch.
  1244. //
  1245. Result = SendDlgItemMessageW(
  1246. DialogHandle,
  1247. ControlIdMatch,
  1248. FindMessage,
  1249. (WPARAM) -1,
  1250. (LPARAM) lpFormattedName
  1251. );
  1252. if (Result == LB_ERR) {
  1253. //
  1254. // Server name not found. Add to list.
  1255. //
  1256. SendDlgItemMessageW(
  1257. DialogHandle,
  1258. ControlId,
  1259. Message,
  1260. 0,
  1261. (LPARAM) lpFormattedName
  1262. );
  1263. }
  1264. }
  1265. else {
  1266. //
  1267. // No alternate list. Just add all servers.
  1268. //
  1269. SendDlgItemMessageW(
  1270. DialogHandle,
  1271. ControlId,
  1272. Message,
  1273. 0,
  1274. (LPARAM) lpFormattedName
  1275. );
  1276. }
  1277. }
  1278. NetR = SavePtr;
  1279. }
  1280. else if (status != WN_NO_MORE_ENTRIES) {
  1281. status = GetLastError();
  1282. if (status == WN_MORE_DATA) {
  1283. //
  1284. // Original buffer was too small. Free it and allocate
  1285. // the recommended size and then some to get as many
  1286. // entries as possible.
  1287. //
  1288. (void) LocalFree((HLOCAL) NetR);
  1289. BytesNeeded += NW_ENUM_EXTRA_BYTES;
  1290. if ((NetR = (LPVOID) LocalAlloc(
  1291. 0,
  1292. BytesNeeded
  1293. )) == NULL) {
  1294. status = ERROR_NOT_ENOUGH_MEMORY;
  1295. goto CleanExit;
  1296. }
  1297. }
  1298. else {
  1299. goto CleanExit;
  1300. }
  1301. }
  1302. } while (status != WN_NO_MORE_ENTRIES);
  1303. if (status == WN_NO_MORE_ENTRIES) {
  1304. status = NO_ERROR;
  1305. }
  1306. CleanExit:
  1307. if (EnumHandle != (HANDLE) NULL) {
  1308. (void) NPCloseEnum(EnumHandle);
  1309. }
  1310. if (NetR != NULL) {
  1311. (void) LocalFree((HLOCAL) NetR);
  1312. }
  1313. }
  1314. VOID
  1315. NwpAddTreeNamesToControl(
  1316. IN HWND DialogHandle,
  1317. IN INT ControlId,
  1318. IN UINT Message,
  1319. IN INT ControlIdMatch OPTIONAL,
  1320. IN UINT FindMessage
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. This function enumerates the NDS tree on the network and adds each
  1325. tree name to the specified Windows control.
  1326. If ControlIdMatch is specified (i.e. non 0), only trees that are
  1327. not found in ControlIdMatch list are added to the list specified
  1328. by ControlId.
  1329. Arguments:
  1330. DialogHandle - Supplies a handle to the Windows dialog.
  1331. ControlId - Supplies id which specifies the control.
  1332. Message - Supplies the window management message to add string.
  1333. ControlIdMatch - Supplies the control ID which contains server
  1334. names that should not be in ControlId.
  1335. FindMessage - Supplies the window management message to find
  1336. string.
  1337. Return Value:
  1338. TRUE - the message was processed.
  1339. FALSE - the message was not processed.
  1340. --*/
  1341. {
  1342. DWORD status = ERROR_NO_NETWORK;
  1343. HANDLE EnumHandle = (HANDLE) NULL;
  1344. LPNETRESOURCE NetR = NULL;
  1345. LPNETRESOURCEW SavePtr;
  1346. WCHAR FormattedNameBuf[MAX_NDS_NAME_CHARS];
  1347. LPWSTR lpFormattedName;
  1348. DWORD dwLength;
  1349. DWORD BytesNeeded = 512;
  1350. DWORD EntriesRead;
  1351. DWORD i;
  1352. //
  1353. // Retrieve the list of trees on the network
  1354. //
  1355. status = NPOpenEnum(
  1356. RESOURCE_GLOBALNET,
  1357. 0,
  1358. 0,
  1359. NULL,
  1360. &EnumHandle
  1361. );
  1362. if (status != NO_ERROR) {
  1363. EnumHandle = (HANDLE) NULL;
  1364. goto CleanExit;
  1365. }
  1366. //
  1367. // Allocate buffer to get trees on the net.
  1368. //
  1369. if ((NetR = (LPVOID) LocalAlloc(
  1370. 0,
  1371. BytesNeeded
  1372. )) == NULL) {
  1373. status = ERROR_NOT_ENOUGH_MEMORY;
  1374. goto CleanExit;
  1375. }
  1376. do {
  1377. EntriesRead = 0xFFFFFFFF; // Read as many as possible
  1378. status = NPEnumResource(
  1379. EnumHandle,
  1380. &EntriesRead,
  1381. (LPVOID) NetR,
  1382. &BytesNeeded
  1383. );
  1384. if (status == WN_SUCCESS) {
  1385. SavePtr = NetR;
  1386. for (i = 0; i < EntriesRead; i++, NetR++)
  1387. {
  1388. if ( NetR->dwDisplayType == RESOURCEDISPLAYTYPE_TREE)
  1389. {
  1390. lpFormattedName = (LPWSTR) FormattedNameBuf;
  1391. }
  1392. else
  1393. {
  1394. continue;
  1395. }
  1396. dwLength = NW_MAX_SERVER_LEN + 1;
  1397. status = NPFormatNetworkName( NetR->lpRemoteName,
  1398. lpFormattedName,
  1399. &dwLength,
  1400. WNFMT_INENUM,
  1401. 0 );
  1402. lpFormattedName = FormattedNameBuf;
  1403. if ( status != WN_SUCCESS )
  1404. {
  1405. continue;
  1406. }
  1407. if ( dwLength > NW_MAX_SERVER_LEN + 1 )
  1408. {
  1409. continue;
  1410. }
  1411. if (ControlIdMatch != 0) {
  1412. LRESULT Result;
  1413. //
  1414. // Add the server to list only if it's not found
  1415. // in the alternate list specified by ControlIdMatch.
  1416. //
  1417. Result = SendDlgItemMessageW(
  1418. DialogHandle,
  1419. ControlIdMatch,
  1420. FindMessage,
  1421. (WPARAM) -1,
  1422. (LPARAM) lpFormattedName
  1423. );
  1424. if (Result == LB_ERR) {
  1425. //
  1426. // Server name not found. Add to list.
  1427. //
  1428. SendDlgItemMessageW(
  1429. DialogHandle,
  1430. ControlId,
  1431. Message,
  1432. 0,
  1433. (LPARAM) lpFormattedName
  1434. );
  1435. }
  1436. }
  1437. else {
  1438. //
  1439. // No alternate list. Just add all servers.
  1440. //
  1441. SendDlgItemMessageW(
  1442. DialogHandle,
  1443. ControlId,
  1444. Message,
  1445. 0,
  1446. (LPARAM) lpFormattedName
  1447. );
  1448. }
  1449. }
  1450. NetR = SavePtr;
  1451. }
  1452. else if (status != WN_NO_MORE_ENTRIES) {
  1453. status = GetLastError();
  1454. if (status == WN_MORE_DATA) {
  1455. //
  1456. // Original buffer was too small. Free it and allocate
  1457. // the recommended size and then some to get as many
  1458. // entries as possible.
  1459. //
  1460. (void) LocalFree((HLOCAL) NetR);
  1461. BytesNeeded += NW_ENUM_EXTRA_BYTES;
  1462. if ((NetR = (LPVOID) LocalAlloc(
  1463. 0,
  1464. BytesNeeded
  1465. )) == NULL) {
  1466. status = ERROR_NOT_ENOUGH_MEMORY;
  1467. goto CleanExit;
  1468. }
  1469. }
  1470. else {
  1471. goto CleanExit;
  1472. }
  1473. }
  1474. } while (status != WN_NO_MORE_ENTRIES);
  1475. if (status == WN_NO_MORE_ENTRIES) {
  1476. status = NO_ERROR;
  1477. }
  1478. CleanExit:
  1479. if (EnumHandle != (HANDLE) NULL) {
  1480. (void) NPCloseEnum(EnumHandle);
  1481. }
  1482. if (NetR != NULL) {
  1483. (void) LocalFree((HLOCAL) NetR);
  1484. }
  1485. }
  1486. VOID
  1487. NwpAddToComboBox(
  1488. IN HWND DialogHandle,
  1489. IN INT ControlId,
  1490. IN LPWSTR pszNone OPTIONAL,
  1491. IN BOOL AllowNone
  1492. )
  1493. {
  1494. NwpAddServersToControl(DialogHandle, ControlId, CB_ADDSTRING, 0, 0);
  1495. //
  1496. // Combo-box will contain at least the <NONE> entry in its list.
  1497. //
  1498. if ( ARGUMENT_PRESENT(pszNone) && AllowNone) {
  1499. SendDlgItemMessageW(
  1500. DialogHandle,
  1501. ControlId,
  1502. CB_INSERTSTRING,
  1503. (WPARAM) -1,
  1504. (LPARAM) pszNone
  1505. );
  1506. }
  1507. }
  1508. DWORD
  1509. NwpGetUserCredential(
  1510. IN HWND hParent,
  1511. IN LPWSTR Unc,
  1512. IN DWORD err,
  1513. IN LPWSTR pszConnectAsUserName,
  1514. OUT LPWSTR *UserName,
  1515. OUT LPWSTR *Password
  1516. )
  1517. /*++
  1518. Routine Description:
  1519. This function puts up a popup dialog for the user, whose default
  1520. credential denied browse directory access, to enter the correct
  1521. credential. If this function returns successful, the pointers
  1522. to memory allocated for the user entered username and password
  1523. are returned.
  1524. Arguments:
  1525. Unc - Supplies the container name in \\Server\Volume format
  1526. under which the user wants to browse directories.
  1527. UserName - Receives the pointer to memory allocated for the
  1528. username gotten from the dialog. This pointer must be freed
  1529. with LocalFree when done.
  1530. Password - Receives the pointer to memory allocated for the
  1531. password gotten from the dialog. This pointer must be freed
  1532. with LocalFree when done.
  1533. Return Value:
  1534. NO_ERROR or reason for failure.
  1535. --*/
  1536. {
  1537. DWORD status;
  1538. INT_PTR Result;
  1539. HWND DialogHandle = hParent? hParent : NwpGetParentHwnd();
  1540. DWORD UserNameSize = NW_MAX_USERNAME_LEN + 1;
  1541. DWORD PasswordSize = NW_MAX_PASSWORD_LEN + 1;
  1542. CONNECTDLGPARAM ConnectParam;
  1543. *UserName = NULL;
  1544. *Password = NULL;
  1545. if (DialogHandle == NULL) {
  1546. return ERROR_WINDOW_NOT_DIALOG;
  1547. }
  1548. //
  1549. // Allocate memory to return UserName and Password
  1550. //
  1551. if ((*UserName = (LPVOID) LocalAlloc(
  1552. 0,
  1553. UserNameSize * sizeof(WCHAR)
  1554. )) == NULL)
  1555. {
  1556. return ERROR_NOT_ENOUGH_MEMORY;
  1557. }
  1558. //
  1559. // Allocate memory to return UserName and Password
  1560. //
  1561. if ((*Password = (LPVOID) LocalAlloc(
  1562. 0,
  1563. PasswordSize * sizeof(WCHAR)
  1564. )) == NULL)
  1565. {
  1566. (void) LocalFree( *UserName );
  1567. *UserName = NULL;
  1568. return ERROR_NOT_ENOUGH_MEMORY;
  1569. }
  1570. ConnectParam.UncPath = Unc;
  1571. ConnectParam.ConnectAsUserName = pszConnectAsUserName;
  1572. ConnectParam.UserName = *UserName;
  1573. ConnectParam.Password = *Password;
  1574. ConnectParam.UserNameSize = UserNameSize;
  1575. ConnectParam.PasswordSize = PasswordSize;
  1576. ConnectParam.LastConnectionError = err;
  1577. Result = DialogBoxParamW(
  1578. hmodNW,
  1579. MAKEINTRESOURCEW(DLG_NETWORK_CREDENTIAL),
  1580. DialogHandle,
  1581. (DLGPROC) NwpConnectDlgProc,
  1582. (LPARAM) &ConnectParam
  1583. );
  1584. if ( Result == -1 )
  1585. {
  1586. status = GetLastError();
  1587. KdPrint(("NWPROVAU: NwpGetUserCredential: DialogBox failed %lu\n",
  1588. status));
  1589. goto ErrorExit;
  1590. }
  1591. else if ( Result == IDCANCEL )
  1592. {
  1593. //
  1594. // Cancel was pressed.
  1595. //
  1596. status = WN_CANCEL;
  1597. goto ErrorExit;
  1598. }
  1599. return NO_ERROR;
  1600. ErrorExit:
  1601. (void) LocalFree((HLOCAL) *UserName);
  1602. (void) LocalFree((HLOCAL) *Password);
  1603. *UserName = NULL;
  1604. *Password = NULL;
  1605. return status;
  1606. }
  1607. BOOL
  1608. WINAPI
  1609. NwpConnectDlgProc(
  1610. HWND DialogHandle,
  1611. UINT Message,
  1612. WPARAM WParam,
  1613. LPARAM LParam
  1614. )
  1615. /*++
  1616. Routine Description:
  1617. This function is the window management message handler which
  1618. initializes, and reads user input from the dialog put up when the
  1619. user fails to browse a directory on the default credential.
  1620. Arguments:
  1621. DialogHandle - Supplies a handle to display the dialog.
  1622. Message - Supplies the window management message.
  1623. LParam - Supplies the pointer to a buffer which on input
  1624. contains the \\Server\Volume string under which the user
  1625. needs to type in a new credential before browsing. On
  1626. output, this pointer contains the username and password
  1627. strings entered to the dialog box.
  1628. Return Value:
  1629. TRUE - the message was processed.
  1630. FALSE - the message was not processed.
  1631. --*/
  1632. {
  1633. static PCONNECTDLGPARAM pConnectParam;
  1634. switch (Message) {
  1635. case WM_INITDIALOG:
  1636. pConnectParam = (PCONNECTDLGPARAM) LParam;
  1637. //
  1638. // Position dialog
  1639. //
  1640. // NwpCenterDialog(DialogHandle);
  1641. //
  1642. // Display the \\Server\Volume string.
  1643. //
  1644. SetDlgItemTextW( DialogHandle,
  1645. ID_VOLUME_PATH,
  1646. pConnectParam->UncPath );
  1647. if ( pConnectParam->LastConnectionError == NO_ERROR )
  1648. {
  1649. WCHAR szTemp[256];
  1650. if ( LoadString( hmodNW, IDS_CONNECT_NO_ERROR_TEXT,
  1651. szTemp, sizeof( szTemp )/sizeof(WCHAR)))
  1652. {
  1653. SetDlgItemTextW( DialogHandle,
  1654. ID_CONNECT_TEXT,
  1655. szTemp );
  1656. }
  1657. }
  1658. //
  1659. // Username is limited to 256 characters.
  1660. //
  1661. SendDlgItemMessageW(
  1662. DialogHandle,
  1663. ID_CONNECT_AS,
  1664. EM_LIMITTEXT,
  1665. pConnectParam->UserNameSize - 1, // minus the space for '\0'
  1666. 0
  1667. );
  1668. //
  1669. // Password is limited to 256 characters.
  1670. //
  1671. SendDlgItemMessageW(
  1672. DialogHandle,
  1673. ID_CONNECT_PASSWORD,
  1674. EM_LIMITTEXT,
  1675. pConnectParam->PasswordSize - 1, // minus the space for '\0'
  1676. 0
  1677. );
  1678. //
  1679. // Display the User name string.
  1680. //
  1681. if ( pConnectParam->ConnectAsUserName )
  1682. {
  1683. SetDlgItemTextW( DialogHandle,
  1684. ID_CONNECT_AS,
  1685. pConnectParam->ConnectAsUserName );
  1686. }
  1687. return TRUE;
  1688. case WM_COMMAND:
  1689. switch (LOWORD(WParam)) {
  1690. case IDOK:
  1691. GetDlgItemTextW(
  1692. DialogHandle,
  1693. ID_CONNECT_AS,
  1694. pConnectParam->UserName,
  1695. pConnectParam->UserNameSize
  1696. );
  1697. GetDlgItemTextW(
  1698. DialogHandle,
  1699. ID_CONNECT_PASSWORD,
  1700. pConnectParam->Password,
  1701. pConnectParam->PasswordSize
  1702. );
  1703. #if DBG
  1704. IF_DEBUG(LOGON) {
  1705. KdPrint(("\n\t[OK] was pressed\n"));
  1706. KdPrint(("\tUserName : %ws\n",
  1707. pConnectParam->UserName));
  1708. KdPrint(("\tPassword : %ws\n",
  1709. pConnectParam->Password));
  1710. }
  1711. #endif
  1712. EndDialog(DialogHandle, (INT) IDOK); // OK
  1713. return TRUE;
  1714. case IDCANCEL:
  1715. #if DBG
  1716. IF_DEBUG(LOGON) {
  1717. KdPrint(("\n\t[CANCEL] was pressed\n"));
  1718. }
  1719. #endif
  1720. EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL
  1721. return TRUE;
  1722. case IDHELP:
  1723. WinHelp( DialogHandle,
  1724. NW_HELP_FILE,
  1725. HELP_CONTEXT,
  1726. IDH_DLG_NETWORK_CREDENTIAL_HELP );
  1727. return TRUE;
  1728. }
  1729. }
  1730. //
  1731. // We didn't process this message
  1732. //
  1733. return FALSE;
  1734. }
  1735. VOID
  1736. NwpCenterDialog(
  1737. HWND hwnd
  1738. )
  1739. /*++
  1740. Routine Description:
  1741. This routine positions the dialog centered horizontally and 1/3
  1742. down the screen vertically. It should be called by the dlg proc
  1743. when processing the WM_INITDIALOG message. This code is stolen
  1744. from Visual Basic written by GustavJ.
  1745. Screen
  1746. -----------------------------
  1747. | 1/3 Above |
  1748. | --------------- |
  1749. | | Dialog | |
  1750. | | | |
  1751. | --------------- |
  1752. | 2/3 Below |
  1753. | |
  1754. -----------------------------
  1755. Arguments:
  1756. hwnd - Supplies the handle to the dialog.
  1757. Return Value:
  1758. None.
  1759. --*/
  1760. {
  1761. RECT rect;
  1762. LONG nx; // New x
  1763. LONG ny; // New y
  1764. LONG width;
  1765. LONG height;
  1766. GetWindowRect( hwnd, &rect );
  1767. width = rect.right - rect.left;
  1768. height = rect.bottom - rect.top;
  1769. nx = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
  1770. ny = (GetSystemMetrics(SM_CYSCREEN) - height) / 3;
  1771. MoveWindow( hwnd, nx, ny, width, height, FALSE );
  1772. }
  1773. HWND
  1774. NwpGetParentHwnd(
  1775. VOID
  1776. )
  1777. /*++
  1778. Routine Description:
  1779. This function gets the parent window handle so that a
  1780. dialog can be displayed in the current context.
  1781. Arguments:
  1782. None.
  1783. Return Value:
  1784. Returns the parent window handle if successful; NULL otherwise.
  1785. --*/
  1786. {
  1787. HWND hwnd;
  1788. LONG lWinStyle;
  1789. //
  1790. // Get the current focus. This is presumably the button
  1791. // that was last clicked.
  1792. //
  1793. hwnd = GetFocus();
  1794. //
  1795. // We must make sure that we don't return the window handle
  1796. // for a child window. Hence, we traverse up the ancestors
  1797. // of this window handle until we find a non-child window.
  1798. // Then, we return that handle. If we ever find a NULL window
  1799. // handle before finding a non-child window, we are unsuccessful
  1800. // and will return NULL.
  1801. //
  1802. // Note on the bit manipulation below. A window is either
  1803. // an overlapped window, a popup window or a child window.
  1804. // Hence, we OR together the possible bit combinations of these
  1805. // possibilities. This should tell us which bits are used in
  1806. // the window style dword (although we know this becomes 0xC000
  1807. // today, we don't know if these will ever change later). Then,
  1808. // we AND the bit combination we with the given window style
  1809. // dword, and compare the result with WS_CHILD. This tells us
  1810. // whether or not the given window is a child window.
  1811. //
  1812. while (hwnd) {
  1813. lWinStyle = GetWindowLong (hwnd, GWL_STYLE);
  1814. if ((lWinStyle & (WS_OVERLAPPED | WS_POPUP | WS_CHILD)) != WS_CHILD) {
  1815. return hwnd;
  1816. }
  1817. hwnd = GetParent(hwnd);
  1818. }
  1819. return NULL;
  1820. }
  1821. BOOL
  1822. WINAPI
  1823. NwpPasswdPromptDlgProc(
  1824. HWND DialogHandle,
  1825. UINT Message,
  1826. WPARAM WParam,
  1827. LPARAM LParam
  1828. )
  1829. /*++
  1830. Routine Description:
  1831. This function is the window management message handler for
  1832. the change password dialog.
  1833. Arguments:
  1834. DialogHandle - Supplies a handle to display the dialog.
  1835. Message - Supplies the window management message.
  1836. LParam - Supplies the pointer to a buffer which on input
  1837. contains the Server string under which the user
  1838. needs to type in a new credential before browsing. On
  1839. output, this pointer contains the username and server
  1840. strings entered to the dialog box.
  1841. Return Value:
  1842. TRUE - the message was processed.
  1843. FALSE - the message was not processed.
  1844. --*/
  1845. {
  1846. LPWSTR UserName;
  1847. LPWSTR ServerName;
  1848. static LPWSTR Password;
  1849. static DWORD PasswordSize ;
  1850. INT Result ;
  1851. PPROMPTDLGPARAM DlgParams ;
  1852. DWORD nLength;
  1853. WCHAR szLocation[MAX_PATH];
  1854. szLocation[0] = 0;
  1855. switch (Message) {
  1856. case WM_INITDIALOG:
  1857. DlgParams = (PPROMPTDLGPARAM) LParam;
  1858. UserName = DlgParams->UserName ;
  1859. ServerName = DlgParams->ServerName ;
  1860. Password = DlgParams->Password ;
  1861. PasswordSize = DlgParams->PasswordSize ;
  1862. ASSERT(ServerName) ;
  1863. //
  1864. // Position dialog
  1865. //
  1866. NwpCenterDialog(DialogHandle);
  1867. //
  1868. // Get the string "Server" or "Context".
  1869. //
  1870. nLength = LoadStringW(
  1871. hmodNW,
  1872. IS_TREE(ServerName) ? IDS_CONTEXT : IDS_SERVER,
  1873. szLocation,
  1874. sizeof(szLocation) / sizeof(szLocation[0])
  1875. );
  1876. if ( nLength == 0) {
  1877. szLocation[0] = 0; // missing text, but still works
  1878. }
  1879. SetDlgItemTextW(DialogHandle, ID_LOCATION, szLocation);
  1880. //
  1881. // Format the server/context string. Note we reuse the
  1882. // location buffer.
  1883. //
  1884. RtlZeroMemory(szLocation, sizeof(szLocation)) ;
  1885. nLength = wcslen(ServerName) ;
  1886. if ( IS_TREE(ServerName) &&
  1887. (nLength+1 < (sizeof(szLocation)/sizeof(szLocation[0]))))
  1888. {
  1889. //
  1890. // NDS tree & context
  1891. //
  1892. WCHAR *pszTmp ;
  1893. wcscpy(szLocation, ServerName+1) ; // skip the * if tree\context
  1894. if (pszTmp = wcschr(szLocation, L'\\'))
  1895. {
  1896. *pszTmp = L'(' ;
  1897. wcscat(szLocation, L")") ;
  1898. }
  1899. }
  1900. else
  1901. {
  1902. wcsncpy(szLocation, ServerName, nLength) ;
  1903. }
  1904. //
  1905. // show the user and server names.
  1906. //
  1907. SetDlgItemTextW(DialogHandle, ID_SERVER, szLocation);
  1908. SetDlgItemTextW(DialogHandle, ID_USERNAME, UserName);
  1909. //
  1910. // set limits
  1911. //
  1912. SendDlgItemMessageW( DialogHandle,
  1913. ID_PASSWORD,
  1914. EM_LIMITTEXT,
  1915. PasswordSize - 1, // minus space for '\0'
  1916. 0 );
  1917. return TRUE;
  1918. case WM_COMMAND:
  1919. switch (LOWORD(WParam)) {
  1920. case IDHELP:
  1921. DialogBoxParamW(
  1922. hmodNW,
  1923. MAKEINTRESOURCEW(DLG_ENTER_PASSWORD_HELP),
  1924. (HWND) DialogHandle,
  1925. (DLGPROC) NwpHelpDlgProc,
  1926. (LPARAM) 0
  1927. );
  1928. return TRUE;
  1929. case IDOK:
  1930. Result = GetDlgItemTextW( DialogHandle,
  1931. ID_PASSWORD,
  1932. Password,
  1933. PasswordSize
  1934. );
  1935. EndDialog(DialogHandle, (INT) IDOK); // OK
  1936. return TRUE;
  1937. case IDCANCEL:
  1938. EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL
  1939. return TRUE;
  1940. }
  1941. }
  1942. //
  1943. // We didn't process this message
  1944. //
  1945. return FALSE;
  1946. }
  1947. BOOL
  1948. WINAPI
  1949. NwpChangePasswordDlgProc(
  1950. HWND DialogHandle,
  1951. UINT Message,
  1952. WPARAM WParam,
  1953. LPARAM LParam
  1954. )
  1955. /*++
  1956. Routine Description:
  1957. This function is the window management message handler for
  1958. the change password dialog.
  1959. Arguments:
  1960. DialogHandle - Supplies a handle to display the dialog.
  1961. Message - Supplies the window management message.
  1962. LParam - Supplies the pointer to a buffer which on input
  1963. contains the Server string under which the user
  1964. needs to type in a new credential before browsing. On
  1965. output, this pointer contains the username and server
  1966. strings entered to the dialog box.
  1967. Return Value:
  1968. TRUE - the message was processed.
  1969. FALSE - the message was not processed.
  1970. --*/
  1971. {
  1972. static PCHANGE_PASS_DLG_PARAM pChangePassParam ;
  1973. switch (Message)
  1974. {
  1975. case WM_INITDIALOG:
  1976. pChangePassParam = (PCHANGE_PASS_DLG_PARAM) LParam;
  1977. NwpCenterDialog(DialogHandle);
  1978. SetDlgItemTextW(DialogHandle, ID_SERVER, pChangePassParam->TreeName);
  1979. SetDlgItemTextW(DialogHandle, ID_USERNAME, pChangePassParam->UserName);
  1980. //
  1981. // set limits
  1982. //
  1983. SendDlgItemMessageW( DialogHandle,
  1984. ID_OLD_PASSWORD,
  1985. EM_LIMITTEXT,
  1986. NW_MAX_PASSWORD_LEN, // minus space for '\0'
  1987. 0 );
  1988. SendDlgItemMessageW( DialogHandle,
  1989. ID_NEW_PASSWORD,
  1990. EM_LIMITTEXT,
  1991. NW_MAX_PASSWORD_LEN, // minus space for '\0'
  1992. 0 );
  1993. SendDlgItemMessageW( DialogHandle,
  1994. ID_CONFIRM_PASSWORD,
  1995. EM_LIMITTEXT,
  1996. NW_MAX_PASSWORD_LEN, // minus space for '\0'
  1997. 0 );
  1998. return TRUE;
  1999. case WM_COMMAND:
  2000. switch (LOWORD(WParam))
  2001. {
  2002. case IDHELP:
  2003. DialogBoxParamW(
  2004. hmodNW,
  2005. MAKEINTRESOURCEW(DLG_CHANGE_PASSWORD_HELP),
  2006. (HWND) DialogHandle,
  2007. (DLGPROC) NwpHelpDlgProc,
  2008. (LPARAM) 0
  2009. );
  2010. return TRUE;
  2011. case IDOK:
  2012. {
  2013. INT Result;
  2014. WCHAR szConfirmPassword[NW_MAX_PASSWORD_LEN + 1];
  2015. UNICODE_STRING OldPasswordStr;
  2016. UNICODE_STRING NewPasswordStr;
  2017. UCHAR EncodeSeed = NW_ENCODE_SEED2;
  2018. Result = GetDlgItemTextW( DialogHandle,
  2019. ID_OLD_PASSWORD,
  2020. pChangePassParam->OldPassword,
  2021. NW_MAX_PASSWORD_LEN
  2022. );
  2023. Result = GetDlgItemTextW( DialogHandle,
  2024. ID_NEW_PASSWORD,
  2025. pChangePassParam->NewPassword,
  2026. NW_MAX_PASSWORD_LEN
  2027. );
  2028. Result = GetDlgItemTextW( DialogHandle,
  2029. ID_CONFIRM_PASSWORD,
  2030. szConfirmPassword,
  2031. NW_MAX_PASSWORD_LEN
  2032. );
  2033. if ( wcscmp( pChangePassParam->NewPassword,
  2034. szConfirmPassword ) )
  2035. {
  2036. //
  2037. // New and Confirm passwords don't match!
  2038. //
  2039. (void) NwpMessageBoxError(
  2040. DialogHandle,
  2041. IDS_CHANGE_PASSWORD_TITLE,
  2042. IDS_CHANGE_PASSWORD_CONFLICT,
  2043. 0,
  2044. NULL,
  2045. MB_OK | MB_ICONSTOP );
  2046. SetDlgItemText( DialogHandle,
  2047. ID_NEW_PASSWORD,
  2048. L"" );
  2049. SetDlgItemText( DialogHandle,
  2050. ID_CONFIRM_PASSWORD,
  2051. L"" );
  2052. SetFocus( GetDlgItem( DialogHandle,
  2053. ID_NEW_PASSWORD ));
  2054. return TRUE;
  2055. }
  2056. RtlInitUnicodeString( &OldPasswordStr,
  2057. pChangePassParam->OldPassword );
  2058. RtlInitUnicodeString( &NewPasswordStr,
  2059. pChangePassParam->NewPassword );
  2060. RtlRunEncodeUnicodeString(&EncodeSeed, &OldPasswordStr);
  2061. RtlRunEncodeUnicodeString(&EncodeSeed, &NewPasswordStr);
  2062. EndDialog(DialogHandle, (INT) IDOK); // OK
  2063. return TRUE;
  2064. }
  2065. case IDCANCEL:
  2066. EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL
  2067. return TRUE;
  2068. default:
  2069. return FALSE;
  2070. }
  2071. }
  2072. //
  2073. // We didn't process this message
  2074. //
  2075. return FALSE;
  2076. }
  2077. BOOL
  2078. WINAPI
  2079. NwpHelpDlgProc(
  2080. HWND DialogHandle,
  2081. UINT Message,
  2082. WPARAM WParam,
  2083. LPARAM LParam
  2084. )
  2085. //
  2086. // This dialog is used for both Help and Question dialogs.
  2087. //
  2088. {
  2089. switch (Message) {
  2090. case WM_INITDIALOG:
  2091. NwpCenterDialog(DialogHandle);
  2092. return TRUE;
  2093. case WM_COMMAND:
  2094. switch (LOWORD(WParam))
  2095. {
  2096. case IDOK:
  2097. case IDCANCEL:
  2098. EndDialog(DialogHandle, IDOK);
  2099. return TRUE;
  2100. case IDYES:
  2101. EndDialog(DialogHandle, IDYES);
  2102. return TRUE;
  2103. case IDNO:
  2104. EndDialog(DialogHandle, IDNO);
  2105. return TRUE;
  2106. default:
  2107. return FALSE ;
  2108. }
  2109. }
  2110. //
  2111. // We didn't process this message
  2112. //
  2113. return FALSE;
  2114. }
  2115. VOID
  2116. NwpGetNoneString(
  2117. LPWSTR pszNone,
  2118. DWORD cBufferSize
  2119. )
  2120. /*++
  2121. Routine Description:
  2122. This function gets the <NONE> string from the resource.
  2123. Arguments:
  2124. pszNone - Supplies the buffer to store the string.
  2125. cBufferSize - Supplies the buffer size in bytes.
  2126. Return Value:
  2127. None.
  2128. --*/
  2129. {
  2130. INT TextLength;
  2131. TextLength = LoadStringW( hmodNW,
  2132. IDS_NONE,
  2133. pszNone,
  2134. cBufferSize / sizeof( WCHAR) );
  2135. if ( TextLength == 0 )
  2136. *pszNone = 0;
  2137. }
  2138. VOID
  2139. NwpAddNetWareTreeConnectionsToList(
  2140. IN HWND DialogHandle,
  2141. IN LPWSTR NtUserName,
  2142. IN LPDWORD lpdwUserLuid,
  2143. IN INT ControlId
  2144. )
  2145. {
  2146. DWORD status = NO_ERROR;
  2147. DWORD BufferSize = 2048; // 2KB Buffer
  2148. BYTE pBuffer[2048];
  2149. DWORD EntriesRead;
  2150. LRESULT Result ;
  2151. status = NwGetConnectedTrees( NtUserName,
  2152. pBuffer,
  2153. BufferSize,
  2154. &EntriesRead,
  2155. lpdwUserLuid );
  2156. // NwGetConnectedTrees doesn't return ERR_NO_SUCH_USER, so we check for no EntriesRead
  2157. // JimTh, 4/25/02 - It looks to me like NwGetConnectedTrees DOES return ERR_NO_SUCH_USER
  2158. // If none found, check for dotted name (fred.flintstone) or UPN ([email protected])
  2159. if ( EntriesRead == 0 )
  2160. {
  2161. // escape any dots in the user name and try again
  2162. WCHAR EscapedName[NW_MAX_USERNAME_LEN * 2];
  2163. PWSTR pChar = NtUserName;
  2164. int i = 0;
  2165. BOOL bEscaped = FALSE;
  2166. RtlZeroMemory(EscapedName, sizeof(EscapedName));
  2167. do
  2168. {
  2169. if (*pChar == L'.')
  2170. {
  2171. EscapedName[i++] = '\\';
  2172. bEscaped = TRUE;
  2173. }
  2174. // also handle UPN names
  2175. else if (*pChar == L'@') {
  2176. EscapedName[i] = 0;
  2177. bEscaped = TRUE;
  2178. break;
  2179. }
  2180. EscapedName[i++] = *pChar;
  2181. } while (*pChar++);
  2182. if (bEscaped)
  2183. {
  2184. status = NwGetConnectedTrees( EscapedName,
  2185. pBuffer,
  2186. BufferSize,
  2187. &EntriesRead,
  2188. lpdwUserLuid );
  2189. }
  2190. }
  2191. if ( status == NO_ERROR && EntriesRead > 0 )
  2192. {
  2193. PCONN_INFORMATION pConnInfo = (PCONN_INFORMATION) pBuffer;
  2194. WCHAR tempTreeName[NW_MAX_TREE_LEN + 1];
  2195. DWORD dwSize;
  2196. while ( EntriesRead-- )
  2197. {
  2198. dwSize = sizeof( CONN_INFORMATION );
  2199. dwSize += pConnInfo->HostServerLength;
  2200. dwSize += pConnInfo->UserNameLength;
  2201. RtlZeroMemory( tempTreeName,
  2202. ( NW_MAX_TREE_LEN + 1 ) * sizeof(WCHAR) );
  2203. wcsncpy( tempTreeName,
  2204. pConnInfo->HostServer,
  2205. pConnInfo->HostServerLength / sizeof(WCHAR) );
  2206. CharUpperW( tempTreeName );
  2207. //
  2208. // Add the tree name to the list only
  2209. // if it's not added already.
  2210. //
  2211. Result = SendDlgItemMessageW( DialogHandle,
  2212. ControlId,
  2213. LB_FINDSTRING,
  2214. (WPARAM) -1,
  2215. (LPARAM) tempTreeName );
  2216. if (Result == LB_ERR)
  2217. {
  2218. Result = SendDlgItemMessageW( DialogHandle,
  2219. ControlId,
  2220. LB_ADDSTRING,
  2221. 0,
  2222. (LPARAM) tempTreeName );
  2223. if (Result != LB_ERR)
  2224. {
  2225. LPWSTR lpNdsUserName = NULL;
  2226. lpNdsUserName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT,
  2227. pConnInfo->UserNameLength +
  2228. sizeof(WCHAR) );
  2229. if ( lpNdsUserName )
  2230. {
  2231. wcsncpy( lpNdsUserName,
  2232. pConnInfo->UserName,
  2233. pConnInfo->UserNameLength / sizeof(WCHAR) );
  2234. SendDlgItemMessageW( DialogHandle,
  2235. ControlId,
  2236. LB_SETITEMDATA,
  2237. (WPARAM) Result, // index of entry
  2238. (LPARAM) lpNdsUserName );
  2239. }
  2240. }
  2241. }
  2242. pConnInfo = (PCONN_INFORMATION) ( ((BYTE *)pConnInfo) + dwSize );
  2243. }
  2244. }
  2245. else
  2246. {
  2247. *lpdwUserLuid = 0;
  2248. }
  2249. }
  2250. BOOL
  2251. WINAPI
  2252. NwpChangePasswdDlgProc(
  2253. HWND DialogHandle,
  2254. UINT Message,
  2255. WPARAM WParam,
  2256. LPARAM LParam
  2257. )
  2258. /*++
  2259. Routine Description:
  2260. This function is the window management message handler for
  2261. the change password dialog.
  2262. Arguments:
  2263. DialogHandle - Supplies a handle to display the dialog.
  2264. Message - Supplies the window management message.
  2265. LParam - Supplies the pointer to a buffer which on input
  2266. contains the Server string under which the user
  2267. needs to type in a new credential before browsing. On
  2268. output, this pointer contains the username and server
  2269. strings entered to the dialog box.
  2270. Return Value:
  2271. TRUE - the message was processed.
  2272. FALSE - the message was not processed.
  2273. --*/
  2274. {
  2275. static LPWSTR UserName;
  2276. static LPWSTR ServerName;
  2277. static DWORD UserNameSize ;
  2278. static DWORD ServerNameSize ;
  2279. INT Result ;
  2280. PPASSWDDLGPARAM DlgParams ;
  2281. switch (Message) {
  2282. case WM_INITDIALOG:
  2283. DlgParams = (PPASSWDDLGPARAM) LParam;
  2284. UserName = DlgParams->UserName ;
  2285. ServerName = DlgParams->ServerName ;
  2286. UserNameSize = DlgParams->UserNameSize ;
  2287. ServerNameSize = DlgParams->ServerNameSize ;
  2288. //
  2289. // Position dialog
  2290. //
  2291. NwpCenterDialog(DialogHandle);
  2292. //
  2293. // setup the default user and server names
  2294. //
  2295. SetDlgItemTextW(DialogHandle, ID_SERVER, ServerName);
  2296. SetDlgItemTextW(DialogHandle, ID_USERNAME, UserName);
  2297. //
  2298. // Username is limited to 256 characters.
  2299. //
  2300. SendDlgItemMessageW(DialogHandle,
  2301. ID_USERNAME,
  2302. EM_LIMITTEXT,
  2303. UserNameSize - 1, // minus space for '\0'
  2304. 0 );
  2305. //
  2306. // Server is limited to 256 characters.
  2307. //
  2308. SendDlgItemMessageW( DialogHandle,
  2309. ID_SERVER,
  2310. EM_LIMITTEXT,
  2311. ServerNameSize - 1, // minus space for '\0'
  2312. 0 );
  2313. //
  2314. // Add trees to list
  2315. //
  2316. NwpAddToComboBox( DialogHandle,
  2317. ID_SERVER,
  2318. NULL,
  2319. FALSE ) ;
  2320. return TRUE;
  2321. case WM_COMMAND:
  2322. switch (LOWORD(WParam)) {
  2323. case IDOK:
  2324. Result = GetDlgItemTextW( DialogHandle,
  2325. ID_USERNAME,
  2326. UserName,
  2327. UserNameSize );
  2328. Result = GetDlgItemTextW( DialogHandle,
  2329. ID_SERVER,
  2330. ServerName,
  2331. ServerNameSize );
  2332. EndDialog(DialogHandle, (INT) IDOK); // OK
  2333. return TRUE;
  2334. case IDCANCEL:
  2335. EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL
  2336. return TRUE;
  2337. }
  2338. }
  2339. //
  2340. // We didn't process this message
  2341. //
  2342. return FALSE;
  2343. }
  2344. BOOL
  2345. WINAPI
  2346. NwpOldPasswordDlgProc(
  2347. HWND DialogHandle,
  2348. UINT Message,
  2349. WPARAM WParam,
  2350. LPARAM LParam
  2351. )
  2352. //
  2353. // This dialog lets the user retype the old password for a specific
  2354. // server/tree.
  2355. //
  2356. {
  2357. static POLD_PW_DLG_PARAM OldPwParam;
  2358. switch (Message) {
  2359. case WM_INITDIALOG:
  2360. OldPwParam = (POLD_PW_DLG_PARAM) LParam;
  2361. NwpCenterDialog(DialogHandle);
  2362. SetDlgItemTextW(DialogHandle, ID_SERVER, OldPwParam->FailedServer);
  2363. SendDlgItemMessageW(
  2364. DialogHandle,
  2365. ID_PASSWORD,
  2366. EM_LIMITTEXT,
  2367. NW_MAX_PASSWORD_LEN,
  2368. 0
  2369. );
  2370. return TRUE;
  2371. case WM_COMMAND:
  2372. switch (LOWORD(WParam))
  2373. {
  2374. case IDCANCEL:
  2375. EndDialog(DialogHandle, IDCANCEL);
  2376. return TRUE;
  2377. case IDOK:
  2378. {
  2379. UCHAR EncodeSeed = NW_ENCODE_SEED2;
  2380. UNICODE_STRING PasswordStr;
  2381. RtlZeroMemory(
  2382. OldPwParam->OldPassword,
  2383. NW_MAX_PASSWORD_LEN * sizeof(WCHAR)
  2384. );
  2385. GetDlgItemTextW(
  2386. DialogHandle,
  2387. ID_PASSWORD,
  2388. OldPwParam->OldPassword,
  2389. NW_MAX_PASSWORD_LEN
  2390. );
  2391. #if DBG
  2392. IF_DEBUG(LOGON) {
  2393. KdPrint(("NWPROVAU: Retyped password %ws\n",
  2394. OldPwParam->OldPassword));
  2395. }
  2396. #endif
  2397. RtlInitUnicodeString(&PasswordStr, OldPwParam->OldPassword);
  2398. RtlRunEncodeUnicodeString(&EncodeSeed, &PasswordStr);
  2399. EndDialog(DialogHandle, IDOK);
  2400. return TRUE;
  2401. }
  2402. case IDHELP:
  2403. DialogBoxParamW(
  2404. hmodNW,
  2405. MAKEINTRESOURCEW(DLG_ENTER_OLD_PW_HELP),
  2406. (HWND) DialogHandle,
  2407. (DLGPROC) NwpHelpDlgProc,
  2408. (LPARAM) 0
  2409. );
  2410. return TRUE;
  2411. default:
  2412. return FALSE;
  2413. }
  2414. }
  2415. //
  2416. // We didn't process this message
  2417. //
  2418. return FALSE;
  2419. }
  2420. BOOL
  2421. WINAPI
  2422. NwpAltUserNameDlgProc(
  2423. HWND DialogHandle,
  2424. UINT Message,
  2425. WPARAM WParam,
  2426. LPARAM LParam
  2427. )
  2428. //
  2429. // This dialog lets the user retype an alternate username for a specific
  2430. // server/tree.
  2431. //
  2432. {
  2433. static PUSERNAME_DLG_PARAM UserNameParam;
  2434. switch (Message)
  2435. {
  2436. case WM_INITDIALOG:
  2437. UserNameParam = (PUSERNAME_DLG_PARAM) LParam;
  2438. NwpCenterDialog(DialogHandle);
  2439. //
  2440. // Display the server/tree.
  2441. //
  2442. SetDlgItemTextW(
  2443. DialogHandle,
  2444. ID_SERVER,
  2445. UserNameParam->TreeServerName
  2446. );
  2447. //
  2448. // Username is limited to 256 characters.
  2449. //
  2450. SendDlgItemMessageW(
  2451. DialogHandle,
  2452. ID_USERNAME,
  2453. EM_LIMITTEXT,
  2454. 256,
  2455. 0
  2456. );
  2457. SetDlgItemTextW(
  2458. DialogHandle,
  2459. ID_USERNAME,
  2460. UserNameParam->UserName
  2461. );
  2462. return TRUE;
  2463. case WM_COMMAND:
  2464. switch (LOWORD(WParam))
  2465. {
  2466. case IDCANCEL:
  2467. EndDialog(DialogHandle, IDCANCEL);
  2468. return TRUE;
  2469. case IDOK:
  2470. {
  2471. RtlZeroMemory(
  2472. UserNameParam->UserName,
  2473. 256 * sizeof(WCHAR)
  2474. );
  2475. GetDlgItemTextW(
  2476. DialogHandle,
  2477. ID_USERNAME,
  2478. UserNameParam->UserName,
  2479. 256
  2480. );
  2481. #if DBG
  2482. IF_DEBUG(LOGON) {
  2483. KdPrint(("NWPROVAU: Retyped username %ws\n",
  2484. UserNameParam->UserName));
  2485. }
  2486. #endif
  2487. EndDialog(DialogHandle, IDOK);
  2488. return TRUE;
  2489. }
  2490. case IDHELP:
  2491. DialogBoxParamW(
  2492. hmodNW,
  2493. MAKEINTRESOURCEW(DLG_ENTER_ALT_UN_HELP),
  2494. (HWND) DialogHandle,
  2495. (DLGPROC) NwpHelpDlgProc,
  2496. (LPARAM) 0
  2497. );
  2498. return TRUE;
  2499. default:
  2500. return FALSE;
  2501. }
  2502. }
  2503. //
  2504. // We didn't process this message
  2505. //
  2506. return FALSE;
  2507. }
  2508. VOID
  2509. EnableAddRemove(
  2510. IN HWND DialogHandle
  2511. )
  2512. /*++
  2513. Routine Description:
  2514. This function enables and disables Add and Remove buttons
  2515. based on list box selections.
  2516. Arguments:
  2517. DialogHandle - Supplies a handle to the windows dialog.
  2518. Return Value:
  2519. None.
  2520. --*/
  2521. {
  2522. LRESULT cSel;
  2523. cSel = SendDlgItemMessageW(
  2524. DialogHandle,
  2525. ID_INACTIVE_LIST,
  2526. LB_GETSELCOUNT,
  2527. 0,
  2528. 0
  2529. );
  2530. EnableWindow(GetDlgItem(DialogHandle, ID_ADD), cSel != 0);
  2531. cSel = SendDlgItemMessageW(
  2532. DialogHandle,
  2533. ID_ACTIVE_LIST,
  2534. LB_GETSELCOUNT,
  2535. 0,
  2536. 0
  2537. );
  2538. EnableWindow(GetDlgItem(DialogHandle, ID_REMOVE), cSel != 0);
  2539. }
  2540. BOOL
  2541. WINAPI
  2542. NwpSelectServersDlgProc(
  2543. HWND DialogHandle,
  2544. UINT Message,
  2545. WPARAM WParam,
  2546. LPARAM LParam
  2547. )
  2548. /*++
  2549. Routine Description:
  2550. This routine displays two listboxes--an active list which includes
  2551. the trees which the user is currently attached to, and an inactive
  2552. list which displays the rest of the trees on the net. The user
  2553. can select trees and move them back and forth between the list
  2554. boxes. When OK is selected, the password is changed on the trees
  2555. in the active listbox.
  2556. Arguments:
  2557. DialogHandle - Supplies a handle to the login dialog.
  2558. Message - Supplies the window management message.
  2559. LParam - Supplies the user credential: username, old password and
  2560. new password. The list of trees from the active listbox
  2561. and the number of entries are returned.
  2562. Return Value:
  2563. TRUE - the message was processed.
  2564. FALSE - the message was not processed.
  2565. --*/
  2566. {
  2567. WCHAR szServer[NW_MAX_SERVER_LEN + 1];
  2568. static PCHANGE_PW_DLG_PARAM Credential;
  2569. DWORD status;
  2570. DWORD UserLuid = 0;
  2571. LRESULT ActiveListBoxCount;
  2572. LRESULT InactiveListBoxCount;
  2573. switch (Message) {
  2574. case WM_INITDIALOG:
  2575. //
  2576. // Get the user credential passed in.
  2577. //
  2578. Credential = (PCHANGE_PW_DLG_PARAM) LParam;
  2579. //
  2580. // Position dialog
  2581. //
  2582. NwpCenterDialog(DialogHandle);
  2583. //
  2584. // Display the username.
  2585. //
  2586. SetDlgItemTextW(
  2587. DialogHandle,
  2588. ID_USERNAME,
  2589. Credential->UserName
  2590. );
  2591. //
  2592. // Display current NetWare tree connections in the active box.
  2593. //
  2594. NwpAddNetWareTreeConnectionsToList(
  2595. DialogHandle,
  2596. Credential->UserName,
  2597. &UserLuid,
  2598. ID_ACTIVE_LIST
  2599. );
  2600. //
  2601. // Display all trees in inactive list box.
  2602. //
  2603. NwpAddTreeNamesToControl(
  2604. DialogHandle,
  2605. ID_INACTIVE_LIST,
  2606. LB_ADDSTRING,
  2607. ID_ACTIVE_LIST,
  2608. LB_FINDSTRING
  2609. );
  2610. //
  2611. // Highlight the first entry of the inactive list.
  2612. //
  2613. SetFocus(GetDlgItem(DialogHandle, ID_INACTIVE_LIST));
  2614. SendDlgItemMessageW(
  2615. DialogHandle,
  2616. ID_INACTIVE_LIST,
  2617. LB_SETSEL,
  2618. TRUE,
  2619. 0
  2620. );
  2621. EnableAddRemove(DialogHandle);
  2622. ActiveListBoxCount = SendDlgItemMessageW( DialogHandle,
  2623. ID_ACTIVE_LIST,
  2624. LB_GETCOUNT,
  2625. 0,
  2626. 0 );
  2627. InactiveListBoxCount = SendDlgItemMessageW( DialogHandle,
  2628. ID_INACTIVE_LIST,
  2629. LB_GETCOUNT,
  2630. 0,
  2631. 0 );
  2632. if ( ActiveListBoxCount == 0 &&
  2633. InactiveListBoxCount == 0 )
  2634. {
  2635. (void) NwpMessageBoxError( DialogHandle,
  2636. IDS_NETWARE_TITLE,
  2637. IDS_NO_TREES_DETECTED,
  2638. 0,
  2639. NULL,
  2640. MB_OK );
  2641. EndDialog(DialogHandle, (INT) IDOK);
  2642. }
  2643. return TRUE;
  2644. case WM_COMMAND:
  2645. switch (LOWORD(WParam))
  2646. {
  2647. case IDOK:
  2648. {
  2649. if ((status = NwpGetTreesAndChangePw(
  2650. DialogHandle,
  2651. szServer,
  2652. UserLuid,
  2653. Credential
  2654. ) != NO_ERROR))
  2655. {
  2656. //
  2657. // System error: e.g. out of memory error.
  2658. //
  2659. (void) NwpMessageBoxError(
  2660. DialogHandle,
  2661. IDS_CHANGE_PASSWORD_TITLE,
  2662. 0,
  2663. status,
  2664. NULL,
  2665. MB_OK | MB_ICONSTOP );
  2666. EndDialog(DialogHandle, (INT) -1);
  2667. return TRUE;
  2668. }
  2669. EndDialog(DialogHandle, (INT) IDOK);
  2670. return TRUE;
  2671. }
  2672. case IDCANCEL:
  2673. EndDialog(DialogHandle, (INT) IDCANCEL);
  2674. return TRUE;
  2675. case IDHELP:
  2676. DialogBoxParamW(
  2677. hmodNW,
  2678. MAKEINTRESOURCEW(DLG_PW_SELECT_SERVERS_HELP),
  2679. (HWND) DialogHandle,
  2680. (DLGPROC) NwpHelpDlgProc,
  2681. (LPARAM) 0
  2682. );
  2683. return TRUE;
  2684. case ID_ACTIVE_LIST:
  2685. //
  2686. // When Remove is pressed the highlights follows
  2687. // the selected entries over to the other
  2688. // list box.
  2689. //
  2690. if (HIWORD(WParam) == LBN_SELCHANGE) {
  2691. //
  2692. // Unselect the other listbox
  2693. //
  2694. SendDlgItemMessageW(
  2695. DialogHandle,
  2696. ID_INACTIVE_LIST,
  2697. LB_SETSEL,
  2698. FALSE,
  2699. (LPARAM) -1
  2700. );
  2701. EnableAddRemove(DialogHandle);
  2702. }
  2703. return TRUE;
  2704. case ID_INACTIVE_LIST:
  2705. //
  2706. // When Add is pressed the highlights follows
  2707. // the selected entries over to the other
  2708. // list box.
  2709. //
  2710. if (HIWORD(WParam) == LBN_SELCHANGE) {
  2711. //
  2712. // Unselect the other listbox
  2713. //
  2714. SendDlgItemMessageW(
  2715. DialogHandle,
  2716. ID_ACTIVE_LIST,
  2717. LB_SETSEL,
  2718. FALSE,
  2719. (LPARAM) -1
  2720. );
  2721. EnableAddRemove(DialogHandle);
  2722. }
  2723. return TRUE;
  2724. case ID_ADD:
  2725. case ID_REMOVE:
  2726. {
  2727. INT idFrom;
  2728. INT idTo;
  2729. LRESULT cSel;
  2730. INT SelItem;
  2731. LRESULT iNew;
  2732. HWND hwndActiveList;
  2733. HWND hwndInactiveList;
  2734. hwndActiveList = GetDlgItem(DialogHandle, ID_ACTIVE_LIST);
  2735. hwndInactiveList = GetDlgItem(DialogHandle, ID_INACTIVE_LIST);
  2736. //
  2737. // Set to NOREDRAW to TRUE
  2738. //
  2739. SetWindowLong(hwndActiveList, GWL_STYLE,
  2740. GetWindowLong(hwndActiveList, GWL_STYLE) | LBS_NOREDRAW);
  2741. SetWindowLong(hwndInactiveList, GWL_STYLE,
  2742. GetWindowLong(hwndInactiveList, GWL_STYLE) | LBS_NOREDRAW);
  2743. if (LOWORD(WParam) == ID_ADD)
  2744. {
  2745. idFrom = ID_INACTIVE_LIST;
  2746. idTo = ID_ACTIVE_LIST;
  2747. }
  2748. else
  2749. {
  2750. idFrom = ID_ACTIVE_LIST;
  2751. idTo = ID_INACTIVE_LIST;
  2752. }
  2753. //
  2754. // Move current selection from idFrom to idTo
  2755. //
  2756. //
  2757. // Loop terminates when selection count is zero
  2758. //
  2759. for (;;) {
  2760. //
  2761. // Get count of selected strings
  2762. //
  2763. cSel = SendDlgItemMessageW(
  2764. DialogHandle,
  2765. idFrom,
  2766. LB_GETSELCOUNT,
  2767. 0,
  2768. 0
  2769. );
  2770. if (cSel == 0) {
  2771. //
  2772. // No more selection
  2773. //
  2774. break;
  2775. }
  2776. //
  2777. // To avoid flickering as strings are added and
  2778. // removed from listboxes, no redraw is set for
  2779. // both listboxes until we are transfering the
  2780. // last entry, in which case we reenable redraw
  2781. // so that both listboxes are updated once.
  2782. //
  2783. if (cSel == 1) {
  2784. SetWindowLong(
  2785. hwndActiveList,
  2786. GWL_STYLE,
  2787. GetWindowLong(hwndActiveList, GWL_STYLE) & ~LBS_NOREDRAW
  2788. );
  2789. SetWindowLong(
  2790. hwndInactiveList,
  2791. GWL_STYLE,
  2792. GetWindowLong(hwndInactiveList, GWL_STYLE) & ~LBS_NOREDRAW
  2793. );
  2794. }
  2795. //
  2796. // Get index of first selected item
  2797. //
  2798. SendDlgItemMessageW(
  2799. DialogHandle,
  2800. idFrom,
  2801. LB_GETSELITEMS,
  2802. 1,
  2803. (LPARAM) &SelItem
  2804. );
  2805. //
  2806. // Get server name from list
  2807. //
  2808. SendDlgItemMessageW(
  2809. DialogHandle,
  2810. idFrom,
  2811. LB_GETTEXT,
  2812. (WPARAM) SelItem,
  2813. (LPARAM) (LPWSTR) szServer
  2814. );
  2815. //
  2816. // Remove entry from list
  2817. //
  2818. SendDlgItemMessageW(
  2819. DialogHandle,
  2820. idFrom,
  2821. LB_DELETESTRING,
  2822. (WPARAM) SelItem,
  2823. 0
  2824. );
  2825. //
  2826. // Add entry to list
  2827. //
  2828. iNew = SendDlgItemMessageW(
  2829. DialogHandle,
  2830. idTo,
  2831. LB_ADDSTRING,
  2832. 0,
  2833. (LPARAM) (LPWSTR) szServer
  2834. );
  2835. //
  2836. // Select the new item
  2837. //
  2838. if (iNew != LB_ERR) {
  2839. SendDlgItemMessageW(
  2840. DialogHandle,
  2841. idTo,
  2842. LB_SETSEL,
  2843. TRUE,
  2844. iNew
  2845. );
  2846. }
  2847. } // for
  2848. EnableAddRemove(DialogHandle);
  2849. } // ID_ADD or ID_REMOVE
  2850. }
  2851. }
  2852. //
  2853. // We didn't process this message
  2854. //
  2855. return FALSE;
  2856. }
  2857. DWORD
  2858. NwpGetTreesAndChangePw(
  2859. IN HWND DialogHandle,
  2860. IN LPWSTR ServerBuf,
  2861. IN DWORD UserLuid,
  2862. IN PCHANGE_PW_DLG_PARAM Credential
  2863. )
  2864. /*++
  2865. Routine Description:
  2866. This routine gets the selected trees from the active list box
  2867. and asks the redirector to change password on them. If a failure
  2868. is encountered when changing password on a tree, we pop up appropriate
  2869. dialogs to see if user can fix problem.
  2870. Arguments:
  2871. DialogHandle - Supplies a handle to the login dialog.
  2872. Return Value:
  2873. TRUE - the message was processed.
  2874. FALSE - the message was not processed.
  2875. --*/
  2876. {
  2877. DWORD status;
  2878. HCURSOR Cursor;
  2879. WCHAR tempOldPassword[NW_MAX_PASSWORD_LEN + 1];
  2880. WCHAR tempNewPassword[NW_MAX_PASSWORD_LEN + 1];
  2881. WCHAR tempUserName[MAX_NDS_NAME_CHARS];
  2882. //
  2883. // Turn cursor into hourglass
  2884. //
  2885. Cursor = LoadCursor(NULL, IDC_WAIT);
  2886. if (Cursor != NULL) {
  2887. SetCursor(Cursor);
  2888. ShowCursor(TRUE);
  2889. }
  2890. Credential->ChangedOne = FALSE;
  2891. Credential->TreeList = NULL;
  2892. Credential->UserList = NULL;
  2893. //
  2894. // Get the number of trees we have to change password on.
  2895. //
  2896. Credential->Entries = (DWORD) SendDlgItemMessageW(
  2897. DialogHandle,
  2898. ID_ACTIVE_LIST,
  2899. LB_GETCOUNT,
  2900. 0,
  2901. 0 );
  2902. if (Credential->Entries != 0) {
  2903. DWORD Entries; // Number of entries in remaining list
  2904. DWORD FullIndex; // Index to the whole tree list
  2905. DWORD i;
  2906. DWORD BytesNeeded = sizeof(LPWSTR) * Credential->Entries +
  2907. (NW_MAX_SERVER_LEN + 1) * sizeof(WCHAR) * Credential->Entries;
  2908. LPBYTE FixedPortion;
  2909. LPWSTR EndOfVariableData;
  2910. LRESULT Result;
  2911. Entries = Credential->Entries;
  2912. Credential->TreeList = LocalAlloc(0, BytesNeeded);
  2913. Credential->UserList = LocalAlloc(0,
  2914. sizeof(LPWSTR) * Credential->Entries);
  2915. if (Credential->TreeList == NULL)
  2916. {
  2917. KdPrint(("NWPROVAU: No memory to change password\n"));
  2918. return ERROR_NOT_ENOUGH_MEMORY;
  2919. }
  2920. if (Credential->UserList == NULL)
  2921. {
  2922. KdPrint(("NWPROVAU: No memory to change password\n"));
  2923. return ERROR_NOT_ENOUGH_MEMORY;
  2924. }
  2925. FixedPortion = (LPBYTE) Credential->TreeList;
  2926. EndOfVariableData = (LPWSTR) ((DWORD_PTR) FixedPortion +
  2927. ROUND_DOWN_COUNT(BytesNeeded, ALIGN_DWORD));
  2928. for (i = 0; i < Entries; i++)
  2929. {
  2930. //
  2931. // Read the user selected list of servers from the dialog.
  2932. //
  2933. SendDlgItemMessageW(
  2934. DialogHandle,
  2935. ID_ACTIVE_LIST,
  2936. LB_GETTEXT,
  2937. (WPARAM) i,
  2938. (LPARAM) (LPWSTR) ServerBuf );
  2939. NwlibCopyStringToBuffer(
  2940. ServerBuf,
  2941. wcslen(ServerBuf),
  2942. (LPCWSTR) FixedPortion,
  2943. &EndOfVariableData,
  2944. &(Credential->TreeList)[i] );
  2945. Result = SendDlgItemMessageW( DialogHandle,
  2946. ID_ACTIVE_LIST,
  2947. LB_GETITEMDATA,
  2948. (WPARAM) i,
  2949. 0 );
  2950. if ( Result != LB_ERR )
  2951. {
  2952. (Credential->UserList)[i] = (LPWSTR) Result;
  2953. }
  2954. else
  2955. {
  2956. (Credential->UserList)[i] = NULL;
  2957. }
  2958. FixedPortion += sizeof(LPWSTR);
  2959. }
  2960. FullIndex = 0;
  2961. do
  2962. {
  2963. RtlZeroMemory( tempUserName, sizeof(tempUserName) );
  2964. RtlZeroMemory( tempOldPassword, sizeof(tempOldPassword) );
  2965. RtlZeroMemory( tempNewPassword, sizeof(tempNewPassword) );
  2966. RtlCopyMemory( tempOldPassword,
  2967. Credential->OldPassword,
  2968. sizeof(tempOldPassword) );
  2969. RtlCopyMemory( tempNewPassword,
  2970. Credential->NewPassword,
  2971. sizeof(tempNewPassword) );
  2972. if ( (Credential->UserList)[FullIndex] == NULL )
  2973. {
  2974. // We don't have any connections to tree <current entry>
  2975. // Prompt user to supply a user name for which account
  2976. // we are to change password, or skip . . .
  2977. USERNAME_DLG_PARAM UserNameParam;
  2978. CHANGE_PASS_DLG_PARAM ChangePassParam;
  2979. UserNameParam.UserName = tempUserName;
  2980. UserNameParam.TreeServerName = (Credential->TreeList)[FullIndex];
  2981. SetCursor(Cursor);
  2982. ShowCursor(FALSE);
  2983. Result = DialogBoxParamW(
  2984. hmodNW,
  2985. MAKEINTRESOURCEW(DLG_ENTER_ALT_USERNAME),
  2986. (HWND) DialogHandle,
  2987. (DLGPROC) NwpAltUserNameDlgProc,
  2988. (LPARAM) &UserNameParam );
  2989. Cursor = LoadCursor(NULL, IDC_WAIT);
  2990. if (Cursor != NULL)
  2991. {
  2992. SetCursor(Cursor);
  2993. ShowCursor(TRUE);
  2994. }
  2995. if ( Result != IDOK )
  2996. {
  2997. *((Credential->TreeList)[FullIndex]) = L'\0';
  2998. goto SkipEntry;
  2999. }
  3000. // Now go reverify the credentials for the user name
  3001. // entered by user.
  3002. ChangePassParam.UserName = tempUserName;
  3003. ChangePassParam.TreeName = (Credential->TreeList)[FullIndex];
  3004. ChangePassParam.OldPassword = tempOldPassword;
  3005. ChangePassParam.NewPassword = tempNewPassword;
  3006. SetCursor(Cursor);
  3007. ShowCursor(FALSE);
  3008. Result = DialogBoxParamW(
  3009. hmodNW,
  3010. MAKEINTRESOURCEW(DLG_CHANGE_PASSWORD3),
  3011. (HWND) DialogHandle,
  3012. (DLGPROC) NwpChangePasswordDlgProc,
  3013. (LPARAM) &ChangePassParam );
  3014. Cursor = LoadCursor(NULL, IDC_WAIT);
  3015. if (Cursor != NULL)
  3016. {
  3017. SetCursor(Cursor);
  3018. ShowCursor(TRUE);
  3019. }
  3020. if ( Result != IDOK )
  3021. {
  3022. *((Credential->TreeList)[FullIndex]) = L'\0';
  3023. goto SkipEntry;
  3024. }
  3025. goto Next;
  3026. }
  3027. else
  3028. {
  3029. wcscpy( tempUserName, (Credential->UserList)[FullIndex] );
  3030. LocalFree( (Credential->UserList)[FullIndex] );
  3031. (Credential->UserList)[FullIndex] = NULL;
  3032. }
  3033. // Test tempUserName with the user name in Credential->UserName
  3034. // to see if they are similar (i.e. The first part of the
  3035. // NDS distinguish name matches).
  3036. if ( _wcsnicmp( tempUserName + 3,
  3037. Credential->UserName,
  3038. wcslen( Credential->UserName ) ) )
  3039. {
  3040. // The names are not similar!
  3041. // Prompt user to ask if they really want to change
  3042. // passwords for dis-similar user on tree <current entry>
  3043. // or skip . . .
  3044. USERNAME_DLG_PARAM UserNameParam;
  3045. CHANGE_PASS_DLG_PARAM ChangePassParam;
  3046. // escape any dots in the user name and try again
  3047. WCHAR EscapedName[NW_MAX_USERNAME_LEN * 2];
  3048. PWSTR pChar = Credential->UserName;
  3049. int i = 0;
  3050. BOOL bEscaped = FALSE;
  3051. RtlZeroMemory(EscapedName, sizeof(EscapedName));
  3052. do
  3053. {
  3054. if (*pChar == L'.')
  3055. {
  3056. EscapedName[i++] = '\\';
  3057. bEscaped = TRUE;
  3058. }
  3059. // also handle UPN names
  3060. else if (*pChar == L'@') {
  3061. EscapedName[i] = 0;
  3062. bEscaped = TRUE;
  3063. break;
  3064. }
  3065. EscapedName[i++] = *pChar;
  3066. } while (*pChar++);
  3067. if (bEscaped)
  3068. {
  3069. if ( !_wcsnicmp( tempUserName + 3,
  3070. EscapedName,
  3071. wcslen( EscapedName ) ) )
  3072. goto Next;
  3073. }
  3074. UserNameParam.UserName = tempUserName;
  3075. UserNameParam.TreeServerName = (Credential->TreeList)[FullIndex];
  3076. SetCursor(Cursor);
  3077. ShowCursor(FALSE);
  3078. Result = DialogBoxParamW(
  3079. hmodNW,
  3080. MAKEINTRESOURCEW(DLG_ENTER_ALT_USERNAME),
  3081. (HWND) DialogHandle,
  3082. (DLGPROC) NwpAltUserNameDlgProc,
  3083. (LPARAM) &UserNameParam );
  3084. Cursor = LoadCursor(NULL, IDC_WAIT);
  3085. if (Cursor != NULL)
  3086. {
  3087. SetCursor(Cursor);
  3088. ShowCursor(TRUE);
  3089. }
  3090. if ( Result != IDOK )
  3091. {
  3092. *((Credential->TreeList)[FullIndex]) = L'\0';
  3093. goto SkipEntry;
  3094. }
  3095. // Now go reverify the credentials for the user name
  3096. // entered by user.
  3097. ChangePassParam.UserName = tempUserName;
  3098. ChangePassParam.TreeName = (Credential->TreeList)[FullIndex];
  3099. ChangePassParam.OldPassword = tempOldPassword;
  3100. ChangePassParam.NewPassword = tempNewPassword;
  3101. SetCursor(Cursor);
  3102. ShowCursor(FALSE);
  3103. Result = DialogBoxParamW(
  3104. hmodNW,
  3105. MAKEINTRESOURCEW(DLG_CHANGE_PASSWORD3),
  3106. (HWND) DialogHandle,
  3107. (DLGPROC) NwpChangePasswordDlgProc,
  3108. (LPARAM) &ChangePassParam );
  3109. Cursor = LoadCursor(NULL, IDC_WAIT);
  3110. if (Cursor != NULL)
  3111. {
  3112. SetCursor(Cursor);
  3113. ShowCursor(TRUE);
  3114. }
  3115. if ( Result != IDOK )
  3116. {
  3117. *((Credential->TreeList)[FullIndex]) = L'\0';
  3118. goto SkipEntry;
  3119. }
  3120. }
  3121. Next:
  3122. status = NwrChangePassword(
  3123. NULL, // Reserved
  3124. UserLuid,
  3125. tempUserName,
  3126. tempOldPassword, // Encoded passwords
  3127. tempNewPassword,
  3128. (LPWSTR) (Credential->TreeList)[FullIndex] );
  3129. if (status == ERROR_INVALID_PASSWORD)
  3130. {
  3131. OLD_PW_DLG_PARAM OldPasswordParam;
  3132. #if DBG
  3133. IF_DEBUG(LOGON)
  3134. {
  3135. KdPrint(("NWPROVAU: First attempt: wrong password on %ws\n",
  3136. (Credential->TreeList)[FullIndex]));
  3137. }
  3138. #endif
  3139. //
  3140. // Display dialog to let user type in an alternate
  3141. // old password.
  3142. //
  3143. //
  3144. // Set up old password buffer to receive from dialog.
  3145. //
  3146. OldPasswordParam.OldPassword = tempOldPassword;
  3147. OldPasswordParam.FailedServer = (Credential->TreeList)[FullIndex];
  3148. SetCursor(Cursor);
  3149. ShowCursor(FALSE);
  3150. Result = DialogBoxParamW(
  3151. hmodNW,
  3152. MAKEINTRESOURCEW(DLG_ENTER_OLD_PASSWORD),
  3153. (HWND) DialogHandle,
  3154. (DLGPROC) NwpOldPasswordDlgProc,
  3155. (LPARAM) &OldPasswordParam );
  3156. Cursor = LoadCursor(NULL, IDC_WAIT);
  3157. if (Cursor != NULL)
  3158. {
  3159. SetCursor(Cursor);
  3160. ShowCursor(TRUE);
  3161. }
  3162. if (Result == IDOK)
  3163. {
  3164. //
  3165. // Retry change password with alternate old password on
  3166. // the failed server.
  3167. //
  3168. status = NwrChangePassword(
  3169. NULL, // Reserved
  3170. UserLuid,
  3171. tempUserName,
  3172. tempOldPassword, // Alternate old password
  3173. tempNewPassword,
  3174. (LPWSTR) (Credential->TreeList)[FullIndex] );
  3175. }
  3176. }
  3177. if (status != NO_ERROR)
  3178. {
  3179. //
  3180. // Either unrecoverable failure or user failed to change
  3181. // password on second attempt.
  3182. //
  3183. #if DBG
  3184. IF_DEBUG(LOGON)
  3185. {
  3186. KdPrint(("NWPROVAU: Failed to change password on %ws %lu\n",
  3187. (Credential->TreeList)[FullIndex], status));
  3188. }
  3189. #endif
  3190. // Pop up error dialog to let user know that password
  3191. // could not be changed.
  3192. (void) NwpMessageBoxError(
  3193. DialogHandle,
  3194. IDS_CHANGE_PASSWORD_TITLE,
  3195. IDS_CP_FAILURE_WARNING,
  3196. status,
  3197. (LPWSTR) (Credential->TreeList)[FullIndex],
  3198. MB_OK | MB_ICONSTOP );
  3199. *((Credential->TreeList)[FullIndex]) = L'\0';
  3200. if (status == ERROR_NOT_ENOUGH_MEMORY)
  3201. return status;
  3202. }
  3203. SkipEntry:
  3204. //
  3205. // Continue to change password on the rest of the entries
  3206. //
  3207. FullIndex++;
  3208. Entries = Credential->Entries - FullIndex;
  3209. } while (Entries);
  3210. //
  3211. // Caller is responsible for freeing TreeList
  3212. //
  3213. }
  3214. SetCursor(Cursor);
  3215. ShowCursor(FALSE);
  3216. return NO_ERROR;
  3217. }
  3218. BOOL
  3219. WINAPI
  3220. NwpChangePasswordSuccessDlgProc(
  3221. HWND DialogHandle,
  3222. UINT Message,
  3223. WPARAM WParam,
  3224. LPARAM LParam
  3225. )
  3226. /*++
  3227. Routine Description:
  3228. Arguments:
  3229. DialogHandle - Supplies a handle to the login dialog.
  3230. Message - Supplies the window management message.
  3231. Return Value:
  3232. TRUE - the message was processed.
  3233. FALSE - the message was not processed.
  3234. --*/
  3235. {
  3236. static PCHANGE_PW_DLG_PARAM Credential;
  3237. DWORD_PTR Count;
  3238. DWORD i;
  3239. switch (Message)
  3240. {
  3241. case WM_INITDIALOG:
  3242. //
  3243. // Get the user credential passed in.
  3244. //
  3245. Credential = (PCHANGE_PW_DLG_PARAM) LParam;
  3246. //
  3247. // Position dialog
  3248. //
  3249. NwpCenterDialog(DialogHandle);
  3250. //
  3251. // Put list of NetWare trees that we changed password on in the
  3252. // list box.
  3253. // ID_SERVER );
  3254. for ( i = 0; i < Credential->Entries; i++ )
  3255. {
  3256. if ( *((Credential->TreeList)[i]) != L'\0' )
  3257. {
  3258. SendDlgItemMessageW( DialogHandle,
  3259. ID_SERVER,
  3260. LB_ADDSTRING,
  3261. 0,
  3262. (LPARAM) (Credential->TreeList)[i] );
  3263. }
  3264. }
  3265. Count = SendDlgItemMessageW( DialogHandle,
  3266. ID_SERVER,
  3267. LB_GETCOUNT,
  3268. 0,
  3269. 0 );
  3270. if ( Count == 0 )
  3271. EndDialog(DialogHandle, 0);
  3272. return TRUE;
  3273. case WM_COMMAND:
  3274. switch (LOWORD(WParam))
  3275. {
  3276. case IDOK:
  3277. case IDCANCEL:
  3278. EndDialog(DialogHandle, 0);
  3279. return TRUE;
  3280. }
  3281. }
  3282. //
  3283. // We didn't process this message
  3284. //
  3285. return FALSE;
  3286. }