|
|
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.13! root 4: Governed by the TrueCrypt License 2.8 the full text of which is contained in ! 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.