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