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.

2352 lines
74 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. KRDLG.CPP
  5. Abstract:
  6. Implementation of the dialog behaviors for three application dialogs:
  7. the add/edit credential dialog, the delete credential dialog, and
  8. the password change dialog. These dialogs are derived fom C_Dlg
  9. Password change operates only on credentials of the form
  10. domain\username. Note that changing a password for such a credential
  11. will change the psw for all creds with the same domain\username to
  12. match (this is done by the credential mgr).
  13. Add and Edit use the same dialog, differing in implementation on
  14. the basis of a flag which initializes the two dialogs differently
  15. and causes the edit case to also delete the underlying previous
  16. version of the credential.
  17. Author:
  18. johnhaw 991118 original version created
  19. georgema 000310 modified, removed "gizmo" services, modified
  20. to use the new credential mgr
  21. georgema 000415 modified, use comboboxex to hold icon as well
  22. as user name
  23. georgema 000515 modified to CPL from EXE, smartcard support
  24. added
  25. georgema 000712 modified to use cred control in lieu of combo
  26. and edit boxes for username/password entry.
  27. Delegating smartcard handling to cred ctrl.
  28. Environment:
  29. Win2000
  30. --*/
  31. #pragma comment(user, "Compiled on " __DATE__ " at " __TIME__)
  32. #pragma comment(compiler)
  33. // test/dev switch variables
  34. #include "switches.h"
  35. #define COOLTIPS
  36. #define ODDUIBUG
  37. #define EDITOFFERPASSWORD
  38. //////////////////////////////////////////////////////////////////////////////
  39. //
  40. // Include files
  41. //
  42. #include <stdlib.h>
  43. #include <crtdbg.h>
  44. #include <nt.h>
  45. #include <ntrtl.h>
  46. #include <nturtl.h>
  47. #include <ntsam.h>
  48. #include <ntlsa.h>
  49. #include <windows.h>
  50. #include <winbase.h>
  51. #include <dsgetdc.h>
  52. #include <lmaccess.h>
  53. #include <lmerr.h>
  54. #include <lmapibuf.h>
  55. #include <windns.h>
  56. #include <shellapi.h>
  57. #include "Dlg.h"
  58. #include "Res.h"
  59. #include "KRDlg.h"
  60. #include "keymgr.h"
  61. // wrapper for certificates in "mystore"
  62. #include <tchar.h>
  63. #include <wincrui.h>
  64. #include "wincred.h"
  65. #include "gmdebug.h"
  66. #include <htmlhelp.h>
  67. #include <credp.h>
  68. #include <comctrlp.h>
  69. #include <shfusion.h>
  70. // in pswchg.cpp:
  71. NET_API_STATUS NetUserChangePasswordEy(LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR);
  72. // estimate of maximum size of target suffixes, possibly localized
  73. #define MAXSUFFIXSIZE (64)
  74. // TCHAR length of a whitespace
  75. #define LENGTHOFWHITESPACE (1)
  76. #ifndef CRED_SESSION_WILDCARD_NAME
  77. #define CRED_SESSION_WILDCARD_NAME CRED_SESSION_WILDCARD_NAME_W
  78. #endif
  79. #define CRED_TYPE_UNKNOWN 0x88
  80. // hack: special data value for RAS cred
  81. #define SESSION_FLAG_VALUE (0x2222)
  82. BOOL fNew; // interlock to prevent multiple dlgs
  83. extern HINSTANCE g_hInstance;
  84. extern C_KeyringDlg *pDlg;
  85. LONG_PTR g_CurrentKey; // currently selected item in the main dlg
  86. BOOL g_fPswChanged; // password window touched by user
  87. DWORD g_dwHCookie; // HTML HELP system cookie
  88. // Globals used for interwindow communication between the main dialog
  89. // and the add/new dialog
  90. HWND g_hMainDlg; // used to give add/new access to target list
  91. C_AddKeyDlg *g_AKdlg; // used for notifications
  92. CREDENTIAL *g_pExistingCred; // current cred under edit
  93. DWORD g_dwPersist;
  94. DWORD g_dwType;
  95. TCHAR g_szTargetName[CRED_MAX_GENERIC_TARGET_NAME_LENGTH + MAXSUFFIXSIZE + 1];
  96. #ifdef SHOWPASSPORT
  97. TCHAR g_rgcPassport[MAXSUFFIXSIZE];
  98. #endif
  99. //TCHAR g_rgcGeneric[MAXSUFFIXSIZE]; // Hold suffix read in from resources
  100. //TCHAR rgcDomain[MAXSUFFIXSIZE]; // Hold suffix read in from resources
  101. TCHAR g_rgcCert[MAXSUFFIXSIZE]; // Hold suffix read in from resources
  102. #ifndef GMDEBUG
  103. #define GM_DEBUG(a)
  104. #else
  105. #define GM_DEBUG(a,b) _DebugPrint(a,b)
  106. void
  107. __cdecl
  108. _DebugPrint(
  109. LPCTSTR szFormat,
  110. ...
  111. )
  112. {
  113. TCHAR szBuffer[1024];
  114. va_list ap;
  115. va_start(ap, szFormat);
  116. _vstprintf(szBuffer, szFormat, ap);
  117. OutputDebugString(szBuffer);
  118. }
  119. void
  120. BugBox(INT n,INT_PTR i) {
  121. TCHAR rgc[512];
  122. _stprintf(rgc,L"Hex %d : %08.8x",n,i);
  123. MessageBox(NULL,rgc,NULL,MB_OK);
  124. }
  125. #endif
  126. DWORD GetPersistenceOptions(void);
  127. //////////////////////////////////////////////////////////////////////////////
  128. //
  129. // KRShowKeyMgr() - static function to present the main keymgr dialog.
  130. //
  131. //
  132. //////////////////////////////////////////////////////////////////////////////
  133. #define KEYMGRMUTEX (TEXT("KeyMgrMutex"))
  134. // Create and show the keyring main dialog. Return -1 (unable to create)
  135. // on errors. If creation goes OK, return the retval from DoModal of
  136. // the keyring dialog class.
  137. //
  138. BOOL WINAPI DllMain(HINSTANCE hinstDll,DWORD fdwReason,LPVOID lpvReserved) {
  139. BOOL bSuccess = TRUE;
  140. switch(fdwReason) {
  141. case DLL_PROCESS_ATTACH:
  142. SHFusionInitializeFromModuleID(hinstDll,123);
  143. DisableThreadLibraryCalls(hinstDll);
  144. g_hInstance = hinstDll;
  145. break;
  146. case DLL_PROCESS_DETACH:
  147. SHFusionUninitialize();
  148. break;
  149. }
  150. return bSuccess;
  151. }
  152. void WINAPI KRShowKeyMgr(HWND hwParent,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow) {
  153. HANDLE hMutex = CreateMutex(NULL,TRUE,KEYMGRMUTEX);
  154. if (NULL == hMutex) return;
  155. if (ERROR_ALREADY_EXISTS == GetLastError()) {
  156. CloseHandle(hMutex);
  157. return;
  158. }
  159. INITCOMMONCONTROLSEX stICC;
  160. BOOL fICC;
  161. stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
  162. stICC.dwICC = ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES;
  163. fICC = InitCommonControlsEx(&stICC);
  164. #ifdef LOUDLY
  165. {
  166. WCHAR wc[500];
  167. if (fICC) OutputDebugString(L"Common control init OK\n");
  168. else
  169. {
  170. DWORD dwe = GetLastError();
  171. OutputDebugString(L"Common control init FAILED\n");
  172. swprintf(wc,L"CCInit error = %x\n",dwe);
  173. OutputDebugString(wc);
  174. }
  175. }
  176. #endif
  177. if (NULL != pDlg) return;
  178. if (!CredUIInitControls()) return;
  179. pDlg = new C_KeyringDlg(hwParent,g_hInstance,IDD_KEYRING,NULL);
  180. if (NULL == pDlg) return;
  181. INT_PTR nResult = pDlg->DoModal((LPARAM) pDlg);
  182. delete pDlg;
  183. pDlg = NULL;
  184. CloseHandle(hMutex);
  185. return;
  186. }
  187. //////////////////////////////////////////////////////////////////////////////
  188. //
  189. // Static initialization
  190. //
  191. static const char _THIS_FILE_[ ] = __FILE__;
  192. //////////////////////////////////////////////////////////////////////////////
  193. //
  194. // Help String Maps - Used only for handling WM_CONTEXTMENU, if context help
  195. // is to appear on right-click
  196. //
  197. //////////////////////////////////////////////////////////////////////////////
  198. //////////////////////////////////////////////////////////////////////////////
  199. //
  200. // Help RESID -> STRINGID map functions
  201. //
  202. // Probably more concise than writing the code to process an
  203. // association array
  204. //
  205. //////////////////////////////////////////////////////////////////////////////
  206. UINT C_KeyringDlg::MapID(UINT uiID) {
  207. switch(uiID) {
  208. case IDC_KEYLIST:
  209. return IDH_KEYLIST;
  210. case IDC_NEWKEY:
  211. return IDH_NEW;
  212. case IDC_DELETEKEY:
  213. return IDH_DELETE;
  214. case IDC_CHANGE_PASSWORD:
  215. return IDH_CHANGEPASSWORD;
  216. case IDC_EDITKEY:
  217. return IDH_EDIT;
  218. case IDOK:
  219. case IDCANCEL:
  220. return IDH_CLOSE;
  221. default:
  222. return IDS_NOHELP;
  223. }
  224. }
  225. UINT C_AddKeyDlg::MapID(UINT uiID) {
  226. switch(uiID) {
  227. case 1003:
  228. return IDH_CUIUSER;
  229. case 1005:
  230. return IDH_CUIPSW;
  231. case 1010:
  232. return IDH_CUIVIEW;
  233. case IDOK:
  234. return IDH_CLOSE;
  235. case IDCANCEL:
  236. return IDH_DCANCEL;
  237. case IDD_ADDCRED:
  238. return IDH_ADDCRED;
  239. case IDC_TARGET_NAME:
  240. return IDH_TARGETNAME;
  241. case IDC_OLD_PASSWORD:
  242. return IDH_OLDPASSWORD;
  243. case IDC_NEW_PASSWORD:
  244. return IDH_NEWPASSWORD;
  245. case IDC_CONFIRM_PASSWORD:
  246. return IDH_CONFIRM;
  247. case IDD_KEYRING:
  248. return IDH_KEYRING;
  249. case IDC_KEYLIST:
  250. return IDH_KEYLIST;
  251. case IDC_NEWKEY:
  252. return IDH_NEW;
  253. case IDC_EDITKEY:
  254. return IDH_EDIT;
  255. case IDC_DELETEKEY:
  256. return IDH_DELETE;
  257. case IDC_CHANGE_PASSWORD:
  258. return IDH_CHANGEPASSWORD;
  259. default:
  260. return IDS_NOHELP;
  261. }
  262. }
  263. //////////////////////////////////////////////////////////////////////////////
  264. //
  265. // C_AddKeyDlg
  266. //
  267. // Constructor.
  268. //
  269. // parameters:
  270. // hwndParent parent window for the dialog (may be NULL)
  271. // hInstance instance handle of the parent window (may be NULL)
  272. // lIDD dialog template id
  273. // pfnDlgProc pointer to the function that will process messages for
  274. // the dialog. if it is NULL, the default dialog proc
  275. // will be used.
  276. //
  277. // returns:
  278. // Nothing.
  279. //
  280. //////////////////////////////////////////////////////////////////////////////
  281. C_AddKeyDlg::C_AddKeyDlg(
  282. HWND hwndParent,
  283. HINSTANCE hInstance,
  284. LONG lIDD,
  285. DLGPROC pfnDlgProc // = NULL
  286. )
  287. : C_Dlg(hwndParent, hInstance, lIDD, pfnDlgProc)
  288. {
  289. m_hInst = hInstance;
  290. } // C_AddKeyDlg::C_AddKeyDlg
  291. // EditFillDialog - read current credential and fill dialog fields with
  292. // the data so recovered.
  293. BOOL gTestReadCredential(void) {
  294. TCHAR *pC;
  295. INT_PTR iIndex,iWhere;
  296. BOOL f;
  297. LRESULT lR,lRet;
  298. TCHAR szTitle[CRED_MAX_STRING_LENGTH]; // buffer to hold window title string
  299. DWORD dwType;
  300. g_pExistingCred = NULL;
  301. // Fetch current credential from list into g_szTargetName
  302. lR = SendDlgItemMessage(g_hMainDlg,IDC_KEYLIST,LB_GETCURSEL,0,0L);
  303. if (lR == LB_ERR)
  304. return FALSE;
  305. else {
  306. g_CurrentKey = lR;
  307. lRet = SendDlgItemMessage(g_hMainDlg,IDC_KEYLIST,LB_GETTEXT,lR,(LPARAM) g_szTargetName);
  308. }
  309. if (lRet == 0) return FALSE; // zero characters returned
  310. // Get the target type from the combo box item data
  311. dwType = (DWORD) SendDlgItemMessage(g_hMainDlg,IDC_KEYLIST,LB_GETITEMDATA,lR,0);
  312. if (LB_ERR == dwType) return FALSE;
  313. // null term the targetname, trimming the suffix if there is one
  314. pC = _tcschr(g_szTargetName,g_rgcCert[0]);
  315. if (pC) {
  316. pC--;
  317. *pC = 0x0; // null terminate namestring
  318. }
  319. // replace special ras cred name string at this point
  320. if (dwType == SESSION_FLAG_VALUE) {
  321. _tcscpy(g_szTargetName,CRED_SESSION_WILDCARD_NAME);
  322. dwType = CRED_TYPE_DOMAIN_PASSWORD;
  323. }
  324. // Attempt to read the credential from the store
  325. // The returned credential will have to be freed if leaving this block
  326. f = (CredRead(g_szTargetName,
  327. (ULONG) dwType,
  328. 0,
  329. &g_pExistingCred));
  330. if (!f)
  331. return FALSE; // g_pExistingCred is empty
  332. return TRUE; // g_pExistingCred has been filled
  333. }
  334. void
  335. C_AddKeyDlg::EditFillDialog(void) {
  336. TCHAR *pC;
  337. INT_PTR iIndex,iWhere;
  338. BOOL f;
  339. LRESULT lR,lRet;
  340. TCHAR szTitle[CRED_MAX_STRING_LENGTH]; // buffer to hold window title string
  341. if (NULL == g_pExistingCred) return;
  342. // Set up persistence in the UI
  343. // bugbug
  344. g_dwPersist = g_pExistingCred->Persist;
  345. g_dwType = g_pExistingCred->Type;
  346. // Enable the change password stuff only on domain password creds
  347. //
  348. switch (g_pExistingCred->Type){
  349. case CRED_TYPE_DOMAIN_PASSWORD:
  350. ShowWindow(m_hwndChgPsw,SW_NORMAL);
  351. ShowWindow(m_hwndPswLbl,SW_NORMAL);
  352. //deliberate fallthrough
  353. case CRED_TYPE_DOMAIN_CERTIFICATE:
  354. LoadString ( m_hInst, IDS_TITLE, szTitle, 200 );
  355. SendMessage(m_hDlg,WM_SETTEXT,0,(LPARAM) szTitle);
  356. break;
  357. default:
  358. break;
  359. }
  360. // Write targetname to the UI
  361. SendMessage(m_hwndTName, WM_SETTEXT,0,(LPARAM) g_pExistingCred->TargetName);
  362. // Write username to the UI - take directly from the existing cred
  363. if (!Credential_SetUserName(m_hwndCred,g_pExistingCred->UserName)) {
  364. // make a copy of the original username
  365. _tcscpy(m_szUsername,g_pExistingCred->UserName);
  366. }
  367. }
  368. // Get permissible persistence types for cred_type_domain_password credentials, which is
  369. // all this UI currently handles.
  370. DWORD GetPersistenceOptions(void) {
  371. BOOL bResult;
  372. DWORD i[CRED_TYPE_MAXIMUM];
  373. DWORD j;
  374. DWORD dwCount = CRED_TYPE_MAXIMUM;
  375. bResult = CredGetSessionTypes(dwCount,i);
  376. if (!bResult) {
  377. return CRED_PERSIST_NONE;
  378. }
  379. j = i[CRED_TYPE_DOMAIN_PASSWORD];
  380. return j;
  381. }
  382. // Create a composite description string from 3 sources:
  383. // 1. the descriptive text for this type of cred
  384. // 2. a general phrase "This informaiton will be available until "
  385. // 3. the persistence tail: "you log off." or "you delete it."
  386. void C_AddKeyDlg::ShowDescriptionText(DWORD dwtype, DWORD Persist)
  387. {
  388. #define DESCBUFFERLEN 500
  389. WCHAR szMsg[DESCBUFFERLEN + 1];
  390. WCHAR szTemp[DESCBUFFERLEN + 1];
  391. INT iRem = DESCBUFFERLEN; // remainging space in the buffer
  392. memset(szMsg,0,sizeof(szMsg));
  393. if ((dwtype != CRED_TYPE_DOMAIN_PASSWORD) &&
  394. (dwtype != CRED_TYPE_DOMAIN_CERTIFICATE))
  395. {
  396. LoadString ( m_hInst, IDS_DESCAPPCRED, szTemp, DESCBUFFERLEN );
  397. wcscpy(szMsg,szTemp);
  398. iRem -= wcslen(szMsg);
  399. }
  400. else
  401. {
  402. if (Persist == CRED_PERSIST_LOCAL_MACHINE)
  403. LoadString ( m_hInst, IDS_DESCLOCAL, szTemp, DESCBUFFERLEN );
  404. else
  405. LoadString ( m_hInst, IDS_DESCBASE, szTemp, DESCBUFFERLEN );
  406. wcscpy(szMsg,szTemp);
  407. iRem -= wcslen(szMsg);
  408. }
  409. LoadString ( m_hInst, IDS_PERSISTBASE, szTemp, DESCBUFFERLEN );
  410. iRem -= wcslen(szTemp);
  411. if (0 < iRem) wcscat(szMsg,szTemp);
  412. if (Persist == CRED_PERSIST_SESSION)
  413. LoadString ( m_hInst, IDS_PERSISTLOGOFF, szTemp, DESCBUFFERLEN );
  414. else
  415. LoadString ( m_hInst, IDS_PERSISTDELETE, szTemp, DESCBUFFERLEN );
  416. iRem -= wcslen(szTemp);
  417. if (0 < iRem) wcscat(szMsg,szTemp);
  418. SendMessage(m_hwndDescription, WM_SETTEXT,0,(LPARAM) szMsg);
  419. return;
  420. }
  421. //////////////////////////////////////////////////////////////////////////////
  422. //
  423. // OnInitDialog
  424. //
  425. // Dialog control and data initialization.
  426. //
  427. // parameters:
  428. // hwndDlg window handle of the dialog box
  429. // hwndFocus window handle of the control that will receive focus
  430. //
  431. // returns:
  432. // TRUE if the system should set the default keyboard focus
  433. // FALSE if the keyboard focus is set by this app
  434. //
  435. //////////////////////////////////////////////////////////////////////////////
  436. BOOL
  437. C_AddKeyDlg::OnInitDialog(
  438. HWND hwndDlg,
  439. HWND hwndFocus
  440. )
  441. {
  442. C_Dlg::OnInitDialog(hwndDlg, hwndFocus);
  443. CenterWindow();
  444. m_hDlg = hwndDlg;
  445. m_hwndCred = GetDlgItem(m_hDlg,IDC_CRED);
  446. if (!Credential_InitStyle(m_hwndCred,CRS_USERNAMES | CRS_CERTIFICATES | CRS_SMARTCARDS)) return FALSE;
  447. m_hwndTName = GetDlgItem(m_hDlg,IDC_TARGET_NAME);
  448. m_hwndChgPsw = GetDlgItem(m_hDlg,IDC_CHGPSW);
  449. m_hwndPswLbl = GetDlgItem(m_hDlg,IDC_DOMAINPSWLABEL);
  450. m_hwndDescription = GetDlgItem(m_hDlg,IDC_DESCRIPTION);
  451. // Establish limits on string lengths from the user
  452. SendMessage(m_hwndTName,EM_LIMITTEXT,CRED_MAX_GENERIC_TARGET_NAME_LENGTH,0);
  453. // Show dummy password for edited credential
  454. if (m_bEdit) Credential_SetPassword(m_hwndCred,L"********");
  455. // Set up the allowable persistence options depending on the type of user session
  456. // Set the default persistence unless overriden by a cred read on edit
  457. g_dwPersist = GetPersistenceOptions();
  458. g_dwType = CRED_TYPE_DOMAIN_PASSWORD;
  459. // By default, hide all optional controls. These will be enabled as appropriate
  460. ShowWindow(m_hwndChgPsw,SW_HIDE);
  461. ShowWindow(m_hwndPswLbl,SW_HIDE);
  462. if (m_bEdit) {
  463. EditFillDialog();
  464. }
  465. g_fPswChanged = FALSE;
  466. ShowDescriptionText(g_dwType,g_dwPersist);
  467. #ifdef LOUDLY
  468. OutputDebugString(L"Dialog init complete--------\n");
  469. #endif
  470. return TRUE;
  471. // On exit from OnInitDialog, g_szTargetName holds the currently selected
  472. // credential's old name, undecorated (having had a null dropped before
  473. // the suffix)
  474. } // C_AddKeyDlg::OnInitDialog
  475. BOOL
  476. C_AddKeyDlg::OnDestroyDialog(
  477. void )
  478. {
  479. return TRUE;
  480. }
  481. //////////////////////////////////////////////////////////////////////////////
  482. //
  483. // OnAppMessage
  484. //
  485. //
  486. //////////////////////////////////////////////////////////////////////////////
  487. BOOL
  488. C_AddKeyDlg::OnAppMessage(
  489. UINT uMessage,
  490. WPARAM wparam,
  491. LPARAM lparam)
  492. {
  493. return TRUE;
  494. }
  495. //////////////////////////////////////////////////////////////////////////////
  496. //
  497. // OnCommand
  498. //
  499. // Route WM_COMMAND message to appropriate handlers.
  500. //
  501. // parameters:
  502. // wNotifyCode code describing action that has occured
  503. // wSenderId id of the control sending the message, if the message
  504. // is from a dialog
  505. // hwndSender window handle of the window sending the message if the
  506. // message is not from a dialog
  507. //
  508. // returns:
  509. // TRUE if the message was processed completely
  510. // FALSE if Windows is to process the message
  511. //
  512. ////////////////////////////////////////////////////////////////////////////
  513. BOOL
  514. C_AddKeyDlg::OnHelpInfo(LPARAM lp) {
  515. HELPINFO* pH;
  516. INT iMapped;
  517. pH = (HELPINFO *) lp;
  518. HH_POPUP stPopUp;
  519. RECT rcW;
  520. UINT gID;
  521. gID = pH->iCtrlId;
  522. iMapped = MapID(gID);
  523. if (iMapped == 0) return TRUE;
  524. if (IDS_NOHELP != iMapped) {
  525. memset(&stPopUp,0,sizeof(stPopUp));
  526. stPopUp.cbStruct = sizeof(HH_POPUP);
  527. stPopUp.hinst = g_hInstance;
  528. stPopUp.idString = iMapped;
  529. stPopUp.pszText = NULL;
  530. stPopUp.clrForeground = -1;
  531. stPopUp.clrBackground = -1;
  532. stPopUp.rcMargins.top = -1;
  533. stPopUp.rcMargins.bottom = -1;
  534. stPopUp.rcMargins.left = -1;
  535. stPopUp.rcMargins.right = -1;
  536. // bug 393244 - leave NULL to allow HHCTRL.OCX to get font information of its own,
  537. // which it needs to perform the UNICODE to multibyte conversion. Otherwise,
  538. // HHCTRL must convert using this font without charset information.
  539. stPopUp.pszFont = NULL;
  540. if (GetWindowRect((HWND)pH->hItemHandle,&rcW)) {
  541. stPopUp.pt.x = (rcW.left + rcW.right) / 2;
  542. stPopUp.pt.y = (rcW.top + rcW.bottom) / 2;
  543. }
  544. else stPopUp.pt = pH->MousePos;
  545. HtmlHelp((HWND) pH->hItemHandle,NULL,HH_DISPLAY_TEXT_POPUP,(DWORD_PTR) &stPopUp);
  546. }
  547. return TRUE;
  548. }
  549. BOOL
  550. C_AddKeyDlg::OnCommand(
  551. WORD wNotifyCode,
  552. WORD wSenderId,
  553. HWND hwndSender
  554. )
  555. {
  556. BOOL fHandled = FALSE; // indicate message handled
  557. LRESULT lR;
  558. INT_PTR f;
  559. switch (wSenderId)
  560. {
  561. case IDC_CRED:
  562. {
  563. if (wNotifyCode == CRN_USERNAMECHANGE) {
  564. #ifdef LOUDLY
  565. OutputDebugString(L"Username changed!\n");
  566. #endif
  567. // Show dummy password for edited credential
  568. if (m_bEdit) Credential_SetPassword(m_hwndCred,NULL);
  569. g_fPswChanged = FALSE;
  570. }
  571. if (wNotifyCode == CRN_PASSWORDCHANGE) {
  572. #ifdef LOUDLY
  573. OutputDebugString(L"Password changed!\n");
  574. #endif
  575. g_fPswChanged = TRUE;
  576. }
  577. }
  578. break;
  579. case IDOK:
  580. if (BN_CLICKED == wNotifyCode)
  581. {
  582. #ifdef LOUDLY
  583. OutputDebugString(L"Call to OnOK\n");
  584. #endif
  585. OnOK( );
  586. fHandled = TRUE;
  587. }
  588. break;
  589. case IDC_CHGPSW:
  590. {
  591. OnChangePassword();
  592. //EndDialog(IDCANCEL); do not cancel out of properties dialog
  593. break;
  594. }
  595. case IDCANCEL:
  596. if (BN_CLICKED == wNotifyCode)
  597. {
  598. EndDialog(IDCANCEL);
  599. fHandled = TRUE;
  600. }
  601. break;
  602. } // switch
  603. return fHandled;
  604. } // C_AddKeyDlg::OnCommand
  605. ////////////////////////////////////////////////////////////////////////////
  606. //
  607. // OnOK
  608. //
  609. // Validate user name, synthesize computer name, and destroy dialog.
  610. //
  611. // parameters:
  612. // None.
  613. //
  614. // returns:
  615. // Nothing.
  616. //
  617. //////////////////////////////////////////////////////////////////////////////
  618. void
  619. C_AddKeyDlg::OnOK( )
  620. {
  621. LONG_PTR j,lCType;
  622. TCHAR szMsg[MAX_STRING_SIZE];
  623. TCHAR szTitle[MAX_STRING_SIZE];
  624. TCHAR szUser[CRED_MAX_STRING_LENGTH + 1]; // in from dialog
  625. TCHAR szPsw[CRED_MAX_STRING_LENGTH + 1]; // in from dialog
  626. TCHAR *pszNewTarget; // in from dialog
  627. TCHAR *pszTrimdName; // mod'd in from dialog
  628. DWORD dwFlags = 0; // in from dialog
  629. CREDENTIAL stCredential; // local copy of cred
  630. UINT cbPassword;
  631. BOOL bResult;
  632. BOOL IsCertificate = FALSE;
  633. BOOL fDeleteOldCred = FALSE;
  634. BOOL fRenameCred = FALSE;
  635. BOOL fPreserve = FALSE;
  636. BOOL fPsw = FALSE;
  637. ASSERT(::IsWindow(m_hwnd));
  638. szPsw[0]= 0;
  639. szUser[0] = 0;
  640. // Start with a blank cred if this is not an edit, else make a copy of existing one
  641. if ((m_bEdit) && (g_pExistingCred))
  642. memcpy((void *) &stCredential,(void *) g_pExistingCred,sizeof(CREDENTIAL));
  643. else
  644. memset((void *) &stCredential,0,sizeof(CREDENTIAL));
  645. pszNewTarget = (TCHAR *) malloc((CRED_MAX_GENERIC_TARGET_NAME_LENGTH + 1) * sizeof(TCHAR));
  646. if (NULL == pszNewTarget) {
  647. return;
  648. }
  649. pszNewTarget[0] = 0;
  650. // Get Username from the cred control - find out if is a certificate by
  651. // IsMarshalledName().
  652. if (Credential_GetUserName(m_hwndCred,szUser,CRED_MAX_STRING_LENGTH))
  653. IsCertificate = CredIsMarshaledCredential(szUser);
  654. #ifdef LOUDLY
  655. if (IsCertificate) OutputDebugString(L"User is a certificate\n");
  656. #endif
  657. // fetch password/PIN into szPsw. set fPsw if value is valid
  658. fPsw = Credential_GetPassword(m_hwndCred,szPsw,CRED_MAX_STRING_LENGTH);
  659. #ifdef LOUDLY
  660. if (fPsw) OutputDebugString(L"Password control is enabled\n");
  661. OutputDebugString(szUser);
  662. OutputDebugString(L":");
  663. OutputDebugString(szPsw);
  664. OutputDebugString(L"\n");
  665. #endif
  666. // Check to see that both name and psw are not missing
  667. if ( wcslen ( szUser ) == 0 &&
  668. wcslen ( szPsw ) == 0 ) {
  669. #ifdef LOUDLY
  670. OutputDebugString(L"Missing username andor password\n");
  671. #endif
  672. LoadString ( m_hInst, IDS_ADDFAILED, szMsg, MAX_STRING_SIZE );
  673. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  674. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  675. if (pszNewTarget) free(pszNewTarget);
  676. return;
  677. }
  678. // If the user has typed a \\server style target name, strip the leading hacks
  679. j = SendMessage(m_hwndTName,WM_GETTEXT,CRED_MAX_GENERIC_TARGET_NAME_LENGTH,(LPARAM)pszNewTarget);
  680. ASSERT(j);
  681. pszTrimdName = pszNewTarget;
  682. while (*pszTrimdName == TCHAR('\\')) pszTrimdName++;
  683. // Now have:
  684. // pszTrimdName
  685. // uzUser
  686. // szPsw
  687. // fPsw
  688. // If target name edited, will need to rename
  689. // If type changed or psw edited, psw blob will be removed/replaced
  690. // If type changed, will need to remove old cred
  691. if ((m_bEdit) && (g_pExistingCred)) {
  692. if (0 != _tcscmp(pszTrimdName,g_szTargetName)) fRenameCred = TRUE;
  693. #ifdef LOUDLY
  694. OutputDebugString(L"Is edit mode\n");
  695. if (fRenameCred) OutputDebugString(L"Cred will be renamed\n");
  696. #endif
  697. // Note that currently DOMAIN_VISIBLE_PASSWORD creds cannot be edited
  698. // or created, so there is no handler for those types.
  699. if (g_pExistingCred->Type == CRED_TYPE_GENERIC) {
  700. lCType = CRED_TYPE_GENERIC;
  701. }
  702. else {
  703. if (IsCertificate) lCType = CRED_TYPE_DOMAIN_CERTIFICATE;
  704. else lCType = CRED_TYPE_DOMAIN_PASSWORD;
  705. }
  706. if ((DWORD)lCType != g_pExistingCred->Type) {
  707. dwFlags &= ~CRED_PRESERVE_CREDENTIAL_BLOB;
  708. fDeleteOldCred = TRUE;
  709. }
  710. else dwFlags |= CRED_PRESERVE_CREDENTIAL_BLOB;
  711. if (g_fPswChanged) dwFlags &= ~CRED_PRESERVE_CREDENTIAL_BLOB;
  712. }
  713. else {
  714. #ifdef LOUDLY
  715. OutputDebugString(L"Is not edit mode\n");
  716. #endif
  717. // if is a certificate marshalled name is cert or generic
  718. // if not is generic or domain
  719. if (IsCertificate) {
  720. lCType = CRED_TYPE_DOMAIN_CERTIFICATE;
  721. }
  722. else {
  723. lCType = CRED_TYPE_DOMAIN_PASSWORD;
  724. }
  725. }
  726. // Save credential. If certificate type, do not include a psw blob.
  727. // After save, if the name had changed, rename the cred
  728. stCredential.UserName = szUser;
  729. stCredential.Type = (DWORD) lCType;
  730. // If not an edit, fill in targetname, else do rename later
  731. if (!m_bEdit) stCredential.TargetName = pszTrimdName;
  732. stCredential.Persist = g_dwPersist;
  733. // fill credential blob data with nothing if the cred control UI has
  734. // disabled the password box. Otherwise supply psw information if
  735. // the user has edited the box contents.
  736. if (fPsw) {
  737. if (g_fPswChanged) {
  738. #ifdef LOUDLY
  739. OutputDebugString(L"Storing new password data\n");
  740. #endif
  741. cbPassword = wcslen(szPsw) * sizeof(TCHAR);
  742. stCredential.CredentialBlob = (unsigned char *)szPsw;
  743. stCredential.CredentialBlobSize = cbPassword;
  744. }
  745. #ifdef LOUDLY
  746. else OutputDebugString(L"No password data stored.\n");
  747. #endif
  748. }
  749. if (lCType == CRED_TYPE_DOMAIN_PASSWORD) {
  750. // validate proper UPN or domain-prefixed credentials.
  751. DNS_STATUS dS = DnsValidateName(szUser,DnsNameDomain);
  752. // gm bugbug - this looks wrong
  753. if (DNS_RCODE_NOERROR == dS) {
  754. LoadString ( m_hInst, IDS_BADUSERDOMAINNAME, szMsg, MAX_STRING_SIZE );
  755. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  756. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  757. if (pszNewTarget) free(pszNewTarget);
  758. return;
  759. }
  760. }
  761. bResult = CredWrite(&stCredential,dwFlags);
  762. memset(szPsw,0,sizeof(szPsw)); // delete psw local copy
  763. if ( bResult != TRUE )
  764. {
  765. #ifdef LOUDLY
  766. WCHAR szw[200];
  767. DWORD dwE = GetLastError();
  768. swprintf(szw,L"CredWrite failed. Last Error is %x\n",dwE);
  769. OutputDebugString(szw);
  770. #endif
  771. AdviseUser();
  772. if (pszNewTarget) free(pszNewTarget);
  773. return;
  774. }
  775. // Delete old credential only if type has changed
  776. // Otherwise if name changed, do a rename of the cred
  777. // If the old cred is deleted, rename is obviated
  778. if (fDeleteOldCred) {
  779. #ifdef LOUDLY
  780. OutputDebugString(L"CredDelete called\n");
  781. #endif
  782. CredDelete(g_szTargetName,(ULONG) g_pExistingCred->Type,0);
  783. }
  784. else if (fRenameCred) {
  785. bResult = CredRename(g_szTargetName, pszTrimdName, (ULONG) stCredential.Type,0);
  786. #ifdef LOUDLY
  787. OutputDebugString(L"CredRename called\n");
  788. #endif
  789. if (!bResult) {
  790. // bugbug: How can rename fail?
  791. // If it does, what would you tell the user?
  792. LoadString ( m_hInst, IDS_RENAMEFAILED, szMsg, MAX_STRING_SIZE );
  793. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  794. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  795. if (pszNewTarget) free(pszNewTarget);
  796. return;
  797. }
  798. }
  799. #ifdef EDITOFFERPASSWORD
  800. // Offer the possibility of changing the password on the domain if the
  801. // password field was edited, but the username was unchanged.
  802. if (g_fPswChanged && m_bEdit) {
  803. if (g_pExistingCred->Type == CRED_TYPE_DOMAIN_PASSWORD) {
  804. #ifdef LOUDLY
  805. OutputDebugString(L"Cred change - offer domain password change\n");
  806. #endif
  807. LoadString ( m_hInst, IDS_DOMAINOFFER, szMsg, MAX_STRING_SIZE );
  808. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  809. if (IDYES == MessageBox ( m_hDlg, szMsg, szTitle, MB_YESNO ))
  810. OnChangePassword();
  811. else {
  812. LoadString ( m_hInst, IDS_DOMAINEDIT, szMsg, MAX_STRING_SIZE );
  813. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  814. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  815. }
  816. }
  817. }
  818. #endif
  819. if (pszNewTarget) free(pszNewTarget);
  820. EndDialog(IDOK);
  821. } // C_AddKeyDlg::OnOK
  822. void C_AddKeyDlg::OnChangePassword()
  823. {
  824. C_ChangePasswordDlg CPdlg(m_hDlg, g_hInstance, IDD_CHANGEPASSWORD, NULL);
  825. CPdlg.m_szDomain[0] = 0;
  826. CPdlg.m_szUsername[0] = 0;
  827. INT_PTR nResult = CPdlg.DoModal((LPARAM)&CPdlg);
  828. }
  829. // Simple test for likelihood that a name is a domain type.
  830. BOOL IsDomainNameType(LPCTSTR pName) {
  831. TCHAR *pC;
  832. pC = _tcschr(pName,TCHAR('@'));
  833. if (NULL != pC) return TRUE;
  834. pC = _tcschr(pName,TCHAR('\\'));
  835. if (NULL != pC) return TRUE;
  836. return FALSE;
  837. }
  838. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  839. //////////////////////////////////////////////////////////////////////////////
  840. //
  841. // C_KeyringDlg
  842. //
  843. // Constructor.
  844. //
  845. // parameters:
  846. // rSetupInfo reference to a C_UpgradeInfo object containing default
  847. // setup parameters
  848. // hwndParent parent window for the dialog (may be NULL)
  849. // hInstance instance handle of the parent window (may be NULL)
  850. // lIDD dialog template id
  851. // pfnDlgProc pointer to the function that will process messages for
  852. // the dialog. if it is NULL, the default dialog proc
  853. // will be used.
  854. //
  855. // returns:
  856. // Nothing.
  857. //
  858. //////////////////////////////////////////////////////////////////////////////
  859. C_KeyringDlg::C_KeyringDlg(
  860. HWND hwndParent,
  861. HINSTANCE hInstance,
  862. LONG lIDD,
  863. DLGPROC pfnDlgProc // = NULL
  864. )
  865. : C_Dlg(hwndParent, hInstance, lIDD, pfnDlgProc)
  866. {
  867. m_hInst = hInstance; // our instance handle
  868. g_AKdlg = NULL; // addkey dialog not up
  869. fInit = FALSE; // initial screen draw undone
  870. } // C_KeyringDlg::C_KeyringDlg
  871. // BuildList() is called to initialize the keyring UI credential list, and
  872. // again after completion of the add dialog, plus again after handling
  873. // the credential delete button.
  874. //
  875. void C_KeyringDlg::BuildList()
  876. {
  877. // Call CredEnumerate(), and populate a list using the TargetName
  878. // field of each credential returned. Note that the associated tag
  879. // data for each list box entry will be the numeric credential type.
  880. //
  881. // Enable or Disable the DELETE button as appropriate.
  882. DWORD dwCredCount = 0;
  883. CREDENTIAL **pCredentialPtrArray;
  884. BOOL bResult;
  885. DWORD i,dwCredType;
  886. PCREDENTIAL pThisCred;
  887. TCHAR *pTargetName;
  888. LRESULT idx;
  889. HWND hH;
  890. TCHAR szMsg[64];
  891. BOOL fSession = FALSE;
  892. INT iCredCount = 0;
  893. // clear the listbox
  894. ::SendDlgItemMessage(m_hDlg,IDC_KEYLIST,LB_RESETCONTENT,NULL,0);
  895. bResult = CredEnumerate(NULL,0,&dwCredCount,&pCredentialPtrArray);
  896. #ifdef LOUDLY
  897. if (!bResult)
  898. {
  899. DWORD dwe = GetLastError();
  900. OutputDebugString(L"CredEnumerate failed\n");
  901. swprintf(szMsg,L"CredEnumerate error %x\n",dwe);
  902. OutputDebugString(szMsg);
  903. }
  904. #endif
  905. if (bResult) {
  906. for (i=0 ; i < dwCredCount ; i++) {
  907. #ifdef LOUDLY
  908. if (!bResult) OutputDebugString(L"Adding a cred to the window\n");
  909. #endif
  910. pThisCred = pCredentialPtrArray[i];
  911. pTargetName = pThisCred->TargetName;
  912. // handle CRED_SESSION_WILDCARD_NAME_W by replacing the string
  913. if (0 == _tcsicmp(pTargetName,CRED_SESSION_WILDCARD_NAME)) {
  914. LoadString ( m_hInst, IDS_SESSIONCRED, szMsg, 64 );
  915. pTargetName = szMsg;
  916. dwCredType = SESSION_FLAG_VALUE;
  917. }
  918. else dwCredType = pThisCred->Type;
  919. // name suffixes are localizable
  920. switch (dwCredType) {
  921. case CRED_TYPE_GENERIC:
  922. continue;
  923. break;
  924. // this particular type is not visible in keymgr
  925. case CRED_TYPE_DOMAIN_VISIBLE_PASSWORD:
  926. #ifndef SHOWPASSPORT
  927. continue;
  928. #endif
  929. #ifdef SHOWPASSPORT
  930. _tcscpy(g_szTargetName,pTargetName);
  931. _tcscat(g_szTargetName,_T(" "));
  932. _tcscat(g_szTargetName,g_rgcPassport);
  933. break;
  934. #endif
  935. case CRED_TYPE_DOMAIN_PASSWORD:
  936. case SESSION_FLAG_VALUE:
  937. // find RAS credential
  938. _tcscpy(g_szTargetName,pTargetName);
  939. break;
  940. case CRED_TYPE_DOMAIN_CERTIFICATE:
  941. _tcscpy(g_szTargetName,pTargetName);
  942. _tcscat(g_szTargetName,_T(" "));
  943. _tcscat(g_szTargetName,g_rgcCert);
  944. break;
  945. default:
  946. break;
  947. }
  948. idx = ::SendDlgItemMessage(m_hDlg,IDC_KEYLIST,LB_ADDSTRING,NULL,(LPARAM) g_szTargetName);
  949. if (idx != LB_ERR) {
  950. idx = ::SendDlgItemMessage(m_hDlg,IDC_KEYLIST,LB_SETITEMDATA,(WPARAM)idx,dwCredType);
  951. }
  952. }
  953. }
  954. // if FALSE below, causes: no creds, no logon session, invalid flags
  955. if (bResult) CredFree(pCredentialPtrArray);
  956. #ifdef ODDUIBUG
  957. //SetCurrentKey(g_CurrentKey);
  958. #else
  959. SetCurrentKey(g_CurrentKey);
  960. #endif
  961. }
  962. // Set the cursor on the keys list to the first item initially.
  963. // Thereafter, this function permits the last cursor to be reloaded after
  964. // doing something to the list. The only time we reset the cursor is
  965. // after adding a credential, because the behavior of the cursor is very
  966. // difficult to do properly under those circumstances, as you don't know
  967. // where the item will be inserted relative to where you are. (At least
  968. // not without a great deal of trouble)
  969. void C_KeyringDlg::SetCurrentKey(LONG_PTR iKey) {
  970. LONG_PTR iKeys;
  971. HWND hH;
  972. LRESULT idx;
  973. BOOL fDisabled = FALSE;
  974. // If there are items in the list, select the first one and set focus to the list
  975. iKeys = ::SendDlgItemMessage ( m_hDlg, IDC_KEYLIST, LB_GETCOUNT, (WPARAM) 0, 0L );
  976. fDisabled = (GetPersistenceOptions() == CRED_PERSIST_NONE);
  977. // If there are no creds and credman is disabled, the dialog should not be displayed
  978. // If there are creds, and credman is disabled, show the dialog without the ADD button
  979. if (fDisabled && !fInit)
  980. {
  981. // Make the intro text better descriptive of this condition
  982. WCHAR szMsg[MAX_STRING_SIZE+1];
  983. LoadString ( m_hInst, IDS_INTROTEXT, szMsg, MAX_STRING_SIZE );
  984. hH = GetDlgItem(m_hDlg,IDC_INTROTEXT);
  985. if (hH) SetWindowText(hH,szMsg);
  986. // we already know that the credcount is nonzero (see startup code for keymgr)
  987. // remove the add button
  988. hH = GetDlgItem(m_hDlg,IDC_NEWKEY);
  989. if (hH)
  990. {
  991. EnableWindow(hH,FALSE);
  992. ShowWindow(hH,SW_HIDE);
  993. }
  994. // move remaining buttons upfield 22 units
  995. hH = GetDlgItem(m_hDlg,IDC_DELETEKEY);
  996. if (hH)
  997. {
  998. HWND hw1;
  999. HWND hw2;
  1000. RECT rw1;
  1001. RECT rw2;
  1002. INT xsize;
  1003. INT ysize;
  1004. INT delta;
  1005. BOOL bOK = FALSE;
  1006. hw1 = hH;
  1007. hw2 = GetDlgItem(m_hDlg,IDC_EDITKEY);
  1008. if (hw1 && hw2)
  1009. {
  1010. if (GetWindowRect(hw1,&rw1) &&
  1011. GetWindowRect(hw2,&rw2))
  1012. {
  1013. MapWindowPoints(NULL,m_hDlg,(LPPOINT)(&rw1),2);
  1014. MapWindowPoints(NULL,m_hDlg,(LPPOINT)(&rw2),2);
  1015. delta = rw2.top - rw1.top;
  1016. xsize = rw2.right - rw2.left;
  1017. ysize = rw2.bottom - rw2.top;
  1018. bOK = MoveWindow(hw1,rw1.left,rw1.top - delta,xsize,ysize,TRUE);
  1019. if (bOK)
  1020. {
  1021. bOK = MoveWindow(hw2,rw2.left,rw2.top - delta,xsize,ysize,TRUE);
  1022. }
  1023. }
  1024. }
  1025. }
  1026. }
  1027. // Set the default button to either properties or add
  1028. if ( iKeys > 0 )
  1029. {
  1030. hH = GetDlgItem(m_hDlg,IDC_KEYLIST);
  1031. //PostMessage(m_hDlg,DM_SETDEFID,(WPARAM)IDC_EDITKEY,(LPARAM)0);
  1032. PostMessage(hH,WM_SETFOCUS,NULL,0);
  1033. if (iKey >= iKeys) iKey = 0;
  1034. idx = SendDlgItemMessage ( m_hDlg, IDC_KEYLIST, LB_SETCURSEL, iKey, 0L );
  1035. hH = GetDlgItem(m_hDlg,IDC_EDITKEY);
  1036. if (hH) EnableWindow(hH,TRUE);
  1037. hH = GetDlgItem(m_hDlg,IDC_DELETEKEY);
  1038. if (hH) EnableWindow(hH,TRUE);
  1039. }
  1040. else
  1041. {
  1042. if (!fDisabled)
  1043. {
  1044. // no items in the list, set focus to the New button
  1045. hH = GetDlgItem(m_hDlg,IDC_NEWKEY);
  1046. //PostMessage(m_hDlg,DM_SETDEFID,(WPARAM)IDC_NEWKEY,(LPARAM)0);
  1047. PostMessage(hH,WM_SETFOCUS,NULL,0);
  1048. }
  1049. hH = GetDlgItem(m_hDlg,IDC_EDITKEY);
  1050. if (hH) EnableWindow(hH,FALSE);
  1051. hH = GetDlgItem(m_hDlg,IDC_DELETEKEY);
  1052. if (hH) EnableWindow(hH,FALSE);
  1053. }
  1054. }
  1055. // Get target string from keys listbox, return assocd data as type
  1056. LONG_PTR C_KeyringDlg::GetCredentialType() {
  1057. TCHAR *pC;
  1058. LONG_PTR idx;
  1059. idx = ::SendDlgItemMessage ( m_hDlg, IDC_KEYLIST, LB_GETCURSEL, 0, 0L );
  1060. if ( idx == LB_ERR) return CRED_TYPE_UNKNOWN;
  1061. idx = ::SendDlgItemMessage ( m_hDlg, IDC_KEYLIST, LB_GETITEMDATA, idx, 0 );
  1062. if (idx != LB_ERR) return idx;
  1063. else return CRED_TYPE_UNKNOWN;
  1064. }
  1065. // Remove the currently highlighted key from the listbox
  1066. void C_KeyringDlg::DeleteKey()
  1067. {
  1068. TCHAR szMsg[MAX_STRING_SIZE + MAXSUFFIXSIZE];
  1069. TCHAR szTitle[MAX_STRING_SIZE];
  1070. TCHAR *pC; // point this to the raw name
  1071. LONG_PTR dwCredType;
  1072. LONG_PTR lr = LB_ERR;
  1073. LONG_PTR idx = LB_ERR;
  1074. BOOL bResult = FALSE;
  1075. INT i=0;
  1076. if (!gTestReadCredential()) return;
  1077. LoadString ( m_hInst, IDS_DELETEWARNING, szMsg, MAX_STRING_SIZE );
  1078. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1079. lr = MessageBox ( m_hDlg, szMsg, szTitle, MB_OKCANCEL );
  1080. if (IDOK != lr) return;
  1081. // trim the suffix from the targetname, null term
  1082. pC = _tcschr(g_szTargetName,g_rgcCert[0]);
  1083. if (pC) {
  1084. *(pC - LENGTHOFWHITESPACE) = 0x0; // null terminate namestring
  1085. }
  1086. bResult = CredDelete(g_szTargetName,(DWORD) g_pExistingCred->Type,0);
  1087. if (bResult != TRUE) {
  1088. LoadString ( m_hInst, IDS_DELETEFAILED, szMsg, MAX_STRING_SIZE );
  1089. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1090. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK);
  1091. }
  1092. if (g_pExistingCred) CredFree(g_pExistingCred);
  1093. g_pExistingCred = NULL;
  1094. }
  1095. BOOL
  1096. C_KeyringDlg::OnAppMessage(
  1097. UINT uMessage,
  1098. WPARAM wparam,
  1099. LPARAM lparam
  1100. )
  1101. {
  1102. return TRUE;
  1103. } // OnAppMessage
  1104. //////////////////////////////////////////////////////////////////////////////
  1105. //
  1106. // OnInitDialog
  1107. //
  1108. // Dialog control and data initialization.
  1109. //
  1110. // parameters:
  1111. // hwndDlg window handle of the dialog box
  1112. // hwndFocus window handle of the control that will receive focus
  1113. //
  1114. // returns:
  1115. // TRUE if the system should set the default keyboard focus
  1116. // FALSE if the keyboard focus is set by this app
  1117. //
  1118. //////////////////////////////////////////////////////////////////////////////
  1119. BOOL
  1120. C_KeyringDlg::OnInitDialog(
  1121. HWND hwndDlg,
  1122. HWND hwndFocus
  1123. )
  1124. {
  1125. BOOL bRc;
  1126. // these really should all be in the keyringdlg class
  1127. fNew = FALSE;
  1128. DWORD i;
  1129. LRESULT lr;
  1130. HtmlHelp(NULL,NULL,HH_INITIALIZE,(DWORD_PTR) &g_dwHCookie);
  1131. // Allow other dialog to query the contents of the listbox
  1132. g_hMainDlg = hwndDlg;
  1133. m_hDlg = hwndDlg;
  1134. g_CurrentKey = 0;
  1135. // Fetch Icons from the image and assoc them with this dialog
  1136. HICON hI = LoadIcon(m_hInst,MAKEINTRESOURCE(IDI_SMALL));
  1137. lr = SendMessage(hwndDlg,WM_SETICON,(WPARAM) ICON_SMALL,(LPARAM)hI);
  1138. C_Dlg::OnInitDialog(hwndDlg, hwndFocus);
  1139. CenterWindow();
  1140. // Even if mirrored language is default, set list box style to LTR
  1141. #ifdef FORCELISTLTR
  1142. {
  1143. LONG_PTR lExStyles;
  1144. HWND hwList;
  1145. hwList = GetDlgItem(hwndDlg,IDC_KEYLIST);
  1146. if (hwList)
  1147. {
  1148. lExStyles = GetWindowLongPtr(hwList,GWL_EXSTYLE);
  1149. lExStyles &= ~WS_EX_RTLREADING;
  1150. SetWindowLongPtr(hwList,GWL_EXSTYLE,lExStyles);
  1151. InvalidateRect(hwList,NULL,TRUE);
  1152. }
  1153. }
  1154. #endif
  1155. // read in the suffix strings for certificate types
  1156. // locate first differing character
  1157. //
  1158. // This code assumes that the strings all have a common preamble,
  1159. // and that all are different in the first character position
  1160. // past the preamble. Localized strings should be selected which
  1161. // have this property, like (Generic) and (Certificate).
  1162. i = LoadString(g_hInstance,IDS_CERTSUFFIX,g_rgcCert,MAXSUFFIXSIZE);
  1163. ASSERT(i !=0);
  1164. i = LoadString(g_hInstance,IDS_PASSPORTSUFFIX,g_rgcPassport,MAXSUFFIXSIZE);
  1165. // Read currently saved creds and display names in list box
  1166. BuildList();
  1167. #ifdef ODDUIBUG
  1168. SetCurrentKey(g_CurrentKey);
  1169. #endif
  1170. InitTooltips();
  1171. fInit = TRUE; // prevent repeating button movement/setup
  1172. return TRUE;
  1173. } // C_KeyringDlg::OnInitDialog
  1174. BOOL
  1175. C_KeyringDlg::OnDestroyDialog(
  1176. void )
  1177. {
  1178. HtmlHelp(NULL,NULL,HH_UNINITIALIZE,(DWORD_PTR)g_dwHCookie);
  1179. return TRUE;
  1180. }
  1181. BOOL C_KeyringDlg::DoEdit(void) {
  1182. LRESULT lR;
  1183. HWND hB;
  1184. if (fNew) return TRUE;
  1185. fNew = TRUE;
  1186. lR = SendDlgItemMessage(m_hDlg,IDC_KEYLIST,LB_GETCURSEL,0,0L);
  1187. if (LB_ERR == lR) {
  1188. // On error, no dialog shown, edit command handled
  1189. fNew = FALSE;
  1190. return TRUE;
  1191. }
  1192. else {
  1193. // something selected
  1194. g_CurrentKey = lR;
  1195. // If a session cred, show it specially, indicate no edit allowed
  1196. lR = SendDlgItemMessage(m_hDlg,IDC_KEYLIST,LB_GETITEMDATA,lR,0);
  1197. if (lR == SESSION_FLAG_VALUE) {
  1198. // load string and display message box
  1199. TCHAR szMsg[MAX_STRING_SIZE];
  1200. TCHAR szTitle[MAX_STRING_SIZE];
  1201. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1202. LoadString ( m_hInst, IDS_CANNOTEDIT, szMsg, MAX_STRING_SIZE );
  1203. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1204. fNew = FALSE;
  1205. return TRUE;
  1206. }
  1207. #ifdef SHOWPASSPORT
  1208. #ifdef NEWPASSPORT
  1209. // if a passport cred, show it specially, indicate no edit allowed
  1210. if (lR == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD) {
  1211. // load string and display message box
  1212. TCHAR szMsg[MAX_STRING_SIZE];
  1213. TCHAR szTitle[MAX_STRING_SIZE];
  1214. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1215. LoadString ( m_hInst, IDS_PASSPORT2, szMsg, MAX_STRING_SIZE );
  1216. INT iResponse = MessageBox ( m_hDlg, szMsg, szTitle, MB_YESNO );
  1217. if (IDYES == iResponse)
  1218. {
  1219. HANDLE hWnd;
  1220. HKEY hKey = NULL;
  1221. DWORD dwType;
  1222. BYTE rgb[500];
  1223. DWORD cbData = sizeof(rgb);
  1224. BOOL Flag = TRUE;
  1225. // launch the passport web site
  1226. #ifndef PASSPORTURLINREGISTRY
  1227. ShellExecute(m_hDlg,L"open",L"http://www.passport.com",NULL,NULL,SW_SHOWNORMAL);
  1228. #else
  1229. // read registry key to get target string for ShellExec
  1230. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  1231. L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  1232. 0,
  1233. KEY_QUERY_VALUE,
  1234. &hKey))
  1235. {
  1236. if (ERROR_SUCCESS == RegQueryValueEx(hKey,
  1237. L"Properties",
  1238. NULL,
  1239. &dwType,
  1240. rgb,
  1241. &cbData))
  1242. {
  1243. ShellExecute(m_hDlg,L"open",(LPCTSTR)rgb,NULL,NULL,SW_SHOWNORMAL);
  1244. Flag = FALSE;
  1245. }
  1246. }
  1247. #ifdef LOUDLY
  1248. else
  1249. {
  1250. OutputDebugString(L"DoEdit: reg key HKCU... open failed\n");
  1251. }
  1252. #endif
  1253. if (Flag)
  1254. {
  1255. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1256. L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  1257. 0,
  1258. KEY_QUERY_VALUE,
  1259. &hKey))
  1260. {
  1261. if (ERROR_SUCCESS == RegQueryValueEx(hKey,
  1262. L"Properties",
  1263. NULL,
  1264. &dwType,
  1265. rgb,
  1266. &cbData))
  1267. {
  1268. ShellExecute(m_hDlg,L"open",(LPCTSTR)rgb,NULL,NULL,SW_SHOWNORMAL);
  1269. Flag = FALSE;
  1270. }
  1271. }
  1272. #ifdef LOUDLY
  1273. else
  1274. {
  1275. OutputDebugString(L"DoEdit: reg key HKLM... open failed\n");
  1276. }
  1277. #endif
  1278. }
  1279. if (Flag)
  1280. {
  1281. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1282. LoadString ( m_hInst, IDS_PASSPORTNOURL, szMsg, MAX_STRING_SIZE );
  1283. MessageBox ( m_hDlg, szMsg, szTitle, MB_ICONHAND );
  1284. #ifdef LOUDLY
  1285. OutputDebugString(L"DoEdit: Passport URL missing\n");
  1286. #endif
  1287. }
  1288. #endif
  1289. }
  1290. fNew = FALSE;
  1291. return TRUE;
  1292. }
  1293. #else
  1294. // if a passport cred, show it specially, indicate no edit allowed
  1295. if (lR == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD) {
  1296. // load string and display message box
  1297. TCHAR szMsg[MAX_STRING_SIZE];
  1298. TCHAR szTitle[MAX_STRING_SIZE];
  1299. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1300. LoadString ( m_hInst, IDS_PASSPORT, szMsg, MAX_STRING_SIZE );
  1301. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1302. fNew = FALSE;
  1303. return TRUE;
  1304. }
  1305. #endif
  1306. #endif
  1307. }
  1308. // cred is selected, not special type. Attempt to read it
  1309. if (FALSE == gTestReadCredential()) {
  1310. fNew = FALSE;
  1311. return TRUE;
  1312. }
  1313. g_AKdlg = new C_AddKeyDlg(g_hMainDlg,g_hInstance,IDD_ADDCRED,NULL);
  1314. if (NULL == g_AKdlg) {
  1315. // failed to instantiate add/new dialog
  1316. fNew = FALSE;
  1317. if (g_pExistingCred) CredFree(g_pExistingCred);
  1318. g_pExistingCred = NULL;
  1319. return TRUE;
  1320. }
  1321. else {
  1322. // read OK, dialog OK, proceed with edit dlg
  1323. g_AKdlg->m_bEdit = TRUE;
  1324. INT_PTR nResult = g_AKdlg->DoModal((LPARAM)g_AKdlg);
  1325. // a credential name may have changed, so reload the list
  1326. delete g_AKdlg;
  1327. g_AKdlg = NULL;
  1328. if (g_pExistingCred) CredFree(g_pExistingCred);
  1329. g_pExistingCred = NULL;
  1330. fNew = FALSE;
  1331. }
  1332. return TRUE;
  1333. }
  1334. //////////////////////////////////////////////////////////////////////////////
  1335. //
  1336. // OnCommand
  1337. //
  1338. // Route WM_COMMAND message to appropriate handlers.
  1339. //
  1340. // parameters:
  1341. // wNotifyCode code describing action that has occured
  1342. // wSenderId id of the control sending the message, if the message
  1343. // is from a dialog
  1344. // hwndSender window handle of the window sending the message if the
  1345. // message is not from a dialog
  1346. //
  1347. // returns:
  1348. // TRUE if the message was processed completely
  1349. // FALSE if Windows is to process the message
  1350. //
  1351. //////////////////////////////////////////////////////////////////////////////
  1352. BOOL
  1353. C_KeyringDlg::OnHelpInfo(LPARAM lp) {
  1354. HELPINFO* pH;
  1355. INT iMapped;
  1356. pH = (HELPINFO *) lp;
  1357. HH_POPUP stPopUp;
  1358. RECT rcW;
  1359. UINT gID;
  1360. gID = pH->iCtrlId;
  1361. iMapped = MapID(gID);
  1362. if (iMapped == 0) return TRUE;
  1363. if (IDS_NOHELP != iMapped) {
  1364. memset(&stPopUp,0,sizeof(stPopUp));
  1365. stPopUp.cbStruct = sizeof(HH_POPUP);
  1366. stPopUp.hinst = g_hInstance;
  1367. stPopUp.idString = iMapped;
  1368. stPopUp.pszText = NULL;
  1369. stPopUp.clrForeground = -1;
  1370. stPopUp.clrBackground = -1;
  1371. stPopUp.rcMargins.top = -1;
  1372. stPopUp.rcMargins.bottom = -1;
  1373. stPopUp.rcMargins.left = -1;
  1374. stPopUp.rcMargins.right = -1;
  1375. // bug 393244 - leave NULL to allow HHCTRL.OCX to get font information of its own,
  1376. // which it needs to perform the UNICODE to multibyte conversion. Otherwise,
  1377. // HHCTRL must convert using this font without charset information.
  1378. stPopUp.pszFont = NULL;
  1379. if (GetWindowRect((HWND)pH->hItemHandle,&rcW)) {
  1380. stPopUp.pt.x = (rcW.left + rcW.right) / 2;
  1381. stPopUp.pt.y = (rcW.top + rcW.bottom) / 2;
  1382. }
  1383. else stPopUp.pt = pH->MousePos;
  1384. HtmlHelp((HWND) pH->hItemHandle,NULL,HH_DISPLAY_TEXT_POPUP,(DWORD_PTR) &stPopUp);
  1385. }
  1386. return TRUE;
  1387. }
  1388. #if 1
  1389. BOOL
  1390. C_KeyringDlg::OnHelpButton(void) {
  1391. return FALSE;
  1392. }
  1393. #else
  1394. BOOL
  1395. C_KeyringDlg::OnHelpButton(void) {
  1396. TCHAR rgc[MAX_PATH + 1];
  1397. TCHAR rgcHelpFile[]=TEXT("\\keyhelp.chm");
  1398. GetSystemDirectory(rgc,MAX_PATH);
  1399. if (_tcslen(rgc) + _tcslen(rgcHelpFile) > MAX_PATH) return FALSE;
  1400. _tcscat(rgc,rgcHelpFile);
  1401. HWND hwnd = (m_hwnd,rgc,HH_DISPLAY_TOC,NULL);
  1402. if (NULL != hwnd) return TRUE;
  1403. return FALSE;
  1404. }
  1405. #endif
  1406. BOOL
  1407. C_KeyringDlg::OnCommand(
  1408. WORD wNotifyCode,
  1409. WORD wSenderId,
  1410. HWND hwndSender
  1411. )
  1412. {
  1413. // Was the message handled?
  1414. //
  1415. BOOL fHandled = FALSE;
  1416. HWND hB;
  1417. BOOL f = TRUE;
  1418. switch (wSenderId)
  1419. {
  1420. case IDC_HELPKEY:
  1421. OnHelpButton();
  1422. break;
  1423. case IDC_KEYLIST:
  1424. if (LBN_SELCHANGE == wNotifyCode)
  1425. break;
  1426. if (LBN_DBLCLK == wNotifyCode) {
  1427. fHandled = DoEdit();
  1428. BuildList(); // targetname could have changed
  1429. SetCurrentKey(g_CurrentKey);
  1430. break;
  1431. }
  1432. case IDCANCEL:
  1433. case IDOK:
  1434. if (BN_CLICKED == wNotifyCode)
  1435. {
  1436. OnOK( );
  1437. fHandled = TRUE;
  1438. }
  1439. break;
  1440. case IDC_EDITKEY:
  1441. {
  1442. fHandled = DoEdit();
  1443. BuildList(); // targetname could have changed
  1444. SetCurrentKey(g_CurrentKey);
  1445. break;
  1446. }
  1447. // NEW and DELETE can alter the count of creds, and the button population
  1448. case IDC_NEWKEY:
  1449. {
  1450. if (fNew) break;
  1451. fNew = TRUE;
  1452. g_pExistingCred = NULL;
  1453. g_AKdlg = new C_AddKeyDlg(g_hMainDlg,g_hInstance,IDD_ADDCRED,NULL);
  1454. if (NULL == g_AKdlg) {
  1455. fNew = FALSE;
  1456. fHandled = TRUE;
  1457. break;
  1458. }
  1459. else {
  1460. g_AKdlg->m_bEdit = FALSE;
  1461. INT_PTR nResult = g_AKdlg->DoModal((LPARAM)g_AKdlg);
  1462. // a credential name may have changed
  1463. delete g_AKdlg;
  1464. g_AKdlg = NULL;
  1465. BuildList();
  1466. SetCurrentKey(g_CurrentKey);
  1467. fNew = FALSE;
  1468. }
  1469. break;
  1470. }
  1471. break;
  1472. case IDC_DELETEKEY:
  1473. DeleteKey(); // frees g_pExistingCred as a side effect
  1474. // refresh list display
  1475. BuildList();
  1476. SetCurrentKey(g_CurrentKey);
  1477. break;
  1478. } // switch
  1479. return fHandled;
  1480. } // C_KeyringDlg::OnCommand
  1481. //////////////////////////////////////////////////////////////////////////////
  1482. //
  1483. // OnOK
  1484. //
  1485. // Validate user name, synthesize computer name, and destroy dialog.
  1486. //
  1487. // parameters:
  1488. // None.
  1489. //
  1490. // returns:
  1491. // Nothing.
  1492. //
  1493. //////////////////////////////////////////////////////////////////////////////
  1494. void
  1495. C_KeyringDlg::OnOK( )
  1496. {
  1497. ASSERT(::IsWindow(m_hwnd));
  1498. EndDialog(IDOK);
  1499. } // C_KeyringDlg::OnOK
  1500. //////////////////////////////////////////////////////////////////////////////
  1501. //
  1502. // ToolTip Support
  1503. //
  1504. //
  1505. //////////////////////////////////////////////////////////////////////////////
  1506. TCHAR szTipString[500];
  1507. WNDPROC lpfnOldWindowProc = NULL;
  1508. // Derive a bounding rectangle for the nth element of a list box, 0 based.
  1509. // Refuse to generate rectangles for nonexistent elements. Return TRUE if a
  1510. // rectangle was generated, otherwise FALSE.
  1511. //
  1512. // Get item number from pD->lParam
  1513. // Fetch that text string from listbox at pD->hwnd
  1514. // trim suffix
  1515. // Call translation API
  1516. // Write back the string
  1517. BOOL
  1518. SetToolText(NMTTDISPINFO *pD) {
  1519. CREDENTIAL *pCred = NULL; // used to read cred under mouse ptr
  1520. INT_PTR iWhich; // which index into list
  1521. HWND hLB; // list box hwnd
  1522. //NMHDR *pHdr; // notification msg hdr
  1523. TCHAR rgt[500]; // temp string for tooltip
  1524. TCHAR szCredName[500]; // credname
  1525. TCHAR *pszTargetName; // ptr to target name in pCred
  1526. INT iLen;
  1527. DWORD dwType; // type of target cred
  1528. TCHAR *pC; // used for suffix trimming
  1529. INT_PTR iIndex,iWhere;
  1530. BOOL f; // used for suffix trimming
  1531. LRESULT lRet; // api ret value
  1532. TCHAR szTitle[CRED_MAX_STRING_LENGTH]; // window title string
  1533. ULONG ulOutSize; // ret from CredpValidateTargetName()
  1534. WILDCARD_TYPE OutType; // enum type to receive ret from api
  1535. UNICODE_STRING OutUString; // UNICODESTRING to package ret from api
  1536. WCHAR *pwc;
  1537. UINT iString; // resource # of string
  1538. TCHAR rgcFormat[500]; // Hold tooltip template string
  1539. NTSTATUS ns;
  1540. //pHdr = &(pD->hdr);
  1541. hLB = GetDlgItem(g_hMainDlg,IDC_KEYLIST);
  1542. iWhich = SendMessage(hLB,LB_GETTOPINDEX,0,0);
  1543. iWhich += pD->lParam;
  1544. #ifdef LOUDLY
  1545. TCHAR rga[100];
  1546. _stprintf(rga,L"Text reqst for %d\n",iWhich);
  1547. OutputDebugString(rga);
  1548. #endif
  1549. // Read the indicated cred from the store, by first fetching the name string and type
  1550. // from the listbox
  1551. lRet = SendDlgItemMessage(g_hMainDlg,IDC_KEYLIST,LB_GETTEXT,iWhich,(LPARAM) szCredName);
  1552. // Nonexistant item return LB_ERR, not zero characters!
  1553. if (LB_ERR == lRet) return FALSE;
  1554. if (lRet == 0) return FALSE; // zero characters returned
  1555. dwType = (DWORD) SendDlgItemMessage(g_hMainDlg,IDC_KEYLIST,LB_GETITEMDATA,iWhich,0);
  1556. #ifdef LOUDLY
  1557. OutputDebugString(L"Target: ");
  1558. OutputDebugString(szCredName);
  1559. OutputDebugString(L"\n");
  1560. #endif
  1561. // null term the targetname, trimming the suffix if there is one
  1562. pC = _tcschr(szCredName,g_rgcCert[0]);
  1563. if (pC) {
  1564. pC--;
  1565. *pC = 0x0; // null terminate namestring
  1566. }
  1567. #ifdef LOUDLY
  1568. OutputDebugString(L"Trimmed target: ");
  1569. OutputDebugString(szCredName);
  1570. OutputDebugString(L"\n");
  1571. #endif
  1572. // watch out for special cred
  1573. if (dwType == SESSION_FLAG_VALUE) {
  1574. _tcscpy(szCredName,CRED_SESSION_WILDCARD_NAME);
  1575. dwType = CRED_TYPE_DOMAIN_PASSWORD;
  1576. }
  1577. // Attempt to read the credential from the store
  1578. // The returned credential will have to be freed if leaving this block
  1579. f = (CredRead(szCredName,
  1580. (ULONG) dwType ,
  1581. 0,
  1582. &pCred));
  1583. if (!f) return FALSE; // if read fails, forget filling the dialog
  1584. #ifdef LOUDLY
  1585. if (f) OutputDebugString(L"Successful Cred Read\n");
  1586. #endif
  1587. // clear tip strings
  1588. szTipString[0] = 0;
  1589. rgt[0] = 0;
  1590. #ifndef SIMPLETOOLTIPS
  1591. pszTargetName = pCred->TargetName;
  1592. if (NULL == pszTargetName) return FALSE;
  1593. ns = CredpValidateTargetName(
  1594. pCred->TargetName,
  1595. pCred->Type,
  1596. MightBeUsernameTarget,
  1597. NULL,
  1598. NULL,
  1599. &ulOutSize,
  1600. &OutType,
  1601. &OutUString);
  1602. if (!SUCCEEDED(ns)) return FALSE;
  1603. pwc = OutUString.Buffer;
  1604. switch (OutType) {
  1605. case WcDfsShareName:
  1606. iString = IDS_TIPDFS;
  1607. break;
  1608. case WcServerName:
  1609. iString = IDS_TIPSERVER;
  1610. break;
  1611. case WcServerWildcard:
  1612. iString = IDS_TIPTAIL;
  1613. pwc++; // trim off the leading '.'
  1614. break;
  1615. case WcDomainWildcard:
  1616. iString = IDS_TIPDOMAIN;
  1617. break;
  1618. case WcUniversalSessionWildcard:
  1619. iString = IDS_TIPDIALUP;
  1620. break;
  1621. case WcUniversalWildcard:
  1622. iString = IDS_TIPOTHER;
  1623. break;
  1624. case WcUserName:
  1625. iString = IDS_TIPUSER;
  1626. break;
  1627. default:
  1628. iString = -1;
  1629. break;
  1630. }
  1631. // Show tip text unless we fail to get the string
  1632. // On fail, show the username
  1633. if (0 != LoadString(g_hInstance,iString,rgcFormat,500))
  1634. _stprintf(rgt,rgcFormat,pwc);
  1635. else
  1636. #endif
  1637. if (0 != LoadString(g_hInstance,IDS_LOGASUSER,rgcFormat,500))
  1638. _stprintf(rgt,rgcFormat,iWhich,pCred->UserName);
  1639. else rgt[0] = 0;
  1640. #ifdef LOUDLY
  1641. OutputDebugString(L"Tip text:");
  1642. //OutputDebugString(pCred->UserName);
  1643. OutputDebugString(rgt);
  1644. OutputDebugString(L"\n");
  1645. #endif
  1646. if (rgt[0] == 0) {
  1647. if (pCred) CredFree(pCred);
  1648. return FALSE;
  1649. }
  1650. //_tcscpy(szTipString,pCred->UserName); // copy to a more persistent buffer
  1651. _tcscpy(szTipString,rgt); // copy to a more persistent buffer
  1652. pD->lpszText = szTipString; // point the response to it
  1653. pD->hinst = NULL;
  1654. if (pCred) CredFree(pCred);
  1655. return TRUE;
  1656. }
  1657. LRESULT CALLBACK ListBoxSubClassFunction(HWND hW,WORD Message,WPARAM wparam,LPARAM lparam) {
  1658. if (Message == WM_NOTIFY) {
  1659. if ((int) wparam == IDC_KEYLIST) {
  1660. NMHDR *pnm = (NMHDR *) lparam;
  1661. if (pnm->code == TTN_GETDISPINFO) {
  1662. NMTTDISPINFO *pDi;
  1663. pDi = (NMTTDISPINFO *) pnm;
  1664. SetToolText(pDi);
  1665. }
  1666. }
  1667. }
  1668. return CallWindowProc(lpfnOldWindowProc,hW,Message,wparam,lparam);
  1669. }
  1670. BOOL
  1671. C_KeyringDlg::InitTooltips(void) {
  1672. TOOLINFO ti;
  1673. HWND hw;
  1674. memset(&ti,0,sizeof(TOOLINFO));
  1675. ti.cbSize = sizeof(TOOLINFO);
  1676. INT n = 0;
  1677. BOOL fGo;
  1678. RECT rTip;
  1679. RECT rLB; // list box bounding rect for client portion
  1680. TCHAR szTemp[200];
  1681. HWND hLB = GetDlgItem(m_hDlg,IDC_KEYLIST);
  1682. if (NULL == hLB) return FALSE;
  1683. HWND hwndTip = CreateWindowEx(NULL,TOOLTIPS_CLASS,NULL,
  1684. WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
  1685. CW_USEDEFAULT,CW_USEDEFAULT,
  1686. CW_USEDEFAULT,CW_USEDEFAULT,
  1687. m_hDlg,NULL,m_hInstance,
  1688. NULL);
  1689. if (NULL == hwndTip) {
  1690. return FALSE;
  1691. }
  1692. SetWindowPos(hwndTip,HWND_TOPMOST, 0, 0, 0, 0,
  1693. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1694. // Subclass the list box here in order to get the TTN_GETDISPINFO notification
  1695. lpfnOldWindowProc = (WNDPROC) SetWindowLongPtr(hLB,GWLP_WNDPROC,(LONG_PTR) ListBoxSubClassFunction);
  1696. INT_PTR iHeight = SendMessage(hLB,LB_GETITEMHEIGHT,0,0);
  1697. if (LB_ERR == iHeight) return FALSE;
  1698. if (!GetClientRect(hLB,&rLB)) return FALSE;
  1699. if (iHeight == 0) return FALSE;
  1700. INT_PTR m = rLB.bottom - rLB.top; // unit count client area height
  1701. m = m/iHeight; // find out how many items
  1702. INT_PTR i; // loop control
  1703. LONG itop = 0; // top of tip item rect
  1704. for (i=0 ; i < m ; i++) {
  1705. ti.uFlags = TTF_SUBCLASS;
  1706. ti.hwnd = hLB; // window that gets the TTN_GETDISPINFO
  1707. ti.uId = IDC_KEYLIST;
  1708. ti.hinst = m_hInstance;
  1709. ti.lpszText = LPSTR_TEXTCALLBACK;
  1710. ti.rect.top = itop;
  1711. ti.rect.bottom = itop + (LONG) iHeight - 1;
  1712. ti.rect.left = rLB.left;
  1713. ti.rect.right = rLB.right;
  1714. itop += (LONG) iHeight;
  1715. ti.lParam = (LPARAM) n++;
  1716. #ifdef LOUDLY2
  1717. OutputDebugString(L"Adding a tip control region\n");
  1718. _stprintf(szTemp,L"top = %d bottom = %d left = %d right = %d\n",ti.rect.top,ti.rect.bottom,ti.rect.left,ti.rect.right);
  1719. OutputDebugString(szTemp);
  1720. #endif
  1721. // Add the keylist to the tool list as a single unit
  1722. SendMessage(hwndTip,TTM_ADDTOOL,(WPARAM) 0,(LPARAM)(LPTOOLINFO)&ti);
  1723. }
  1724. return TRUE;
  1725. }
  1726. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1727. //////////////////////////////////////////////////////////////////////////////
  1728. //
  1729. // C_ChangePasswordDlg
  1730. //
  1731. // Constructor.
  1732. //
  1733. // parameters:
  1734. // hwndParent parent window for the dialog (may be NULL)
  1735. // hInstance instance handle of the parent window (may be NULL)
  1736. // lIDD dialog template id
  1737. // pfnDlgProc pointer to the function that will process messages for
  1738. // the dialog. if it is NULL, the default dialog proc
  1739. // will be used.
  1740. //
  1741. // returns:
  1742. // Nothing.
  1743. //
  1744. //////////////////////////////////////////////////////////////////////////////
  1745. C_ChangePasswordDlg::C_ChangePasswordDlg(
  1746. HWND hwndParent,
  1747. HINSTANCE hInstance,
  1748. LONG lIDD,
  1749. DLGPROC pfnDlgProc // = NULL
  1750. )
  1751. : C_Dlg(hwndParent, hInstance, lIDD, pfnDlgProc)
  1752. {
  1753. m_hInst = hInstance;
  1754. } // C_ChangePasswordDlg::C_ChangePasswordDlg
  1755. //////////////////////////////////////////////////////////////////////////////
  1756. //
  1757. // OnInitDialog
  1758. //
  1759. // Dialog control and data initialization.
  1760. //
  1761. // parameters:
  1762. // hwndDlg window handle of the dialog box
  1763. // hwndFocus window handle of the control that will receive focus
  1764. //
  1765. // returns:
  1766. // TRUE if the system should set the default keyboard focus
  1767. // FALSE if the keyboard focus is set by this app
  1768. //
  1769. //////////////////////////////////////////////////////////////////////////////
  1770. BOOL
  1771. C_ChangePasswordDlg::OnInitDialog(
  1772. HWND hwndDlg,
  1773. HWND hwndFocus
  1774. )
  1775. {
  1776. TCHAR szMsg[CRED_MAX_USERNAME_LENGTH];
  1777. TCHAR szTitle[MAX_STRING_SIZE];
  1778. CREDENTIAL *pOldCred = NULL;
  1779. BOOL bResult;
  1780. TCHAR *pC;
  1781. C_Dlg::OnInitDialog(hwndDlg, hwndFocus);
  1782. CenterWindow();
  1783. SetFocus (GetDlgItem ( hwndDlg, IDC_OLD_PASSWORD));
  1784. m_hDlg = hwndDlg;
  1785. // read the currently selected credential, read the cred to get the username,
  1786. // extract the domain, and set the text to show the affected domain.
  1787. bResult = CredRead(g_szTargetName,CRED_TYPE_DOMAIN_PASSWORD,0,&pOldCred);
  1788. if (bResult != TRUE) {
  1789. LoadString ( m_hInst, IDS_PSWFAILED, szMsg, MAX_STRING_SIZE );
  1790. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1791. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1792. EndDialog(IDOK);
  1793. return TRUE;
  1794. }
  1795. // Get the domain and user names from the username string in the credential
  1796. // handle domain\user, domain.etc.etc\user, [email protected]
  1797. _tcscpy(m_szFullUsername,pOldCred->UserName);
  1798. _tcscpy(szMsg,pOldCred->UserName); // use szMsg for scratch
  1799. pC = _tcschr(szMsg,((TCHAR)'\\'));
  1800. if (NULL != pC) {
  1801. // name is format domain\something
  1802. *pC = 0;
  1803. _tcscpy(m_szDomain,szMsg);
  1804. _tcscpy(m_szUsername, (pC + 1));
  1805. }
  1806. else {
  1807. // see if name@something
  1808. pC = _tcschr(szMsg,((TCHAR)'@'));
  1809. if (NULL == pC) {
  1810. LoadString ( m_hInst, IDS_DOMAINFAILED, szMsg, MAX_STRING_SIZE );
  1811. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1812. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1813. if (pOldCred) CredFree(pOldCred);
  1814. return TRUE; // don't call EndDialog()
  1815. }
  1816. *pC = 0;
  1817. _tcscpy(m_szDomain,(pC + 1));
  1818. _tcscpy(m_szUsername, szMsg);
  1819. }
  1820. if (pOldCred) CredFree(pOldCred);
  1821. if (0 != LoadString(g_hInstance,IDS_CPLABEL,szTitle,MAX_STRING_SIZE)) {
  1822. _tcscat(szTitle,m_szDomain);
  1823. SetDlgItemText(m_hwnd,IDC_CPLABEL,szTitle);
  1824. }
  1825. return TRUE;
  1826. } // C_ChangePasswordDlg::OnInitDialog
  1827. //////////////////////////////////////////////////////////////////////////////
  1828. //
  1829. // OnCommand
  1830. //
  1831. // Route WM_COMMAND message to appropriate handlers.
  1832. //
  1833. // parameters:
  1834. // wNotifyCode code describing action that has occured
  1835. // wSenderId id of the control sending the message, if the message
  1836. // is from a dialog
  1837. // hwndSender window handle of the window sending the message if the
  1838. // message is not from a dialog
  1839. //
  1840. // returns:
  1841. // TRUE if the message was processed completely
  1842. // FALSE if Windows is to process the message
  1843. //
  1844. //////////////////////////////////////////////////////////////////////////////
  1845. BOOL
  1846. C_ChangePasswordDlg::OnCommand(
  1847. WORD wNotifyCode,
  1848. WORD wSenderId,
  1849. HWND hwndSender
  1850. )
  1851. {
  1852. // Was the message handled?
  1853. //
  1854. BOOL fHandled = FALSE;
  1855. switch (wSenderId)
  1856. {
  1857. case IDOK:
  1858. if (BN_CLICKED == wNotifyCode)
  1859. {
  1860. OnOK( );
  1861. fHandled = TRUE;
  1862. }
  1863. break;
  1864. case IDCANCEL:
  1865. if (BN_CLICKED == wNotifyCode)
  1866. {
  1867. EndDialog(IDCANCEL);
  1868. fHandled = TRUE;
  1869. }
  1870. break;
  1871. } // switch
  1872. return fHandled;
  1873. } // C_ChangePasswordDlg::OnCommand
  1874. ////////////////////////////////////////////////////////////////////////////
  1875. //
  1876. // OnOK
  1877. //
  1878. // Validate user name, synthesize computer name, and destroy dialog.
  1879. //
  1880. // parameters:
  1881. // None.
  1882. //
  1883. // returns:
  1884. // Nothing.
  1885. //
  1886. //////////////////////////////////////////////////////////////////////////////
  1887. void
  1888. C_ChangePasswordDlg::OnOK( )
  1889. {
  1890. DWORD dwBytes;
  1891. TCHAR szMsg[CRED_MAX_USERNAME_LENGTH];
  1892. TCHAR szTitle[MAX_STRING_SIZE];
  1893. BOOL bDefault;
  1894. ULONG Error = 0;
  1895. LRESULT lResult;
  1896. BOOL bResult;
  1897. ASSERT(::IsWindow(m_hwnd));
  1898. // get old and new passwords from the dialog box
  1899. GetDlgItemText ( m_hDlg, IDC_OLD_PASSWORD, m_szOldPassword, MAX_STRING_SIZE );
  1900. GetDlgItemText ( m_hDlg, IDC_NEW_PASSWORD, m_szNewPassword, MAX_STRING_SIZE );
  1901. GetDlgItemText ( m_hDlg, IDC_CONFIRM_PASSWORD, m_szConfirmPassword, MAX_STRING_SIZE );
  1902. if ( wcslen ( m_szOldPassword ) == 0 && wcslen ( m_szNewPassword ) ==0 && wcslen (m_szConfirmPassword) == 0 )
  1903. {
  1904. // must have something filled in
  1905. return;
  1906. }
  1907. else if ( wcscmp ( m_szNewPassword, m_szConfirmPassword) != 0 )
  1908. {
  1909. LoadString ( m_hInst, IDS_NEWPASSWORDNOTCONFIRMED, szMsg, MAX_STRING_SIZE );
  1910. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1911. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1912. return; // don't call EndDialog()
  1913. }
  1914. else
  1915. {
  1916. HCURSOR hCursor, hOldCursor;
  1917. hOldCursor = NULL;
  1918. hCursor = ::LoadCursor ( m_hInst, IDC_WAIT );
  1919. if ( hCursor )
  1920. {
  1921. hOldCursor = ::SetCursor ( hCursor );
  1922. }
  1923. // let's try changing it
  1924. // The targetname is not used. Only the domain name the username, and
  1925. // old/new passwords are used
  1926. #ifdef LOUDLY
  1927. OutputDebugString(L"Changing password on the domain :");
  1928. OutputDebugString(m_szDomain);
  1929. OutputDebugString(L" for ");
  1930. OutputDebugString(m_szUsername);
  1931. OutputDebugString(L" to ");
  1932. OutputDebugString(m_szNewPassword);
  1933. OutputDebugString(L"\n");
  1934. #endif
  1935. // gm: pass full username and crack it in NetUserChangePasswordEy, so that routine can
  1936. // decide whether we are facing a Kerberos domain
  1937. Error = NetUserChangePasswordEy ( NULL, m_szFullUsername, m_szOldPassword, m_szNewPassword );
  1938. if ( hOldCursor )
  1939. ::SetCursor ( hOldCursor );
  1940. }
  1941. if ( Error == NERR_Success )
  1942. {
  1943. #ifdef LOUDLY
  1944. OutputDebugString(L"Remote password set succeeded\n");
  1945. #endif
  1946. // Store the new credential in the keyring. It will overlay
  1947. // a previous version if present
  1948. // Note that the user must have knowledge of and actually type in
  1949. // the old password as well as the new password. If the user
  1950. // elects to update only the local cache, the old password
  1951. // information is not actually used.
  1952. // CredWriteDomainCredentials() is used
  1953. // m_szDomain holds the domain name
  1954. // m_szUsername holds the username
  1955. // m_szNewPassword holds the password
  1956. CREDENTIAL stCredential;
  1957. UINT cbPassword;
  1958. memcpy((void *)&stCredential,(void *)g_pExistingCred,sizeof(CREDENTIAL));
  1959. // password length does not include zero term
  1960. cbPassword = _tcslen(m_szNewPassword) * sizeof(TCHAR);
  1961. // Form the domain\username composite username
  1962. stCredential.Type = CRED_TYPE_DOMAIN_PASSWORD;
  1963. stCredential.TargetName = g_szTargetName;
  1964. stCredential.CredentialBlob = (unsigned char *)m_szNewPassword;
  1965. stCredential.CredentialBlobSize = cbPassword;
  1966. stCredential.UserName = m_szFullUsername;
  1967. stCredential.Persist = g_dwPersist;
  1968. bResult = CredWrite(&stCredential,0);
  1969. if (bResult) {
  1970. LoadString ( m_hInst, IDS_DOMAINCHANGE, szMsg, MAX_STRING_SIZE );
  1971. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1972. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1973. }
  1974. else {
  1975. LoadString ( m_hInst, IDS_LOCALFAILED, szMsg, MAX_STRING_SIZE );
  1976. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1977. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1978. }
  1979. // BUGBUG - what to do if the local update operation fails?
  1980. // This is not a very big failure, as the first prompt would
  1981. // ripple through all domain\username matching creds on the
  1982. // keyring and update them later. You're pretty much stuck
  1983. // here, since the domain probably will not let you reset the
  1984. // psw to the old value.
  1985. }
  1986. else
  1987. {
  1988. // Attempt to be specific about failure to change the psw on the
  1989. // remote system
  1990. #ifdef LOUDLY
  1991. OutputDebugString(L"Remote password set failed\n");
  1992. #endif
  1993. if (Error == ERROR_INVALID_PASSWORD) {
  1994. LoadString ( m_hInst, IDS_CP_INVPSW, szMsg, MAX_STRING_SIZE );
  1995. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  1996. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  1997. }
  1998. else if (Error == NERR_UserNotFound) {
  1999. LoadString ( m_hInst, IDS_CP_NOUSER, szMsg, MAX_STRING_SIZE );
  2000. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2001. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2002. }
  2003. else if (Error == NERR_PasswordTooShort) {
  2004. LoadString ( m_hInst, IDS_CP_BADPSW, szMsg, MAX_STRING_SIZE );
  2005. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2006. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2007. }
  2008. else if (Error == NERR_InvalidComputer) {
  2009. LoadString ( m_hInst, IDS_CP_NOSVR, szMsg, MAX_STRING_SIZE );
  2010. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2011. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2012. }
  2013. else if (Error == NERR_NotPrimary) {
  2014. LoadString ( m_hInst, IDS_CP_NOTALLOWED, szMsg, MAX_STRING_SIZE );
  2015. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2016. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2017. }
  2018. else {
  2019. // Reaching here signifies a failure to set the remote domain
  2020. // password for more general reasons
  2021. LoadString ( m_hInst, IDS_DOMAINFAILED, szMsg, MAX_STRING_SIZE );
  2022. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2023. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2024. }
  2025. }
  2026. // clean any psw buffers, release the old cred, and go.
  2027. memset(m_szOldPassword,0,sizeof(m_szOldPassword));
  2028. memset(m_szNewPassword,0,sizeof(m_szNewPassword));
  2029. EndDialog(IDOK);
  2030. } // C_ChangePasswordDlg::OnOK
  2031. void C_AddKeyDlg::AdviseUser(void) {
  2032. DWORD dwErr;
  2033. TCHAR szMsg[MAX_STRING_SIZE];
  2034. TCHAR szTitle[MAX_STRING_SIZE];
  2035. dwErr = GetLastError();
  2036. if (dwErr == ERROR_NO_SUCH_LOGON_SESSION) {
  2037. LoadString ( m_hInst, IDS_NOLOGON, szMsg, MAX_STRING_SIZE );
  2038. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2039. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2040. // return leaving credential dialog up
  2041. return;
  2042. }
  2043. else if (dwErr == ERROR_BAD_USERNAME) {
  2044. LoadString ( m_hInst, IDS_BADUNAME, szMsg, MAX_STRING_SIZE );
  2045. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2046. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2047. // return leaving credential dialog up
  2048. return;
  2049. }
  2050. else if (dwErr == ERROR_INVALID_PASSWORD) {
  2051. LoadString ( m_hInst, IDS_BADPASSWORD, szMsg, MAX_STRING_SIZE );
  2052. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2053. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2054. // return leaving credential dialog up
  2055. return;
  2056. }
  2057. else {
  2058. // ERROR_INVALID_PARAMETER, ERROR_INVALID_FLAGS, etc
  2059. LoadString ( m_hInst, IDS_ADDFAILED, szMsg, MAX_STRING_SIZE );
  2060. LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
  2061. MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
  2062. // return leaving credential dialog up
  2063. return;
  2064. }
  2065. }
  2066. //
  2067. ///// End of file: krDlg.cpp ///////////////////////////////////////////////