home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / security / crypto / cfiler / crp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-13  |  66.5 KB  |  2,496 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright 1996-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. // CRP.C
  13. #include "cfiler.h"
  14.  
  15. HCRYPTPROV                    hMe;
  16. ALG_ID                        AlgidEncrypt;
  17. ALG_ID                        AlgidSign;
  18. TCHAR                        sPass[BUF_SIZE];
  19. TCHAR                        szPassName[BUF_SIZE];
  20.  
  21. extern HANDLE                 ghModule; 
  22. extern HMENU                ghMenu;                                                                                    
  23.  
  24. /************************************************************************\
  25. * EnterPass()
  26. *
  27. * Dialog procedure for the "PASSWORD" dialog box.
  28. *
  29. * Stores the password entered by the user into 
  30. * the global buffer sPass
  31. \************************************************************************/
  32.  
  33. WINAPI EnterPass(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam)  {
  34.     TCHAR szMessage[BUF_SIZE];
  35.     
  36.     switch(wMsgID) {
  37.         case WM_INITDIALOG:
  38.             lstrcpy(szMessage, TEXT("Enter password: "));
  39.             lstrcat(szMessage, szPassName);
  40.             SetDlgItemText(hDlg, IDC_PASSTEXT, szMessage);
  41.             SetDlgItemText(hDlg, IDC_EDIT1, TEXT("\0"));
  42.             SetDlgItemText(hDlg, IDC_EDIT2, TEXT("\0"));
  43.  
  44.             return FALSE;
  45.             
  46.         case WM_COMMAND:
  47.             switch(LOWORD(wParam)) {
  48.                 TCHAR szVerify[BUF_SIZE];
  49.                 
  50.                 case IDOK:
  51.                     if (!GetDlgItemText(hDlg, IDC_EDIT1, sPass, BUF_SIZE)) {
  52.                         if (MessageBox(hDlg, TEXT("No password entered."), NULL, MB_OK) == IDOK) {
  53.                             EndDialog(hDlg, FALSE);
  54.                             return FALSE;
  55.                         }
  56.                     }
  57.                                     
  58.                     SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  59.                     
  60.                     if (!GetDlgItemText(hDlg, IDC_EDIT2, szVerify, BUF_SIZE)) {
  61.                         MessageBox(hDlg, TEXT("No password entered."), NULL, MB_OK);
  62.                         EndDialog(hDlg, FALSE);
  63.                         return FALSE;
  64.                     }
  65.                     
  66.                     if (lstrcmp(sPass, szVerify)) {
  67.                         MessageBox(hDlg, TEXT("Could not verify password."), NULL, MB_OK);
  68.                         EndDialog(hDlg, FALSE);
  69.                         return FALSE;
  70.                     }
  71.  
  72.                     EndDialog(hDlg, TRUE);                    
  73.                     
  74.                     return TRUE;
  75.                     
  76.                 case IDCANCEL:
  77.                     EndDialog(hDlg, -1);
  78.                     return -1;
  79.                     
  80.                 default:
  81.                     return FALSE;
  82.             }
  83.             break;
  84.     }
  85.     return FALSE;
  86. }    
  87.  
  88. /************************************************************************\
  89. * CryptDlgProc()
  90. *
  91. * Dialog procedure for all dialog boxes of the
  92. * application besides "PASSWORD", "ENCRYPTION_ALGORITHM,"
  93. * and "HASH_ALGORITHM."
  94. \************************************************************************/
  95.  
  96. LRESULT WINAPI CryptDlgProc(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam) {
  97.     switch(wMsgID) {
  98.         case WM_INITDIALOG:
  99.             return FALSE;
  100.             
  101.         case WM_COMMAND:
  102.             switch(LOWORD(wParam)) {
  103.                 case IDOK:
  104.                     EndDialog(hDlg, TRUE);
  105.                     return TRUE;
  106.                     
  107.                 case IDCANCEL:
  108.                     EndDialog(hDlg, FALSE);
  109.                     return TRUE;
  110.                     
  111.                 default:
  112.                     return FALSE;
  113.             }
  114.             break;
  115.     }
  116.     return FALSE;
  117. }
  118.  
  119. /************************************************************************\
  120. * EncryptDlgProc()
  121. *
  122. * Dialog procedure for "ENCRYPTION_ALGORITHM" dialog box.
  123. \************************************************************************/
  124.  
  125. LRESULT WINAPI EncryptDlgProc(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam) {
  126.     switch(wMsgID) {
  127.         case WM_INITDIALOG:
  128.             if (AlgidEncrypt == CALG_RC4)
  129.                 CheckRadioButton(hDlg, IDC_RC2, IDC_RC4, IDC_RC4);
  130.             else
  131.                 CheckRadioButton(hDlg, IDC_RC2, IDC_RC4, IDC_RC2);
  132.             return FALSE;
  133.             
  134.         case WM_COMMAND:
  135.             switch(LOWORD(wParam)) {
  136.                 case IDC_RC2:
  137.                     AlgidEncrypt = CALG_RC2;
  138.                     return TRUE;
  139.  
  140.                 case IDC_RC4:
  141.                     AlgidEncrypt = CALG_RC4;
  142.                     return TRUE;
  143.             
  144.                 case IDOK:
  145.                     if (!AlgidEncrypt)
  146.                         AlgidEncrypt = CALG_RC2;
  147.                     EndDialog(hDlg, TRUE);
  148.                     return TRUE;
  149.                     
  150.                 case IDCANCEL:
  151.                     EndDialog(hDlg, FALSE);
  152.                     return TRUE;
  153.                     
  154.                 default:
  155.                     return FALSE;
  156.             }
  157.             break;
  158.     }
  159.     return FALSE;
  160. }
  161.  
  162. /************************************************************************\
  163. * HashDlgProc()
  164. *
  165. * Dialog procedure for "HASH_ALGORITHM" dialog box
  166. \************************************************************************/
  167.  
  168. LRESULT WINAPI HashDlgProc(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam) {
  169.     switch(wMsgID) {
  170.         case WM_INITDIALOG:
  171.             if (AlgidSign == CALG_SHA)
  172.                 CheckRadioButton(hDlg, IDC_MD4, IDC_SHA, IDC_SHA);
  173.             else if (AlgidSign == CALG_MD5)
  174.                 CheckRadioButton(hDlg, IDC_MD4, IDC_SHA, IDC_MD5);
  175.             else
  176.                 CheckRadioButton(hDlg, IDC_MD4, IDC_SHA, IDC_MD4);
  177.             return FALSE;
  178.             
  179.         case WM_COMMAND:
  180.             switch(LOWORD(wParam)) {
  181.                 case IDC_MD4:
  182.                     AlgidSign = CALG_MD4;
  183.                     return TRUE;
  184.  
  185.                 case IDC_MD5:
  186.                     AlgidSign = CALG_MD5;
  187.                     return TRUE;
  188.  
  189.                 case IDC_SHA:
  190.                     AlgidSign = CALG_SHA;
  191.                     return TRUE;
  192.  
  193.                 case IDOK:
  194.                     EndDialog(hDlg, TRUE);
  195.                     return TRUE;
  196.                     
  197.                 case IDCANCEL:
  198.                     EndDialog(hDlg, FALSE);
  199.                     return TRUE;
  200.                     
  201.                 default:
  202.                     return FALSE;
  203.             }
  204.             break;
  205.     }
  206.     return FALSE;
  207. }
  208.  
  209. /************************************************************************\
  210. * GetPass()
  211. *
  212. * input:
  213. * hWnd - HWND of caller
  214. *
  215. * purpose:
  216. * Creates a dialog box prompting the user to enter a password.
  217. *
  218. * returns:
  219. * TRUE if successful
  220. * FALSE if unsuccessful
  221. \************************************************************************/
  222.  
  223. BOOL GetPass(HWND hWnd) {
  224.     INT bRet = 0;
  225.  
  226.     do {
  227.         if (bRet == -1)
  228.             break;
  229.  
  230.         // Prompt the user to enter a password.
  231.  
  232.         bRet = DialogBox(ghModule, TEXT("PASSWORD"), hWnd, EnterPass);
  233.     } while (!bRet || !lstrcmp(sPass, TEXT("\0")) || !lstrcmp(sPass, TEXT("")));
  234.  
  235.     AlgidEncrypt = 0;
  236.     
  237.     return TRUE;
  238. }
  239.  
  240. /************************************************************************\
  241. * GetfnKey()
  242. *
  243. * purpose:
  244. * Retrieves fnKey from the registry.
  245. * fnKey is used to encrypt and decrypt filenames.
  246. * If fnKey does not exist in the registry, GetfnKey creates it.
  247. *
  248. * returns
  249. * a valid key if successful
  250. * 0 if unsuccessful.
  251. \************************************************************************/
  252.  
  253. HCRYPTKEY GetfnKey(HWND hWnd) {
  254.     BYTE         pbFileKeyBlob[BUF_SIZE];
  255.     DWORD         dwFileBlobLen = BUF_SIZE;
  256.     LONG        lRv;
  257.     HKEY        hKey;
  258.     DWORD        dwType;
  259.     DWORD        dwSize;
  260.     DWORD        dwDisposition;
  261.     HCRYPTKEY    phEncryptPubKey;
  262.     HCRYPTKEY    hfnKey;
  263.  
  264.     if (!GetEncryptPublicKey(hWnd, &phEncryptPubKey)) {
  265.         ErrorMsg(TEXT("GetfnKey: GetEncryptPublicKey failed."));
  266.         return (HCRYPTKEY)0;
  267.     }
  268.  
  269. #ifdef WIN95
  270.  
  271.     lRv = RegOpenKeyEx(HKEY_CURRENT_USER, 
  272.                         TEXT("SOFTWARE\\Microsoft\\Cryptfiler.ini"), 
  273.                        0, 
  274.                        KEY_ALL_ACCESS,
  275.                        &hKey);
  276.  
  277. #else
  278.  
  279.     lRv = RegOpenKeyEx(HKEY_CURRENT_USER, 
  280.                         TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\Cryptfiler.ini"), 
  281.                        0, 
  282.                        KEY_ALL_ACCESS,
  283.                        &hKey);
  284. #endif
  285.  
  286.     if (lRv != ERROR_SUCCESS) {
  287.  
  288.         // not in registry; we must create.
  289.  
  290. #ifdef WIN95
  291.  
  292.         lRv = RegCreateKeyEx(HKEY_CURRENT_USER, 
  293.                               TEXT("SOFTWARE\\Microsoft\\Cryptfiler.ini"), 
  294.                              0, 
  295.                              NULL, 
  296.                              REG_OPTION_NON_VOLATILE,
  297.                              KEY_ALL_ACCESS,
  298.                              NULL,
  299.                              &hKey,
  300.                              &dwDisposition);
  301. #else
  302.         lRv = RegCreateKeyEx(HKEY_CURRENT_USER, 
  303.                               TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\Cryptfiler.ini"), 
  304.                              0, 
  305.                              NULL, 
  306.                              REG_OPTION_NON_VOLATILE,
  307.                              KEY_ALL_ACCESS,
  308.                              NULL,
  309.                              &hKey,
  310.                              &dwDisposition);
  311. #endif
  312.     
  313.         if (lRv != ERROR_SUCCESS) {
  314.             ErrorMsg(TEXT("GetfnKey: RegCreateKeyEx failed."));
  315.             return (HCRYPTKEY)0;
  316.         }
  317.  
  318.         if (RCRYPT_FAILED(CryptGenKey(hMe, CALG_RC4, CRYPT_EXPORTABLE, &hfnKey))) {
  319.             ErrorMsg(TEXT("GetfnKey: CryptGenKey failed."));
  320.             return (HCRYPTKEY)0;
  321.         } 
  322.         
  323.         //Export the key so that it can be stored in the registry.
  324.         
  325.         if (RCRYPT_FAILED(CryptExportKey(hfnKey, 
  326.                           phEncryptPubKey, 
  327.                           SIMPLEBLOB, 
  328.                           0, 
  329.                           pbFileKeyBlob, 
  330.                           &dwFileBlobLen))) {
  331.             ErrorMsg(TEXT("GetfnKey: CryptExportKey failed."));
  332.             return (HCRYPTKEY)0;
  333.         }
  334.  
  335.         // Store the key blob in the registry.
  336.         
  337.         if (RegSetValueEx(hKey,
  338.                           TEXT("fnKey"),
  339.                           0,
  340.                           REG_BINARY,
  341.                           pbFileKeyBlob,
  342.                           dwFileBlobLen * sizeof(*pbFileKeyBlob)) != ERROR_SUCCESS) {
  343.                     
  344.             ErrorMsg(TEXT("GetfnKey: RegSetValueEx failed."));
  345.             return (HCRYPTKEY)0;
  346.         }
  347.     }    
  348.     else {
  349.         // in registry. We must extract.
  350.         
  351.         dwType = 0;
  352.         dwFileBlobLen = 0;
  353.         dwSize = BUF_SIZE;
  354.  
  355.         if (RegQueryValueEx(hKey, 
  356.                             TEXT("fnKey"),
  357.                             NULL, 
  358.                             &dwType, 
  359.                             pbFileKeyBlob, 
  360.                             &dwSize) != ERROR_SUCCESS)
  361.         {
  362.             MessageBox(hWnd, TEXT("GetfnKey: RegQueryValueEx failed querrying pbFileKeyBlob."), NULL, MB_OK);
  363.             return (HCRYPTKEY)0;
  364.         };
  365.  
  366.         // Read the key blob from the disk into a Buf.
  367.         
  368.         if (!dwSize || (dwSize > BUF_SIZE)) {
  369.             ErrorMsg(TEXT("GetfnKey: dwSize is not in acceptable range."));
  370.             return FALSE;
  371.         }
  372.         
  373.         // Import the key whose blob is contained in the Buf pbDecryptBlob
  374.  
  375.         dwFileBlobLen = dwSize;
  376.  
  377.         if (RCRYPT_FAILED(CryptImportKey(hMe, 
  378.                           pbFileKeyBlob, 
  379.                           dwFileBlobLen, 
  380.                           0, 
  381.                           0,
  382.                           &hfnKey))) {
  383.  
  384.             MessageBox(hWnd, TEXT("GetfnKey: CryptImportKey failed"), NULL, MB_OK);
  385.             return (HCRYPTKEY)0;
  386.         }
  387.     }
  388.  
  389.     return hfnKey;
  390. }
  391.  
  392. /************************************************************************\
  393. * Logon()
  394. *
  395. * input:
  396. * hWnd - HWND of caller
  397. *
  398. * purpose:
  399. * Creates a dialog box which says "Performing context acquisition."
  400. * Calls CryptAcquireContext.
  401. * Destroys the dialog box
  402. *
  403. * returns:
  404. * TRUE if successful
  405. * FALSE if unsuccessful
  406. \************************************************************************/
  407.  
  408. BOOL Logon(HWND hWnd) {
  409.     HWND            hwndDlg;
  410.     TCHAR            pszName[64];
  411.  
  412.     pszName[0] = TEXT('\0');
  413.     hwndDlg = CreateDialog(ghModule, TEXT("ACQUIRE_CONTEXT"), hWnd, CryptDlgProc);
  414.  
  415.     if (!hwndDlg) {
  416.         ErrorMsg(TEXT("Logon: CreateDialog failed."));
  417.         return FALSE;
  418.     }
  419.  
  420.     if (RCRYPT_FAILED(CryptAcquireContext(&hMe, pszName, MS_DEF_PROV, PROV_RSA_FULL, 0))) {
  421.         if (RCRYPT_FAILED(CryptAcquireContext(&hMe, 
  422.                           pszName, 
  423.                           TEXT(MS_DEF_PROV), 
  424.                           PROV_RSA_FULL, 
  425.                           CRYPT_NEWKEYSET))) {
  426.             EndDialog(hwndDlg, FALSE);
  427.             MessageBox(hWnd, TEXT("Logon: CryptAcquireContext failed."), NULL, MB_OK);
  428.             return FALSE;
  429.         }
  430.     }
  431.  
  432.     EndDialog(hwndDlg, FALSE);
  433.     return TRUE;
  434.  
  435. return FALSE;
  436. }
  437.  
  438. /************************************************************************\
  439. * Logoff()
  440. *
  441. * input:
  442. * hWnd - HWND of caller
  443. *
  444. * purpose:
  445. * Calls CryptReleaseContext.
  446. *
  447. * returns:
  448. * TRUE if successful
  449. * FALSE if unsuccessful
  450. \************************************************************************/
  451.  
  452. BOOL Logoff(HWND hWnd) 
  453. {
  454.     if (hMe) {
  455.         if (RCRYPT_FAILED(CryptReleaseContext(hMe, 0))) {
  456.             ErrorMsg(TEXT("Logoff: CryptReleaseContext failed."));
  457.             return FALSE;
  458.         }
  459.     }
  460.     else {
  461.         ErrorMsg(TEXT("Logoff: hMe is NULL."));
  462.         return FALSE;
  463.     }
  464.  
  465.     return TRUE;
  466. }
  467.  
  468. /************************************************************************\
  469. * GetEncryptPublicKey()
  470. *
  471. * input:
  472. * hWnd - HWND specified by caller
  473. * phEncryptPubKey - address to store key
  474. *
  475. * purpose: calls CryptGetUserKey to obtain the AT_KEYEXCHANGE public
  476. * key.
  477. *
  478. * returns:
  479. * TRUE if successful
  480. * FALSE if unsuccessful
  481. \************************************************************************/
  482.  
  483. BOOL GetEncryptPublicKey(HWND hWnd, HCRYPTKEY *phEncryptPubKey) {
  484.     if (!phEncryptPubKey) {
  485.         ErrorMsg(TEXT("GetEncryptPubKey: phEncryptPubKey is NULL."));
  486.         return FALSE;
  487.     }
  488.     
  489.     if (RCRYPT_FAILED(CryptGetUserKey(hMe, AT_KEYEXCHANGE, phEncryptPubKey))) {
  490.         if (RCRYPT_FAILED(CryptGenKey(hMe, AT_KEYEXCHANGE, 0, phEncryptPubKey))) {
  491.             ErrorMsg(TEXT("GetEncryptPublicKey: CryptGenKey failed."));
  492.             return TRUE;
  493.         }
  494.     }    
  495.     
  496.     return TRUE;
  497. }
  498.  
  499. /************************************************************************\
  500. * GetSignaturePublicKey()
  501. *
  502. * input:
  503. * hWnd - HWND specified by caller
  504. * phSignaturePubKey - address to store key
  505. *
  506. * purpose: calls CryptGetUserKey to obtain the AT_SIGNATURE public
  507. * key.
  508. *
  509. * returns:
  510. * TRUE if successful
  511. * FALSE if unsuccessful
  512. \************************************************************************/
  513.  
  514. BOOL GetSignaturePublicKey(HWND hWnd, HCRYPTKEY *phSignaturePubKey) {
  515.     if (!phSignaturePubKey) {
  516.         ErrorMsg(TEXT("GetSignaturePublicKey: phSignaturePubKey is NULL."));
  517.         return FALSE;
  518.     }
  519.     
  520.     if (RCRYPT_FAILED(CryptGetUserKey(hMe, AT_SIGNATURE, phSignaturePubKey))) {
  521.         if (RCRYPT_FAILED(CryptGenKey(hMe, AT_SIGNATURE, 0, phSignaturePubKey))) {
  522.             ErrorMsg(TEXT("GetSignaturePublicKey: CryptGenKey failed."));
  523.             return FALSE;
  524.         }
  525.     }
  526.     
  527.     return TRUE;
  528. }
  529.  
  530. /************************************************************************\
  531. * MakeHashDirectory()
  532. *
  533. * purpose: 
  534. * Creates the directory \sig on the same drive as the 
  535. * system directory as a hidden directory if
  536. * it doesn't exist and checks the menu item ID_HIDE.
  537. * If it does exist and it is hidden it checks the menu item ID_HIDE.
  538. * If it does exist and it is not hidden it sets the menu item ID_HIDE
  539. * to be unchecked.
  540. *
  541. * returns: 
  542. * TRUE if successful
  543. * FALSE if unsuccessful
  544. \************************************************************************/
  545.  
  546. BOOL MakeHashDirectory(VOID) {
  547.     DWORD dwFileAttributes;
  548.     TCHAR szSigDir[PATH_SIZE];
  549.     
  550.     GetSigDir(szSigDir);
  551.     
  552.     // Does this directory exist?
  553.     
  554.     if (GetFileAttributes(szSigDir) == 0xFFFFFFFF) {
  555.         // Create the directory
  556.         if (!CreateDirectory(szSigDir, NULL)) {
  557.             ErrorMsg(TEXT("MakeHashDirectory: CreateDirectory failed."));
  558.             return FALSE;
  559.         }
  560.         // Make the directory hidden
  561.         if (!SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN)) {
  562.             ErrorMsg(TEXT("Another process is using the \\sig directory."));
  563.             return FALSE;
  564.         }
  565.     }
  566.  
  567.     dwFileAttributes = GetFileAttributes(szSigDir);
  568.  
  569.     // Toggle the "Hide Signatures" menu item appropriately.
  570.     
  571.     if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
  572.           CheckMenuItem(ghMenu, ID_HIDE, MF_CHECKED);
  573.     else
  574.         CheckMenuItem(ghMenu, ID_HIDE, MF_UNCHECKED);
  575.                  
  576.     return TRUE;
  577. }
  578.  
  579. /************************************************************************\
  580. * DeleteHashDirectory()
  581. *
  582. * purpose: 
  583. * Deletes the directory \sig on the same drive as the system directory
  584. * if the \sig directory is empty. This function is called when the
  585. * application terminates.
  586. *
  587. * returns: 
  588. * TRUE if successful
  589. * FALSE if unsuccessful
  590. \************************************************************************/
  591.  
  592. BOOL DeleteHashDirectory(VOID) {
  593.     TCHAR szSigDir[PATH_SIZE];
  594.     TCHAR szFiles[PATH_SIZE];
  595.     WIN32_FIND_DATA FindFileData;
  596.     HANDLE hFindFile;
  597.     
  598.     GetSigDir(szSigDir);
  599.  
  600.     lstrcpy(szFiles, szSigDir);
  601.     lstrcat(szFiles, TEXT("\\*"));
  602.     
  603.     // Does this directory exist?
  604.     
  605.     if (GetFileAttributes(szSigDir) == 0xFFFFFFFF) {
  606.         return TRUE;
  607.     }
  608.  
  609.     hFindFile = FindFirstFile(szFiles, &FindFileData);
  610.  
  611.     FindNextFile(hFindFile, &FindFileData);
  612.  
  613.     if (!FindNextFile(hFindFile, &FindFileData)) {
  614.         FindClose(hFindFile);
  615.         SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL);
  616.         if (!RemoveDirectory(szSigDir)) {
  617.             ErrorMsg(TEXT("DeleteHashDirectory: RemoveDirectory failed."));
  618.             return FALSE;
  619.         }
  620.     }
  621.     else                 
  622.         FindClose(hFindFile);
  623.     
  624.     return TRUE;
  625. }
  626.  
  627. /************************************************************************\
  628. * HideSignatures()
  629. *
  630. * purpose:
  631. * Hides the directory \sig and its contents
  632. *
  633. * returns
  634. * TRUE if successful
  635. * FALSE if unsuccessful
  636. \************************************************************************/
  637.  
  638. BOOL HideSignatures(VOID) {
  639.     WIN32_FIND_DATA FindFileData;
  640.     HANDLE hFindFile;
  641.     TCHAR szFiles[PATH_SIZE];
  642.     TCHAR szFileName[PATH_SIZE];
  643.     TCHAR szSigDir[PATH_SIZE];
  644.  
  645.     GetSigDir(szSigDir);
  646.     lstrcpy(szFiles, szSigDir);
  647.     lstrcat(szFiles, TEXT("\\*"));
  648.  
  649.     // hide the directory.
  650.     
  651.     if (!SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN)) {
  652.         ErrorMsg(TEXT("Another process is using the \\sig directory."));
  653.         return FALSE;
  654.     }
  655.     
  656.     hFindFile = FindFirstFile(szFiles, &FindFileData);
  657.  
  658.     if (hFindFile == INVALID_HANDLE_VALUE) {
  659.         SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL);
  660.         return FALSE;
  661.     }
  662.  
  663.     // Hide all the signature files.
  664.     
  665.     do {
  666.         lstrcpy(szFileName, szSigDir);
  667.         lstrcat(szFileName, TEXT("\\"));
  668.         lstrcat(szFileName, FindFileData.cFileName);
  669.                 
  670.         if (!CFilerIsDirectory(szFileName)) {
  671.             if (!SetFileAttributes(szFileName, FILE_ATTRIBUTE_HIDDEN)) {
  672.                 SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL);
  673.                 FindClose(hFindFile);
  674.                 ErrorMsg(TEXT("Another process is using a signature file."));
  675.                 return FALSE;
  676.             }
  677.         }
  678.     } while (FindNextFile(hFindFile, &FindFileData) 
  679.                     || GetLastError() != ERROR_NO_MORE_FILES);
  680.  
  681.     FindClose(hFindFile);
  682.  
  683.     return TRUE;
  684. }    
  685.  
  686. /************************************************************************\
  687. * ShowSignatures()
  688. *
  689. * purpose:
  690. * "unhides" the directory \sig and its contents
  691. *
  692. * returns
  693. * TRUE if successful
  694. * FALSE if unsuccessful
  695. \************************************************************************/
  696.  
  697. BOOL ShowSignatures(VOID) {
  698.     WIN32_FIND_DATA FindFileData;
  699.     HANDLE hFindFile;
  700.     TCHAR szFiles[PATH_SIZE];
  701.     TCHAR szFileName[PATH_SIZE];
  702.     TCHAR szSigDir[PATH_SIZE];
  703.  
  704.     GetSigDir(szSigDir);
  705.     lstrcpy(szFiles, szSigDir);
  706.     lstrcat(szFiles, TEXT("\\*"));
  707.  
  708.     // unhide the directory
  709.     
  710.     if (!SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL)) {
  711.         ErrorMsg(TEXT("Another process is using the \\sig directory."));
  712.         return FALSE;
  713.     }
  714.     
  715.     hFindFile = FindFirstFile(szFiles, &FindFileData);
  716.  
  717.     if (hFindFile == INVALID_HANDLE_VALUE) {
  718.         SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN);
  719.         return FALSE;
  720.     }
  721.  
  722.     // unhide all the signature files.
  723.     
  724.     do {
  725.         lstrcpy(szFileName, szSigDir);
  726.         lstrcat(szFileName, TEXT("\\"));
  727.         lstrcat(szFileName, FindFileData.cFileName);
  728.                 
  729.         if (!CFilerIsDirectory(szFileName)) {
  730.             if (!SetFileAttributes(szFileName, FILE_ATTRIBUTE_NORMAL)) {
  731.                 SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN);
  732.                 FindClose(hFindFile);
  733.                 ErrorMsg(TEXT("Another process is using a signature file."));
  734.                 return FALSE;
  735.             }
  736.         }
  737.     } while (FindNextFile(hFindFile, &FindFileData) 
  738.                     || GetLastError() != ERROR_NO_MORE_FILES);
  739.  
  740.     FindClose(hFindFile);
  741.  
  742.     return TRUE;
  743. }    
  744.  
  745. /************************************************************************\
  746. * c2r64()
  747. *
  748. * input:
  749. * i - integer value to be converted to a radix64 character
  750. * c - address where character is to be stored
  751. *
  752. * purpose:
  753. * converts an integer between 0 and 63 to a character.
  754. * 0-25 -> A-Z
  755. * 26 - 51 -> a-z
  756. * 52 - 61 -> 0-9
  757. * 62 -> +
  758. * 63 -> _
  759. *
  760. * returns:
  761. * TRUE if successful
  762. * FALSE if unsuccessful
  763. \************************************************************************/
  764.  
  765. BOOL c2r64(INT i, LPTSTR c) {
  766.     if (!c) {
  767.         ErrorMsg(TEXT("c2r64: c is NULL."));
  768.         return FALSE;
  769.     }
  770.     
  771.     if (0 <= i && i <= 25)
  772.         *c = TEXT('A') + i;
  773.     else if (26 <= i && i <= 51)
  774.         *c = TEXT('a') + i - 26;
  775.     else if (52 <= i && i <= 61)
  776.         *c = TEXT('0') + i - 52;
  777.     else if (i == 62)
  778.         *c = TEXT('+');
  779.     else if (i == 63)
  780.         *c = TEXT('_');
  781.     else {
  782.         ErrorMsg(TEXT("c2r64: c is not between 0 and 63."));
  783.         return FALSE;
  784.     }
  785.     return TRUE;
  786. }
  787.  
  788. /************************************************************************\
  789. * SHAtoRadix64 takes as input a SHA_SIZE-byte hash of the full 
  790. * pathname of a file. It produces a 27-byte "Radix64" 
  791. * representation of the hash, where each byte in the
  792. * "Radix64" representation is between 0 and 2^6.
  793. * It pretends that the SHZ_SIZE + 1st input byte is NULL.
  794. \************************************************************************/
  795.  
  796. BOOL SHAtoRadix64(LPBYTE pbPathHash, LPTSTR szFileName) {
  797.     INT i, j;
  798.     TCHAR c1 = 0, c2 = 0, c3 = 0, c4 = 0;
  799.     
  800.     if (!pbPathHash) {
  801.         ErrorMsg(TEXT("SHAtoRadix64: pbPathHash is NULL."));
  802.         return FALSE;
  803.     }
  804.  
  805.     if (!szFileName) {
  806.         ErrorMsg(TEXT("SHAtoRadix64: szFileName is NULL."));
  807.         return FALSE;
  808.     }
  809.     
  810.     for (i = 0, j = 0; i < 18 && j < 24; i += 3, j += 4) {
  811.         c1 = c1 | (((pbPathHash[i + 0] >> 7) & 1) << 5);
  812.         c1 = c1 | (((pbPathHash[i + 0] >> 6) & 1) << 4);
  813.         c1 = c1 | (((pbPathHash[i + 0] >> 5) & 1) << 3);
  814.         c1 = c1 | (((pbPathHash[i + 0] >> 4) & 1) << 2);
  815.         c1 = c1 | (((pbPathHash[i + 0] >> 3) & 1) << 1);
  816.         c1 = c1 | (((pbPathHash[i + 0] >> 2) & 1) << 0);
  817.     
  818.         c2 = c2 | (((pbPathHash[i + 0] >> 1) & 1) << 5);
  819.         c2 = c2 | (((pbPathHash[i + 0] >> 0) & 1) << 4);
  820.         c2 = c2 | (((pbPathHash[i + 1] >> 7) & 1) << 3);
  821.         c2 = c2 | (((pbPathHash[i + 1] >> 6) & 1) << 2);
  822.         c2 = c2 | (((pbPathHash[i + 1] >> 5) & 1) << 1);
  823.         c2 = c2 | (((pbPathHash[i + 1] >> 4) & 1) << 0);
  824.  
  825.         c3 = c3 | (((pbPathHash[i + 1] >> 3) & 1) << 5);
  826.         c3 = c3 | (((pbPathHash[i + 1] >> 2) & 1) << 4);
  827.         c3 = c3 | (((pbPathHash[i + 1] >> 1) & 1) << 3);
  828.         c3 = c3 | (((pbPathHash[i + 1] >> 0) & 1) << 2);
  829.         c3 = c3 | (((pbPathHash[i + 2] >> 7) & 1) << 1);
  830.         c3 = c3 | (((pbPathHash[i + 2] >> 6) & 1) << 0);
  831.  
  832.         c4 = c4 | (((pbPathHash[i + 2] >> 5) & 1) << 5);
  833.         c4 = c4 | (((pbPathHash[i + 2] >> 4) & 1) << 4);
  834.         c4 = c4 | (((pbPathHash[i + 2] >> 3) & 1) << 3);
  835.         c4 = c4 | (((pbPathHash[i + 2] >> 2) & 1) << 2);
  836.         c4 = c4 | (((pbPathHash[i + 2] >> 1) & 1) << 1);
  837.         c4 = c4 | (((pbPathHash[i + 2] >> 0) & 1) << 0);
  838.  
  839.         c2r64(c1, &(szFileName[j + 0]));
  840.         c2r64(c2, &(szFileName[j + 1]));
  841.         c2r64(c3, &(szFileName[j + 2]));
  842.         c2r64(c4, &(szFileName[j + 3]));
  843.  
  844.         c1 = 0; c2 = 0; c3 = 0; c4 = 0;
  845.     }
  846.     
  847.     c1 = c1 | (((pbPathHash[18] >> 7) & 1) << 5);
  848.     c1 = c1 | (((pbPathHash[18] >> 6) & 1) << 4);
  849.     c1 = c1 | (((pbPathHash[18] >> 5) & 1) << 3);
  850.     c1 = c1 | (((pbPathHash[18] >> 4) & 1) << 2);
  851.     c1 = c1 | (((pbPathHash[18] >> 3) & 1) << 1);
  852.     c1 = c1 | (((pbPathHash[18] >> 2) & 1) << 0);
  853.         
  854.     c2 = c2 | (((pbPathHash[18] >> 1) & 1) << 5);
  855.     c2 = c2 | (((pbPathHash[18] >> 0) & 1) << 4);
  856.     c2 = c2 | (((pbPathHash[19] >> 7) & 1) << 3);
  857.     c2 = c2 | (((pbPathHash[19] >> 6) & 1) << 2);
  858.     c2 = c2 | (((pbPathHash[19] >> 5) & 1) << 1);
  859.     c2 = c2 | (((pbPathHash[19] >> 4) & 1) << 0);
  860.  
  861.     c3 = c3 | (((pbPathHash[19] >> 3) & 1) << 5);
  862.     c3 = c3 | (((pbPathHash[19] >> 2) & 1) << 4);
  863.     c3 = c3 | (((pbPathHash[19] >> 1) & 1) << 3);
  864.     c3 = c3 | (((pbPathHash[19] >> 0) & 1) << 2);
  865.     c3 = c3 | (((0              >> 7) & 1) << 1);
  866.     c3 = c3 | (((0              >> 6) & 1) << 0);
  867.  
  868.     c2r64(c1, &(szFileName[24]));
  869.     c2r64(c2, &(szFileName[25]));
  870.     c2r64(c3, &(szFileName[26]));
  871.  
  872.     szFileName[27] = TEXT('\0');
  873.  
  874.     return TRUE;
  875. }
  876.  
  877. /************************************************************************\
  878. * Exit1 and Exit2 close handles, etc. for CFILEREncryptFile,
  879. * CFILERDecryptFile, SignFile, and VerifyFile.
  880. \************************************************************************/
  881.  
  882. void Exit1(HWND hWnd, LPTSTR message, HANDLE hFile1, HANDLE hFile2) {
  883.     CloseHandle(hFile1);
  884.     CloseHandle(hFile2);
  885.     MessageBox(hWnd, message, NULL, MB_OK);
  886.     return;
  887. }
  888.  
  889. void Exit2(HWND hWnd, LPTSTR message, HWND hwndDlg, HANDLE hFile1, HANDLE hFile2) {
  890.     CloseHandle(hFile1);
  891.     CloseHandle(hFile2);
  892.     EndDialog(hwndDlg, FALSE);
  893.     MessageBox(hWnd, message, NULL, MB_OK);
  894.     return;
  895. }
  896.  
  897.  
  898. /************************************************************************\
  899. * CFILEREncryptFile()
  900. *
  901. * input:
  902. * hWnd - HWND specified by caller
  903. * szFileName - buffer containing full pathname of file to encrypt
  904. *
  905. * Opens a file to encrypt and saves the file in
  906. * encrypted form in the same path as the plaintext file.
  907. * It is saved as a hidden file with a random filename. Its filename is
  908. * encrypted with fnKey and is stored in the header of the file.
  909. * Deletes the plaintext file.
  910. *
  911. * returns:
  912. * TRUE if successful
  913. * FALSE if unsuccessful
  914. \************************************************************************/
  915.  
  916. BOOL CFILEREncryptFile(HWND hWnd, LPTSTR szFileName) {
  917.     TCHAR                    szEncryptedFileName[PATH_SIZE];    
  918.     TCHAR                    szFileName2[PATH_SIZE];
  919.     TCHAR                    szRandomName[PATH_SIZE];
  920.     TCHAR                    szDirBuf[PATH_SIZE];
  921.     BYTE                    pEncryptBuf[2 * BUF_SIZE];
  922.     DWORD                    dwNumBytesRead = BUF_SIZE;
  923.     DWORD                    dwNumBytesWritten;
  924.     DWORD                    dwEncryptLen = BUF_SIZE;
  925.     HWND                    hwndDlg;
  926.     HCRYPTKEY                hFileKey;
  927.     HCRYPTKEY                phEncryptPubKey;
  928.     HCRYPTKEY                hfnKey;
  929.     BYTE                     pbFileKeyBlob[BUF_SIZE];
  930.     DWORD                     dwFileBlobLen = BUF_SIZE;
  931.     HANDLE                    hFileRead = INVALID_HANDLE_VALUE;
  932.     HANDLE                    hFileWrite = INVALID_HANDLE_VALUE;
  933.     HCRYPTHASH                hHash;
  934.     DWORD                    dwBufLen = HEADER_SIZE * sizeof(TCHAR);
  935.     DWORD                    dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  936.  
  937.     if (!szFileName) {
  938.         MessageBox(hWnd, TEXT("CFILEREncryptFile: szFileName is NULL."), NULL, MB_OK);
  939.         return FALSE;
  940.     }
  941.     
  942.     hfnKey = GetfnKey(hWnd);
  943.     
  944.     if (!hfnKey) {
  945.         MessageBox(hWnd, TEXT("CFILEREncryptFile: GetfnKey failed."), NULL, MB_OK);
  946.         return FALSE;
  947.     }
  948.     
  949.     SeparatePathName2(szFileName, szDirBuf, szEncryptedFileName);
  950.     
  951.     GetEncryptPublicKey(hWnd, &phEncryptPubKey);
  952.     GenRandomName(szRandomName);
  953.     
  954.     // Generate a key to encrypt this file only if the user
  955.     // selected the password option
  956.  
  957.     if (!AlgidEncrypt) {
  958.         if (RCRYPT_FAILED(CryptCreateHash(hMe, CALG_MD4, 0, 0, &hHash))) {
  959.             MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptCreateHash failed."), NULL, MB_OK);
  960.             return FALSE;
  961.         }
  962.  
  963.         if (RCRYPT_FAILED(CryptHashData(hHash, (LPBYTE)sPass, lstrlen(sPass), 0))) {
  964.             MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptHashData failed."), NULL, MB_OK);
  965.             return FALSE;
  966.         }
  967.  
  968.         if (RCRYPT_FAILED(CryptDeriveKey(hMe, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hFileKey))) {
  969.             MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptDeriveKey failed."), NULL, MB_OK);
  970.             return FALSE;
  971.         }
  972.     
  973.         CryptDestroyHash(hHash);
  974.     }
  975.     // Generate a key to encrypt this file only (not derived from password).
  976.     else if (RCRYPT_FAILED(CryptGenKey(hMe, AlgidEncrypt, CRYPT_EXPORTABLE, &hFileKey))) {
  977.         MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptGenKey failed."), NULL, MB_OK);
  978.         return FALSE;
  979.     } 
  980.  
  981.     dwFileBlobLen = MAXBLOBLEN;
  982.  
  983.     //Export the key so that it can be stored on the disk.
  984.  
  985.     if (RCRYPT_FAILED(CryptExportKey(hFileKey, 
  986.                       phEncryptPubKey, 
  987.                       SIMPLEBLOB, 
  988.                       0, 
  989.                       pbFileKeyBlob, 
  990.                       &dwFileBlobLen))) {
  991.         MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptExportKey failed."), NULL, MB_OK);
  992.         return FALSE;
  993.     }
  994.  
  995.        if (!AlgidEncrypt)
  996.            dwFileBlobLen = 0;
  997.            
  998.        // Open a file to encrypt
  999.     
  1000.     hFileRead = CreateFile(szFileName, 
  1001.                            GENERIC_READ, 
  1002.                            0, 
  1003.                            0, 
  1004.                            OPEN_EXISTING, 
  1005.                            FILE_ATTRIBUTE_READONLY, 
  1006.                            0);
  1007.  
  1008.     if (hFileRead == INVALID_HANDLE_VALUE) {
  1009.         MessageBox(hWnd, TEXT("CFILEREncryptFile: CreateFile failed."), NULL, MB_OK);
  1010.         return FALSE;
  1011.     }
  1012.           
  1013.     lstrcpy(szFileName2, szDirBuf);
  1014.     lstrcat(szFileName2, TEXT("\\"));
  1015.     lstrcat(szFileName2, szRandomName); 
  1016.     
  1017.     // Create a hidden .CRP file with a random filename.
  1018.     
  1019.     hFileWrite = CreateFile(szFileName2, 
  1020.                             GENERIC_READ | GENERIC_WRITE, 
  1021.                             0, 
  1022.                             0, 
  1023.                             CREATE_NEW, 
  1024.                             FILE_ATTRIBUTE_HIDDEN, 
  1025.                             0);
  1026.     
  1027.     if (hFileWrite == INVALID_HANDLE_VALUE) {
  1028.         MessageBox(hWnd, TEXT("Cannot write to media."), NULL, MB_OK);
  1029.         CloseHandle(hFileRead);
  1030.         return FALSE;
  1031.     
  1032.     }
  1033.     
  1034.     // Tell the user that the program is busy encrypting data
  1035.     hwndDlg = CreateDialog(ghModule, TEXT("ENCRYPTING"), hWnd, CryptDlgProc);
  1036.  
  1037.     if (!hwndDlg) {
  1038.         Exit2(hWnd, TEXT("CFILEREncryptFile: CreateDialog failed."), hwndDlg, hFileRead, hFileWrite);
  1039.         DeleteFile(szFileName2);
  1040.         return FALSE;
  1041.     }
  1042.     
  1043.     if (RCRYPT_FAILED(CryptEncrypt(hfnKey, 0, TRUE, 0, (LPBYTE)szEncryptedFileName, &dwDataLen, dwBufLen))) {
  1044.         Exit2(hWnd, TEXT("CFILEREncryptFile: CryptEncrypt failed."), hwndDlg, hFileRead, hFileWrite);
  1045.         DeleteFile(szFileName2);
  1046.         return FALSE;
  1047.     }    
  1048.  
  1049.     // Write the original file's encrypted name to disk.
  1050.     
  1051.     if (RCRYPT_FAILED(WriteFile(hFileWrite, 
  1052.                       szEncryptedFileName, 
  1053.                       HEADER_SIZE * sizeof(*szEncryptedFileName), 
  1054.                       &dwNumBytesWritten, 
  1055.                       0))) {
  1056.         Exit2(hWnd, TEXT("CFILEREncryptFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  1057.         DeleteFile(szFileName2);
  1058.         return FALSE;
  1059.     }
  1060.  
  1061.     // Write the key blob length to disk.    
  1062.     
  1063.     if (!WriteFile(hFileWrite, &dwFileBlobLen, sizeof(dwFileBlobLen), &dwNumBytesWritten, 0)) {
  1064.         Exit2(hWnd, TEXT("CFILEREncryptFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  1065.         DeleteFile(szFileName2);
  1066.         return FALSE;
  1067.     }
  1068.  
  1069.     // Write the key blob to disk.
  1070.     
  1071.     if (dwFileBlobLen && !WriteFile(hFileWrite, 
  1072.                                     pbFileKeyBlob, 
  1073.                                     dwFileBlobLen, 
  1074.                                     &dwNumBytesWritten, 
  1075.                                     0)) {
  1076.         Exit2(hWnd, TEXT("CFILEREncryptFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  1077.         DeleteFile(szFileName2);
  1078.         return FALSE;
  1079.     }
  1080.  
  1081.     // Encrypt the file by reading small amounts
  1082.     // of data from the disk, encrypting those Bufs, and saving the
  1083.     // encrypted Bufs to disk. The loop terminates as soon as there is
  1084.     // not enough data left on the disk to read a full Buf.
  1085.  
  1086.     for ( ; ; ) {
  1087.  
  1088.         if (!ReadFile(hFileRead, pEncryptBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1089.             Exit2(hWnd, 
  1090.                     TEXT("CFILEREncryptFile: ReadFile failed."),
  1091.                     hwndDlg, 
  1092.                     hFileRead, 
  1093.                     hFileWrite);
  1094.             DeleteFile(szFileName2);
  1095.             return FALSE;
  1096.         }
  1097.         
  1098.         if (dwNumBytesRead != BUF_SIZE)
  1099.             break;
  1100.             
  1101.         if (RCRYPT_FAILED(CryptEncrypt(hFileKey, 0, FALSE, 0, pEncryptBuf, &dwEncryptLen, BUF_SIZE))) {
  1102.             Exit2(hWnd, 
  1103.                     TEXT("CFILEREncryptFile: CryptEncrypt failed."),
  1104.                     hwndDlg, 
  1105.                     hFileRead, 
  1106.                     hFileWrite);
  1107.             DeleteFile(szFileName2);
  1108.             return FALSE;
  1109.         }
  1110.  
  1111.         if (!WriteFile(hFileWrite, pEncryptBuf, dwEncryptLen, &dwNumBytesWritten, 0)) {
  1112.             Exit2(hWnd, 
  1113.                     TEXT("CFILEREncryptFile: WriteFile failed."),
  1114.                     hwndDlg, 
  1115.                     hFileRead, 
  1116.                     hFileWrite);
  1117.             DeleteFile(szFileName2);
  1118.             return FALSE;
  1119.         }
  1120.  
  1121.         dwEncryptLen = BUF_SIZE;
  1122.     }
  1123.  
  1124.     // Encrypt the last block of data.
  1125.  
  1126.     if (0 < dwNumBytesRead && dwNumBytesRead < BUF_SIZE) {
  1127.         dwEncryptLen = dwNumBytesRead;
  1128.  
  1129.         if (RCRYPT_FAILED(CryptEncrypt(hFileKey, 0, TRUE, 0, pEncryptBuf, &dwEncryptLen, BUF_SIZE))) {
  1130.             Exit2(hWnd, TEXT("CryptEncrypt failed."), hwndDlg, hFileRead, hFileWrite);
  1131.             DeleteFile(szFileName2);
  1132.             return FALSE;
  1133.         }
  1134.  
  1135.         if (!WriteFile(hFileWrite, pEncryptBuf, dwEncryptLen, &dwNumBytesWritten, 0)) {
  1136.             Exit2(hWnd, TEXT("WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  1137.             DeleteFile(szFileName2);
  1138.             return FALSE;
  1139.         }
  1140.     }
  1141.  
  1142.     if (RCRYPT_FAILED(CryptDestroyKey(hFileKey))) {
  1143.         Exit2(hWnd, TEXT("CryptDestroyKey failed."), hwndDlg, hFileRead,hFileWrite);
  1144.         DeleteFile(szFileName2);
  1145.         return FALSE;
  1146.     }
  1147.  
  1148.     CloseHandle(hFileRead);
  1149.     
  1150.     if (!DeleteFile(szFileName)) {
  1151.         EndDialog(hwndDlg, FALSE);
  1152.         MessageBox(hWnd, TEXT("File cannot be deleted: It is either in use by another process, or it is a system file."), NULL, MB_OK);
  1153.         CloseHandle(hFileWrite);
  1154.         DeleteFile(szFileName2);
  1155.         return FALSE;
  1156.     }
  1157.     
  1158.     EndDialog(hwndDlg, FALSE);
  1159.     CloseHandle(hFileWrite);
  1160.     SetFileAttributes(szFileName2, FILE_ATTRIBUTE_HIDDEN);
  1161.     
  1162.     return TRUE;
  1163. }
  1164.  
  1165. /************************************************************************\
  1166. * CFILERDecryptFile()
  1167. *
  1168. * input:
  1169. * hWnd - HWND specified by caller
  1170. * szFileName - buffer containing full pathname of file to decrypt.
  1171. *
  1172. * purpose:
  1173. * decrypts the file specified by szFileName and stores the file in
  1174. * the same directory. Deletes the encrypted file.
  1175. *
  1176. * returns:
  1177. * TRUE if successful
  1178. * FALSE if unsuccessful
  1179. \************************************************************************/
  1180.  
  1181. BOOL CFILERDecryptFile(HWND hWnd, LPTSTR szFileName)
  1182. {
  1183.     TCHAR                    szFileName2[PATH_SIZE];
  1184.     TCHAR                    szDecryptedFileName[PATH_SIZE];
  1185.     TCHAR                    szFile[PATH_SIZE];
  1186.     BYTE                    pDecryptBuf[2 * BUF_SIZE];
  1187.     DWORD                    dwNumBytesRead;
  1188.     DWORD                    dwNumBytesWritten;
  1189.     DWORD                    dwDecryptDataLen = BUF_SIZE;
  1190.     HCRYPTKEY                hFileKey;
  1191.     HCRYPTKEY                phEncryptPubKey;
  1192.     BYTE                     pbDecryptBlob[BUF_SIZE];
  1193.     DWORD                     dwDecryptBlobLen;            
  1194.     HWND                    hwndDlg;
  1195.     HANDLE                    hFileRead;
  1196.     HANDLE                    hFileWrite = INVALID_HANDLE_VALUE;
  1197.     HCRYPTHASH                hHash;
  1198.     DWORD                    dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  1199. //    BYTE                    pHashData[BUF_SIZE];
  1200.     DWORD                    HashDataLen;
  1201.  
  1202.     if (!szFileName) {
  1203.         MessageBox(hWnd, TEXT("CFILERDecryptFile: szFileName is NULL."), NULL, MB_OK);
  1204.         return FALSE;
  1205.     }
  1206.     
  1207.     GetEncryptPublicKey(hWnd, &phEncryptPubKey);
  1208.     
  1209.     GetDecryptedFileName(hWnd, 
  1210.                          szFileName, 
  1211.                          szDecryptedFileName, 
  1212.                          &hFileRead);
  1213.  
  1214.     // Read the key blob length from the disk.    
  1215.     
  1216.     if (!ReadFile(hFileRead, &dwDecryptBlobLen, sizeof(dwDecryptBlobLen), &dwNumBytesRead, 0)) {
  1217.         MessageBox(hWnd, TEXT("CFILERDecryptFile: ReadFile failed."), NULL, MB_OK);
  1218.         CloseHandle(hFileRead);
  1219.         return FALSE;
  1220.     }
  1221.  
  1222.     // Read the key blob from the disk into a Buf.
  1223.     
  1224.     if (dwDecryptBlobLen && !ReadFile(hFileRead, 
  1225.                                       pbDecryptBlob, 
  1226.                                       dwDecryptBlobLen, 
  1227.                                       &dwNumBytesRead, 
  1228.                                       0)) {
  1229.         MessageBox(hWnd, TEXT("CFILERDecryptFile: ReadFile failed."), NULL, MB_OK);
  1230.         CloseHandle(hFileRead);
  1231.         return FALSE;
  1232.     } 
  1233.  
  1234.     // Import the key whose blob is contained in the Buf pbDecryptBlob
  1235.     
  1236.     if (dwDecryptBlobLen && !CryptImportKey(hMe, 
  1237.                                             pbDecryptBlob, 
  1238.                                             dwDecryptBlobLen, 
  1239.                                             0, 
  1240.                                             0, 
  1241.                                             &hFileKey)) {
  1242.         MessageBox(hWnd, TEXT("CFILERDecryptFile: CryptImportKey failed."), NULL, MB_OK);
  1243.         CloseHandle(hFileRead);
  1244.         return FALSE;
  1245.     }
  1246.  
  1247.     SeparatePathName(szFileName, szFileName2, szFile);
  1248.     
  1249.     lstrcat(szFileName2, TEXT("\\"));
  1250.     lstrcat(szFileName2, szDecryptedFileName);
  1251.     
  1252.     // Generate a key to decrypt this file if the user
  1253.     // selected the password option
  1254.  
  1255.     if (!dwDecryptBlobLen) {
  1256.         lstrcpy(szPassName, szFileName2);
  1257.             
  1258.         if (!GetPass(hWnd)) {
  1259.             MessageBox(hWnd, TEXT("CFILERDecryptFile: GetPass failed."), NULL, MB_OK);
  1260.             CloseHandle(hFileRead);
  1261.             return FALSE;
  1262.         }
  1263.  
  1264.         lstrcpy(szPassName, TEXT("\0"));
  1265.         
  1266.         if (RCRYPT_FAILED(CryptCreateHash(hMe, CALG_MD4, 0, 0, &hHash))) {
  1267.             MessageBox(hWnd, TEXT("CFILERDecryptFile: CryptCreateHash failed."), NULL, MB_OK);
  1268.             CloseHandle(hFileRead);
  1269.             return FALSE;
  1270.         }
  1271.  
  1272.         if (RCRYPT_FAILED(CryptHashData(hHash, (LPBYTE)sPass, lstrlen(sPass), 0))) {
  1273.             MessageBox(hWnd, TEXT("DecrypttFile: CryptHashData failed."), NULL, MB_OK);
  1274.             return FALSE;
  1275.         }
  1276.  
  1277.         HashDataLen = BUF_SIZE;
  1278.  
  1279.         if (RCRYPT_FAILED(CryptDeriveKey(hMe, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hFileKey))) {
  1280.             MessageBox(hWnd, TEXT("CFILERDecryptFile: CryptDeriveKey failed."), NULL, MB_OK);
  1281.             CloseHandle(hFileRead);
  1282.             return FALSE;
  1283.         }
  1284.  
  1285.         CryptDestroyHash(hHash);
  1286.         
  1287.         dwDecryptBlobLen = 0;
  1288.     }
  1289.     
  1290.     // Recreate the plaintext file
  1291.     
  1292.     hFileWrite = CreateFile(szFileName2, 
  1293.                             GENERIC_READ | GENERIC_WRITE, 
  1294.                             0, 
  1295.                             0, 
  1296.                             CREATE_ALWAYS, 
  1297.                             FILE_ATTRIBUTE_NORMAL, 
  1298.                             0);
  1299.  
  1300.     if (hFileWrite == INVALID_HANDLE_VALUE) {
  1301.         if (GetLastError() == ERROR_FILENAME_EXCED_RANGE) {
  1302.             TCHAR szEmergencyName[PATH_SIZE];
  1303.             TCHAR szEmergencyRandomName[PATH_SIZE];
  1304.             TCHAR szDir1[PATH_SIZE];
  1305.             TCHAR szFile1[PATH_SIZE];
  1306.             SeparatePathName(szFileName, szDir1, szFile1);
  1307.             GenRandomName2(szEmergencyRandomName);
  1308.             lstrcpy(szEmergencyName, szDir1);
  1309.             lstrcat(szEmergencyName, TEXT("\\recovered"));
  1310.             lstrcat(szEmergencyName, szEmergencyRandomName);
  1311.             hFileWrite = CreateFile(szEmergencyName, GENERIC_READ | GENERIC_WRITE,
  1312.                                         0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  1313.             if (hFileWrite == INVALID_HANDLE_VALUE) {
  1314.                 ErrorMsg(TEXT("Could not recover file."));
  1315.                 return FALSE;
  1316.             }
  1317.         }
  1318.         else {
  1319.             MessageBox(hWnd, TEXT("CFILERDecryptFile: CreateFile failed."), NULL, MB_OK);
  1320.             CloseHandle(hFileRead);
  1321.             return FALSE;
  1322.         }
  1323.     }
  1324.     
  1325.     // Create a dialog box to inform the user that the program is busy decrypting data.
  1326.  
  1327.     hwndDlg = CreateDialog(ghModule, TEXT("DECRYPTING"), hWnd, CryptDlgProc);
  1328.  
  1329.     if (!hwndDlg) {
  1330.         Exit2(hWnd, TEXT("CFILERDecryptFile: CreateDialog failed."), hwndDlg, hFileRead, hFileWrite);
  1331.         DeleteFile(szFileName2);
  1332.         return FALSE;
  1333.     }
  1334.  
  1335.     // The following for loop decrypts the data in units of BUF_SIZE
  1336.     // at a time and stores the decrypted data into the file hFileWrite.
  1337.     // The loop terminates when fewer than BUF_SIZE have been read.
  1338.  
  1339.     for ( ; ; ) {
  1340.         if (!ReadFile(hFileRead, pDecryptBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1341.             Exit2(hWnd, 
  1342.                     TEXT("CFILERDecryptFile: ReadFile failed."),
  1343.                     hwndDlg, 
  1344.                     hFileRead, 
  1345.                     hFileWrite);
  1346.             DeleteFile(szFileName2);
  1347.             return FALSE;
  1348.         }
  1349.  
  1350.         if (dwNumBytesRead != BUF_SIZE)
  1351.             break;
  1352.         
  1353.         if (RCRYPT_FAILED(CryptDecrypt(hFileKey, 0, FALSE, 0, pDecryptBuf, &dwDecryptDataLen))) {
  1354.             Exit2(hWnd, 
  1355.                     TEXT("CFILERDecryptFile: CryptDecrypt failed."),
  1356.                     hwndDlg, 
  1357.                     hFileRead, 
  1358.                     hFileWrite);
  1359.             DeleteFile(szFileName2);
  1360.             return FALSE;
  1361.         }
  1362.  
  1363.         if (!WriteFile(hFileWrite, pDecryptBuf, dwDecryptDataLen, &dwNumBytesWritten, 0)) {
  1364.             Exit2(hWnd, 
  1365.                     TEXT("CFILERDecryptFile: WriteFile failed."),
  1366.                     hwndDlg, 
  1367.                     hFileRead, 
  1368.                     hFileWrite);
  1369.             DeleteFile(szFileName2);
  1370.             return FALSE;
  1371.         }
  1372.  
  1373.         dwDecryptDataLen = BUF_SIZE;
  1374.     }
  1375.  
  1376.     // Decrypt the final block of data.
  1377.     
  1378.     if (0 < dwNumBytesRead && dwNumBytesRead < BUF_SIZE) {
  1379.         dwDecryptDataLen = dwNumBytesRead;
  1380.         
  1381.         if (RCRYPT_FAILED(CryptDecrypt(hFileKey, 0, TRUE, 0, pDecryptBuf, &dwDecryptDataLen))) {
  1382.  
  1383.             MessageBox(hWnd, TEXT("GetfnKey: CryptImportKey failed"), NULL, MB_OK);
  1384.             Exit2(hWnd, 
  1385.                     TEXT("CFILERDecryptFile: CryptDecrypt failed."),
  1386.                     hwndDlg, 
  1387.                     hFileRead, 
  1388.                     hFileWrite);
  1389.             DeleteFile(szFileName2);
  1390.             return FALSE;
  1391.         }
  1392.  
  1393.         if (!WriteFile(hFileWrite, pDecryptBuf, dwDecryptDataLen, &dwNumBytesWritten, 0)) {
  1394.             Exit2(hWnd, 
  1395.                     TEXT("CFILERDecryptFile: WriteFile failed."),
  1396.                     hwndDlg, 
  1397.                     hFileRead, 
  1398.                     hFileWrite);
  1399.             DeleteFile(szFileName2);
  1400.             return FALSE;
  1401.         }
  1402.     }
  1403.  
  1404.     if (!CryptDestroyKey(hFileKey)) {
  1405.         Exit2(hWnd, 
  1406.                 TEXT("CFILERDecryptFile: CryptDestroyKey failed."),
  1407.                 hwndDlg, 
  1408.                 hFileRead, 
  1409.                 hFileWrite);
  1410.         DeleteFile(szFileName2);
  1411.         return FALSE;
  1412.     }
  1413.  
  1414.     EndDialog(hwndDlg, FALSE);
  1415.     CloseHandle(hFileRead);
  1416.     CloseHandle(hFileWrite);
  1417.     
  1418.     if (!DeleteFile(szFileName)) {
  1419.         MessageBox(hWnd, TEXT("CFILERDecryptFile: DeleteFile failed."), NULL, MB_OK);
  1420.         DeleteFile(szFileName2);
  1421.     }
  1422.     
  1423.     return TRUE;
  1424. }
  1425.  
  1426. /************************************************************************\
  1427. * SignFile:
  1428. * Opens a file, creates a hash value of the file,
  1429. * signs that hash value, and stores the result to disk.
  1430. \************************************************************************/
  1431.  
  1432. BOOL SignFile(HWND hWnd, LPTSTR szFileName) {
  1433.     TCHAR                     szFilter1[] = TEXT("Signature Files (*.SGN)\0*.SGN\0");
  1434.     TCHAR                     szFilter2[] = TEXT("All Files (*.*)\0*.*\0");
  1435.     TCHAR                    szFile[PATH_SIZE] = TEXT("\0");
  1436.     TCHAR                    szFile2[PATH_SIZE] = TEXT("\0");
  1437.     TCHAR                    szFileTitle[PATH_SIZE];
  1438.     TCHAR                    szFileName2[PATH_SIZE];
  1439.     DWORD                    dwNumBytesRead = BUF_SIZE;
  1440.     DWORD                    dwNumBytesWritten;
  1441.     HWND                    hwndDlg;
  1442.     HANDLE                    hFileRead = INVALID_HANDLE_VALUE;
  1443.     HANDLE                    hFileWrite = INVALID_HANDLE_VALUE;
  1444.     HCRYPTKEY                phSignaturePubKey;
  1445.     HCRYPTHASH                hHash;
  1446.     BYTE                    pSignBuf[BUF_SIZE];
  1447.     BYTE                    pbHash[BUF_SIZE];
  1448.     DWORD                    dwHashLen;
  1449.  
  1450.     GetSignaturePublicKey(hWnd, &phSignaturePubKey);
  1451.     
  1452.     if (!szFileName) {
  1453.         MessageBox(hWnd, TEXT("SignFile: szFileName is NULL."), NULL, MB_OK);
  1454.         return FALSE;
  1455.     }
  1456.  
  1457.     lstrcpy(szFile, TEXT(""));
  1458.     lstrcpy(szFileTitle, TEXT(""));
  1459.     
  1460.     // Open plaintext file
  1461.     
  1462.     hFileRead = CreateFile(szFileName, 
  1463.                            GENERIC_READ, 
  1464.                            0, 
  1465.                            0, 
  1466.                            OPEN_EXISTING, 
  1467.                            FILE_ATTRIBUTE_READONLY, 
  1468.                            0);
  1469.  
  1470.     if (hFileRead == INVALID_HANDLE_VALUE) {
  1471.         MessageBox(hWnd, TEXT("SignFile: CreateFile failed."), NULL, MB_OK);
  1472.         return FALSE;
  1473.     }
  1474.  
  1475.     // hash the full pathname of the file. This will be the name of
  1476.     // the signature file.
  1477.     
  1478.     if (!GetSigFileName(szFileName, szFileName2)) {
  1479.         MessageBox(hWnd, TEXT("SignFile: GetSigFileName failed."), NULL, MB_OK);
  1480.         return FALSE;
  1481.     }
  1482.  
  1483.     // Create signature file.
  1484.     
  1485.     if (GetFileAttributes(szFileName2) == 0xFFFFFFFF) {
  1486.         
  1487.         hFileWrite = CreateFile(szFileName2, 
  1488.                                 GENERIC_READ | GENERIC_WRITE, 
  1489.                                 0, 
  1490.                                 0, 
  1491.                                 CREATE_NEW, 
  1492.                                 FILE_ATTRIBUTE_HIDDEN, 
  1493.                                 0);
  1494.                 
  1495.         if (hFileWrite == INVALID_HANDLE_VALUE) {
  1496.             Exit1(hWnd, TEXT("SignFile: CreateFile failed."), hFileRead, hFileWrite);
  1497.             return FALSE;
  1498.         } 
  1499.     }
  1500.     else {
  1501.         if (MessageBox(hWnd, 
  1502.                        TEXT("Delete signature?"), 
  1503.                        TEXT("Signature file already exists."), 
  1504.                        MB_OKCANCEL) == IDOK) {
  1505.  
  1506.             DeleteFile(szFileName2);
  1507.  
  1508.             hFileWrite = CreateFile(szFileName2,
  1509.                                     GENERIC_READ | GENERIC_WRITE,
  1510.                                     0,
  1511.                                     0,
  1512.                                     CREATE_NEW,
  1513.                                     FILE_ATTRIBUTE_HIDDEN,
  1514.                                     0);
  1515.         
  1516.             if (hFileWrite == INVALID_HANDLE_VALUE) {
  1517.                 Exit1(hWnd, TEXT("SignFile: CreateFile failed."), hFileRead, hFileWrite);
  1518.                 return FALSE;
  1519.             }
  1520.         }
  1521.         else {
  1522.             CloseHandle(hFileRead);
  1523.             
  1524.             return FALSE;
  1525.         }
  1526.     }
  1527.     
  1528.     // Create a dialog box to inform the user that the program is hashing data.
  1529.     
  1530.     hwndDlg = CreateDialog(ghModule, TEXT("SIGNING"), hWnd, CryptDlgProc);
  1531.     
  1532.     if (RCRYPT_FAILED(CryptCreateHash(hMe, AlgidSign, 0, 0, &hHash))) {
  1533.         Exit2(hWnd, TEXT("SignFile: CryptCreateHash failed."), hwndDlg, hFileRead, hFileWrite);
  1534.         DeleteFile(szFileName2);
  1535.         return FALSE;
  1536.     }
  1537.  
  1538.     // The following for loop hashes the file in BUF_SIZE Bufs at a time.
  1539.     
  1540.     for (dwNumBytesRead = BUF_SIZE ; dwNumBytesRead == BUF_SIZE; ) {
  1541.         if (!ReadFile(hFileRead, pSignBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1542.             Exit2(hWnd, 
  1543.                     TEXT("SignFile: ReadFile failed."), 
  1544.                     hwndDlg, 
  1545.                     hFileRead, 
  1546.                     hFileWrite);
  1547.             DeleteFile(szFileName2);
  1548.             return FALSE;
  1549.         }
  1550.         else if (RCRYPT_FAILED(CryptHashData(hHash, pSignBuf, dwNumBytesRead, 0))) {
  1551.             Exit2(hWnd, 
  1552.                     TEXT("SignFile: CryptHashData failed."), 
  1553.                     hwndDlg, 
  1554.                     hFileRead, 
  1555.                     hFileWrite);
  1556.             DeleteFile(szFileName2);
  1557.             return FALSE;
  1558.         }
  1559.     }
  1560.  
  1561.     dwHashLen = BUF_SIZE;
  1562.  
  1563.     if (RCRYPT_FAILED(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbHash, &dwHashLen)))
  1564.     {
  1565.  
  1566.         MessageBox(hWnd, TEXT("SignFile: CryptSignHash failed"), NULL, MB_OK);
  1567.  
  1568.         Exit2(hWnd, 
  1569.                 TEXT("SignFile: CryptSignHash failed."), 
  1570.                 hwndDlg, 
  1571.                 hFileRead, 
  1572.                 hFileWrite);
  1573.         DeleteFile(szFileName2);
  1574.         return FALSE;
  1575.     } 
  1576.  
  1577.     // Write ALG_ID to disk
  1578.     
  1579.     if (!WriteFile(hFileWrite, &AlgidSign, sizeof(ALG_ID), &dwNumBytesWritten, 0)) {
  1580.         Exit2(hWnd, TEXT("SignFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  1581.         return FALSE;
  1582.     }
  1583.     
  1584.     // Write hash to disk.
  1585.     
  1586.     if (!WriteFile(hFileWrite, pbHash, dwHashLen, &dwNumBytesWritten, 0)) {
  1587.         Exit2(hWnd, 
  1588.                 TEXT("SignFile: WriteFile failed."), 
  1589.                 hwndDlg, 
  1590.                 hFileRead, 
  1591.                 hFileWrite);
  1592.         DeleteFile(szFileName2);
  1593.         return FALSE;
  1594.     }
  1595.  
  1596.     CryptDestroyHash(hHash);
  1597.     EndDialog(hwndDlg, FALSE);
  1598.     CloseHandle(hFileRead);
  1599.     CloseHandle(hFileWrite);
  1600.     
  1601.     return TRUE;
  1602. }
  1603.  
  1604. /************************************************************************\
  1605. * VerifyFile
  1606. * Opens a signature file and the original file.
  1607. * Hashes the original file and tries to verify
  1608. * the hash.
  1609. \************************************************************************/
  1610.  
  1611. BOOL VerifyFile(HWND hWnd, LPTSTR szFileName) {
  1612.     TCHAR                     szFilter1[] = TEXT("Signature Files (*.SGN)\0*.SGN\0");
  1613.     TCHAR                     szFilter2[] = TEXT("All Files (*.*)\0*.*\0");
  1614.     TCHAR                    szFile[PATH_SIZE] = TEXT("\0");
  1615.     TCHAR                    szFile2[PATH_SIZE] = TEXT("\0");
  1616.     TCHAR                    szFileTitle[PATH_SIZE];
  1617.     TCHAR                    szFileName2[PATH_SIZE];
  1618.     DWORD                    dwNumBytesRead;
  1619.     DWORD                    dwNumBytesRead2;
  1620.     HWND                    hwndDlg;
  1621.     HANDLE                    hFileOrig = INVALID_HANDLE_VALUE;
  1622.     HANDLE                    hFileSig = INVALID_HANDLE_VALUE;
  1623.     BYTE                    pbSig[BUF_SIZE];
  1624.     BYTE                    pVerifyBuf[BUF_SIZE];
  1625.     DWORD                    dwSigLen;
  1626.     HCRYPTHASH                hHash;
  1627.     HCRYPTKEY                phSignaturePubKey;
  1628.     ALG_ID                     DiskAlgid;
  1629.  
  1630.     if (!szFileName) {
  1631.         MessageBox(hWnd, TEXT("VerifyFile: szFileName is NULL."), NULL, MB_OK);
  1632.         return FALSE;
  1633.     }
  1634.     
  1635.     GetSignaturePublicKey(hWnd, &phSignaturePubKey);
  1636.     
  1637.     // hash the full pathname of the file to determine the signature file
  1638.     // to open.
  1639.     
  1640.     if (!GetSigFileName(szFileName, szFileName2)) {
  1641.         MessageBox(hWnd, TEXT("VerifyFile: GetSigFileName failed."), NULL, MB_OK);
  1642.         return FALSE;
  1643.     }
  1644.  
  1645.     lstrcpy(szFile, TEXT(""));
  1646.     lstrcpy(szFileTitle, TEXT(""));
  1647.  
  1648.     // Open the plaintext file to hash it.
  1649.     
  1650.     hFileOrig = CreateFile(szFileName, 
  1651.                            GENERIC_READ, 
  1652.                            0, 
  1653.                            0, 
  1654.                            OPEN_EXISTING, 
  1655.                            FILE_ATTRIBUTE_READONLY, 
  1656.                            0);
  1657.  
  1658.     if (hFileOrig == INVALID_HANDLE_VALUE) {
  1659.         MessageBox(hWnd, TEXT("VerifyFile: CreateFile failed."), NULL, MB_OK);
  1660.         CloseHandle(hFileOrig);
  1661.         return FALSE;
  1662.     }
  1663.  
  1664.     // Automatically open the signature file if it 
  1665.     // exists in the same directory as the file to be verified.
  1666.     // Otherwise, prompt the user to browse the directory tree 
  1667.     // for the signature file.
  1668.     
  1669.     if (GetFileAttributes(szFileName2) != 0xFFFFFFFF) {
  1670.         
  1671.         hFileSig = CreateFile(szFileName2, 
  1672.                               GENERIC_READ, 
  1673.                               0, 
  1674.                               0, 
  1675.                               OPEN_EXISTING, 
  1676.                               FILE_ATTRIBUTE_READONLY, 
  1677.                               0);
  1678.         
  1679.         if (hFileSig == INVALID_HANDLE_VALUE) {
  1680.             Exit1(hWnd, TEXT("VerifyFile: CreateFile failed."), hFileOrig, hFileSig);
  1681.             return FALSE;
  1682.         } 
  1683.     }
  1684.     else {
  1685.         Exit1(hWnd, TEXT("Signature file does not exist."), hFileOrig, hFileSig);
  1686.         return FALSE;
  1687.     } 
  1688.     
  1689.     // Create a dialog box to tell the user that the program is busy hashing data.
  1690.  
  1691.     hwndDlg = CreateDialog(ghModule, TEXT("VERIFYING"), hWnd, CryptDlgProc);
  1692.     
  1693.     // Read the ALG_ID
  1694.     
  1695.     if (!ReadFile(hFileSig, &DiskAlgid, sizeof(ALG_ID), &dwNumBytesRead2, 0)) {
  1696.         Exit2(hWnd, TEXT("VerifyFile: ReadFile failed."), hwndDlg, hFileOrig, hFileSig);
  1697.         return FALSE;
  1698.     }
  1699.     
  1700.     // Read the hash
  1701.     
  1702.     if (!ReadFile(hFileSig, pbSig, BUF_SIZE, &dwSigLen, 0)) {
  1703.         Exit2(hWnd, TEXT("VerifyFile: ReadFile failed."), hwndDlg, hFileOrig, hFileSig);
  1704.         return FALSE;
  1705.     }
  1706.  
  1707.     if (RCRYPT_FAILED(CryptCreateHash(hMe, DiskAlgid, 0, 0, &hHash))) {
  1708.         Exit2(hWnd, TEXT("VerifyFile: CryptCreateHash failed."), hwndDlg, hFileOrig, hFileSig);
  1709.         return FALSE;
  1710.     }
  1711.  
  1712.     // hash the file in BUF_SIZE chunks
  1713.     
  1714.     for (dwNumBytesRead = BUF_SIZE; dwNumBytesRead == BUF_SIZE; ) {
  1715.         if (!ReadFile(hFileOrig, pVerifyBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1716.             Exit2(hWnd, TEXT("VerifyFile: ReadFile failed."), hwndDlg, hFileOrig, hFileSig);
  1717.             return FALSE;
  1718.         }
  1719.         if (RCRYPT_FAILED(CryptHashData(hHash, pVerifyBuf, dwNumBytesRead, 0))) {
  1720.             Exit2(hWnd, 
  1721.                     TEXT("VerifyFile: CryptHashData failed."), 
  1722.                     hwndDlg, 
  1723.                     hFileOrig, 
  1724.                     hFileSig);
  1725.             return FALSE;
  1726.         }
  1727.     }
  1728.  
  1729.  
  1730.     if (RCRYPT_FAILED(CryptVerifySignature(hHash, pbSig, dwSigLen, phSignaturePubKey, 0, 0))) {
  1731.         EndDialog(hwndDlg, FALSE);
  1732.         MessageBox(hWnd, 
  1733.                    TEXT("Could not verify signature."), 
  1734.                    TEXT("Result"), 
  1735.                    MB_OK | MB_ICONINFORMATION);
  1736.         CloseHandle(hFileOrig);
  1737.         CloseHandle(hFileSig);
  1738.         return TRUE;
  1739.     }
  1740.  
  1741.     if (RCRYPT_FAILED(CryptDestroyHash(hHash))) {
  1742.         Exit2(hWnd, 
  1743.                 TEXT("Could not destroy hash."), 
  1744.                 hwndDlg, 
  1745.                 hFileOrig, 
  1746.                 hFileSig);
  1747.         return FALSE;
  1748.     }
  1749.     
  1750.     EndDialog(hwndDlg, FALSE);
  1751.     
  1752.     MessageBox(hWnd, 
  1753.                TEXT("Signature verified."), 
  1754.                TEXT("Result"), 
  1755.                MB_OK | MB_ICONINFORMATION);
  1756.     CloseHandle(hFileOrig);
  1757.     CloseHandle(hFileSig);
  1758.     
  1759.     return TRUE;
  1760. }
  1761.  
  1762. /************************************************************************\
  1763. * EncryptDir()
  1764. *
  1765. * in parameters
  1766. * hWnd - HWND specified by caller
  1767. * szDirName - full path of directory to encrypt
  1768. * lpCInfo - instance data for drive child
  1769. *
  1770. * purpose: 
  1771. * Encrypts szDirName and recursively encrypts all of its
  1772. * subdirectories. Confirmation is needed for each subdirectory.
  1773. * A random directory name is generated, and szDirName is
  1774. * renamed and given hidden attributes.
  1775. * dirinfo contains the fnKey-encrypted directory name.
  1776. *
  1777. * returns
  1778. * TRUE if successful
  1779. * FALSE if unsuccessful
  1780. \************************************************************************/
  1781.  
  1782. BOOL EncryptDir(HWND hWnd, LPTSTR szDirName, LPCINFO lpCInfo) {
  1783.     TCHAR                szDirInfo[PATH_SIZE];
  1784.     TCHAR                szFileName[PATH_SIZE];
  1785.     TCHAR                szEncryptedDirName[PATH_SIZE];
  1786.     TCHAR                szRandom[PATH_SIZE];
  1787.     TCHAR                szRandomName[PATH_SIZE];
  1788.     TCHAR                szDir[PATH_SIZE];
  1789.     TCHAR                szFile[PATH_SIZE];
  1790.     TCHAR                szMessage[PATH_SIZE];
  1791.     TCHAR                szOldDir[PATH_SIZE];
  1792.     TCHAR                Buf[PATH_SIZE];
  1793.     TCHAR                szDirName2[PATH_SIZE];
  1794.     LPTSTR                lpszDirName2;
  1795.     HANDLE                 hFileDirInfo;
  1796.     HANDLE                hFindFile;
  1797.     WIN32_FIND_DATA        FindFileData;
  1798.     BOOL                fNextFile;
  1799.     DWORD                dwLastError;
  1800.     DWORD                dwDataLen = BUF_SIZE;
  1801.     DWORD                dwNumBytesWritten;
  1802.     LONG                lIndex;
  1803.     LONG                lCount;
  1804.     HCRYPTKEY            hfnKey;
  1805.         
  1806.     if (!szDirName) {
  1807.         MessageBox(hWnd, TEXT("EncryptDir: szDirName is NULL."), NULL, MB_OK);
  1808.         return FALSE;
  1809.     }
  1810.     
  1811.     if (!lpCInfo) {
  1812.         MessageBox(hWnd, TEXT("EncryptDir: lpCInfo is NULL."), NULL, MB_OK);
  1813.         return FALSE;
  1814.     }
  1815.     
  1816.     hfnKey = GetfnKey(hWnd);
  1817.     
  1818.     if (!hfnKey) {
  1819.         MessageBox(hWnd, TEXT("EncryptDir: GetfnKey failed."), NULL, MB_OK);
  1820.         return FALSE;
  1821.     }
  1822.  
  1823.     SeparatePathName2(szDirName, szDir, szEncryptedDirName);
  1824.         
  1825.     lstrcpy(szMessage, TEXT("\0"));
  1826.     wsprintf(szMessage, TEXT("Encrypt the directory %s?\n"), szDirName);
  1827.  
  1828.     // ask for confirmation about encrypting the directory
  1829.     
  1830.     if (MessageBox(hWnd, szMessage, 
  1831.                 TEXT("Confirmation needed."), MB_OKCANCEL) == IDCANCEL)
  1832.         return FALSE;
  1833.  
  1834.     lstrcpy(szFileName, szDir);
  1835.     lstrcat(szFileName, TEXT("\\"));
  1836.     lstrcat(szFileName, szEncryptedDirName);
  1837.  
  1838.     if (!szDirName) {
  1839.         MessageBox(hWnd, TEXT("EncryptDir: szDirName is NULL."), NULL, MB_OK);
  1840.         return FALSE;
  1841.     }
  1842.  
  1843.     GenRandomName(szRandom);
  1844.     
  1845.     lstrcpy(szRandomName, szDir);
  1846.     lstrcat(szRandomName, TEXT("\\"));
  1847.     lstrcat(szRandomName, szRandom);
  1848.     lstrcpy(szDirInfo, szFileName);
  1849.     lstrcat(szDirInfo, TEXT("\\dirinfo"));
  1850.  
  1851.     // Create a file called "dirinfo" in directory about to encrypted.
  1852.     // This will contain the original directory name encrypted with fnKey.
  1853.     
  1854.     hFileDirInfo = CreateFile(szDirInfo, 
  1855.                               GENERIC_READ | GENERIC_WRITE, 
  1856.                               0, 
  1857.                               0, 
  1858.                               CREATE_ALWAYS, 
  1859.                               FILE_ATTRIBUTE_HIDDEN, 
  1860.                               0);
  1861.     
  1862.     if (hFileDirInfo == INVALID_HANDLE_VALUE) {
  1863.         MessageBox(hWnd, TEXT("EncryptDir: CreateFile failed."), NULL, MB_OK);
  1864.         return FALSE;
  1865.     
  1866.     }
  1867.         
  1868.     // Encrypt the directory name with fnKey.
  1869.     
  1870.     if (RCRYPT_FAILED(CryptEncrypt(hfnKey, 
  1871.                       0, 
  1872.                       TRUE, 
  1873.                       0, 
  1874.                       (LPBYTE)szEncryptedDirName, 
  1875.                       &dwDataLen, 
  1876.                       HEADER_SIZE * sizeof(*szEncryptedDirName)))) {
  1877.         MessageBox(hWnd, TEXT("EncryptDir: CryptEncrypt failed."), NULL, MB_OK);
  1878.         CloseHandle(hFileDirInfo);
  1879.         return FALSE;
  1880.     }    
  1881.  
  1882.     // Write the original directory's encrypted name to disk.
  1883.     
  1884.     if (!WriteFile(hFileDirInfo, 
  1885.                    szEncryptedDirName, 
  1886.                    HEADER_SIZE * sizeof(*szEncryptedDirName), 
  1887.                    &dwNumBytesWritten, 
  1888.                    0)) {
  1889.         MessageBox(hWnd, TEXT("EncryptDir: WriteFile failed."), NULL, MB_OK);
  1890.         CloseHandle(hFileDirInfo);
  1891.         return FALSE;
  1892.     }
  1893.     
  1894.     CloseHandle(hFileDirInfo);
  1895.     
  1896.     SeparatePathName2(szDirName, szDir, szFile);
  1897.     
  1898.     lstrcpy(szDirName, szDir);
  1899.     lstrcat(szDirName, TEXT("\\"));
  1900.     lstrcat(szDirName, szFile);
  1901.     lstrcpy(szOldDir, szDirName);
  1902.     lstrcat(szDirName, TEXT("\\*"));
  1903.  
  1904.     if ((hFindFile = FindFirstFile(szDirName, &FindFileData)) 
  1905.                                         == INVALID_HANDLE_VALUE) {
  1906.         MessageBox(hWnd, TEXT("EncryptDir: FindFirstFile failed."), NULL, MB_OK);
  1907.         return FALSE;
  1908.     }
  1909.  
  1910.     // Loop through, calling FindNextFiles until no more files are left.
  1911.                     
  1912.     do {
  1913.     
  1914.         lstrcpy(szFileName, szDir);
  1915.         lstrcat(szFileName, TEXT("\\"));
  1916.         lstrcat(szFileName, szFile);
  1917.         lstrcat(szFileName, TEXT("\\"));            
  1918.         lstrcat(szFileName, FindFileData.cFileName);
  1919.         
  1920.         // is szFileName encrypted and not .., ., or dirinfo?
  1921.         if (!IsEncrypted(szFileName)
  1922.            && lstrcmp(FindFileData.cFileName, TEXT("."))
  1923.            && lstrcmp(FindFileData.cFileName, TEXT(".."))
  1924.            && lstrcmp(FindFileData.cFileName, TEXT("dirinfo"))) {    
  1925.             // Is szFileName a directory?
  1926.             if (CFilerIsDirectory(szFileName)) {
  1927.                 // Encrypt the directory szFileName.
  1928.                 if (!EncryptDir(hWnd, szFileName, lpCInfo)) {
  1929.                     MessageBox(hWnd, TEXT("EncryptDir: EncryptDir failed."), NULL, MB_OK);
  1930.                     return FALSE;
  1931.                 }
  1932.             }
  1933.             // encrypt the file szFileName.
  1934.             else if (!CFILEREncryptFile(hWnd, szFileName)) {
  1935.                 MessageBox(hWnd, TEXT("EncryptDir: CFILEREncryptFile failed."), NULL, MB_OK);
  1936.                 return FALSE;
  1937.             }
  1938.         }
  1939.         
  1940.         fNextFile = FindNextFile(hFindFile, &FindFileData);
  1941.  
  1942.         dwLastError = GetLastError();
  1943.  
  1944.     } while (fNextFile || dwLastError != ERROR_NO_MORE_FILES);
  1945.                     
  1946.     FindClose(hFindFile);
  1947.     
  1948.     lpszDirName2 = szDirName2;
  1949.     
  1950.     // Collapse the selected directory.
  1951.  
  1952.     lIndex = GetLBText(lpCInfo->hDirLB, Buf);
  1953.     lCount = GetDirDepth(Buf, &lpszDirName2);
  1954.     CollapseDir(lpCInfo, lIndex, lCount);
  1955.     
  1956.     // rename the directory with a random name.
  1957. #ifdef UNICODE
  1958.     if (_wrename((const wchar_t *)szOldDir, (const wchar_t *)szRandomName)) {
  1959. #else
  1960.     if (rename(szOldDir, szRandomName)) {
  1961. #endif
  1962.         MessageBox(hWnd, TEXT("Another process is using this directory."), NULL, MB_OK);
  1963.         return FALSE;
  1964.     }
  1965.         
  1966.     // hide the directory.
  1967.  
  1968.     SetFileAttributes(szRandomName, FILE_ATTRIBUTE_HIDDEN);
  1969.     
  1970.     return TRUE;
  1971. }
  1972.  
  1973. /************************************************************************\
  1974. * GenRandomName()
  1975. *
  1976. * out parameters
  1977. * szRandomName - buffer to receive random filename
  1978. *
  1979. * purpose:
  1980. * Uses the random number generator to generate a random filename with
  1981. * a .CRP extension.
  1982. *
  1983. * returns
  1984. * TRUE if successful
  1985. * FALSE if unsuccessful
  1986. \************************************************************************/
  1987.  
  1988. BOOL GenRandomName(LPTSTR szRandomName) {
  1989.     INT i;
  1990.  
  1991.     if (!szRandomName) {
  1992.         ErrorMsg(TEXT("GenRandomName: szRandomName is NULL."));
  1993.         return FALSE;
  1994.     }
  1995.     
  1996.     for (i = 0; i < RANDOM_NAME_LENGTH; i++)
  1997.         szRandomName[i] = rand() % 26 + TEXT('a');
  1998.     szRandomName[i] = TEXT('\0');
  1999.  
  2000.     lstrcat(szRandomName, TEXT(".CRP\0"));
  2001.  
  2002.     return TRUE;
  2003. }
  2004.  
  2005. /************************************************************************\
  2006. * GenRandomName2()
  2007. *
  2008. * out parameters
  2009. * szRandomName - buffer to receive random filename
  2010. *
  2011. * purpose:
  2012. * Uses the random number generator to generate a random filename without
  2013. * a .CRP extension.
  2014. *
  2015. * returns
  2016. * TRUE if successful
  2017. * FALSE if unsuccessful
  2018. \************************************************************************/
  2019.  
  2020. BOOL GenRandomName2(LPTSTR szRandomName) {
  2021.     INT i;
  2022.  
  2023.     if (!szRandomName) {
  2024.         ErrorMsg(TEXT("GenRandomName: szRandomName is NULL."));
  2025.         return FALSE;
  2026.     }
  2027.     
  2028.     for (i = 0; i < RANDOM_NAME_LENGTH; i++)
  2029.         szRandomName[i] = rand() % 26 + TEXT('a');
  2030.     szRandomName[i] = TEXT('\0');
  2031.  
  2032.     return TRUE;
  2033. }
  2034.  
  2035. /************************************************************************\
  2036. * GetSigFileName()
  2037. *
  2038. * input
  2039. * in parameters:
  2040. * szFileName - full path of filename
  2041. * out parameters:
  2042. * szOutName - buffer containing name of signature file.
  2043. *
  2044. * purpose:
  2045. * obtains the name of the signature file that corresponds to szFileName.
  2046. * by hashing it and converting it to ascii.
  2047. *
  2048. * returns
  2049. * TRUE if successful
  2050. * FALSE if unsuccessful
  2051. \************************************************************************/
  2052.  
  2053. BOOL GetSigFileName(LPTSTR szFileName, LPTSTR szOutName) {
  2054.     HCRYPTHASH hHash;
  2055.     BYTE pbHash[BUF_SIZE];
  2056.     DWORD dwHashLen;
  2057.     TCHAR szFileBuf[PATH_SIZE];
  2058.     TCHAR szSigDir[PATH_SIZE];
  2059.  
  2060.     if (!szFileName) {    
  2061.         ErrorMsg(TEXT("GetSigFileName: szFileName is NULL."));
  2062.         return FALSE;
  2063.     }
  2064.     
  2065.     if (!szOutName) {
  2066.         ErrorMsg(TEXT("GetSigFileName: szOutName is NULL."));
  2067.         return FALSE;
  2068.     }
  2069.     
  2070.      GetSigDir(szSigDir);
  2071.     
  2072.     // Hash szFileName.
  2073.     
  2074.     if (RCRYPT_FAILED(CryptCreateHash(hMe, CALG_SHA, 0, 0, &hHash))) {
  2075.         ErrorMsg(TEXT("GetSigFileName: CryptCreateHash failed."));
  2076.         return FALSE;
  2077.     }
  2078.  
  2079.     if (RCRYPT_FAILED(CryptHashData(hHash, (LPBYTE)szFileName, lstrlen(szFileName) * sizeof(*szFileName), 0))) {
  2080.         ErrorMsg(TEXT("GetSigFileName: CryptHashData failed."));
  2081.         return FALSE;
  2082.     }
  2083.  
  2084.     dwHashLen = SHA_SIZE;
  2085.     
  2086.     if (RCRYPT_FAILED(CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0))) {
  2087.         ErrorMsg(TEXT("GetSigFileName: CryptFinishHash failed."));
  2088.         return FALSE;
  2089.     }
  2090.     
  2091.     // Convert the hash to ascii
  2092.     
  2093.     if (!SHAtoRadix64(pbHash, szFileBuf)) {
  2094.         ErrorMsg(TEXT("DrvWndProc: FILLFILE: SHAtoRadix64 failed."));
  2095.         return 0;
  2096.     }
  2097.                             
  2098.     lstrcpy(szOutName, szSigDir);
  2099.     lstrcat(szOutName, TEXT("\\"));
  2100.     lstrcat(szOutName, szFileBuf);
  2101.  
  2102.     CryptDestroyHash(hHash);
  2103. }
  2104.  
  2105. /************************************************************************\
  2106. * HasSignature()
  2107. *
  2108. * in parameters
  2109. * szFileName - full path of filename in question
  2110. * sigtable - pointer to a string table with displayed fields containing
  2111. * the filenames of all the files in the \sig directory, which is located
  2112. * on the same drive as the system directory.
  2113. *
  2114. * out parameters
  2115. * bHasSignature - flag specifying whether szFileName has a signature
  2116. *
  2117. * purpose:
  2118. * determines whether \sig\szFileName has a signature by calling
  2119. * GetSigFileName.
  2120. *
  2121. * returns
  2122. * TRUE if such a file exists
  2123. * FALSE otherwise or if unsuccessful
  2124. \************************************************************************/
  2125.  
  2126. BOOL HasSignature(LPTSTR szFileName, TABLE sigtable, BOOL *bHasSignature) {
  2127.     TCHAR szFileName2[PATH_SIZE];
  2128.     
  2129.     if (!szFileName) {    
  2130.         ErrorMsg(TEXT("HasSignature: szFileName is NULL."));
  2131.         return FALSE;
  2132.     }
  2133.     
  2134.     if (!bHasSignature) {
  2135.         ErrorMsg(TEXT("HasSignature: bHasSignature is NULL."));
  2136.         return FALSE;
  2137.     }
  2138.     
  2139.     if (!GetSigFileName(szFileName, szFileName2)) {
  2140.         ErrorMsg(TEXT("HasSignature: GetSigFileName failed."));
  2141.         return FALSE;
  2142.     }
  2143.  
  2144.     // Does this file exist?
  2145.     
  2146.     if (TableFind(sigtable, szFileName2))
  2147.         *bHasSignature = TRUE;
  2148.     else
  2149.         *bHasSignature = FALSE;
  2150. }
  2151.                 
  2152. /************************************************************************\
  2153. * GetDecryptedFileName()
  2154. *
  2155. * in parameters
  2156. * hWnd - HWND specified by caller
  2157. * szFileName - full path of file
  2158. * out parameters
  2159. * szDecryptedFileName - buffer to hold full decrypted path
  2160. * hFileRead - pointer to file handle
  2161. *
  2162. * purpose:
  2163. * reads HEADER_SIZE bytes from szFileName, decrypts it with fnKey, and
  2164. * stores the result on szDecryptedFileName, the decrypted file name.
  2165. *
  2166. * returns:
  2167. * TRUE if successful
  2168. * FALSE if unsuccessful
  2169. \************************************************************************/
  2170.  
  2171. BOOL GetDecryptedFileName(HWND hWnd, 
  2172.                           LPTSTR szFileName, 
  2173.                           LPTSTR szDecryptedFileName, 
  2174.                           HANDLE *hFileRead) {
  2175.     DWORD dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  2176.     DWORD dwNumBytesRead;
  2177.     TCHAR szDir[PATH_SIZE];
  2178.     HCRYPTKEY hfnKey;
  2179.  
  2180.     if (!szFileName) {
  2181.         MessageBox(hWnd, TEXT("GetDecryptedFileName: szFileName is NULL."), NULL, MB_OK);
  2182.         return FALSE;
  2183.     }
  2184.  
  2185.     if (!szDecryptedFileName) {
  2186.         MessageBox(hWnd, TEXT("GetDecryptedFileName: szDecryptedFileName is NULL."), NULL, MB_OK);
  2187.         return FALSE;
  2188.     }
  2189.  
  2190.     hfnKey = GetfnKey(hWnd);
  2191.     
  2192.     if (!hfnKey) {
  2193.         MessageBox(hWnd, TEXT("GetDecryptedFileName: GetfnKey failed."), NULL, MB_OK);
  2194.         return FALSE;
  2195.     }
  2196.  
  2197.     // Open encrypted file.
  2198.     
  2199.     *hFileRead = CreateFile(szFileName, 
  2200.                            GENERIC_READ, 
  2201.                            0, 
  2202.                            0, 
  2203.                            OPEN_EXISTING, 
  2204.                            GetFileAttributes(szFileName),
  2205.                            0);
  2206.  
  2207.     if (*hFileRead == INVALID_HANDLE_VALUE) {
  2208.         MessageBox(hWnd, TEXT("GetDecryptedFileName: CreateFile failed."), NULL, MB_OK);
  2209.         return FALSE;
  2210.     }
  2211.     
  2212.     // Read the encrypted filename from the disk.
  2213.                         
  2214.     if (!ReadFile(*hFileRead, 
  2215.                    szDecryptedFileName, 
  2216.                    HEADER_SIZE * sizeof(*szDecryptedFileName), 
  2217.                    &dwNumBytesRead, 
  2218.                    0))
  2219.         return FALSE;
  2220.                         
  2221.     if (dwNumBytesRead != HEADER_SIZE * sizeof(*szDecryptedFileName)) {
  2222.         SeparatePathName2(szFileName, szDir, szDecryptedFileName);
  2223.         return FALSE;
  2224.     }
  2225.  
  2226.     // Decrypt the filename.
  2227.                         
  2228.     CryptDecrypt(hfnKey, 0, TRUE, 0, (LPBYTE)szDecryptedFileName, &dwDataLen);
  2229.  
  2230.     return TRUE;
  2231. }
  2232.  
  2233. /************************************************************************\
  2234. * GetDecryptedDirName()
  2235. *
  2236. * in parameters
  2237. * hWnd - HWND specified by caller
  2238. * szDirectoryName - full path of directory
  2239. * bDeldirinfo - flag: TRUE means caller wants dirinfo to be deleted
  2240. *
  2241. * out parameters
  2242. * szDecryptedDirName - buffer to hold full decrypted pathname of
  2243. * szDirName
  2244. * hFileRead - pointer to file handle
  2245. *
  2246. * purpose:
  2247. * reads HEADER_SIZE bytes from file dirinfo in directory szDirectoryName,
  2248. * decrypts it with fnKey, and stores the result in szDecryptedDirName,
  2249. * a buffer to hold the decrypted directory name.
  2250. *
  2251. * returns
  2252. * TRUE if successful
  2253. * FALSE if unsuccessful
  2254. \************************************************************************/
  2255.  
  2256. BOOL GetDecryptedDirName(HWND hWnd, 
  2257.                            LPTSTR szDirectoryName, 
  2258.                            LPTSTR szDecryptedDirName, 
  2259.                            BOOL bDeldirinfo,
  2260.                            HANDLE *hFileRead) {
  2261.     DWORD dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  2262.     DWORD dwNumBytesRead;
  2263.     TCHAR szDir[PATH_SIZE];
  2264.     TCHAR szBuf[PATH_SIZE];
  2265.     HCRYPTKEY hfnKey;
  2266.  
  2267.     hfnKey = GetfnKey(hWnd);
  2268.     
  2269.     if (!hfnKey) {
  2270.         MessageBox(hWnd, TEXT("GetDecryptedFileName: GetfnKey failed."), NULL, MB_OK);
  2271.         return FALSE;
  2272.     }
  2273.  
  2274.     if (!szDirectoryName) {
  2275.         MessageBox(hWnd, TEXT("GetDecryptedDirName: szDirectoryName is NULL."), NULL, MB_OK);
  2276.         return FALSE;
  2277.     }
  2278.     
  2279.     if (!szDecryptedDirName) {
  2280.         MessageBox(hWnd, TEXT("GetDecryptedDirNAme: szDecryptedDirName is NULL."), NULL, MB_OK);
  2281.         return FALSE;
  2282.     }
  2283.     
  2284.     lstrcpy(szDir, szDirectoryName);
  2285.  
  2286.     if (szDir[lstrlen(szDir) - 1] != TEXT('\\'))
  2287.         lstrcat(szDir, TEXT("\\"));
  2288.  
  2289.     lstrcat(szDir, TEXT("dirinfo"));
  2290.  
  2291.     // open dirinfo in szDirectoryName.
  2292.     
  2293.     *hFileRead = CreateFile(szDir,
  2294.                                GENERIC_READ,
  2295.                                0,
  2296.                                0,
  2297.                                OPEN_EXISTING,
  2298.                                GetFileAttributes(szDir),
  2299.                                0);
  2300.  
  2301.     if (*hFileRead == INVALID_HANDLE_VALUE)
  2302.         return FALSE;
  2303.  
  2304.     // Read the encrypted filename from the disk.
  2305.     
  2306.     if (!ReadFile(*hFileRead,
  2307.                    szDecryptedDirName,
  2308.                    HEADER_SIZE * sizeof(*szDecryptedDirName),
  2309.                    &dwNumBytesRead,
  2310.                    0))
  2311.         return FALSE;
  2312.  
  2313.     CloseHandle(*hFileRead);
  2314.  
  2315.     // Decrypt the directoryname.
  2316.     
  2317.     CryptDecrypt(hfnKey, 0, TRUE, 0, (LPBYTE)szDecryptedDirName, &dwDataLen);
  2318.  
  2319.     // enclose the directory name with brackets.
  2320.     
  2321.     lstrcpy(szBuf, TEXT("["));
  2322.     lstrcat(szBuf, szDecryptedDirName);
  2323.     lstrcat(szBuf, TEXT("]"));
  2324.     lstrcpy(szDecryptedDirName, szBuf);
  2325.  
  2326.     if (bDeldirinfo)
  2327.         DeleteFile(szDir);
  2328.  
  2329.     return TRUE;
  2330. }
  2331.  
  2332. /************************************************************************\
  2333. * DecryptDir()
  2334. *
  2335. * in parameters
  2336. * hWnd - HWND specified by caller
  2337. * szDirName - Full path of directory to be decrypted
  2338. * lpCInfo - instance data for drive child
  2339. *
  2340. * purpose:
  2341. * recursively decrypts szDirName and all of its subdirectories.
  2342. *
  2343. * returns
  2344. * TRUE if successful
  2345. * FALSE if unsuccessful
  2346. \************************************************************************/
  2347.  
  2348. BOOL DecryptDir(HWND hWnd, LPTSTR szDirName, LPCINFO lpCInfo) {
  2349.     INT i, j;
  2350.     TCHAR szDir[PATH_SIZE];
  2351.     TCHAR szDir2[PATH_SIZE];
  2352.     TCHAR szFile[PATH_SIZE];
  2353.     TCHAR szBuf2[PATH_SIZE];
  2354.     TCHAR Buf[PATH_SIZE];
  2355.     TCHAR szDecryptedDirName[PATH_SIZE];
  2356.     TCHAR szFileName[PATH_SIZE];
  2357.     TCHAR szDirName2[PATH_SIZE];
  2358.     LPTSTR lpszDirName2;
  2359.     HANDLE hFileRead;
  2360.     HANDLE hFindFile;
  2361.     WIN32_FIND_DATA FindFileData;
  2362.     BOOL fNextFile;
  2363.     DWORD dwLastError;
  2364.     LONG lIndex, lCount;
  2365.     
  2366.     if (!szDirName) {
  2367.         MessageBox(hWnd, TEXT("DecryptDir: szDirName is NULL."), NULL, MB_OK);
  2368.         return FALSE;
  2369.     }
  2370.     
  2371.     if (!lpCInfo) {
  2372.         MessageBox(hWnd, TEXT("DecryptDir: lpCInfo is NULL."), NULL, MB_OK);
  2373.         return FALSE;
  2374.     }
  2375.     
  2376.     GetDecryptedDirName(hWnd, szDirName, szDecryptedDirName, 1, &hFileRead);
  2377.  
  2378.     // strip the brackets off szDecryptedDirName.
  2379.  
  2380.     if (szDecryptedDirName[0] == TEXT('[')) {
  2381.         for (i = 1, j = 0; szDecryptedDirName[i] 
  2382.                         && szDecryptedDirName[i] != TEXT(']'); i++, j++)
  2383.             szBuf2[j] = szDecryptedDirName[i];
  2384.         szBuf2[j] = TEXT('\0');
  2385.         lstrcpy(szDecryptedDirName, szBuf2);
  2386.     }    
  2387.  
  2388.     CloseHandle(hFileRead);
  2389.  
  2390.     lpszDirName2 = szDirName2;
  2391.  
  2392.     // Collapse the selected directory in the directory listbox.
  2393.     
  2394.     lIndex = GetLBText(lpCInfo->hDirLB, Buf);
  2395.     lCount = GetDirDepth(Buf, &lpszDirName2);
  2396.     CollapseDir(lpCInfo, lIndex, lCount);
  2397.     
  2398.     SeparatePathName2(szDirName, szDir, szFile);
  2399.     
  2400.     // unhide the directory.
  2401.     
  2402.     lstrcat(szDir, TEXT("\\"));
  2403.     lstrcat(szDir, szDecryptedDirName);
  2404.     SetFileAttributes(szDirName, GetFileAttributes(szDirName) ^ FILE_ATTRIBUTE_HIDDEN);
  2405.     
  2406.     // rename the directory to its original name.
  2407.  
  2408. #ifdef UNICODE
  2409.     if (_wrename((const wchar_t *)szDirName, (const wchar_t *)szDir)) {
  2410. #else
  2411.     if (rename(szDirName, szDir)) {
  2412. #endif
  2413.         MessageBox(hWnd, TEXT("Another process is using this directory."), NULL, MB_OK);
  2414.         return FALSE;
  2415.     }
  2416.     
  2417.     lstrcpy(szDir2, szDir);
  2418.     lstrcat(szDir2, TEXT("\\*"));
  2419.     
  2420.     if ((hFindFile = FindFirstFile(szDir2, &FindFileData)) == INVALID_HANDLE_VALUE) {
  2421.         MessageBox(hWnd, TEXT("DecryptDir: FindFirstFile failed."), NULL, MB_OK);
  2422.         return FALSE;
  2423.     }
  2424.  
  2425.     // decrypt all the files in the directory, recursing on directories
  2426.     
  2427.     do {
  2428.         lstrcpy(szFileName, szDir);
  2429.         lstrcat(szFileName, TEXT("\\"));
  2430.         lstrcat(szFileName, FindFileData.cFileName);
  2431.         
  2432.         // is szFileName encrypted?
  2433.         if (IsEncrypted(szFileName)
  2434.            && lstrcmp(FindFileData.cFileName, TEXT("."))
  2435.            && lstrcmp(FindFileData.cFileName, TEXT(".."))) {    
  2436.             // is szFileName a directory?
  2437.             if (CFilerIsDirectory(szFileName)) {
  2438.                 // Decrypt the directory szFileName.
  2439.                 if (!DecryptDir(hWnd, szFileName, lpCInfo)) {
  2440.                     MessageBox(hWnd, TEXT("DecryptDir: DecryptDir failed."), NULL, MB_OK);
  2441.                     return FALSE;
  2442.                 }
  2443.             }
  2444.             // decrypt the file szFileName.
  2445.             else if (!CFILERDecryptFile(hWnd, szFileName)) {
  2446.                 MessageBox(hWnd, TEXT("DecryptDir: CFILERDecryptFile failed."), NULL, MB_OK);
  2447.                 return FALSE;
  2448.             }
  2449.         }
  2450.         
  2451.         fNextFile = FindNextFile(hFindFile, &FindFileData);
  2452.  
  2453.         dwLastError = GetLastError();
  2454.         
  2455.     } while (fNextFile || dwLastError != ERROR_NO_MORE_FILES);
  2456.  
  2457.     FindClose(hFindFile);
  2458.  
  2459.     return TRUE;
  2460. }
  2461.  
  2462. /************************************************************************\
  2463. * GetSigDir()
  2464. *
  2465. * in parameters
  2466. * szSigDir - buffer to hold result
  2467. *
  2468. * purpose: 
  2469. * stores in buffer szSigDir the name of the directory containing
  2470. * the signatures
  2471. *
  2472. * returns
  2473. * TRUE if successful
  2474. * FALSE if unsuccessful
  2475. \************************************************************************/
  2476.  
  2477. BOOL GetSigDir(LPTSTR szSigDir)
  2478. {
  2479.     TCHAR szSystemDirectory[PATH_SIZE];
  2480.  
  2481.     if (!szSigDir) {
  2482.         ErrorMsg(TEXT("GetSigDir: szSigDir is NULL."));
  2483.         return FALSE;
  2484.     }
  2485.         
  2486.     // [system directory drive]:\sig -> szSigDir
  2487.     
  2488.     GetSystemDirectory(szSystemDirectory, PATH_SIZE * sizeof(*szSystemDirectory));
  2489.     szSigDir[0] = szSystemDirectory[0];
  2490.     szSigDir[1] = TEXT('\0');
  2491.     lstrcat(szSigDir, TEXT(":\\sig"));
  2492.     
  2493.     return TRUE;
  2494. }
  2495.