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 / cfiler.c < prev    next >
C/C++ Source or Header  |  1997-10-08  |  42KB  |  1,346 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. // CFILER.C
  13. #include "cfiler.h"
  14. #include "time.h"
  15.  
  16. HANDLE                  ghModule;                                    
  17. HANDLE              ghDrvThread = NULL;
  18. HWND                ghwndMain = NULL;                      
  19. HWND                ghwndDrives;              
  20. HWND                ghwndDrv;
  21. HWND                ghFocusWnd;                   
  22. HFONT               ghFont;
  23. HMENU                ghMenu;                        
  24. BOOL                gfDrvWndOrient = SIDE_BY_SIDE,
  25.                     gfKeepCommandWin = FALSE;
  26. DRVCHILDINFO        gDrvChildInfo;
  27. LPDINFO             glpDrives = (LPDINFO)0;            
  28. CRITICAL_SECTION    gDrvCS;                                   
  29.                                              
  30. extern LPTSTR         lpDriveStrings;
  31. extern ALG_ID        AlgidEncrypt;
  32. extern ALG_ID        AlgidSign;
  33. extern CHAR            sPass[BUF_SIZE];
  34. extern TCHAR        szPassName[BUF_SIZE];
  35.  
  36. int WINAPI WinMain(HINSTANCE hInstance, 
  37.                    HINSTANCE hPrevInstance, 
  38.                    LPSTR lpCmdLine, 
  39.                    INT nCmdShow) {
  40.     MSG    msg;
  41.     HANDLE hAccel;
  42.  
  43.     ghModule = hInstance;
  44.  
  45.     if (!InitializeApp()) {
  46.         ErrorMsg(TEXT("WinMain: InitializeApp failed."));
  47.         return 0;
  48.     }
  49.  
  50.     ShowWindow(ghwndMain, nCmdShow);
  51.  
  52.     if (!(hAccel = LoadAccelerators (ghModule, MAKEINTRESOURCE(ACCEL_ID))))
  53.         ErrorMsg(TEXT("WinMain: LoadAccelerators failed."));
  54.  
  55.     while (GetMessage(&msg, NULL, 0, 0)) {
  56.         if( !TranslateAccelerator(ghwndMain, hAccel, &msg) ) {
  57.             TranslateMessage(&msg);
  58.             DispatchMessage(&msg);
  59.         }
  60.     }
  61.  
  62.     return 1;
  63.  
  64.     UNREFERENCED_PARAMETER(lpCmdLine);
  65.     UNREFERENCED_PARAMETER(hPrevInstance);
  66. }
  67.  
  68. BOOL InitializeApp(void)
  69. {
  70.     WNDCLASS wc;
  71.     HWND FirsthWnd, FirstChildhWnd;
  72.  
  73.     if (FirsthWnd = FindWindow("CRYPTFILERClass", NULL))
  74.     {
  75.        // Found another running application with the same class name.
  76.        // Therefore, one instance is already running.
  77.  
  78.        FirstChildhWnd = GetLastActivePopup(FirsthWnd);
  79.        BringWindowToTop(FirsthWnd);         // bring main window to top
  80.  
  81.        if (FirsthWnd != FirstChildhWnd)
  82.           BringWindowToTop(FirstChildhWnd); // a pop-up window is active
  83.                                             // bring it to the top too
  84.  
  85.        return FALSE;                        // do not run second instance
  86.     }
  87.  
  88.     srand(time(0));
  89.        
  90.     lstrcpy(szPassName, TEXT("\0"));
  91.     
  92.     wc.style            = 0;
  93.     wc.lpfnWndProc      = (WNDPROC)MainWndProc;
  94.     wc.cbClsExtra       = 0;
  95.     wc.cbWndExtra       = 0;
  96.     wc.hInstance        = ghModule;
  97.     wc.hIcon            = LoadIcon(ghModule, MAKEINTRESOURCE(UI_CRYPTFILERICON));
  98.     wc.hCursor          = 0;
  99.     wc.hbrBackground    = (HBRUSH)(COLOR_APPWORKSPACE);
  100.     wc.lpszMenuName     = TEXT("CRYPTFILERMenu");
  101.     wc.lpszClassName    = TEXT("CRYPTFILERClass");
  102.  
  103.     if (!RegisterClass(&wc)) {
  104.         ErrorMsg(TEXT("InitializeApp: RegisterClass failed."));
  105.         return FALSE;
  106.     }
  107.  
  108.     wc.lpfnWndProc  = DrvWndProc;
  109.     wc.hIcon        = NULL;
  110.     wc.lpszMenuName = NULL;
  111.     wc.lpszClassName    = TEXT("DrvClass");
  112.  
  113.     if (!RegisterClass(&wc)) {
  114.         ErrorMsg(TEXT("InitializeApp: RegisterClass failed."));
  115.         return FALSE;
  116.     }
  117.     
  118.     wc.style        = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  119.     wc.lpfnWndProc  = DriveBarProc;
  120.     wc.hbrBackground    = (HBRUSH)(COLOR_BTNSHADOW);
  121.     wc.lpszClassName    = TEXT("DriveBarClass");
  122.  
  123.     if (!RegisterClass(&wc)) {
  124.         ErrorMsg(TEXT("InitializeApp: RegisterClass failed."));
  125.         return FALSE;
  126.     }
  127.  
  128.     wc.style        = CS_HREDRAW | CS_VREDRAW;
  129.     wc.lpfnWndProc  = TextWndProc;
  130.     wc.hbrBackground    = (HBRUSH)(COLOR_INACTIVECAPTION);
  131.     wc.lpszClassName    = TEXT("TextClass");
  132.  
  133.     if (!RegisterClass(&wc)) {
  134.         ErrorMsg(TEXT("InitializeApp: RegisterClass failed."));
  135.         return FALSE;
  136.     }
  137.  
  138.     ghMenu = LoadMenu(ghModule, TEXT("CRYPTFILERMenu"));
  139.  
  140.     if (!ghMenu)
  141.         return FALSE;    
  142.     
  143.     AlgidEncrypt = CALG_RC2;
  144.     AlgidSign = CALG_MD4;
  145.     
  146.     ghwndMain = CreateWindow(TEXT("CRYPTFILERClass"),
  147.                              TEXT("CRYPTFILER"),
  148.                              WS_OVERLAPPEDWINDOW,
  149.                              CW_USEDEFAULT,
  150.                              CW_USEDEFAULT,
  151.                              MAIN_WIDTH,
  152.                              MAIN_HEIGHT,
  153.                              HWND_DESKTOP,
  154.                              ghMenu,
  155.                              ghModule,
  156.                              NULL);
  157.  
  158.     if (!ghwndMain) {
  159.         ErrorMsg(TEXT("InitializeApp: CreateWindow failed."));
  160.         return FALSE;
  161.     }
  162.  
  163.     if (!MakeHashDirectory()) {
  164.         ErrorMsg(TEXT("InitializeApp: MakeHashDirectory failed."));
  165.         return FALSE;
  166.     }
  167.  
  168.     return TRUE;
  169. }
  170.  
  171. LRESULT WINAPI MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  172. {
  173.     INT bRet;
  174.     
  175.     switch (message) {
  176.         case WM_CREATE: { 
  177.         LOGFONT    lf;
  178.         HDC        hDC;
  179.         HGDIOBJ    hOldFont;
  180.         HGDIOBJ       hFont;
  181.         TEXTMETRIC tm;
  182.         DWORD dwThreadID;
  183.         DWORD dwLastError = GetLastError();
  184.         LPCINFO lpCInfo;
  185.             
  186.         //
  187.         // Initialize drive list and Set Directory critical sections.
  188.         //
  189.         InitializeCriticalSection(&gDrvCS);
  190.        
  191.         ghDrvThread = CreateThread(NULL, 0,
  192.                                    (LPTHREAD_START_ROUTINE)EnumDrives,
  193.                                    (LPVOID)&glpDrives,
  194.                                    0, &dwThreadID);
  195.         
  196.         if (!ghDrvThread) {
  197.             ErrorMsg(TEXT("MainWndProc: CreateThread failed."));
  198.             return 0;
  199.         }       
  200.         
  201.         //
  202.         // Compute default application font by creating a bold version
  203.         //   of the system default icon font.
  204.         //
  205.         if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, 
  206.                                   sizeof(lf), 
  207.                                   (PVOID) &lf, 
  208.                                   FALSE)) {
  209.             
  210.             ErrorMsg(TEXT("MainWndProc: SystemParametersInfo failed."));
  211.             return 0;
  212.         }
  213.  
  214.         hDC = GetDC(hwnd);
  215.  
  216.         if (!hDC) {
  217.             ErrorMsg(TEXT("MainWndProc: GetDC failed."));
  218.             return 0;
  219.         }
  220.         
  221.         //
  222.         // this is the height for 8 point size font in pixels.
  223.         //  (1 point = 1/72 in.)
  224.         //
  225.         lf.lfHeight = 8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72;
  226.         lf.lfWeight = BOLD_FONT;
  227.  
  228.         ghFont = CreateFontIndirect(&lf);
  229.         if (!ghFont) {
  230.             ErrorMsg(TEXT("MainWndProc: CreateFontIndirect failed."));
  231.             return 0;
  232.         }
  233.  
  234.         hOldFont = SelectObject(hDC, ghFont);
  235.  
  236.         if (!hOldFont || (HGDIOBJ)hOldFont == (HGDIOBJ)GDI_ERROR) {
  237.             ErrorMsg(TEXT("MainWndProc: SelectObject failed."));
  238.             return 0;
  239.         }
  240.  
  241.         if (!GetTextMetrics(hDC, &tm)) {
  242.             ErrorMsg(TEXT("MainWndProc: GetTextMetrics failed."));
  243.             return 0;
  244.         }
  245.  
  246.         if (hOldFont) {
  247.             hFont = SelectObject(hDC, hOldFont);
  248.              if (!hFont || (HGDIOBJ)hFont == (HGDIOBJ)GDI_ERROR) {
  249.                  ErrorMsg(TEXT("MainWndProc: SelectObject failed."));
  250.                  return 0;
  251.              }
  252.          } 
  253.         
  254.         if (!ReleaseDC(hwnd, hDC)) {
  255.             ErrorMsg(TEXT("MainWndProc: ReleaseDC failed.\r\n"));
  256.             return 0;
  257.         }
  258.  
  259.         //
  260.         // Create Drive windows
  261.         //
  262.         gDrvChildInfo.hParent = hwnd;
  263.       
  264.           ghwndDrv = CreateWindow(TEXT("DrvClass"), NULL,
  265.                                  WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
  266.                                  0, 0, 0, 0,
  267.                                  hwnd, (HMENU) 1, ghModule,
  268.                                  (LPVOID)&gDrvChildInfo);
  269.  
  270.         if (!ghwndDrv) {
  271.             ErrorMsg(TEXT("MainWndProc: CreateWindow failed."));
  272.             dwLastError = GetLastError();
  273.             return 0;
  274.         }
  275.  
  276.         ghwndDrv = ghwndDrv;
  277.  
  278.         //
  279.         // Set initial focus to Drive Child 1's Directory listbox.
  280.         //
  281.         lpCInfo = (LPCINFO)GetWindowLong(ghwndDrv, GWL_USERDATA);
  282.  
  283.         if (!lpCInfo) {
  284.             ErrorMsg(TEXT("MainWndProc: WM_CREATE: lpCInfo is NULL."));
  285.             return 0;
  286.         }
  287.         
  288.         ghFocusWnd = lpCInfo->hDirLB;
  289.  
  290.         if (!ghFocusWnd) {
  291.             ErrorMsg(TEXT("MainWndProc: GetWindowLong failed."));
  292.             return 0;
  293.         }
  294.             
  295.         // Create DriveBar, FunctionBar and Command windows
  296.         
  297.         ghwndDrives = CreateWindow(TEXT("DriveBarClass"), NULL,
  298.                                     WS_CHILD | WS_VISIBLE | WS_BORDER,
  299.                                    0, 0, 0, 0,
  300.                                    hwnd, (HMENU) 3, ghModule,
  301.                                    (LPVOID)NULL);
  302.  
  303.         if (!ghwndDrives) {
  304.             ErrorMsg(TEXT("MainWndProc: CreateWindow failed."));
  305.             return 0;
  306.         }
  307.  
  308.         UpdateDrivesMenu(ghMenu, ghDrvThread);
  309.                     
  310.           return 1;
  311.       }
  312.  
  313.       case WM_COMMAND:{
  314.  
  315.         //
  316.         // The menu Identifiers for the drives are (potentially)
  317.         // MM_DRIVE_NUM + 0 thru MM_DRIVE_NUM + 25. They all go to the
  318.         // same case, so we will put the Menu ID in lParam, and
  319.         // MM_DRIVE_NUM in LOWORD(wParam).
  320.         //
  321.         if( (LOWORD(wParam) - MM_DRIVE_NUM) <= 25 &&
  322.             (LOWORD(wParam) - MM_DRIVE_NUM) >= 0 ){
  323.             lParam = LOWORD(wParam);
  324.             wParam = MM_DRIVE_NUM;
  325.         }
  326.  
  327.         switch (LOWORD(wParam)) {
  328.             //
  329.             // If a drive is selected from the Drives menu, or clicked
  330.             //  on the drives toolbar, the currently active child will
  331.             //  switch to this drive. Message 'unconverted' (see top of
  332.             //  WM_COMMAND case), and sent to DriveBarProc
  333.             //
  334.             case MM_DRIVE_NUM:{
  335.  
  336.                 SendMessage(ghwndDrives, WM_COMMAND,
  337.                             (WPARAM)lParam, (LPARAM)NULL);
  338.                 return 1;
  339.             }
  340.  
  341.             //
  342.             // Passes these WM_COMMAND messages to the appropriate active child
  343.             //  window proc for processing
  344.             //
  345.             case MM_TAB:
  346.             case MM_ESCAPE:
  347.             case MM_ENCRYPT_DECRYPT:
  348.             case MM_SIGN:
  349.             case MM_VERIFY:
  350.             case MM_EXPAND:{
  351.  
  352.                 SendMessage(ghwndDrv, WM_COMMAND, wParam, lParam);
  353.                 return 1;
  354.             }
  355.  
  356.             case MM_EXIT:{
  357.                 SendMessage(ghwndMain, WM_CLOSE, wParam, lParam);
  358.                 return 1;
  359.             }
  360.  
  361.             //
  362.             // Creates the drive enumeration thread to re-enumerate the
  363.             //   available drives in the main menu.  Also sends a refresh
  364.             //   to the active drive child, and repaints the window.
  365.             //
  366.             case MM_REFRESH: {
  367.                 DWORD   dwThreadID;
  368.  
  369.                 //
  370.                 // Initialize/Refresh Drives linked list
  371.                 //
  372.  
  373.                 if( WaitForSingleObject(ghDrvThread, 0) != WAIT_TIMEOUT ){
  374.  
  375.                     //
  376.                     // Close previous Drive Thread handle before creating new handle.
  377.                     //
  378.                     CloseHandle( ghDrvThread );
  379.  
  380.                     ghDrvThread = CreateThread(NULL, 0,
  381.                                            (LPTHREAD_START_ROUTINE)EnumDrives,
  382.                                            (LPVOID)&glpDrives,
  383.                                            0, &dwThreadID);
  384.  
  385.                     //
  386.                     // Refresh active child, drive toolbar, and drives menu
  387.                     //
  388.                     SendMessage(ghwndDrv, WM_COMMAND, wParam, lParam);
  389.                     SendMessage(ghwndDrives, WM_COMMAND, wParam, lParam);
  390.                     UpdateDrivesMenu(ghMenu, ghDrvThread);
  391.  
  392.                     //
  393.                     // Mark all for repaint
  394.                     //
  395.                     InvalidateRect(hwnd,NULL,TRUE);
  396.  
  397.                 }
  398.                 else
  399.                     MessageBeep(MB_ICONASTERISK);
  400.  
  401.                 return 1;
  402.             }
  403.  
  404.             //
  405.             // Swaps the directory and file list boxes of the active drv child.
  406.             //
  407.             case MM_SWAP:{
  408.                 LPCINFO lpCInfo;
  409.                 RECT    rect;
  410.  
  411.                 lpCInfo = (LPCINFO)GetWindowLong(ghwndDrv, GWL_USERDATA);
  412.  
  413.                 if (!lpCInfo) {
  414.                     ErrorMsg(TEXT("MainWndProc: MM_SWAP: lpCInfo is NULL."));
  415.                     return FALSE;
  416.                 }
  417.                 
  418.                 //
  419.                 // Switch the flag which indicates which side the Directory
  420.                 //  LB is on.  This is used by the WM_SIZE case of DrvWndProc.
  421.                 //
  422.                 lpCInfo->fDirLeft = !lpCInfo->fDirLeft;
  423.  
  424.                 //
  425.                 // Send size message with current size to active child,
  426.                 //   in order to redraw the listboxes.
  427.                 //
  428.                 if( !GetClientRect( ghwndDrv, &rect ) )
  429.                     return 0;
  430.  
  431.                 SendMessage( ghwndDrv, WM_SIZE, SIZENORMAL,
  432.                              MAKELONG( rect.right - rect.left,
  433.                                        rect.bottom - rect.top) );
  434.                 return 1;
  435.             }
  436.  
  437.             case MM_KEEPCMD:{
  438.  
  439.                 gfKeepCommandWin = !gfKeepCommandWin;
  440.  
  441.                 if( gfKeepCommandWin )
  442.                     CheckMenuItem( ghMenu, MM_KEEPCMD,
  443.                                     MF_BYCOMMAND | MF_CHECKED);
  444.                 else
  445.                     CheckMenuItem( ghMenu, MM_KEEPCMD,
  446.                                 MF_BYCOMMAND | MF_UNCHECKED);
  447.             }
  448.             break;
  449.  
  450.             //
  451.             // Toggles the relative Drive Child orientaion between
  452.             // Over/under and side/side.  gfDrvWndOrient is a flag checked
  453.             // by WM_SIZE to size Drv children
  454.             //
  455.             case MM_ORIENT:{
  456.                 RECT    rect;
  457.  
  458.                 if( gfDrvWndOrient == OVER_UNDER )
  459.                     gfDrvWndOrient = SIDE_BY_SIDE;
  460.                 else
  461.                     gfDrvWndOrient = OVER_UNDER;
  462.  
  463.                 //
  464.                 // Send size message with current size to self (main window),
  465.                 //   in order to redraw the Drv children.
  466.                 //
  467.                 if( !GetClientRect( hwnd, &rect ) )
  468.                     return 0;
  469.  
  470.                 SendMessage( hwnd, WM_SIZE, SIZENORMAL,
  471.                              MAKELONG( rect.right - rect.left,
  472.                                        rect.bottom - rect.top) );
  473.  
  474.                 InvalidateRect(ghwndDrv,NULL,TRUE);
  475.            
  476.                 return 1;
  477.             }
  478.  
  479.             //
  480.             // Launches the About DialogBox.
  481.             //
  482.             case MM_ABOUT:{
  483.                 if (DialogBox(ghModule, 
  484.                               TEXT("AboutBox"), 
  485.                               ghwndMain, 
  486.                               (DLGPROC)AboutProc) == -1)
  487.                         
  488.                     ErrorMsg(TEXT("Main: About Dialog Creation Error!"));
  489.                 return 1;
  490.             }
  491.  
  492.             case ID_HELP:
  493.                 if (!WinHelp(hwnd, TEXT("cf.hlp"), HELP_CONTENTS, 0L)) {
  494.                     ErrorMsg(TEXT("MainWndProc: WinHelp failed."));
  495.                     return 0;
  496.                 }
  497.             
  498.                 return 1;
  499.  
  500.             case ID_ENCRYPTION_ALGORITHM:
  501.                 bRet = DialogBox(ghModule, 
  502.                                  TEXT("ENCRYPTION_ALGORITHM"), 
  503.                                  ghwndMain, 
  504.                                  EncryptDlgProc);
  505.                 if (bRet == TRUE)
  506.                     InvalidateRect(ghwndMain, NULL, TRUE);
  507.                 else if (bRet == FALSE)
  508.                     return FALSE;
  509.                 return 1; 
  510.  
  511.             case ID_SIGNATURE_ALGORITHM:
  512.                 bRet = DialogBox(ghModule, TEXT("HASH_ALGORITHM"), ghwndMain, HashDlgProc);
  513.                 if (bRet == TRUE)
  514.                     InvalidateRect(ghwndMain, NULL, TRUE);
  515.                 else if (bRet == FALSE)
  516.                     return FALSE;
  517.                 return 1;
  518.         
  519.             case MM_PASS:
  520.                 AlgidEncrypt = 0;
  521.                 if (!GetPass(ghwndMain) || strlen(sPass) == 0) {
  522.                     AlgidEncrypt = CALG_RC2;
  523.                     return FALSE;
  524.                 }
  525.                 return 1;
  526.                     
  527.             case ID_HIDE: {
  528.                 DWORD cm;
  529.                 
  530.                 cm = CheckMenuItem(ghMenu, ID_HIDE, MF_CHECKED);
  531.  
  532.                 if (cm == MF_CHECKED) {
  533.                     if (ShowSignatures())
  534.                         CheckMenuItem(ghMenu, ID_HIDE, MF_UNCHECKED);
  535.                 }
  536.                 else if (cm == MF_UNCHECKED) {
  537.                     if (HideSignatures())
  538.                         CheckMenuItem(ghMenu, ID_HIDE, MF_CHECKED);
  539.                 }
  540.                 else {
  541.                     ErrorMsg(TEXT("ID_HIDE: CheckMenuItem failed."));
  542.                     return 0;
  543.                 }
  544.  
  545.                 return 1;
  546.             }
  547.             
  548.             default:
  549.                 return(DefWindowProc(hwnd, message, wParam, lParam));
  550.         }
  551.         return 1;
  552.       }
  553.       //
  554.       // Whenever the window is resized, its children have to be
  555.       //  resized accordingly.  The GetWindowLong values are the height
  556.       //  of the windows queried by this function, and are set in the
  557.       //  WM_CREATE cases of their respective WNDPROCs.
  558.       //
  559.       case WM_SIZE:{
  560.         int DrvWndHeight;
  561.  
  562.         //
  563.         // Always put the drives toolbar at the top of the frame window
  564.         //
  565.         MoveWindow(ghwndDrives,
  566.            0,
  567.            0,
  568.            LOWORD(lParam),
  569.            GetWindowLong(ghwndDrives, GWL_USERDATA),
  570.            TRUE);
  571.  
  572.         //
  573.         // Always size the Drive Children between the Drives and Command
  574.         // windows. The width is set so that borders overlap.
  575.         //
  576.  
  577.         if( gfDrvWndOrient == OVER_UNDER ){
  578.  
  579.             DrvWndHeight = ( HIWORD(lParam) -
  580.                            GetWindowLong(ghwndDrives, GWL_USERDATA));
  581.  
  582.             MoveWindow(ghwndDrv,
  583.                        -1,
  584.                        GetWindowLong(ghwndDrives, GWL_USERDATA),
  585.                        (LOWORD(lParam) + 2),
  586.                        DrvWndHeight,
  587.                        TRUE);
  588.         }
  589.         else{
  590.  
  591.             DrvWndHeight = HIWORD(lParam) -
  592.                            GetWindowLong(ghwndDrives, GWL_USERDATA);
  593.  
  594.             MoveWindow(ghwndDrv,
  595.                         -1,
  596.                         GetWindowLong(ghwndDrives, GWL_USERDATA),
  597.                         (LOWORD(lParam)/2 + 1)*2,
  598.                         DrvWndHeight,
  599.                         TRUE);
  600.         }
  601.  
  602.         return 1;
  603.       }
  604.  
  605.       case WM_DESTROY: {
  606.         Logoff(hwnd);
  607.        
  608.            DeleteHashDirectory();
  609.  
  610.         free(lpDriveStrings);
  611.         
  612.         DestroyMenu(ghMenu);
  613.         
  614.         SendMessage(ghwndDrv, WM_CLOSE, 0, 0);
  615.         
  616.         //
  617.         // Close last drive thread handle,
  618.         //  the created font, and the Drive list critical section.
  619.         //
  620.         CloseHandle( ghDrvThread );
  621.  
  622.         DeleteObject(ghFont);
  623.  
  624.         DeleteCriticalSection(&gDrvCS);
  625.  
  626.         PostQuitMessage(0);
  627.     
  628.         return 1;
  629.       }
  630.  
  631.       default:
  632.         return DefWindowProc(hwnd, message, wParam, lParam);
  633.     }
  634. }
  635.  
  636. LRESULT WINAPI AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  637. {
  638.     switch (message) {
  639.       case WM_INITDIALOG:{
  640.         return TRUE;
  641.       }
  642.  
  643.       case WM_COMMAND:{
  644.         if (wParam == IDOK)
  645.             EndDialog(hDlg, wParam);
  646.         break;
  647.       }
  648.     }
  649.  
  650.     return FALSE;
  651.  
  652.     UNREFERENCED_PARAMETER(lParam);
  653.     UNREFERENCED_PARAMETER(hDlg);
  654. }
  655.  
  656. /************************************************************************\
  657. * DriveBarProc()                                                        
  658. *                                                                                
  659. * Drive Toolbar procedure for displaying available drive Icons.            
  660. *  A bitmap button is displayed corresponding to the drive type of the    
  661. *  given drive, with the drive letter alongside.                        
  662. *  ghwndDrives is the global handle assoc. w/ this window procedure.    
  663. \***********************************************************************/
  664.  
  665. LRESULT WINAPI DriveBarProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  666. {
  667.     static HBITMAP  hDrvBmp[NUM_BITMAPS];
  668.     static HBRUSH   hBrush;         // background brush
  669.     static int      nDrvEntryWidth; // width of button/letter entry
  670.     static int      yVal;           // y value in toolbar for top left of bmp
  671.     static LPBINFO  lpDrvButtonRoot;
  672.     static int      nActiveDrvIndex;
  673.  
  674.     switch (message)
  675.     {
  676.         case WM_CREATE:{
  677.             HDC        hDC;
  678.             HGDIOBJ    hOldFont;
  679.             TEXTMETRIC tm;
  680.             LONG       lHeight;
  681.  
  682.  
  683.             lpDrvButtonRoot = NULL;
  684.  
  685.             //
  686.             // Load drive button bitmaps.
  687.             //
  688.             for(yVal = 0; yVal < NUM_BITMAPS; yVal++)
  689.                 hDrvBmp[yVal] = LoadBitmap( ghModule,
  690.                                       MAKEINTRESOURCE(UB_BMP_MARKER + yVal) );
  691.  
  692.             //
  693.             // Sets background color of Toolbar non-modal dialog children.
  694.             //
  695.             hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
  696.  
  697.             hDC = GetDC(hwnd);
  698.  
  699.             hOldFont = SelectObject(hDC, ghFont);
  700.             GetTextMetrics(hDC, &tm);
  701.  
  702.             //
  703.             // base the height of the window on size of text
  704.             //
  705.             lHeight = tm.tmHeight + GetSystemMetrics(SM_CYBORDER) + 6;
  706.  
  707.             //
  708.             // saved the window height, drive button entry width
  709.             //   and button y starting value for later reference
  710.             //
  711.             SetWindowLong(hwnd, GWL_USERDATA, lHeight);
  712.  
  713.             //
  714.             // Width of one button entry = spacing, button, sm. space,
  715.             //   drive letter, spacing.
  716.             //
  717.             nDrvEntryWidth = DRIVE_BITMAP_SPACING + DRIVE_BITMAP_WIDTH +
  718.                              DRIVE_LETTER_SPACING + tm.tmAveCharWidth +
  719.                              DRIVE_BITMAP_SPACING;
  720.  
  721.             //
  722.             // Center bitmaps (by height) in drive toolbar.
  723.             //
  724.             yVal = (lHeight - DRIVE_BITMAP_HEIGHT)/2;
  725.  
  726.             SelectObject(hDC, hOldFont);
  727.             ReleaseDC(hwnd, hDC);
  728.  
  729.             SendMessage(hwnd, WM_COMMAND, (WPARAM)MM_REFRESH, (LPARAM)NULL);
  730.  
  731.             break;
  732.         }
  733.  
  734.         case WM_COMMAND:{
  735.             //
  736.             // The button Identifiers for the drives are (potentially)
  737.             // MM_DRIVE_NUM + 0 thru MM_DRIVE_NUM + 25. They all go to the
  738.             // same case, so we will put the Menu ID in lParam, and
  739.             // MM_DRIVE_NUM in LOWORD(wParam).
  740.             //
  741.             if( (LOWORD(wParam) - MM_DRIVE_NUM) <= 25 &&
  742.                 (LOWORD(wParam) - MM_DRIVE_NUM) >= 0 ){
  743.                 lParam = LOWORD(wParam);
  744.                 wParam = MM_DRIVE_NUM;
  745.             }
  746.  
  747.             switch( LOWORD(wParam) ){
  748.               case MM_REFRESH:{
  749.  
  750.                 LPDINFO lpWalk;
  751.                 LPBINFO lpBWalk, lpBHold;
  752.                 LPCINFO lpCInfo;
  753.                 int     xVal = 0;
  754.                 int        nCount = MM_DRIVE_NUM;
  755.                                
  756.                 lpCInfo = (LPCINFO)GetWindowLong(ghwndDrv, GWL_USERDATA);
  757.  
  758.                 if (!lpCInfo) {
  759.                     ErrorMsg(TEXT("DriveBarProc: MM_REFRESH: lpCInfo is NULL."));
  760.                     return FALSE;
  761.                 }
  762.                 
  763.                 //
  764.                 // Wait for Drive Thread to complete, if necessary.
  765.                 //
  766.                 WaitForSingleObject(ghDrvThread, INFINITE);
  767.                 EnterCriticalSection(&gDrvCS);
  768.  
  769.                 //
  770.                 // Traverse DRVINFO linked list, creating drive buttons and
  771.                 //   allocating corresp. structures as necessary.
  772.                 //
  773.                 lpWalk = glpDrives;
  774.                 lpBWalk = lpDrvButtonRoot;
  775.  
  776.                 while( lpWalk != NULL ){
  777.                     if( lpBWalk == NULL ){ //If at the end of the button list
  778.  
  779.                         // Allocate a LPBINFO (button) structure
  780.                         
  781.                         lpBWalk = (LPBINFO)malloc((DWORD)sizeof(BINFO));
  782.                         
  783.                         if (!lpBWalk) {
  784.                             ErrorMsg(TEXT("DriveBarProc: MM_REFRESH: malloc failed."));
  785.                             return 0;
  786.                         }
  787.                         
  788.                         lpBWalk->next = NULL;
  789.  
  790.                         // Create a button window
  791.                         lpBWalk->hButton = (HANDLE)CreateWindow(TEXT("BUTTON"),
  792.                                                  lpWalk->DriveName,
  793.                                                  WS_CHILD | WS_VISIBLE |
  794.                                                  BS_OWNERDRAW ,
  795.                                                  xVal + DRIVE_BITMAP_SPACING,
  796.                                                  yVal,
  797.                                                  DRIVE_BITMAP_WIDTH,
  798.                                                  DRIVE_BITMAP_HEIGHT,
  799.                                                  hwnd,
  800.                                                  (HMENU)nCount,
  801.                                                  ghModule,
  802.                                                  NULL);
  803.                         
  804.                         // Insert structure into list
  805.                         if( lpDrvButtonRoot == NULL)
  806.                             lpDrvButtonRoot = lpBHold = lpBWalk;
  807.                         else{
  808.                             lpBHold->next = lpBWalk;
  809.                             lpBWalk->next = NULL;
  810.                         }
  811.  
  812.                     }
  813.  
  814.                     // An LPBINFO (button) structure exists: now initialize
  815.  
  816.                     // Set Title of Button (Drive Letter)
  817.  
  818.                     SetWindowText(lpBWalk->hButton, lpWalk->DriveName);
  819.  
  820.                     // Set Child Window ID for Button
  821.                     // SetMenu(lpBWalk->hButton, (HMENU)nCount);
  822.  
  823.                     // Determine button up/down status
  824.                     if( lpCInfo->lpDriveInfo == lpWalk ){
  825.                         nActiveDrvIndex = nCount;
  826.                         lpBWalk->fButtonDown = TRUE;
  827.                     }
  828.                     else
  829.                         lpBWalk->fButtonDown = FALSE;
  830.  
  831.                     // Set a pointer to the corresponding drive in Drive list
  832.                     lpBWalk->lpDrive = lpWalk;
  833.  
  834.                     nCount++;
  835.                     xVal += nDrvEntryWidth;
  836.                     lpBHold = lpBWalk;
  837.                     lpBWalk = lpBWalk->next;
  838.  
  839.                     lpWalk = lpWalk->next;
  840.                 
  841.                 }
  842.  
  843.                 LeaveCriticalSection(&gDrvCS);
  844.  
  845.                 //
  846.                 // Free any remaining button windows.
  847.                 //
  848.                 while( lpBWalk != NULL ){
  849.                     // NULL out new end of list
  850.                     lpBHold->next = NULL;
  851.  
  852.                     // Assign pointer to doomed node
  853.                     lpBHold = lpBWalk;
  854.                     lpBWalk = lpBWalk->next;
  855.  
  856.                     // Free doomed node resources
  857.                     if( !DestroyWindow(lpBHold->hButton) )
  858.                         ErrorMsg(TEXT("DriveBarProc: Drive Button Destroy Error"));
  859.  
  860.                     free(lpBHold);
  861.                 }
  862.  
  863.                 SendMessage(hwnd, WM_PAINT, (WPARAM)NULL, (LPARAM)NULL);
  864.                                 
  865.                 break;
  866.               }
  867.  
  868.  
  869.               //
  870.               // switches the drive button to the newly active drv child's
  871.               //   current drive.  Called by WM_MOUSEACTIVATE in DrvWndProc,
  872.               //   as well as ChangeDrive.
  873.               //   lParam contains the drive linked list pointer of the active
  874.               //   drv child's LPCINFO struct.
  875.               //
  876.               case MM_ACTIVEDRV:{
  877.                 LPBINFO lpBWalk = lpDrvButtonRoot;
  878.                 int     nCount = 0;
  879.  
  880.                 //
  881.                 // 'unpush' old active button
  882.                 //
  883.                 for( nCount = MM_DRIVE_NUM; nCount < nActiveDrvIndex; nCount++)
  884.                     lpBWalk = lpBWalk->next;
  885.                 lpBWalk->fButtonDown = FALSE;
  886.  
  887.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  888.  
  889.                 //
  890.                 // change active drive to new before redrawing old.
  891.                 //  'push' new active button
  892.                 //
  893.                 lpBWalk = lpDrvButtonRoot;
  894.                 nCount = MM_DRIVE_NUM;
  895.                 while( lpBWalk->lpDrive != (LPDINFO)lParam){
  896.                     lpBWalk = lpBWalk->next;
  897.                     nCount++;
  898.                 }
  899.  
  900.                 nActiveDrvIndex = nCount;
  901.  
  902.                 lpBWalk->fButtonDown = TRUE;
  903.  
  904.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  905.  
  906.                 break;
  907.               }
  908.  
  909.               //
  910.               // Changes drive of active child.  ButtonID in lParam.
  911.               //
  912.               case MM_DRIVE_NUM:{
  913.  
  914.                 LPBINFO lpBWalk = lpDrvButtonRoot;
  915.                 int     nCount = 0;
  916.                 TCHAR    szDrvBuff[DIRECTORY_STRING_SIZE];
  917.  
  918.                 //
  919.                 // if drive chosen is already current drive, leave.
  920.                 //
  921.                 if( nActiveDrvIndex == (int)lParam )
  922.                     break;
  923.  
  924.                 //
  925.                 // unpush' old active button
  926.                 //
  927.                 for( nCount = MM_DRIVE_NUM; nCount < nActiveDrvIndex; nCount++)
  928.                     lpBWalk = lpBWalk->next;
  929.                 lpBWalk->fButtonDown = FALSE;
  930.  
  931.                 //
  932.                 // change active drive to new before redrawing old.
  933.                 //
  934.                 nActiveDrvIndex = (int)lParam;
  935.  
  936.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  937.  
  938.                 //
  939.                 // 'push' new active button
  940.                 //
  941.                 lpBWalk = lpDrvButtonRoot;
  942.  
  943.                 for( nCount = MM_DRIVE_NUM; nCount < nActiveDrvIndex; nCount++)
  944.                     lpBWalk = lpBWalk->next;
  945.                 lpBWalk->fButtonDown = TRUE;
  946.  
  947.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  948.  
  949.                 GetWindowText(lpBWalk->hButton, szDrvBuff,
  950.                               DIRECTORY_STRING_SIZE);
  951.  
  952.                 if( !ChangeDrive(szDrvBuff, (DWORD)nActiveDrvIndex) ){
  953.                     ErrorMsg(TEXT("Error changing Drives.\r\n"));
  954.                     return 0;
  955.                 }
  956.  
  957.                 break;
  958.               }
  959.             }
  960.             return 1;
  961.         }
  962.  
  963.         //
  964.         // Sent by all created buttons for initialization purposes.
  965.         //
  966.         case WM_MEASUREITEM:{
  967.             LPMEASUREITEMSTRUCT lpMIS;
  968.  
  969.             lpMIS = (LPMEASUREITEMSTRUCT)lParam;
  970.  
  971.             lpMIS->CtlType = ODT_BUTTON;
  972.             lpMIS->CtlID = (UINT)wParam;
  973.             lpMIS->itemWidth = DRIVE_BITMAP_WIDTH;
  974.             lpMIS->itemHeight = DRIVE_BITMAP_HEIGHT;
  975.  
  976.             return 1;
  977.         }
  978.  
  979.         //
  980.         // Sent by owner draw drive buttons when needing redrawing.
  981.         //
  982.         case WM_DRAWITEM:{
  983.             LPBINFO lpBWalk = lpDrvButtonRoot;
  984.             int     nCount;
  985.             int     nBmpIndex;
  986.             HDC     hDC;
  987.             HDC     hCompatDC;
  988.             HGDIOBJ hOldBitmap;
  989.             TCHAR    szDrvBuff[DIRECTORY_STRING_SIZE];
  990.             LPDRAWITEMSTRUCT    lpDIS;
  991.  
  992.             lpDIS = (LPDRAWITEMSTRUCT)lParam;
  993.  
  994.             for( nCount = MM_DRIVE_NUM; nCount < (int)wParam; nCount++)
  995.                 lpBWalk = lpBWalk->next;
  996.  
  997.             //
  998.             // If not the current selected button, handle button stuff.
  999.             //
  1000.             if( (int)wParam != nActiveDrvIndex ){
  1001.                 //
  1002.                 // mousebutton is down...
  1003.                 //
  1004.                 if( lpDIS->itemAction & ODA_SELECT ){
  1005.                     //
  1006.                     // left button region, 'unpush' button
  1007.                     //
  1008.                     if( lpDIS->itemState == (UINT)ODS_FOCUS )
  1009.                         lpBWalk->fButtonDown = FALSE;
  1010.                     //
  1011.                     // clicked on a button, draw 'pushed' button
  1012.                     //
  1013.                     if( lpDIS->itemState == (UINT)(ODS_SELECTED | ODS_FOCUS))
  1014.                         lpBWalk->fButtonDown = TRUE;
  1015.                 }
  1016.             }
  1017.  
  1018.             //
  1019.             // draw current state of button.
  1020.             //
  1021.             GetWindowText(lpDIS->hwndItem, szDrvBuff,
  1022.                           DIRECTORY_STRING_SIZE);
  1023.  
  1024.             szDrvBuff[1] = TEXT('\0');
  1025.  
  1026.             hCompatDC = CreateCompatibleDC(lpDIS->hDC);
  1027.             hOldBitmap = CreateCompatibleBitmap(hCompatDC,
  1028.                                                 DRIVE_BITMAP_WIDTH,
  1029.                                                 DRIVE_BITMAP_HEIGHT);
  1030.  
  1031.             nBmpIndex = GetDriveBitmap(lpBWalk);
  1032.  
  1033.             SelectObject( hCompatDC, hDrvBmp[nBmpIndex] );
  1034.  
  1035.             if( !hOldBitmap )
  1036.                 ErrorMsg(TEXT("WM_DRAWITEM: SelectObject failure."));
  1037.  
  1038.             if( !BitBlt(lpDIS->hDC, lpDIS->rcItem.left, lpDIS->rcItem.top,
  1039.                    DRIVE_BITMAP_WIDTH,
  1040.                    DRIVE_BITMAP_HEIGHT,
  1041.                    hCompatDC, 0, 0, SRCCOPY) )
  1042.                 ErrorMsg(TEXT("WM_DRAWITEM: BitBlt failure."));
  1043.  
  1044.  
  1045.             SelectObject( hCompatDC, hOldBitmap);
  1046.             DeleteDC(hCompatDC);
  1047.  
  1048.             hDC = GetDC(hwnd);
  1049.             SetBkMode(hDC, OPAQUE);
  1050.             SetTextColor(hDC, GetSysColor(COLOR_MENUTEXT) );
  1051.             SetBkColor(hDC, GetSysColor(COLOR_MENU) );
  1052.  
  1053.             TextOut(hDC,
  1054.                     ((int)(wParam - MM_DRIVE_NUM) * nDrvEntryWidth) +
  1055.                         DRIVE_BITMAP_SPACING + DRIVE_BITMAP_WIDTH +
  1056.                         DRIVE_LETTER_SPACING,
  1057.                     (GetSystemMetrics(SM_CYBORDER) + 6)/2,
  1058.                     szDrvBuff, 1);
  1059.  
  1060.             SetBkMode(hDC, OPAQUE);
  1061.  
  1062.             ReleaseDC(hwnd, hDC);
  1063.             
  1064.             DeleteObject(hOldBitmap);
  1065.  
  1066.             break;
  1067.         }
  1068.  
  1069.  
  1070.         case WM_PAINT:{
  1071.             HDC     hCompatDC;
  1072.             RECT     rc;
  1073.             PAINTSTRUCT ps;
  1074.  
  1075.             //
  1076.             // Paint btnshadow background.
  1077.             //
  1078.             GetClientRect(hwnd, &rc);
  1079.  
  1080.             BeginPaint(hwnd, &ps);
  1081.  
  1082.             hCompatDC = CreateCompatibleDC(ps.hdc);
  1083.             FillRect(ps.hdc, &rc, hBrush);
  1084.  
  1085.             EndPaint(hwnd, &ps);
  1086.  
  1087.             DeleteDC(hCompatDC);
  1088.             
  1089.             return(TRUE);
  1090.         }
  1091.  
  1092.         case WM_DESTROY:{
  1093.             LPBINFO p, q;
  1094.             LPDINFO p1, q1;
  1095.  
  1096.             DeleteObject(hBrush);
  1097.  
  1098.             for (p = lpDrvButtonRoot; p; p = q) {
  1099.                 q = p->next;
  1100.                 free(p);
  1101.             }
  1102.             
  1103.             for (p1 = glpDrives; p1; p1 = q1) {
  1104.                 q1 = p1->next;
  1105.                 free(p1);
  1106.                 p1 = NULL;
  1107.             }
  1108.             
  1109.             for(yVal = 0; yVal < NUM_BITMAPS; yVal++)
  1110.                 DeleteObject(hDrvBmp[yVal]);
  1111.  
  1112.             break;
  1113.         }
  1114.     }
  1115.     return DefWindowProc(hwnd, message, wParam, lParam);
  1116. }
  1117.  
  1118. /************************************************************************\
  1119. * GetDriveBitmap()                                                        
  1120. *                                                                        
  1121. * Determines the appropriate index into the drive button bitmap array    
  1122. * (hDrvBmp[]), given a pointer to a drive info structure (LPDINFO)    
  1123. *                                                                        
  1124. * lpWalk          -   pointer to LPDINFO structure.                    
  1125. * lpCurrentDrv    -   pointer to current drive of active child.        
  1126. \***********************************************************************/
  1127.  
  1128. int GetDriveBitmap(LPBINFO lpBWalk)
  1129. {
  1130.     int nBmpIndex;
  1131.  
  1132.     EnterCriticalSection(&gDrvCS);
  1133.  
  1134.     switch( lpBWalk->lpDrive->DriveType ){
  1135.         case DRIVE_REMOVABLE:{
  1136.           nBmpIndex = UB_FLOPPY1 - UB_BMP_MARKER;
  1137.           break;
  1138.         }
  1139.  
  1140.         case DRIVE_REMOTE:{
  1141.           nBmpIndex = UB_REMOTE1 - UB_BMP_MARKER;
  1142.             break;
  1143.         }
  1144.  
  1145.         case DRIVE_CDROM:{
  1146.           nBmpIndex = UB_CD1 - UB_BMP_MARKER;
  1147.             break;
  1148.         }
  1149.  
  1150.         case DRIVE_FIXED:
  1151.         default:{
  1152.           nBmpIndex = UB_FIXED1 - UB_BMP_MARKER;
  1153.             break;
  1154.         }
  1155.     }
  1156.  
  1157.     LeaveCriticalSection(&gDrvCS);
  1158.  
  1159.     if( lpBWalk->fButtonDown == TRUE )
  1160.         nBmpIndex++;
  1161.  
  1162.     return(nBmpIndex);
  1163. }
  1164.  
  1165. /********************************************************************************\
  1166. * ChangeDrive()
  1167. *
  1168. *   Changes the current drive of the child.  Called by the MM_DRIVE_NUM
  1169. *   cases in MainWndProc and DriveBarProc.  This is caused by choosing a
  1170. *   Drive menu item or selecting a drive button from the drive toolbar.
  1171. *
  1172. *   lpszDriveName -   points to a buffer containing the name of the drive
  1173. *   DriveID       -   points to the ID of the Menu item or button, which
  1174. *                         corresponds to the index into the drives linked list
  1175. *                         of the new drive.
  1176. \********************************************************************************/
  1177.  
  1178. BOOL ChangeDrive(LPTSTR lpszDriveName, DWORD DriveIndex)
  1179. {
  1180.     LPCINFO     lpCInfo;
  1181.     LPDINFO     lpWalk;
  1182.     DWORD       dwLoop;
  1183.     UINT        nDriveType;
  1184.  
  1185.     //
  1186.     // Retrieve active child handle.
  1187.     //
  1188.     if( (ghwndDrv != ghwndDrv) ){
  1189.         ErrorMsg(TEXT("A Drive Window Must be Active."));
  1190.         return 0;
  1191.     }
  1192.  
  1193.     //
  1194.     // Retrieving the child window's DRVCHILDINFO data
  1195.     //
  1196.     lpCInfo = (LPCINFO)GetWindowLong(ghwndDrv, GWL_USERDATA);
  1197.  
  1198.     if (!lpCInfo) {
  1199.         ErrorMsg(TEXT("ChangeDrive: lpCInfo is NULL."));
  1200.         return FALSE;
  1201.     }
  1202.     
  1203.     //
  1204.     // Enter Drive list critical section
  1205.     //
  1206.     EnterCriticalSection(&gDrvCS);
  1207.  
  1208.     //
  1209.     // if removable drive, check for existing media.
  1210.     //
  1211.     nDriveType = GetDriveType(lpszDriveName);
  1212.     if( nDriveType == DRIVE_REMOVABLE ||
  1213.         nDriveType == DRIVE_CDROM ){
  1214.         dwLoop = (DWORD)IDOK;
  1215.  
  1216.         while( !CheckRM(lpszDriveName) && (dwLoop == (DWORD)IDOK) ){
  1217.  
  1218.            dwLoop = (DWORD)MessageBox(ghwndMain,
  1219.                            TEXT("CRYPTFILER: Insert some media in drive"),
  1220.                            lpszDriveName, MB_OKCANCEL);
  1221.         }
  1222.  
  1223.         if( dwLoop == (DWORD)IDCANCEL ){
  1224.             SendMessage(ghwndDrives, WM_COMMAND, MM_ACTIVEDRV,
  1225.                         (LPARAM)lpCInfo->lpDriveInfo);
  1226.         LeaveCriticalSection(&gDrvCS);
  1227.             return 0;
  1228.         }
  1229.     }
  1230.  
  1231.     //
  1232.     // set lpDriveInfo member to associated drive struct.
  1233.     //
  1234.     lpWalk = glpDrives;
  1235.     for( dwLoop = 0; dwLoop < DriveIndex - MM_DRIVE_NUM;
  1236.          dwLoop++)
  1237.          lpWalk = lpWalk->next;
  1238.  
  1239.     lpCInfo->lpDriveInfo = lpWalk;
  1240.  
  1241.     lstrcpy(lpCInfo->CaptionBarText, lpWalk->DriveName);
  1242.  
  1243.     LeaveCriticalSection(&gDrvCS);
  1244.  
  1245.     //
  1246.     // This will terminate any currently running drive thread.
  1247.     //
  1248.     SendMessage(ghwndDrv, WM_COMMAND, MM_ESCAPE, (LPARAM)0);
  1249.     lpCInfo->fEscape = FALSE;
  1250.  
  1251.     //
  1252.     // enact the drive change.
  1253.     //
  1254.     PostMessage(ghwndDrv, WM_COMMAND, MM_REFRESH, (LPARAM)0);
  1255.  
  1256.     return 1;
  1257. }
  1258.  
  1259. /********************************************************************************\
  1260. * UpdateDrivesMenu()
  1261. *
  1262. * Adds current drives from the glpDrives linked list to the TEXT('Drives') menu
  1263. *
  1264. * Input: hDrivesMenu - handle to TEXT('Drives') Menu
  1265. *        hThread    - used to wait for drives thread to terminate
  1266. \********************************************************************************/
  1267.  
  1268. BOOL UpdateDrivesMenu(HMENU hMenu, HANDLE hThread)
  1269. {
  1270.     HMENU   hDrivesMenu;
  1271.     int     NumMenuItems;
  1272.     DWORD   dwLoop;
  1273.     LPDINFO lpWalk;
  1274.  
  1275.     //
  1276.     // Remove list of drive menu items from Drive menu, if any.
  1277.     //
  1278.     hDrivesMenu = GetSubMenu( hMenu, DRIVE_MENU_NUM);
  1279.     if(!hDrivesMenu){
  1280.         ErrorMsg(TEXT("UpdateDrivesMenu: GetSubMenu error."));
  1281.         return FALSE;
  1282.     }
  1283.  
  1284.     if((NumMenuItems = GetMenuItemCount(hDrivesMenu)) == -1) {
  1285.         ErrorMsg(TEXT("Main Refresh: Menu Item Count Error."));
  1286.         return FALSE;
  1287.     }
  1288.  
  1289.     //
  1290.     // Delete previous menu items.
  1291.     //
  1292.     for( dwLoop = 0; dwLoop < (DWORD)NumMenuItems; dwLoop++)
  1293.         if(!DeleteMenu(hDrivesMenu, 0, MF_BYPOSITION)){
  1294.             ErrorMsg(TEXT("Main Refresh: Menu Item Delete Error."));
  1295.             return FALSE;
  1296.         }
  1297.  
  1298.     //
  1299.     // Wait for Enumdrv Thread to terminate, and
  1300.     //   enter drive list critical section
  1301.     //
  1302.     if (WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) {
  1303.         ErrorMsg(TEXT("UpdateDrivesMenu: WaitForSingleObject failed."));
  1304.         return FALSE;
  1305.     }
  1306.  
  1307.     EnterCriticalSection(&gDrvCS);
  1308.  
  1309.     //
  1310.     // Fill drive menu from glpDrives linked list
  1311.     //
  1312.     NumMenuItems = 0;
  1313.     lpWalk = glpDrives;
  1314.  
  1315.     while(lpWalk != NULL){
  1316.         if(!InsertMenu(hDrivesMenu, NumMenuItems, MF_STRING | MF_BYPOSITION 
  1317.                     | MF_ENABLED, MM_DRIVE_NUM + NumMenuItems, lpWalk->DriveName)) {
  1318.             ErrorMsg(TEXT("Main Refresh: Menu Item Insert Error."));
  1319.             return FALSE;
  1320.         }
  1321.         NumMenuItems++;
  1322.         lpWalk = lpWalk->next;
  1323.     }
  1324.  
  1325.     LeaveCriticalSection(&gDrvCS);
  1326.  
  1327.     return TRUE;
  1328. }
  1329.  
  1330. /***************************************************************\
  1331. * ErrorMsg()
  1332. *
  1333. *   Displays a Message Box with a given error message.
  1334. *
  1335. \***************************************************************/
  1336.  
  1337. void ErrorMsg(LPTSTR szMsg)
  1338. {
  1339.     TCHAR szHold[DIRECTORY_STRING_SIZE + 1];
  1340.  
  1341.     lstrcpy( szHold, szMsg );
  1342.     lstrcat( szHold, TEXT("\n") );
  1343.  
  1344.        OutputDebugString(szHold);
  1345. }
  1346.