|
|
1.1.1.5 root 1: /* 1.1.1.7 root 2: Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. 1.1 root 3: 1.1.1.12! root 4: Governed by the TrueCrypt License 2.8 the full text of which is contained 1.1.1.5 root 5: in the file License.txt included in TrueCrypt binary and source code 6: distribution 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: else 151: Warning ("GETFILETIME_FAILED_KEYFILE"); 152: } 1.1 root 153: 154: f = fopen (keyFile->FileName, "rb"); 155: if (f == NULL) return FALSE; 156: 157: while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0) 158: { 159: size_t i; 160: 1.1.1.6 root 161: if (ferror (f)) 162: { 163: status = FALSE; 164: goto close; 165: } 166: 1.1 root 167: for (i = 0; i < bytesRead; i++) 168: { 169: crc = UPDC32 (buffer[i], crc); 170: 171: keyPool[writePos++] += (unsigned __int8) (crc >> 24); 172: keyPool[writePos++] += (unsigned __int8) (crc >> 16); 173: keyPool[writePos++] += (unsigned __int8) (crc >> 8); 174: keyPool[writePos++] += (unsigned __int8) crc; 175: 176: if (writePos >= KEYFILE_POOL_SIZE) 177: writePos = 0; 178: 179: if (++totalRead >= KEYFILE_MAX_READ_LEN) 180: goto close; 181: } 182: } 183: 1.1.1.6 root 184: if (ferror (f)) 1.1.1.9 root 185: { 186: status = FALSE; 187: } 188: else if (totalRead == 0) 189: { 1.1.1.6 root 190: status = FALSE; 1.1.1.9 root 191: SetLastError (ERROR_HANDLE_EOF); 192: } 1.1.1.6 root 193: 1.1 root 194: close: 1.1.1.9 root 195: DWORD err = GetLastError(); 1.1 root 196: fclose (f); 197: 1.1.1.9 root 198: if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName)) 1.1 root 199: { 200: // Restore the keyfile timestamp 201: if (!SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) 202: Warning ("SETFILETIME_FAILED_KEYFILE"); 203: CloseHandle (src); 204: } 205: 1.1.1.9 root 206: SetLastError (err); 1.1.1.6 root 207: return status; 1.1 root 208: } 209: 210: 1.1.1.6 root 211: BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile) 1.1 root 212: { 213: BOOL status = TRUE; 214: KeyFile kfSubStruct; 215: KeyFile *kf; 216: KeyFile *kfSub = &kfSubStruct; 217: static unsigned __int8 keyPool [KEYFILE_POOL_SIZE]; 1.1.1.10 root 218: size_t i; 1.1 root 219: struct stat statStruct; 220: char searchPath [TC_MAX_PATH*2]; 221: struct _finddata_t fBuf; 222: intptr_t searchHandle; 223: 224: if (firstKeyFile == NULL) return TRUE; 225: 226: VirtualLock (keyPool, sizeof (keyPool)); 227: memset (keyPool, 0, sizeof (keyPool)); 228: 229: for (kf = firstKeyFile; kf != NULL; kf = kf->Next) 230: { 1.1.1.9 root 231: // Determine whether it's a security token path 232: try 233: { 234: if (SecurityToken::IsKeyfilePathValid (SingleStringToWide (kf->FileName))) 235: { 236: // Apply security token keyfile 237: vector <byte> keyfileData; 238: SecurityToken::GetKeyfileData (SecurityTokenKeyfile (SingleStringToWide (kf->FileName)), keyfileData); 239: 240: if (keyfileData.empty()) 241: { 242: SetLastError (ERROR_HANDLE_EOF); 243: handleWin32Error (MainDlg); 244: Error ("ERR_PROCESS_KEYFILE"); 245: status = FALSE; 246: continue; 247: } 248: 249: unsigned __int32 crc = 0xffffffff; 250: int writePos = 0; 251: size_t totalRead = 0; 252: 253: for (size_t i = 0; i < keyfileData.size(); i++) 254: { 255: crc = UPDC32 (keyfileData[i], crc); 256: 257: keyPool[writePos++] += (unsigned __int8) (crc >> 24); 258: keyPool[writePos++] += (unsigned __int8) (crc >> 16); 259: keyPool[writePos++] += (unsigned __int8) (crc >> 8); 260: keyPool[writePos++] += (unsigned __int8) crc; 261: 262: if (writePos >= KEYFILE_POOL_SIZE) 263: writePos = 0; 264: 265: if (++totalRead >= KEYFILE_MAX_READ_LEN) 266: break; 267: } 268: 269: burn (&keyfileData.front(), keyfileData.size()); 270: continue; 271: } 272: } 273: catch (Exception &e) 274: { 275: e.Show (NULL); 276: return FALSE; 277: } 278: 1.1 root 279: // Determine whether it's a path or a file 280: if (stat (kf->FileName, &statStruct) != 0) 281: { 1.1.1.6 root 282: handleWin32Error (MainDlg); 1.1 root 283: Error ("ERR_PROCESS_KEYFILE"); 284: status = FALSE; 285: continue; 286: } 287: 288: if (statStruct.st_mode & S_IFDIR) // If it's a directory 289: { 290: /* Find and process all keyfiles in the directory */ 291: 292: snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName); 293: if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1) 294: { 1.1.1.6 root 295: handleWin32Error (MainDlg); 1.1 root 296: Error ("ERR_PROCESS_KEYFILE_PATH"); 297: status = FALSE; 298: continue; 299: } 300: 301: do 302: { 303: snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName, 304: '\\', 305: fBuf.name 306: ); 307: 308: // Determine whether it's a path or a file 309: if (stat (kfSub->FileName, &statStruct) != 0) 310: { 1.1.1.6 root 311: handleWin32Error (MainDlg); 1.1 root 312: Error ("ERR_PROCESS_KEYFILE"); 313: status = FALSE; 314: continue; 315: } 316: else if (statStruct.st_mode & S_IFDIR) // If it's a directory 317: { 318: // Prevent recursive folder scanning 319: continue; 320: } 321: 322: 323: // Apply keyfile to the pool 1.1.1.6 root 324: if (!KeyFileProcess (keyPool, kfSub)) 1.1 root 325: { 1.1.1.6 root 326: handleWin32Error (MainDlg); 1.1 root 327: Error ("ERR_PROCESS_KEYFILE"); 328: status = FALSE; 329: } 330: 331: } while (_findnext (searchHandle, &fBuf) != -1); 332: _findclose (searchHandle); 333: 334: burn (&kfSubStruct, sizeof (kfSubStruct)); 335: 336: } 337: // Apply keyfile to the pool 1.1.1.6 root 338: else if (!KeyFileProcess (keyPool, kf)) 1.1 root 339: { 1.1.1.6 root 340: handleWin32Error (MainDlg); 1.1 root 341: Error ("ERR_PROCESS_KEYFILE"); 342: status = FALSE; 343: } 344: } 345: 346: /* Mix the keyfile pool contents into the password */ 347: 1.1.1.10 root 348: for (i = 0; i < sizeof (keyPool); i++) 1.1 root 349: { 350: if (i < password->Length) 351: password->Text[i] += keyPool[i]; 352: else 353: password->Text[i] = keyPool[i]; 354: } 355: 356: if (password->Length < (int)sizeof (keyPool)) 357: password->Length = sizeof (keyPool); 358: 359: burn (keyPool, sizeof (keyPool)); 360: 361: return status; 362: } 363: 364: 365: static void LoadKeyList (HWND hwndDlg, KeyFile *firstKeyFile) 366: { 367: KeyFile *kf; 368: LVITEM LvItem; 369: int line = 0; 370: HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST); 371: 372: ListView_DeleteAllItems (hList); 373: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), FALSE); 374: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVEALL), firstKeyFile != NULL); 375: SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, firstKeyFile != NULL); 376: 377: for (kf = firstKeyFile; kf != NULL; kf = kf->Next) 378: { 379: memset (&LvItem,0,sizeof(LvItem)); 380: LvItem.mask = LVIF_TEXT|LVIF_PARAM; 381: LvItem.iItem = line++; 382: LvItem.iSubItem = 0; 383: LvItem.pszText = kf->FileName; 384: LvItem.lParam = (LPARAM) kf; 385: SendMessage (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); 386: } 387: } 388: 389: #if KEYFILE_POOL_SIZE % 4 != 0 390: #error KEYFILE_POOL_SIZE must be a multiple of 4 391: #endif 392: 1.1.1.6 root 393: BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 1.1 root 394: { 395: static KeyFilesDlgParam *param; 396: static KeyFilesDlgParam origParam; 397: 398: WORD lw = LOWORD (wParam); 399: 400: switch (msg) 401: { 402: case WM_INITDIALOG: 403: { 1.1.1.2 root 404: LVCOLUMNW LvCol; 1.1 root 405: HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST); 406: 407: param = (KeyFilesDlgParam *) lParam; 408: origParam = *(KeyFilesDlgParam *) lParam; 409: 410: param->FirstKeyFile = KeyFileCloneAll (param->FirstKeyFile); 411: 412: LocalizeDialog (hwndDlg, "IDD_KEYFILES"); 413: DragAcceptFiles (hwndDlg, TRUE); 414: 1.1.1.2 root 415: SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, 1.1 root 416: LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP 417: ); 418: 419: memset (&LvCol,0,sizeof(LvCol)); 420: LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; 1.1.1.2 root 421: LvCol.pszText = GetString ("KEYFILE"); 1.1.1.9 root 422: LvCol.cx = CompensateXDPI (374); 1.1 root 423: LvCol.fmt = LVCFMT_LEFT; 1.1.1.2 root 424: SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol); 1.1 root 425: 426: LoadKeyList (hwndDlg, param->FirstKeyFile); 427: SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, param->EnableKeyFiles); 428: 1.1.1.9 root 429: SetWindowTextW(GetDlgItem(hwndDlg, IDT_KEYFILES_NOTE), GetString ("KEYFILES_NOTE")); 1.1.1.5 root 430: 431: ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_INFO); 1.1 root 432: } 433: return 1; 434: 435: case WM_COMMAND: 436: 437: if (lw == IDC_KEYADD) 438: { 1.1.1.9 root 439: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 1.1.1.4 root 440: if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory)) 1.1 root 441: { 1.1.1.3 root 442: do 443: { 444: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 445: LoadKeyList (hwndDlg, param->FirstKeyFile); 446: 1.1.1.9 root 447: kf = (KeyFile *) malloc (sizeof (KeyFile)); 1.1.1.3 root 448: } while (SelectMultipleFilesNext (kf->FileName)); 1.1 root 449: } 1.1.1.3 root 450: 451: free (kf); 1.1 root 452: return 1; 453: } 454: 455: if (lw == IDC_ADD_KEYFILE_PATH) 456: { 1.1.1.9 root 457: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 1.1 root 458: 459: if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) 460: { 461: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 462: LoadKeyList (hwndDlg, param->FirstKeyFile); 463: } 464: else 465: { 466: free (kf); 467: } 468: return 1; 469: } 470: 1.1.1.9 root 471: if (lw == IDC_TOKEN_FILES_ADD) 472: { 473: list <SecurityTokenKeyfilePath> selectedTokenKeyfiles; 474: if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) 475: { 476: foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) 477: { 478: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 479: strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str()); 480: 481: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 482: LoadKeyList (hwndDlg, param->FirstKeyFile); 483: } 484: } 485: 486: return 1; 487: } 488: 1.1 root 489: if (lw == IDC_KEYREMOVE) 490: { 491: HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST); 492: LVITEM LvItem; 493: memset (&LvItem, 0, sizeof(LvItem)); 494: LvItem.mask = LVIF_PARAM; 495: LvItem.iItem = -1; 496: 497: while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED))) 498: { 499: ListView_GetItem (list, &LvItem); 500: param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam); 501: } 502: 503: LoadKeyList (hwndDlg, param->FirstKeyFile); 504: return 1; 505: } 506: 507: if (lw == IDC_KEYREMOVEALL) 508: { 509: KeyFileRemoveAll (¶m->FirstKeyFile); 510: LoadKeyList (hwndDlg, NULL); 511: return 1; 512: } 513: 514: if (lw == IDC_GENERATE_KEYFILE) 515: { 516: DialogBoxParamW (hInst, 517: MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg, 518: (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0); 519: return 1; 520: } 521: 1.1.1.5 root 522: if (lw == IDC_LINK_KEYFILES_INFO) 523: { 524: Applink ("keyfiles", TRUE, ""); 525: } 526: 1.1 root 527: if (lw == IDOK) 528: { 529: param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE)); 530: EndDialog (hwndDlg, IDOK); 531: return 1; 532: } 533: 534: if (lw == IDCANCEL) 535: { 536: KeyFileRemoveAll (¶m->FirstKeyFile); 537: *param = origParam; 538: 539: EndDialog (hwndDlg, IDCLOSE); 540: return 1; 541: } 542: 543: case WM_DROPFILES: 544: { 545: HDROP hdrop = (HDROP) wParam; 546: 1.1.1.12! root 547: int i = 0, count = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0); 1.1 root 548: 549: while (count-- > 0) 550: { 1.1.1.9 root 551: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 1.1 root 552: DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName)); 553: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 554: LoadKeyList (hwndDlg, param->FirstKeyFile); 555: } 556: 557: DragFinish (hdrop); 558: } 559: return 1; 560: 561: case WM_NOTIFY: 562: if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) 563: { 564: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), 565: ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1); 566: return 1; 567: } 568: break; 569: 570: case WM_CLOSE: 571: KeyFileRemoveAll (¶m->FirstKeyFile); 572: *param = origParam; 573: 574: EndDialog (hwndDlg, IDCLOSE); 575: return 1; 576: 577: break; 578: 579: } 580: 581: return 0; 582: } 583: 584: 1.1.1.9 root 585: #define IDM_KEYFILES_POPUP_ADD_FILES 9001 586: #define IDM_KEYFILES_POPUP_ADD_DIR 9002 587: #define IDM_KEYFILES_POPUP_ADD_TOKEN_FILES 9003 588: 589: BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *param) 590: { 591: HMENU popup = CreatePopupMenu (); 592: int sel; 593: BOOL status = FALSE; 594: 595: AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_FILES, GetString ("IDC_KEYADD")); 596: AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_DIR, GetString ("IDC_ADD_KEYFILE_PATH")); 597: AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_TOKEN_FILES, GetString ("IDC_TOKEN_FILES_ADD")); 598: 599: sel = TrackPopupMenu (popup, TPM_RETURNCMD | TPM_LEFTBUTTON, popupPosition.x, popupPosition.y, 0, hwndDlg, NULL); 600: 601: switch (sel) 602: { 603: case IDM_KEYFILES_POPUP_ADD_FILES: 604: { 605: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 606: if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory)) 607: { 608: do 609: { 610: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 611: kf = (KeyFile *) malloc (sizeof (KeyFile)); 612: } while (SelectMultipleFilesNext (kf->FileName)); 613: 614: param->EnableKeyFiles = TRUE; 615: status = TRUE; 616: } 617: 618: free (kf); 619: } 620: break; 621: 622: case IDM_KEYFILES_POPUP_ADD_DIR: 623: { 624: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 625: 626: if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) 627: { 628: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 629: param->EnableKeyFiles = TRUE; 630: status = TRUE; 631: } 632: else 633: { 634: free (kf); 635: } 636: } 637: break; 638: 639: case IDM_KEYFILES_POPUP_ADD_TOKEN_FILES: 640: { 641: list <SecurityTokenKeyfilePath> selectedTokenKeyfiles; 642: if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) 643: { 644: foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) 645: { 646: KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); 647: strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str()); 648: 649: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 650: param->EnableKeyFiles = TRUE; 651: status = TRUE; 652: } 653: } 654: } 655: break; 656: } 657: 658: DestroyMenu (popup); 659: return status; 660: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.