Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

523 lines
22 KiB

  1. /*
  2. SHEET2.CPP
  3. Implements the property sheet page's behaviors.
  4. On initialization of this sheet, an authentication challenge is fetched from
  5. the card by a call to CardGetChallenge(). Both the challenge and the
  6. response from the user are in binary form when used, so helper functions
  7. exist to convert to and from string form.
  8. This sheet is implemented as two dialogs, the opening one in which the
  9. challenge is presented and the user returns the response, and a second
  10. one in which ther user enters the new PIN for the card.
  11. The user switches between the two dialogs by pressing the "Unblock"
  12. button on the dialog. When this happens, the response entered by the user
  13. is cached, and the UI changes to present a panel in which the user enters the
  14. desired new PIN in duplicate. There is no second button on this panel, so
  15. the user presses OK when data entry is completed.
  16. At that point, the card module CardUnblockPin function is called, passing
  17. in the response and the new pin.
  18. The user is prevented from leaving this dialog once the "unblock" button is
  19. pressed, except by means of the OK or Cancel buttons (Cannot switch pages).
  20. */
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <windows.h>
  25. #include <commdlg.h>
  26. #include <commctrl.h>
  27. #include <ole2.h>
  28. #include <stdio.h>
  29. #include <scarderr.h>
  30. #include "helpers.h"
  31. #include "support.h"
  32. #include "res.h"
  33. #include "utils.h"
  34. #include "helpers.h"
  35. extern HINSTANCE ghInstance;
  36. extern HWND hwndContainer;
  37. extern BOOL fUnblockActive; // showing PIN entry phase of unblock
  38. extern INT iCurrent;
  39. BOOL fTransacted = FALSE;
  40. // Help handler for the sheet
  41. void HelpHandler(LPARAM lp);
  42. // stash of UI handles, because we use them more than normal
  43. HWND hwndTopText = NULL;
  44. HWND hwndCardIDLabel = NULL;
  45. HWND hwndCardID = NULL;
  46. HWND hwndPIN1Label = NULL;
  47. HWND hwndPIN2Label = NULL;
  48. HWND hwndChallengeLabel = NULL;
  49. HWND hwndResponseLabel = NULL;
  50. HWND hwndChallenge = NULL;
  51. HWND hwndResponse = NULL;
  52. HWND hwndButton1 = NULL;
  53. // buffer to hold the response from the UI which has to persist through changes in window
  54. // mode.
  55. WCHAR wszResponse[100];
  56. BYTE *pBin = NULL;
  57. DWORD dwBin = 0;
  58. /* ---------------------------------------------------------------------
  59. SetWindowTextFromResource
  60. Accept hwnd of window and resource ID. Fetch string from resources and write to
  61. the window Text.
  62. --------------------------------------------------------------------- */
  63. BOOL SetWindowTextFromResource(HWND hwnd,UINT uiResid)
  64. {
  65. WCHAR szTmp[1024];
  66. if (NULL == hwnd) return FALSE;
  67. if (0 != LoadString(ghInstance,uiResid,szTmp,1024))
  68. {
  69. SendMessage(hwnd,WM_SETTEXT,0,(LPARAM) szTmp);
  70. return TRUE;
  71. }
  72. return FALSE;
  73. }
  74. /* ---------------------------------------------------------------------
  75. Page2InitUIHandles
  76. --------------------------------------------------------------------- */
  77. DWORD Page2InitUIHandles(HWND hwnd)
  78. {
  79. hwndTopText = GetDlgItem(hwnd,IDC_TOPTEXT);
  80. ASSERT(hwndTopText);
  81. hwndPIN1Label = GetDlgItem(hwnd,IDC_NEWPIN1LABEL);
  82. ASSERT(hwndPIN1Label);
  83. hwndPIN2Label = GetDlgItem(hwnd,IDC_NEWPIN2LABEL);
  84. ASSERT(hwndPIN2Label);
  85. hwndCardIDLabel = GetDlgItem(hwnd,IDC_SCARDIDLABEL);
  86. ASSERT(hwndCardIDLabel);
  87. hwndCardID = GetDlgItem(hwnd,IDC_SCARDID);
  88. ASSERT(hwndCardID);
  89. hwndChallengeLabel = GetDlgItem(hwnd,IDC_CHALLENGELABEL);
  90. ASSERT(hwndChallengeLabel);
  91. hwndChallenge = GetDlgItem(hwnd,IDC_CHALLENGE);
  92. ASSERT(hwndChallenge);
  93. hwndResponseLabel = GetDlgItem(hwnd,IDC_RESPONSELABEL);
  94. ASSERT(hwndResponseLabel);
  95. hwndResponse = GetDlgItem(hwnd,IDC_RESPONSE);
  96. ASSERT(hwndResponse);
  97. hwndButton1 = GetDlgItem(hwnd,IDBUTTON1);
  98. ASSERT(hwndButton1);
  99. return 0;
  100. }
  101. /* ---------------------------------------------------------------------
  102. Page2SetUIToChallenge
  103. --------------------------------------------------------------------- */
  104. DWORD Page2SetUIToChallenge(void)
  105. {
  106. // Set user instructions
  107. SetWindowTextFromResource(hwndTopText,IDS_UNBLOCK1);
  108. // Hide the pin UI labels
  109. ShowWindow(hwndPIN1Label,SW_HIDE);
  110. ShowWindow(hwndPIN2Label,SW_HIDE);
  111. // Show the card id information and the challenge/response labels
  112. ShowWindow(hwndCardIDLabel,SW_NORMAL);
  113. ShowWindow(hwndCardID,SW_NORMAL);
  114. ShowWindow(hwndChallengeLabel,SW_NORMAL);
  115. ShowWindow(hwndResponseLabel,SW_NORMAL);
  116. ShowWindow(hwndButton1,SW_NORMAL);
  117. // Show the CardID
  118. WCHAR *psId = NULL;
  119. DWORD dwRet = DoGetCardId(&psId);
  120. if (psId != NULL)
  121. SetWindowText(hwndCardID,psId);
  122. // Turn off password style
  123. SendMessage(hwndChallenge,EM_SETPASSWORDCHAR,0,0);
  124. SendMessage(hwndChallenge,EM_SETREADONLY,TRUE,0);
  125. SendMessage(hwndResponse,EM_SETPASSWORDCHAR,0,0);
  126. SetFocus(hwndResponse);
  127. return 0;
  128. }
  129. /* ---------------------------------------------------------------------
  130. Page2SetUIToPin
  131. --------------------------------------------------------------------- */
  132. DWORD Page2SetUIToPin(void)
  133. {
  134. // clean both text boxes
  135. SetWindowText(hwndChallenge,L"");
  136. SetWindowText(hwndResponse,L"");
  137. // Set user instructions
  138. SetWindowTextFromResource(hwndTopText,IDS_UNBLOCK2);
  139. // Hide challenge/response labels and the card id information
  140. ShowWindow(hwndChallengeLabel,SW_HIDE);
  141. ShowWindow(hwndResponseLabel,SW_HIDE);
  142. ShowWindow(hwndCardIDLabel,SW_HIDE);
  143. ShowWindow(hwndCardID,SW_HIDE);
  144. ShowWindow(hwndButton1,SW_HIDE);
  145. // Show the PIN labels
  146. ShowWindow(hwndPIN1Label,SW_NORMAL);
  147. ShowWindow(hwndPIN2Label,SW_NORMAL);
  148. // Hide the PIN
  149. SendMessage(hwndChallenge,EM_SETPASSWORDCHAR,L'*',0);
  150. SendMessage(hwndChallenge,EM_SETREADONLY,0,0);
  151. SendMessage(hwndResponse,EM_SETPASSWORDCHAR,L'*',0);
  152. SetFocus(hwndChallenge);
  153. return 0;
  154. }
  155. /* ---------------------------------------------------------------------
  156. PageProc2
  157. Page procedure for page 2, the Card unblock page.
  158. Once the user begins the unblock operation, he is not allowed to leave this page
  159. except via attempting completion of the operation or cancelling. Simply selecting
  160. the other UI tab is disabled once he hits the "Unblock" button.
  161. --------------------------------------------------------------------- */
  162. INT_PTR CALLBACK PageProc2(
  163. HWND hwnd,
  164. UINT msg,
  165. WPARAM wparam,
  166. LPARAM lparam)
  167. {
  168. INT_PTR ret;
  169. HWND hwndCred = NULL;
  170. BOOL gfSuccess = FALSE;
  171. switch (msg)
  172. {
  173. case WM_HELP:
  174. {
  175. // context sensitive help - call the sheet help handler
  176. HelpHandler(lparam);
  177. break;
  178. };
  179. case WM_NOTIFY:
  180. {
  181. NMHDR *pHdr = (NMHDR *)lparam;
  182. switch (pHdr->code)
  183. {
  184. case PSN_SETACTIVE:
  185. iCurrent = 2;
  186. if (NULL == hwndContainer)
  187. {
  188. hwndContainer = pHdr->hwndFrom;
  189. ASSERT(hwndContainer);
  190. }
  191. // Cache control handles the first time this page is seen
  192. if (!hwndChallenge) Page2InitUIHandles(hwnd);
  193. ASSERT(hwndChallenge);
  194. // We are activating or returning to this page. If we have not presented
  195. // the PIN UI yet, init the challenge/response UI.
  196. if (!fUnblockActive)
  197. {
  198. WCHAR rgwc[100];
  199. Page2SetUIToChallenge();
  200. // Fetch up to 100 characters of challenge information from the control to
  201. // see if it is empty. If so, call CardGetChallenge.
  202. if (GetWindowText(hwndChallenge,rgwc,100) == 0)
  203. {
  204. BYTE *pChal = NULL;
  205. DWORD dwChal = 0;
  206. WCHAR *pUI = NULL;
  207. DWORD dwUI = 0;
  208. if (!FAILED(DoGetChallenge(&pChal,&dwChal)))
  209. {
  210. if (!FAILED(DoConvertBinaryToBuffer(pChal,dwChal,(BYTE **)&pUI,&dwUI)))
  211. {
  212. SetWindowText(hwndChallenge,pUI);
  213. CspFreeH(pUI);
  214. SendMessage(hwndResponse, EM_SETSEL,0,-1);
  215. SetFocus(hwndResponse);
  216. }
  217. else ASSERT(0); // should be impossible to get conversion error here
  218. CspFreeH(pChal);
  219. }
  220. else
  221. {
  222. ASSERT(0);
  223. // fetch challenge failed - present msg box and restart the page
  224. PresentModalMessageBox(hwnd, IDS_SCERROR,MB_ICONHAND);
  225. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,IDD_PAGE2);
  226. return TRUE;
  227. }
  228. }
  229. // Put the keyboard focus on the response control.
  230. SetFocus(hwndResponse);
  231. }
  232. return 0;
  233. break;
  234. case PSN_RESET:
  235. // User cancelled the property sheet or hit the close button on the top right corner
  236. if (fTransacted) SCardEndTransaction(pCardData->hScard,SCARD_RESET_CARD);
  237. fTransacted = FALSE;
  238. if (pBin)
  239. {
  240. CspFreeH(pBin);
  241. pBin = NULL;
  242. dwBin = 0;
  243. }
  244. return FALSE;
  245. break;
  246. case PSN_KILLACTIVE:
  247. //User hit OK, or switched to another page
  248. // Watch out! When you are on page 2, this notification is received
  249. // before the PSN_APPLY notification
  250. //do validation, return FALSE if ok to lose focus, else TRUE
  251. return FALSE;
  252. break;
  253. case PSN_QUERYCANCEL:
  254. // Return TRUE to prevent cancel, FALSE to allow it.
  255. // clear the edit control, and return the sheet to the initial state
  256. if (fTransacted) SCardEndTransaction(pCardData->hScard,SCARD_RESET_CARD);
  257. fTransacted = FALSE;
  258. if (pBin)
  259. {
  260. CspFreeH(pBin);
  261. pBin = NULL;
  262. dwBin = 0;
  263. }
  264. if (fUnblockActive)
  265. {
  266. fUnblockActive = FALSE;
  267. Page2SetUIToChallenge();
  268. SendMessage(hwndResponse,WM_SETTEXT,0,0);
  269. return FALSE;
  270. }
  271. return TRUE;
  272. case PSN_APPLY:
  273. // Only process an apply for this page if sheet 2 is active
  274. // This will entail getting the two copies of the PIN, making sure they are
  275. // identical, and
  276. if (iCurrent != 2)
  277. {
  278. // If the user was looking at the other sheet when he hit OK, do
  279. // nothing with the page.
  280. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,PSNRET_NOERROR);
  281. return TRUE;
  282. }
  283. if (fUnblockActive)
  284. {
  285. WCHAR sz[100]; // buffer for PIN from the UI
  286. WCHAR sz2[100];
  287. // SetWindowLong(DWL_MSGRESULT = PSNRET_INVALID if unable
  288. // PSN_INVALID_NOCHANGEPAGE looks the same
  289. // PSNRET_NOERROR - OK, page can be destroyed if OK
  290. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,PSNRET_NOERROR);
  291. GetWindowText(hwndResponse,sz,100);
  292. GetWindowText(hwndChallenge,sz2,100);
  293. // Make sure that the two copies match
  294. if (0 != wcscmp(sz,sz2))
  295. {
  296. PresentModalMessageBox(hwnd, IDS_NOTSAME,MB_ICONHAND);
  297. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,PSNRET_INVALID);
  298. return TRUE;
  299. }
  300. // make sure we have a pin at all
  301. if (wcslen(sz) == 0)
  302. {
  303. PresentModalMessageBox(hwnd, IDS_NEEDPIN,MB_ICONHAND);
  304. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,PSNRET_INVALID);
  305. return TRUE;
  306. }
  307. {
  308. // Attempt the unblock
  309. char AnsiPin[64];
  310. DWORD dwRet = 0;
  311. // change WCHAR PINs to ANSI
  312. WideCharToMultiByte(GetConsoleOutputCP(),
  313. 0,
  314. (WCHAR *) sz,
  315. -1,
  316. AnsiPin,
  317. 64,
  318. NULL,
  319. NULL);
  320. dwRet = DoCardUnblock(pBin,dwBin,(BYTE *)AnsiPin,strlen(AnsiPin));
  321. // done with the response binary - release it
  322. if (pBin)
  323. {
  324. CspFreeH(pBin);
  325. pBin = NULL;
  326. dwBin = 0;
  327. }
  328. // End the transaction
  329. SCardEndTransaction(pCardData->hScard,SCARD_LEAVE_CARD);
  330. fTransacted = FALSE;
  331. // Process success or failure
  332. if (!FAILED(dwRet ))
  333. {
  334. PresentModalMessageBox(hwnd, IDS_UNBLOCKOK,MB_OK);
  335. return TRUE;
  336. }
  337. else
  338. {
  339. switch(dwRet)
  340. {
  341. case SCARD_F_INTERNAL_ERROR:
  342. PresentModalMessageBox(hwnd, IDS_INTERROR ,MB_ICONHAND);
  343. break;
  344. case SCARD_E_CANCELLED:
  345. PresentModalMessageBox(hwnd, IDS_CANCELLED,MB_ICONHAND);
  346. break;
  347. case SCARD_E_NO_SERVICE:
  348. PresentModalMessageBox(hwnd, IDS_NOSERVICE,MB_ICONHAND);
  349. break;
  350. case SCARD_E_SERVICE_STOPPED:
  351. PresentModalMessageBox(hwnd, IDS_STOPPED,MB_ICONHAND);
  352. break;
  353. case SCARD_E_UNSUPPORTED_FEATURE:
  354. PresentModalMessageBox(hwnd, IDS_UNSUPPORTED,MB_ICONHAND);
  355. break;
  356. case SCARD_E_FILE_NOT_FOUND:
  357. PresentModalMessageBox(hwnd, IDS_NOTFOUND,MB_ICONHAND);
  358. break;
  359. case SCARD_E_WRITE_TOO_MANY:
  360. PresentModalMessageBox(hwnd, IDS_TOOMANY,MB_ICONHAND);
  361. break;
  362. case SCARD_E_INVALID_CHV:
  363. // !!! Note the mapping of invalid to wrong.
  364. // consult public\sdk\inc\scarderr.h @ 562
  365. PresentModalMessageBox(hwnd, IDS_BADCHV,MB_ICONHAND);
  366. break;
  367. case SCARD_W_UNSUPPORTED_CARD:
  368. PresentModalMessageBox(hwnd, IDS_UNSUPPORTED,MB_ICONHAND);
  369. break;
  370. case SCARD_W_UNRESPONSIVE_CARD:
  371. PresentModalMessageBox(hwnd, IDS_UNRESP ,MB_ICONHAND);
  372. break;
  373. case SCARD_W_REMOVED_CARD:
  374. PresentModalMessageBox(hwnd, IDS_REMOVED ,MB_ICONHAND);
  375. break;
  376. case SCARD_W_WRONG_CHV:
  377. PresentModalMessageBox(hwnd, IDS_WRONGCHV,MB_ICONHAND);
  378. break;
  379. case SCARD_W_CHV_BLOCKED:
  380. PresentModalMessageBox(hwnd, IDS_BLOCKEDCHV,MB_ICONHAND);
  381. break;
  382. default:
  383. PresentModalMessageBox(hwnd, IDS_UNBLOCKFAIL,MB_ICONHAND);
  384. break;
  385. }
  386. SetWindowText(hwndResponse,L"");
  387. SetWindowText(hwndChallenge,L"");
  388. Page2SetUIToChallenge();
  389. fUnblockActive = FALSE;
  390. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,PSNRET_INVALID);
  391. return TRUE;
  392. }
  393. } // end block of code that used to be in an IF
  394. }
  395. // Don't close the prop sheet if OK was pressed from the unblock page,
  396. // and we have not completed PIN entry. Else OK to close.
  397. if (!fUnblockActive)
  398. {
  399. PresentModalMessageBox(hwnd, IDS_WRONGBUTTON,MB_ICONHAND);
  400. SetWindowLongPtr(hwnd,DWLP_MSGRESULT,PSNRET_INVALID);
  401. }
  402. break;
  403. }
  404. return TRUE;
  405. }
  406. break;
  407. case WM_COMMAND:
  408. // Button clicks.
  409. switch(LOWORD(wparam))
  410. {
  411. case IDBUTTON1:
  412. if (HIWORD(wparam) == BN_CLICKED)
  413. {
  414. // On button, fetch the response text, hide the chal/response controls, hide the
  415. // launch button, and expose the gather PIN controls.
  416. //
  417. //Notify the 'apply' button that something is appliable. - but we don't have an apply button
  418. //SendMessage(hwndContainer,PSM_CHANGED,(WPARAM)hwnd,(LPARAM)0);
  419. // Get challenge value back and store it for later use by the apply code
  420. INT iCount = GetWindowText(hwndResponse,wszResponse,100);
  421. if (0 != iCount)
  422. {
  423. if (!FAILED(DoConvertBufferToBinary((BYTE *)wszResponse,100,&pBin,&dwBin)))
  424. {
  425. Page2SetUIToPin();
  426. fUnblockActive = TRUE;
  427. }
  428. else
  429. {
  430. SetWindowText(hwndResponse,L"");
  431. PresentModalMessageBox(hwnd, IDS_BADRESPONSE,MB_ICONHAND);
  432. if (pBin) CspFreeH(pBin);
  433. }
  434. }
  435. else
  436. PresentModalMessageBox(hwnd, IDS_NEEDRESPONSE,MB_ICONHAND);
  437. }
  438. break;
  439. default:
  440. break;
  441. }
  442. break;
  443. default:
  444. break;
  445. }
  446. return FALSE;
  447. }