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