|
|
1.1.1.5 root 1: /*
1.1.1.13 root 2: Copyright (c) 2005-2009 TrueCrypt Developers Association. All rights reserved.
1.1 root 3:
1.1.1.14! root 4: Governed by the TrueCrypt License 3.0 the full text of which is contained in
1.1.1.13 root 5: the file License.txt included in TrueCrypt binary and source code distribution
6: packages.
1.1 root 7: */
8:
1.1.1.5 root 9: #include <stdlib.h>
10: #include <string.h>
1.1 root 11: #include <sys/stat.h>
12: #include <sys/types.h>
13:
14: #include "Tcdefs.h"
15: #include "Keyfiles.h"
16: #include "Crc.h"
17:
18: #include <io.h>
19: #include "Dlgcode.h"
20: #include "Language.h"
1.1.1.9 root 21: #include "SecurityToken.h"
22: #include "Common/resource.h"
23: #include "Platform/ForEach.h"
24:
25: using namespace TrueCrypt;
1.1 root 26:
27: #define stat _stat
28: #define S_IFDIR _S_IFDIR
29: #define snprintf _snprintf
30:
31:
32: KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile)
33: {
34: KeyFile *kf = firstKeyFile;
35:
36: if (firstKeyFile != NULL)
37: {
38: while (kf->Next)
39: kf = kf->Next;
40:
41: kf->Next = keyFile;
42: }
43: else
44: firstKeyFile = keyFile;
45:
46: keyFile->Next = NULL;
47:
48: return firstKeyFile;
49: }
50:
51:
52: // Returns first keyfile, NULL if last keyfile was removed
53: static KeyFile *KeyFileRemove (KeyFile *firstKeyFile, KeyFile *keyFile)
54: {
55: KeyFile *prevkf = NULL, *kf = firstKeyFile;
56:
57: if (firstKeyFile == NULL) return NULL;
58: do
59: {
60: if (kf == keyFile)
61: {
62: if (prevkf == NULL)
63: firstKeyFile = kf->Next;
64: else
65: prevkf->Next = kf->Next;
66:
1.1.1.7 root 67: burn (keyFile, sizeof(*keyFile)); // wipe
1.1 root 68: free (keyFile);
69: break;
70: }
71: prevkf = kf;
72: }
73: while (kf = kf->Next);
74:
75: return firstKeyFile;
76: }
77:
78:
79: void KeyFileRemoveAll (KeyFile **firstKeyFile)
80: {
81: KeyFile *kf = *firstKeyFile;
82: while (kf != NULL)
83: {
84: KeyFile *d = kf;
85: kf = kf->Next;
86: burn (d, sizeof(*d)); // wipe
87: free (d);
88: }
89:
90: *firstKeyFile = NULL;
91: }
92:
93:
94: KeyFile *KeyFileClone (KeyFile *keyFile)
95: {
96: KeyFile *clone;
97:
98: if (keyFile == NULL) return NULL;
99:
1.1.1.9 root 100: clone = (KeyFile *) malloc (sizeof (KeyFile));
1.1 root 101: strcpy (clone->FileName, keyFile->FileName);
102: clone->Next = NULL;
103: return clone;
104: }
105:
106:
107: KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile)
108: {
109: KeyFile *cloneFirstKeyFile = KeyFileClone (firstKeyFile);
110: KeyFile *kf;
111:
112: if (firstKeyFile == NULL) return NULL;
113: kf = firstKeyFile->Next;
114: while (kf != NULL)
115: {
116: KeyFileAdd (cloneFirstKeyFile, KeyFileClone (kf));
117: kf = kf->Next;
118: }
119:
120: return cloneFirstKeyFile;
121: }
122:
123:
1.1.1.6 root 124: static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile)
1.1 root 125: {
126: FILE *f;
127: unsigned __int8 buffer[64 * 1024];
128: unsigned __int32 crc = 0xffffffff;
129: int writePos = 0;
130: size_t bytesRead, totalRead = 0;
1.1.1.6 root 131: int status = TRUE;
1.1 root 132:
133: HANDLE src;
134: FILETIME ftCreationTime;
135: FILETIME ftLastWriteTime;
136: FILETIME ftLastAccessTime;
137:
138: BOOL bTimeStampValid = FALSE;
139:
1.1.1.6 root 140: /* Remember the last access time of the keyfile. It will be preserved in order to prevent
141: an adversary from determining which file may have been used as keyfile. */
142: src = CreateFile (keyFile->FileName,
143: GENERIC_READ | GENERIC_WRITE,
144: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
1.1 root 145:
1.1.1.6 root 146: if (src != INVALID_HANDLE_VALUE)
147: {
148: if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
149: bTimeStampValid = TRUE;
150: }
1.1 root 151:
152: f = fopen (keyFile->FileName, "rb");
153: if (f == NULL) return FALSE;
154:
155: while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0)
156: {
157: size_t i;
158:
1.1.1.6 root 159: if (ferror (f))
160: {
161: status = FALSE;
162: goto close;
163: }
164:
1.1 root 165: for (i = 0; i < bytesRead; i++)
166: {
167: crc = UPDC32 (buffer[i], crc);
168:
169: keyPool[writePos++] += (unsigned __int8) (crc >> 24);
170: keyPool[writePos++] += (unsigned __int8) (crc >> 16);
171: keyPool[writePos++] += (unsigned __int8) (crc >> 8);
172: keyPool[writePos++] += (unsigned __int8) crc;
173:
174: if (writePos >= KEYFILE_POOL_SIZE)
175: writePos = 0;
176:
177: if (++totalRead >= KEYFILE_MAX_READ_LEN)
178: goto close;
179: }
180: }
181:
1.1.1.6 root 182: if (ferror (f))
1.1.1.9 root 183: {
184: status = FALSE;
185: }
186: else if (totalRead == 0)
187: {
1.1.1.6 root 188: status = FALSE;
1.1.1.9 root 189: SetLastError (ERROR_HANDLE_EOF);
190: }
1.1.1.6 root 191:
1.1 root 192: close:
1.1.1.9 root 193: DWORD err = GetLastError();
1.1 root 194: fclose (f);
195:
1.1.1.9 root 196: if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName))
1.1 root 197: {
198: // Restore the keyfile timestamp
1.1.1.13 root 199: SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
1.1 root 200: CloseHandle (src);
201: }
202:
1.1.1.9 root 203: SetLastError (err);
1.1.1.6 root 204: return status;
1.1 root 205: }
206:
207:
1.1.1.6 root 208: BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile)
1.1 root 209: {
210: BOOL status = TRUE;
211: KeyFile kfSubStruct;
212: KeyFile *kf;
213: KeyFile *kfSub = &kfSubStruct;
214: static unsigned __int8 keyPool [KEYFILE_POOL_SIZE];
1.1.1.10 root 215: size_t i;
1.1 root 216: struct stat statStruct;
217: char searchPath [TC_MAX_PATH*2];
218: struct _finddata_t fBuf;
219: intptr_t searchHandle;
220:
221: if (firstKeyFile == NULL) return TRUE;
222:
223: VirtualLock (keyPool, sizeof (keyPool));
224: memset (keyPool, 0, sizeof (keyPool));
225:
226: for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
227: {
1.1.1.9 root 228: // Determine whether it's a security token path
229: try
230: {
231: if (SecurityToken::IsKeyfilePathValid (SingleStringToWide (kf->FileName)))
232: {
233: // Apply security token keyfile
234: vector <byte> keyfileData;
235: SecurityToken::GetKeyfileData (SecurityTokenKeyfile (SingleStringToWide (kf->FileName)), keyfileData);
236:
237: if (keyfileData.empty())
238: {
239: SetLastError (ERROR_HANDLE_EOF);
240: handleWin32Error (MainDlg);
241: Error ("ERR_PROCESS_KEYFILE");
242: status = FALSE;
243: continue;
244: }
245:
246: unsigned __int32 crc = 0xffffffff;
247: int writePos = 0;
248: size_t totalRead = 0;
249:
250: for (size_t i = 0; i < keyfileData.size(); i++)
251: {
252: crc = UPDC32 (keyfileData[i], crc);
253:
254: keyPool[writePos++] += (unsigned __int8) (crc >> 24);
255: keyPool[writePos++] += (unsigned __int8) (crc >> 16);
256: keyPool[writePos++] += (unsigned __int8) (crc >> 8);
257: keyPool[writePos++] += (unsigned __int8) crc;
258:
259: if (writePos >= KEYFILE_POOL_SIZE)
260: writePos = 0;
261:
262: if (++totalRead >= KEYFILE_MAX_READ_LEN)
263: break;
264: }
265:
266: burn (&keyfileData.front(), keyfileData.size());
267: continue;
268: }
269: }
270: catch (Exception &e)
271: {
272: e.Show (NULL);
273: return FALSE;
274: }
275:
1.1 root 276: // Determine whether it's a path or a file
277: if (stat (kf->FileName, &statStruct) != 0)
278: {
1.1.1.6 root 279: handleWin32Error (MainDlg);
1.1 root 280: Error ("ERR_PROCESS_KEYFILE");
281: status = FALSE;
282: continue;
283: }
284:
285: if (statStruct.st_mode & S_IFDIR) // If it's a directory
286: {
287: /* Find and process all keyfiles in the directory */
1.1.1.13 root 288: int keyfileCount = 0;
1.1 root 289:
290: snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName);
291: if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1)
292: {
1.1.1.6 root 293: handleWin32Error (MainDlg);
1.1 root 294: Error ("ERR_PROCESS_KEYFILE_PATH");
295: status = FALSE;
296: continue;
297: }
298:
299: do
300: {
301: snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName,
302: '\\',
303: fBuf.name
304: );
305:
306: // Determine whether it's a path or a file
307: if (stat (kfSub->FileName, &statStruct) != 0)
308: {
1.1.1.6 root 309: handleWin32Error (MainDlg);
1.1 root 310: Error ("ERR_PROCESS_KEYFILE");
311: status = FALSE;
312: continue;
313: }
314: else if (statStruct.st_mode & S_IFDIR) // If it's a directory
315: {
316: // Prevent recursive folder scanning
317: continue;
318: }
319:
1.1.1.13 root 320: ++keyfileCount;
1.1 root 321:
322: // Apply keyfile to the pool
1.1.1.6 root 323: if (!KeyFileProcess (keyPool, kfSub))
1.1 root 324: {
1.1.1.6 root 325: handleWin32Error (MainDlg);
1.1 root 326: Error ("ERR_PROCESS_KEYFILE");
327: status = FALSE;
328: }
329:
330: } while (_findnext (searchHandle, &fBuf) != -1);
331: _findclose (searchHandle);
332:
333: burn (&kfSubStruct, sizeof (kfSubStruct));
334:
1.1.1.13 root 335: if (keyfileCount == 0)
336: {
337: ErrorDirect ((wstring (GetString ("ERR_KEYFILE_PATH_EMPTY")) + L"\n\n" + SingleStringToWide (kf->FileName)).c_str());
338: status = FALSE;
339: }
1.1 root 340: }
341: // Apply keyfile to the pool
1.1.1.6 root 342: else if (!KeyFileProcess (keyPool, kf))
1.1 root 343: {
1.1.1.6 root 344: handleWin32Error (MainDlg);
1.1 root 345: Error ("ERR_PROCESS_KEYFILE");
346: status = FALSE;
347: }
348: }
349:
350: /* Mix the keyfile pool contents into the password */
351:
1.1.1.10 root 352: for (i = 0; i < sizeof (keyPool); i++)
1.1 root 353: {
354: if (i < password->Length)
355: password->Text[i] += keyPool[i];
356: else
357: password->Text[i] = keyPool[i];
358: }
359:
360: if (password->Length < (int)sizeof (keyPool))
361: password->Length = sizeof (keyPool);
362:
363: burn (keyPool, sizeof (keyPool));
364:
365: return status;
366: }
367:
368:
369: static void LoadKeyList (HWND hwndDlg, KeyFile *firstKeyFile)
370: {
371: KeyFile *kf;
372: LVITEM LvItem;
373: int line = 0;
374: HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST);
375:
376: ListView_DeleteAllItems (hList);
377: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), FALSE);
378: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVEALL), firstKeyFile != NULL);
379: SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, firstKeyFile != NULL);
380:
381: for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
382: {
383: memset (&LvItem,0,sizeof(LvItem));
384: LvItem.mask = LVIF_TEXT|LVIF_PARAM;
385: LvItem.iItem = line++;
386: LvItem.iSubItem = 0;
387: LvItem.pszText = kf->FileName;
388: LvItem.lParam = (LPARAM) kf;
389: SendMessage (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
390: }
391: }
392:
393: #if KEYFILE_POOL_SIZE % 4 != 0
394: #error KEYFILE_POOL_SIZE must be a multiple of 4
395: #endif
396:
1.1.1.6 root 397: BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
1.1 root 398: {
399: static KeyFilesDlgParam *param;
400: static KeyFilesDlgParam origParam;
401:
402: WORD lw = LOWORD (wParam);
403:
404: switch (msg)
405: {
406: case WM_INITDIALOG:
407: {
1.1.1.2 root 408: LVCOLUMNW LvCol;
1.1 root 409: HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST);
410:
411: param = (KeyFilesDlgParam *) lParam;
412: origParam = *(KeyFilesDlgParam *) lParam;
413:
414: param->FirstKeyFile = KeyFileCloneAll (param->FirstKeyFile);
415:
416: LocalizeDialog (hwndDlg, "IDD_KEYFILES");
417: DragAcceptFiles (hwndDlg, TRUE);
418:
1.1.1.2 root 419: SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
1.1 root 420: LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP
421: );
422:
423: memset (&LvCol,0,sizeof(LvCol));
424: LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;
1.1.1.2 root 425: LvCol.pszText = GetString ("KEYFILE");
1.1.1.9 root 426: LvCol.cx = CompensateXDPI (374);
1.1 root 427: LvCol.fmt = LVCFMT_LEFT;
1.1.1.2 root 428: SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol);
1.1 root 429:
430: LoadKeyList (hwndDlg, param->FirstKeyFile);
431: SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, param->EnableKeyFiles);
432:
1.1.1.9 root 433: SetWindowTextW(GetDlgItem(hwndDlg, IDT_KEYFILES_NOTE), GetString ("KEYFILES_NOTE"));
1.1.1.5 root 434:
435: ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_INFO);
1.1 root 436: }
437: return 1;
438:
439: case WM_COMMAND:
440:
441: if (lw == IDC_KEYADD)
442: {
1.1.1.9 root 443: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
1.1.1.4 root 444: if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory))
1.1 root 445: {
1.1.1.3 root 446: do
447: {
448: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
449: LoadKeyList (hwndDlg, param->FirstKeyFile);
450:
1.1.1.9 root 451: kf = (KeyFile *) malloc (sizeof (KeyFile));
1.1.1.3 root 452: } while (SelectMultipleFilesNext (kf->FileName));
1.1 root 453: }
1.1.1.3 root 454:
455: free (kf);
1.1 root 456: return 1;
457: }
458:
459: if (lw == IDC_ADD_KEYFILE_PATH)
460: {
1.1.1.9 root 461: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
1.1 root 462:
463: if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName))
464: {
465: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
466: LoadKeyList (hwndDlg, param->FirstKeyFile);
467: }
468: else
469: {
470: free (kf);
471: }
472: return 1;
473: }
474:
1.1.1.9 root 475: if (lw == IDC_TOKEN_FILES_ADD)
476: {
477: list <SecurityTokenKeyfilePath> selectedTokenKeyfiles;
478: if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK)
479: {
480: foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles)
481: {
482: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
483: strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str());
484:
485: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
486: LoadKeyList (hwndDlg, param->FirstKeyFile);
487: }
488: }
489:
490: return 1;
491: }
492:
1.1 root 493: if (lw == IDC_KEYREMOVE)
494: {
495: HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST);
496: LVITEM LvItem;
497: memset (&LvItem, 0, sizeof(LvItem));
498: LvItem.mask = LVIF_PARAM;
499: LvItem.iItem = -1;
500:
501: while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED)))
502: {
503: ListView_GetItem (list, &LvItem);
504: param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam);
505: }
506:
507: LoadKeyList (hwndDlg, param->FirstKeyFile);
508: return 1;
509: }
510:
511: if (lw == IDC_KEYREMOVEALL)
512: {
513: KeyFileRemoveAll (¶m->FirstKeyFile);
514: LoadKeyList (hwndDlg, NULL);
515: return 1;
516: }
517:
518: if (lw == IDC_GENERATE_KEYFILE)
519: {
520: DialogBoxParamW (hInst,
521: MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg,
522: (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0);
523: return 1;
524: }
525:
1.1.1.5 root 526: if (lw == IDC_LINK_KEYFILES_INFO)
527: {
528: Applink ("keyfiles", TRUE, "");
529: }
530:
1.1 root 531: if (lw == IDOK)
532: {
533: param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE));
534: EndDialog (hwndDlg, IDOK);
535: return 1;
536: }
537:
538: if (lw == IDCANCEL)
539: {
540: KeyFileRemoveAll (¶m->FirstKeyFile);
541: *param = origParam;
542:
543: EndDialog (hwndDlg, IDCLOSE);
544: return 1;
545: }
546:
547: case WM_DROPFILES:
548: {
549: HDROP hdrop = (HDROP) wParam;
550:
1.1.1.12 root 551: int i = 0, count = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
1.1 root 552:
553: while (count-- > 0)
554: {
1.1.1.9 root 555: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
1.1 root 556: DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName));
557: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
558: LoadKeyList (hwndDlg, param->FirstKeyFile);
559: }
560:
561: DragFinish (hdrop);
562: }
563: return 1;
564:
565: case WM_NOTIFY:
566: if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED)
567: {
568: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE),
569: ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1);
570: return 1;
571: }
572: break;
573:
574: case WM_CLOSE:
575: KeyFileRemoveAll (¶m->FirstKeyFile);
576: *param = origParam;
577:
578: EndDialog (hwndDlg, IDCLOSE);
579: return 1;
580:
581: break;
582:
583: }
584:
585: return 0;
586: }
587:
588:
1.1.1.9 root 589: #define IDM_KEYFILES_POPUP_ADD_FILES 9001
590: #define IDM_KEYFILES_POPUP_ADD_DIR 9002
591: #define IDM_KEYFILES_POPUP_ADD_TOKEN_FILES 9003
592:
593: BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *param)
594: {
595: HMENU popup = CreatePopupMenu ();
596: int sel;
597: BOOL status = FALSE;
598:
599: AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_FILES, GetString ("IDC_KEYADD"));
600: AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_DIR, GetString ("IDC_ADD_KEYFILE_PATH"));
601: AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_TOKEN_FILES, GetString ("IDC_TOKEN_FILES_ADD"));
602:
603: sel = TrackPopupMenu (popup, TPM_RETURNCMD | TPM_LEFTBUTTON, popupPosition.x, popupPosition.y, 0, hwndDlg, NULL);
604:
605: switch (sel)
606: {
607: case IDM_KEYFILES_POPUP_ADD_FILES:
608: {
609: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
610: if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory))
611: {
612: do
613: {
614: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
615: kf = (KeyFile *) malloc (sizeof (KeyFile));
616: } while (SelectMultipleFilesNext (kf->FileName));
617:
618: param->EnableKeyFiles = TRUE;
619: status = TRUE;
620: }
621:
622: free (kf);
623: }
624: break;
625:
626: case IDM_KEYFILES_POPUP_ADD_DIR:
627: {
628: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
629:
630: if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName))
631: {
632: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
633: param->EnableKeyFiles = TRUE;
634: status = TRUE;
635: }
636: else
637: {
638: free (kf);
639: }
640: }
641: break;
642:
643: case IDM_KEYFILES_POPUP_ADD_TOKEN_FILES:
644: {
645: list <SecurityTokenKeyfilePath> selectedTokenKeyfiles;
646: if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK)
647: {
648: foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles)
649: {
650: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
651: strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str());
652:
653: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
654: param->EnableKeyFiles = TRUE;
655: status = TRUE;
656: }
657: }
658: }
659: break;
660: }
661:
662: DestroyMenu (popup);
663: return status;
664: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.