home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / io / filer / filer.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  50KB  |  1,570 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-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. /******************************Module*Header*******************************\
  13. *
  14. * Module Name:  Filer.c
  15. *
  16. *
  17. * Filer: SDK sample
  18. *   +   Simple File Management program with GUI front end.
  19. *       Demonstrates Win32 File I/O API and various User algorithms.
  20. *
  21. * Dependencies:
  22. *
  23. *   (#defines)
  24. *   (#includes)
  25. *         -Enumdrv.h
  26. *         -Walk.h
  27. *         -Drvproc.h
  28. *         -Filer.h
  29. *
  30. \**************************************************************************/
  31. #define  STRICT
  32. #include <windows.h>
  33. #include <stdlib.h>
  34. #include <stdarg.h>
  35. #include "globals.h"
  36. #include "enumdrv.h"
  37. #include "drvproc.h"
  38. #include "filer.h"
  39.  
  40. //
  41. // Global Handles
  42. //
  43. HANDLE  ghModule;                     // Process Instance handle
  44.  
  45. HWND    ghwndMain;                       // Main window handle
  46. HWND    ghwndDrives;                     // Drives Toolbar window handle
  47. HWND    ghwndFunction;                   // Function Toolbar window handle
  48. HWND    ghwndCommand;                    // Command Line window handle
  49. HWND    ghwndDrv1,
  50.         ghwndDrv2;
  51. HWND    ghActiveChild = NULL;            // Handle to active drive child window
  52. HWND    ghFocusWnd;                      // Handle to last listbox with focus
  53.  
  54.  
  55. HANDLE  ghHeap;                          // Application heap handle
  56. HFONT   ghFont;
  57. HANDLE  ghDrvThread = NULL;
  58.  
  59. HMENU   ghMenu;                          // App Menu variables
  60.  
  61. //
  62. //   Global Data Items
  63. //
  64. BOOL                gfDrvWndOrient = SIDE_BY_SIDE, // relative Drv child pos.
  65.                     gfKeepCommandWin = FALSE;
  66.  
  67. DRVCHILDINFO        gDrvChild1Info,
  68.                     gDrvChild2Info;
  69.  
  70. LPDINFO             glpDrives = NULL;    // Root of Available Drives linked list
  71.  
  72. CRITICAL_SECTION    gDrvCS;              // Drive list critical section var.
  73. CRITICAL_SECTION    gHeapCS;             // Global heap critical section.
  74.  
  75. TCHAR    gszCommandLine[DIRECTORY_STRING_SIZE * 2];
  76. TCHAR    gszExtensions[NUM_EXTENSION_STRINGS][EXTENSION_LENGTH];
  77.  
  78. VKINFO  gVKArray[NUM_VERSION_INFO_KEYS];     // .EXE version info array.
  79.                                              // See GetVersion() in DRVPROC.C
  80.  
  81. /***************************************************************************\
  82. * WinMain
  83. *
  84. *
  85. * History:
  86. * 04-17-91
  87. *   Created.
  88. \***************************************************************************/
  89. int WINAPI WinMain(
  90.     HINSTANCE hInstance,
  91.     HINSTANCE hPrevInstance,
  92.     LPSTR lpCmdLine,
  93.     int nCmdShow)
  94. {
  95.     MSG    msg;
  96.     HANDLE hAccel;
  97.  
  98.     //-- check to make sure we are running on Windows NT
  99.     if( GetVersion() & 0x80000000 ) {            // 0x80000000 == Windows 3.1
  100.         MessageBox( NULL,
  101.         TEXT("Sorry, Filer must run under Windows NT.  Filer will now terminate."),
  102.         TEXT("Error: Windows NT Required"),  MB_OK );
  103.         return( 0 );
  104.     }
  105.  
  106.     ghModule = hInstance;
  107.  
  108.     if (!InitializeApp()) {
  109.         ErrorMsg(TEXT("Filer: InitializeApp failure!"));
  110.         return 0;
  111.     }
  112.     ShowWindow(ghwndMain, nCmdShow);
  113.  
  114.     if (!(hAccel = LoadAccelerators (ghModule, MAKEINTRESOURCE(ACCEL_ID))))
  115.         ErrorMsg(TEXT("Filer: Load Accel failure!"));
  116.  
  117.  
  118.     while (GetMessage(&msg, NULL, 0, 0)) {
  119.         if( !TranslateAccelerator(ghwndMain, hAccel, &msg) ) {
  120.             TranslateMessage(&msg);
  121.             DispatchMessage(&msg);
  122.         }
  123.     }
  124.  
  125.     return 1;
  126.  
  127.     UNREFERENCED_PARAMETER(lpCmdLine);
  128.     UNREFERENCED_PARAMETER(hPrevInstance);
  129. }
  130.  
  131.  
  132. /***************************************************************************\
  133. * InitializeApp
  134. *
  135. * History:
  136. * 5/5/92
  137. *   Created
  138. \***************************************************************************/
  139.  
  140. BOOL InitializeApp(void)
  141. {
  142.     WNDCLASS wc;
  143.  
  144.     wc.style            = 0;
  145.     wc.lpfnWndProc      = (WNDPROC)MainWndProc;
  146.     wc.cbClsExtra       = 0;
  147.     wc.cbWndExtra   = 0;
  148.     wc.hInstance        = ghModule;
  149.     wc.hIcon            = LoadIcon(ghModule, MAKEINTRESOURCE(UI_FILERICON));
  150.     wc.hCursor          = LoadCursor(ghModule, IDC_ARROW);
  151.     wc.hbrBackground    = (HBRUSH)(COLOR_APPWORKSPACE);
  152.     wc.lpszMenuName     = TEXT("FilerMenu");
  153.     wc.lpszClassName    = TEXT("FilerClass");
  154.  
  155.     if (!RegisterClass(&wc))
  156.     return(FALSE);
  157.  
  158.     wc.lpfnWndProc  = DrvWndProc;
  159.     wc.hIcon        = NULL;
  160.     wc.lpszMenuName = NULL;
  161.     wc.lpszClassName    = TEXT("DrvClass");
  162.  
  163.     if (!RegisterClass(&wc))
  164.         return(FALSE);
  165.  
  166.     wc.style        = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  167.     wc.lpfnWndProc  = DriveBarProc;
  168.     wc.hbrBackground    = (HBRUSH)(COLOR_BTNSHADOW);
  169.     wc.lpszClassName    = TEXT("DriveBarClass");
  170.  
  171.     if (!RegisterClass(&wc))
  172.             return(FALSE);
  173.  
  174.     wc.style        = CS_HREDRAW | CS_VREDRAW;
  175.     wc.lpfnWndProc  = TextWndProc;
  176.     wc.hbrBackground    = (HBRUSH)(COLOR_INACTIVECAPTION);
  177.     wc.lpszClassName    = TEXT("TextClass");
  178.  
  179.     if (!RegisterClass(&wc))
  180.             return(FALSE);
  181.  
  182.     ghMenu = LoadMenu(ghModule, TEXT("FilerMenu"));
  183.  
  184.     ghwndMain = CreateWindow(TEXT("FilerClass"),
  185.                              TEXT("Filer"),
  186.                              WS_OVERLAPPEDWINDOW,
  187.                              CW_USEDEFAULT,
  188.                              CW_USEDEFAULT,
  189.                              MAIN_WIDTH,
  190.                              MAIN_HEIGHT,
  191.                              HWND_DESKTOP,
  192.                              ghMenu,
  193.                              ghModule,
  194.                              NULL);
  195.  
  196.     if (ghwndMain == NULL)
  197.     return(FALSE);
  198.  
  199.     return(TRUE);
  200. }
  201.  
  202.  
  203. /***************************************************************************\
  204. * MainWndProc
  205. *
  206. * History:
  207. * 05-01-92  Created.
  208. \***************************************************************************/
  209.  
  210. LRESULT WINAPI MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  211. {
  212.     switch (message) {
  213.  
  214.       case WM_CREATE:{
  215.         LOGFONT    lf;
  216.         HDC        hDC;
  217.         HGDIOBJ    hOldFont;
  218.         TEXTMETRIC tm;
  219.  
  220.         DWORD dwThreadID;
  221.  
  222.         //
  223.         // Initialize drive list and Set Directory critical sections.
  224.         //
  225.         InitializeCriticalSection(&gDrvCS);
  226.         InitializeCriticalSection(&gHeapCS);
  227.  
  228.         ghDrvThread = CreateThread(NULL, 0,
  229.                                    (LPTHREAD_START_ROUTINE)EnumDrives,
  230.                                    (LPVOID)&glpDrives,
  231.                                    0, &dwThreadID);
  232.  
  233.         //
  234.         // Create the application's heap
  235.         //
  236.         ghHeap = HeapCreate( 0, (DWORD)sizeof(DRVCHILDINFO), 0);
  237.         if( ghHeap == NULL )
  238.             ErrorMsg(TEXT("Main Create: Failed in Creating Heap"));
  239.  
  240.         //
  241.         // Compute default application font by creating a bold version
  242.         //   of the system default icon font.
  243.         //
  244.         SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf),
  245.                              (PVOID) &lf, FALSE);
  246.  
  247.         hDC = GetDC(hwnd);
  248.  
  249.         // this is the height for 8 point size font in pixels.
  250.         //  (1 point = 1/72 in.)
  251.         //  Japanese fonts have different characteristics and don't look good in bold
  252.         if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
  253.             lf.lfHeight = 10 * GetDeviceCaps(hDC, LOGPIXELSY) / 72;
  254.         else {
  255.             lf.lfHeight = 8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72;
  256.             lf.lfWeight = BOLD_FONT;
  257.         }
  258.  
  259.         ghFont = CreateFontIndirect(&lf);
  260.         hOldFont = SelectObject(hDC, ghFont);
  261.         GetTextMetrics(hDC, &tm);
  262.  
  263.         if(hOldFont)
  264.             SelectObject(hDC, hOldFont);
  265.  
  266.         ReleaseDC(hwnd, hDC);
  267.  
  268.         //
  269.         // Create Drive windows
  270.         //
  271.         gDrvChild1Info.hParent = hwnd;
  272.         gDrvChild2Info.hParent = hwnd;
  273.  
  274.         ghwndDrv1 = CreateWindow(TEXT("DrvClass"), NULL,
  275.                                  WS_CHILD |
  276.                                  WS_CLIPSIBLINGS | WS_VISIBLE,
  277.                                  0, 0, 0, 0,
  278.                                  hwnd, (HMENU) 1, ghModule,
  279.                                  (LPVOID)&gDrvChild1Info);
  280.  
  281.         ghActiveChild = ghwndDrv1;
  282.  
  283.         //
  284.         // Set initial focus to Drive Child 1's Directory listbox.
  285.         //
  286.         ghFocusWnd = ((LPCINFO)GetWindowLong(ghwndDrv1, GWL_USERDATA))->hDirLB;
  287.  
  288.         ghwndDrv2 = CreateWindow(TEXT("DrvClass"), NULL,
  289.                                  WS_CHILD |
  290.                                  WS_CLIPSIBLINGS | WS_VISIBLE,
  291.                                  0, 0, 0, 0,
  292.                                  hwnd, (HMENU) 2, ghModule,
  293.                                  (LPVOID)&gDrvChild2Info);
  294.  
  295.         //
  296.         // Create DriveBar, FunctionBar and Command windows
  297.         //
  298.         ghwndDrives = CreateWindow(TEXT("DriveBarClass"), NULL,
  299.                                    WS_CHILD | WS_VISIBLE | WS_BORDER,
  300.                                    0, 0, 0, 0,
  301.                                    hwnd, (HMENU) 3, ghModule,
  302.                                    (LPVOID)NULL);
  303.  
  304.         ghwndFunction = CreateDialog(ghModule,
  305.                                     TEXT("FunctionBar"),
  306.                                     hwnd,
  307.                                     (DLGPROC)FunctionBarProc);
  308.  
  309.         ghwndCommand = CreateWindow(TEXT("EDIT"), NULL,
  310.                                    ES_AUTOHSCROLL | ES_LEFT | WS_BORDER |
  311.                                    ES_NOHIDESEL | WS_CHILD | WS_VISIBLE,
  312.                                    0, 0, 0, 0,
  313.                                    hwnd,
  314.                                    (HMENU) COMMAND_ID,
  315.                                    ghModule,
  316.                                    NULL);
  317.  
  318.         //
  319.         // Compute height of command window from font; store in window info.
  320.         // Set command window to default font.
  321.         //
  322.         SetWindowLong( ghwndCommand, GWL_USERDATA,
  323.                        tm.tmHeight + GetSystemMetrics(SM_CYBORDER) + 6);
  324.         SendMessage(ghwndCommand, WM_SETFONT, (WPARAM)ghFont, (LPARAM)FALSE);
  325.  
  326.         //
  327.         // Load String table entries
  328.         //
  329.         LoadString( ghModule, STR_EXE, &gszExtensions[0][0], EXTENSION_LENGTH);
  330.         LoadString( ghModule, STR_COM, &gszExtensions[1][0], EXTENSION_LENGTH);
  331.         LoadString( ghModule, STR_CMD, &gszExtensions[2][0], EXTENSION_LENGTH);
  332.         LoadString( ghModule, STR_BAT, &gszExtensions[3][0], EXTENSION_LENGTH);
  333.  
  334.         UpdateDrivesMenu(ghMenu, ghDrvThread);
  335.  
  336.         return(1);
  337.       }
  338.  
  339.       case WM_COMMAND:{
  340.  
  341.         //
  342.         // The menu Identifiers for the drives are (potentially)
  343.         // MM_DRIVE_NUM + 0 thru MM_DRIVE_NUM + 25. They all go to the
  344.         // same case, so we will put the Menu ID in lParam, and
  345.         // MM_DRIVE_NUM in LOWORD(wParam).
  346.         //
  347.         if( (LOWORD(wParam) - MM_DRIVE_NUM) <= 25 &&
  348.             (LOWORD(wParam) - MM_DRIVE_NUM) >= 0 ){
  349.             lParam = LOWORD(wParam);
  350.             wParam = MM_DRIVE_NUM;
  351.         }
  352.  
  353.         switch (LOWORD(wParam)) {
  354.             //
  355.             // If a drive is selected from the Drives menu, or clicked
  356.             //  on the drives toolbar, the currently active child will
  357.             //  switch to this drive. Message 'unconverted' (see top of
  358.             //  WM_COMMAND case), and sent to DriveBarProc
  359.             //
  360.             case MM_DRIVE_NUM:{
  361.  
  362.                 SendMessage(ghwndDrives, WM_COMMAND,
  363.                             (WPARAM)lParam, (LPARAM)NULL);
  364.                 return(1);
  365.             }
  366.  
  367.             //
  368.             // Passes these WM_COMMAND messages to the appropriate active child
  369.             //  window proc for processing
  370.             //
  371.             case MM_TAB:
  372.             case MM_ESCAPE:
  373.             case MM_OPEN:
  374.             case MM_COPY:
  375.             case MM_DELETE:
  376.             case MM_MOVE:
  377.             case MM_RENAME:
  378.             case MM_MKDIR:
  379.             case MM_EXPAND:
  380.             case MM_VERSION:{
  381.  
  382.                 SendMessage(ghActiveChild, WM_COMMAND, wParam, lParam);
  383.                 return(1);
  384.             }
  385.  
  386.             case MM_EXIT:{
  387.                 SendMessage(ghwndMain, WM_CLOSE, wParam, lParam);
  388.                 return(1);
  389.             }
  390.  
  391.             //
  392.             // Creates the drive enumeration thread to re-enumerate the
  393.             //   available drives in the main menu.  Also sends a refresh
  394.             //   to the active drive child, and repaints the window.
  395.             //
  396.             case MM_REFRESH: {
  397.                 DWORD   dwThreadID;
  398.  
  399.                 //
  400.                 // Initialize/Refresh Drives linked list
  401.                 //
  402.  
  403.                 if( WaitForSingleObject(ghDrvThread, 0) != WAIT_TIMEOUT ){
  404.  
  405.                     //
  406.                     // Close previous Drive Thread handle before creating new handle.
  407.                     //
  408.                     CloseHandle( ghDrvThread );
  409.  
  410.                     ghDrvThread = CreateThread(NULL, 0,
  411.                                            (LPTHREAD_START_ROUTINE)EnumDrives,
  412.                                            (LPVOID)&glpDrives,
  413.                                            0, &dwThreadID);
  414.  
  415.                     //
  416.                     // Refresh active child, drive toolbar, and drives menu
  417.                     //
  418.                     SendMessage(ghActiveChild, WM_COMMAND, wParam, lParam);
  419.                     SendMessage(ghwndDrives, WM_COMMAND, wParam, lParam);
  420.                     UpdateDrivesMenu(ghMenu, ghDrvThread);
  421.  
  422.                     //
  423.                     // Mark all for repaint
  424.                     //
  425.                     InvalidateRect(hwnd,NULL,TRUE);
  426.  
  427.                 }
  428.                 else
  429.                     MessageBeep(MB_ICONASTERISK);
  430.  
  431.                 return(1);
  432.             }
  433.  
  434.             //
  435.             // Swaps the directory and file list boxes of the active drv child.
  436.             //
  437.             case MM_SWAP:{
  438.                 LPCINFO lpCInfo;
  439.                 RECT    rect;
  440.  
  441.                 lpCInfo = (LPCINFO)GetWindowLong(ghActiveChild, GWL_USERDATA);
  442.  
  443.                 //
  444.                 // Switch the flag which indicates which side the Directory
  445.                 //  LB is on.  This is used by the WM_SIZE case of DrvWndProc.
  446.                 //
  447.                 lpCInfo->fDirLeft = !lpCInfo->fDirLeft;
  448.  
  449.                 //
  450.                 // Send size message with current size to active child,
  451.                 //   in order to redraw the listboxes.
  452.                 //
  453.                 if( !GetClientRect( ghActiveChild, &rect ) )
  454.                     return(0);
  455.  
  456.                 SendMessage( ghActiveChild, WM_SIZE, SIZENORMAL,
  457.                              MAKELONG( rect.right - rect.left,
  458.                                        rect.bottom - rect.top) );
  459.                 return(1);
  460.             }
  461.  
  462.             case MM_KEEPCMD:{
  463.  
  464.                 gfKeepCommandWin = !gfKeepCommandWin;
  465.  
  466.                 if( gfKeepCommandWin )
  467.                     CheckMenuItem( ghMenu, MM_KEEPCMD,
  468.                                     MF_BYCOMMAND | MF_CHECKED);
  469.                 else
  470.                     CheckMenuItem( ghMenu, MM_KEEPCMD,
  471.                                 MF_BYCOMMAND | MF_UNCHECKED);
  472.             }
  473.             break;
  474.  
  475.             //
  476.             // Toggles the relative Drive Child orientaion between
  477.             // Over/under and side/side.  gfDrvWndOrient is a flag checked
  478.             // by WM_SIZE to size Drv children
  479.             //
  480.             case MM_ORIENT:{
  481.                 RECT    rect;
  482.  
  483.                 if( gfDrvWndOrient == OVER_UNDER )
  484.                     gfDrvWndOrient = SIDE_BY_SIDE;
  485.                 else
  486.                     gfDrvWndOrient = OVER_UNDER;
  487.  
  488.                 //
  489.                 // Send size message with current size to self (main window),
  490.                 //   in order to redraw the Drv children.
  491.                 //
  492.                 if( !GetClientRect( hwnd, &rect ) )
  493.                     return(0);
  494.  
  495.                 SendMessage( hwnd, WM_SIZE, SIZENORMAL,
  496.                              MAKELONG( rect.right - rect.left,
  497.                                        rect.bottom - rect.top) );
  498.  
  499.                 InvalidateRect(ghwndDrv1,NULL,TRUE);
  500.                 InvalidateRect(ghwndDrv2,NULL,TRUE);
  501.  
  502.                 return(1);
  503.             }
  504.  
  505.             //
  506.             // Toggles the active drive child.  Sent from menu.
  507.             // This behaves the same as a WM_MOUSEACTIVATE in one of the
  508.             //   Drive children.  The PostMessage is so the current Active
  509.             //   child will not process the MM_TOGGLE message until after it
  510.             //   is no longer active.
  511.             //
  512.             case MM_ACTIVEDRV:{
  513.                 LPCINFO lpCInfo;
  514.  
  515.                 PostMessage(ghActiveChild, WM_COMMAND, (WPARAM)MM_TOGGLE,
  516.                             (LPARAM)NULL);
  517.  
  518.                 if( ghActiveChild == ghwndDrv1 )
  519.                     ghActiveChild = ghwndDrv2;
  520.                 else
  521.                     ghActiveChild = ghwndDrv1;
  522.  
  523.                 SendMessage(ghActiveChild, WM_COMMAND, (WPARAM)MM_TOGGLE,
  524.                             (LPARAM)NULL);
  525.  
  526.                 // change drive button
  527.                 lpCInfo = (LPCINFO)GetWindowLong(ghActiveChild, GWL_USERDATA);
  528.                 SendMessage(ghwndDrives, WM_COMMAND, MM_ACTIVEDRV,
  529.                             (LPARAM)lpCInfo->lpDriveInfo);
  530.                 return(1);
  531.             }
  532.  
  533.             //
  534.             // Sent by the Command line Edit control.
  535.             //
  536.             case COMMAND_ID:{
  537.  
  538.                 if( HIWORD(wParam) == EN_SETFOCUS )
  539.                     ghFocusWnd = ghwndCommand;
  540.             }
  541.             break;
  542.  
  543.             //
  544.             // Launches the About DialogBox.
  545.             //
  546.             case MM_ABOUT:{
  547.                 TCHAR   lpBuffer[128];
  548.  
  549.                 if (DialogBox(ghModule, TEXT("AboutBox"), ghwndMain, (DLGPROC)AboutProc) == -1) {
  550.                     LoadString(ghModule, IDS_ABOUTDLGERR, lpBuffer, sizeof(lpBuffer));
  551.                     ErrorMsg(lpBuffer);
  552.                 }
  553.                 return(1);
  554.             }
  555.  
  556.             default:
  557.                 return( DefWindowProc(hwnd, message, wParam, lParam) );
  558.         }
  559.         return(1);
  560.       }
  561.       //
  562.       // Whenever the window is resized, its children have to be
  563.       //  resized accordingly.  The GetWindowLong values are the height
  564.       //  of the windows queried by this function, and are set in the
  565.       //  WM_CREATE cases of their respective WNDPROCs.
  566.       //
  567.       case WM_SIZE:{
  568.         int DrvWndHeight;
  569.  
  570.         //
  571.         // Always put the command window at the bottom of the frame window
  572.         //
  573.         MoveWindow(ghwndCommand,
  574.            0,
  575.            HIWORD(lParam) - GetWindowLong(ghwndCommand, GWL_USERDATA),
  576.            LOWORD(lParam),
  577.            GetWindowLong(ghwndCommand, GWL_USERDATA),
  578.                TRUE);
  579.         //
  580.         // Always put the drives toolbar at the top of the frame window
  581.         //
  582.         MoveWindow(ghwndDrives,
  583.            0,
  584.            0,
  585.            LOWORD(lParam),
  586.            GetWindowLong(ghwndDrives, GWL_USERDATA),
  587.                TRUE);
  588.  
  589.         //
  590.         // Always put the Function window just below the drives toolbar.
  591.         //
  592.         MoveWindow(ghwndFunction,
  593.                    0,
  594.                    GetWindowLong(ghwndDrives, GWL_USERDATA),
  595.                    LOWORD(lParam),
  596.                    GetWindowLong(ghwndFunction, GWL_USERDATA),
  597.                    TRUE);
  598.  
  599.         //
  600.         // Always size the Drive Children between the Drives and Command
  601.         // windows. The width is set so that borders overlap.
  602.         //
  603.  
  604.         if( gfDrvWndOrient == OVER_UNDER ){
  605.  
  606.             DrvWndHeight = ( HIWORD(lParam) -
  607.                            GetWindowLong(ghwndDrives, GWL_USERDATA) -
  608.                            GetWindowLong(ghwndFunction, GWL_USERDATA) -
  609.                            GetWindowLong(ghwndCommand, GWL_USERDATA) ) / 2;
  610.  
  611.             MoveWindow(ghwndDrv1,
  612.                         -1,
  613.                         GetWindowLong(ghwndDrives, GWL_USERDATA)+
  614.                             GetWindowLong(ghwndFunction, GWL_USERDATA),
  615.                         LOWORD(lParam) + 2,
  616.                         DrvWndHeight,
  617.                         TRUE);
  618.  
  619.             MoveWindow(ghwndDrv2,
  620.                         -1,
  621.                         GetWindowLong(ghwndDrives, GWL_USERDATA)+
  622.                             GetWindowLong(ghwndFunction, GWL_USERDATA) +
  623.                             DrvWndHeight,
  624.                         LOWORD(lParam) + 2,
  625.                         DrvWndHeight,
  626.                         TRUE);
  627.         }
  628.         else{
  629.  
  630.             DrvWndHeight = HIWORD(lParam) -
  631.                            GetWindowLong(ghwndDrives, GWL_USERDATA) -
  632.                            GetWindowLong(ghwndFunction, GWL_USERDATA) -
  633.                            GetWindowLong(ghwndCommand, GWL_USERDATA);
  634.  
  635.             MoveWindow(ghwndDrv1,
  636.                         -1,
  637.                         GetWindowLong(ghwndDrives, GWL_USERDATA)+
  638.                             GetWindowLong(ghwndFunction, GWL_USERDATA),
  639.                         LOWORD(lParam)/2 + 1,
  640.                         DrvWndHeight,
  641.                         TRUE);
  642.  
  643.             MoveWindow(ghwndDrv2,
  644.                         LOWORD(lParam)/2,
  645.                         GetWindowLong(ghwndDrives, GWL_USERDATA)+
  646.                             GetWindowLong(ghwndFunction, GWL_USERDATA),
  647.                         LOWORD(lParam)/2 + 1,
  648.                         DrvWndHeight,
  649.                         TRUE);
  650.         }
  651.  
  652.         return(1);
  653.       }
  654.  
  655.       case WM_DESTROY: {
  656.         //
  657.         // Close last drive thread handle, the global heap and it's corresponding critical section,
  658.         //  the created font, and the Drive list critical section.
  659.         //
  660.         CloseHandle( ghDrvThread );
  661.  
  662.         EnterCriticalSection(&gHeapCS);
  663.         HeapDestroy(ghHeap);
  664.         LeaveCriticalSection(&gHeapCS);
  665.  
  666.         DeleteObject(ghFont);
  667.  
  668.         DeleteCriticalSection(&gDrvCS);
  669.         DeleteCriticalSection(&gHeapCS);
  670.  
  671.         PostQuitMessage(0);
  672.         return(1);
  673.       }
  674.  
  675.       default:
  676.         return DefWindowProc(hwnd, message, wParam, lParam);
  677.     }
  678. }
  679.  
  680.  
  681. /***************************************************************************\
  682. * AboutProc
  683. *
  684. * About dialog proc.
  685. *
  686. * History:
  687. *   05-13-92      Created.
  688. \***************************************************************************/
  689.  
  690. LRESULT WINAPI AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  691. {
  692.     switch (message) {
  693.       case WM_INITDIALOG:{
  694.         return TRUE;
  695.       }
  696.  
  697.       case WM_COMMAND:{
  698.         if (wParam == IDOK)
  699.             EndDialog(hDlg, wParam);
  700.         break;
  701.       }
  702.     }
  703.  
  704.     return FALSE;
  705.  
  706.     UNREFERENCED_PARAMETER(lParam);
  707.     UNREFERENCED_PARAMETER(hDlg);
  708. }
  709.  
  710.  
  711. /***************************************************************************\
  712. *
  713. * DriveBarProc()
  714. *
  715. * Drive Toolbar procedure for displaying available drive Icons.
  716. *  A bitmap button is displayed corresponding to the drive type of the
  717. *  given drive, with the drive letter alongside.
  718. *  ghwndDrives is the global handle assoc. w/ this window procedure.
  719. *
  720. *
  721. * History:
  722. * 6/9/92
  723. *   Created.
  724. *
  725. \***************************************************************************/
  726.  
  727. LRESULT WINAPI DriveBarProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  728. {
  729.     static HBITMAP  hDrvBmp[NUM_BITMAPS];
  730.     static HBRUSH   hBrush;         // background brush
  731.     static int      nDrvEntryWidth; // width of button/letter entry
  732.     static int      yVal;           // y value in toolbar for top left of bmp
  733.     static LPBINFO  lpDrvButtonRoot;
  734.     static int      nActiveDrvIndex;
  735.     TCHAR           lpBuffer[128];
  736.  
  737.     switch (message)
  738.     {
  739.         case WM_CREATE:{
  740.             HDC        hDC;
  741.             HGDIOBJ    hOldFont;
  742.             TEXTMETRIC tm;
  743.             LONG       lHeight;
  744.  
  745.  
  746.             lpDrvButtonRoot = NULL;
  747.  
  748.             //
  749.             // Load drive button bitmaps.
  750.             //
  751.             for(yVal = 0; yVal < NUM_BITMAPS; yVal++)
  752.                 hDrvBmp[yVal] = LoadBitmap( ghModule,
  753.                                       MAKEINTRESOURCE(UB_BMP_MARKER + yVal) );
  754.  
  755.             //
  756.             // Sets background color of Toolbar non-modal dialog children.
  757.             //
  758.             hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  759.  
  760.             hDC = GetDC(hwnd);
  761.  
  762.             hOldFont = SelectObject(hDC, ghFont);
  763.             GetTextMetrics(hDC, &tm);
  764.             
  765.             // base the height of the window on size of text
  766.             // Different display height is optimal if on a Japanese language system
  767.             //
  768.             if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE) 
  769.                 lHeight = tm.tmHeight + GetSystemMetrics(SM_CYBORDER) + 8;
  770.             else 
  771.                 lHeight = tm.tmHeight + GetSystemMetrics(SM_CYBORDER) + 6;
  772.  
  773.             //
  774.             // saved the window height, drive button entry width
  775.             //   and button y starting value for later reference
  776.             //
  777.             SetWindowLong(hwnd, GWL_USERDATA, lHeight);
  778.  
  779.             //
  780.             // Width of one button entry = spacing, button, sm. space,
  781.             //   drive letter, spacing.
  782.             //
  783.             nDrvEntryWidth = DRIVE_BITMAP_SPACING + DRIVE_BITMAP_WIDTH +
  784.                              DRIVE_LETTER_SPACING + tm.tmAveCharWidth +
  785.                              DRIVE_BITMAP_SPACING;
  786.  
  787.             //
  788.             // Center bitmaps (by height) in drive toolbar.
  789.             //
  790.             yVal = (lHeight - DRIVE_BITMAP_HEIGHT)/2;
  791.  
  792.             SelectObject(hDC, hOldFont);
  793.             ReleaseDC(hwnd, hDC);
  794.  
  795.             SendMessage(hwnd, WM_COMMAND, (WPARAM)MM_REFRESH, (LPARAM)NULL);
  796.  
  797.             break;
  798.         }
  799.  
  800.         case WM_COMMAND:{
  801.             //
  802.             // The button Identifiers for the drives are (potentially)
  803.             // MM_DRIVE_NUM + 0 thru MM_DRIVE_NUM + 25. They all go to the
  804.             // same case, so we will put the Menu ID in lParam, and
  805.             // MM_DRIVE_NUM in LOWORD(wParam).
  806.             //
  807.             if( (LOWORD(wParam) - MM_DRIVE_NUM) <= 25 &&
  808.                 (LOWORD(wParam) - MM_DRIVE_NUM) >= 0 ){
  809.                 lParam = LOWORD(wParam);
  810.                 wParam = MM_DRIVE_NUM;
  811.             }
  812.  
  813.             switch( LOWORD(wParam) ){
  814.               case MM_REFRESH:{
  815.  
  816.                 LPDINFO lpWalk;
  817.                 LPBINFO lpBWalk, lpBHold;
  818.                 LPCINFO lpCInfo;
  819.                 int     xVal = 0;
  820.                 int     nCount = MM_DRIVE_NUM;
  821.                 TCHAR   lpBuffer[128];
  822.  
  823.                 lpCInfo = (LPCINFO)GetWindowLong(ghActiveChild, GWL_USERDATA);
  824.  
  825.                 //
  826.                 // Wait for Drive Thread to complete, if necessary.
  827.                 //
  828.                 WaitForSingleObject(ghDrvThread, INFINITE);
  829.                 EnterCriticalSection(&gDrvCS);
  830.  
  831.                 //
  832.                 // Traverse DRVINFO linked list, creating drive buttons and
  833.                 //   allocating corresp. structures as necessary.
  834.                 //
  835.                 lpWalk = glpDrives;
  836.                 lpBWalk = lpDrvButtonRoot;
  837.  
  838.                 while( lpWalk != NULL ){
  839.                     if( lpBWalk == NULL ){ //If at the end of the button list
  840.  
  841.                         // Allocate a LPBINFO (button) structure
  842.                         EnterCriticalSection(&gHeapCS);
  843.                         lpBWalk = (LPBINFO)HeapAlloc(ghHeap, 0, (DWORD)sizeof(BINFO) );
  844.                         LeaveCriticalSection(&gHeapCS);
  845.  
  846.                         // Create a button window
  847.                         lpBWalk->hButton = (HANDLE)CreateWindow(TEXT("BUTTON"),
  848.                                                  lpWalk->DriveName,
  849.                                                  WS_CHILD | WS_VISIBLE |
  850.                                                  BS_OWNERDRAW,
  851.                                                  xVal + DRIVE_BITMAP_SPACING,
  852.                                                  yVal,
  853.                                                  DRIVE_BITMAP_WIDTH,
  854.                                                  DRIVE_BITMAP_HEIGHT,
  855.                                                  hwnd,
  856.                                                  (HMENU)nCount,
  857.                                                  ghModule,
  858.                                                  NULL);
  859.  
  860.                         // Insert structure into list
  861.                         if( lpDrvButtonRoot == NULL)
  862.                             lpDrvButtonRoot = lpBHold = lpBWalk;
  863.                         else{
  864.                             lpBHold->next = lpBWalk;
  865.                             lpBWalk->next = NULL;
  866.                         }
  867.  
  868.                     }
  869.  
  870.                     // An LPBINFO (button) structure exists: now initialize
  871.  
  872.                     // Set Title of Button (Drive Letter)
  873.                     SetWindowText(lpBWalk->hButton, lpWalk->DriveName);
  874.  
  875.                     // Set Child Window ID for Button
  876.                     SetMenu( lpBWalk->hButton, (HMENU)nCount);
  877.  
  878.                     // Determine button up/down status
  879.                     if( lpCInfo->lpDriveInfo == lpWalk ){
  880.                         nActiveDrvIndex = nCount;
  881.                         lpBWalk->fButtonDown = TRUE;
  882.                     }
  883.                     else
  884.                         lpBWalk->fButtonDown = FALSE;
  885.  
  886.                     // Set a pointer to the corresponding drive in Drive list
  887.                     lpBWalk->lpDrive = lpWalk;
  888.  
  889.                     nCount++;
  890.                     xVal += nDrvEntryWidth;
  891.                     lpBHold = lpBWalk;
  892.                     lpBWalk = lpBWalk->next;
  893.  
  894.                     lpWalk = lpWalk->next;
  895.                 }
  896.  
  897.                 LeaveCriticalSection(&gDrvCS);
  898.  
  899.                 //
  900.                 // Free any remaining button windows.
  901.                 //
  902.                 while( lpBWalk != NULL ){
  903.                     // NULL out new end of list
  904.                     lpBHold->next = NULL;
  905.  
  906.                     // Assign pointer to doomed node
  907.                     lpBHold = lpBWalk;
  908.                     lpBWalk = lpBWalk->next;
  909.  
  910.                     // Free doomed node resources
  911.                     if( !DestroyWindow(lpBHold->hButton) ) {
  912.                         LoadString(ghModule, IDS_DRVBUTTNERR, lpBuffer, sizeof(lpBuffer));
  913.                         ErrorMsg(lpBuffer);
  914.                     }
  915.  
  916.                     EnterCriticalSection(&gHeapCS);
  917.                     HeapFree(ghHeap, 0, (LPVOID)lpBHold);
  918.                     LeaveCriticalSection(&gHeapCS);
  919.                 }
  920.  
  921.                 SendMessage(hwnd, WM_PAINT, (WPARAM)NULL, (LPARAM)NULL);
  922.                 break;
  923.               }
  924.  
  925.  
  926.               //
  927.               // switches the drive button to the newly active drv child's
  928.               //   current drive.  Called by WM_MOUSEACTIVATE in DrvWndProc,
  929.               //   as well as ChangeDrive.
  930.               //   lParam contains the drive linked list pointer of the active
  931.               //   drv child's LPCINFO struct.
  932.               //
  933.               case MM_ACTIVEDRV:{
  934.                 LPBINFO lpBWalk = lpDrvButtonRoot;
  935.                 int     nCount = 0;
  936.  
  937.                 //
  938.                 // 'unpush' old active button
  939.                 //
  940.                 for( nCount = MM_DRIVE_NUM; nCount < nActiveDrvIndex; nCount++)
  941.                     lpBWalk = lpBWalk->next;
  942.                 lpBWalk->fButtonDown = FALSE;
  943.  
  944.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  945.  
  946.                 //
  947.                 // change active drive to new before redrawing old.
  948.                 //  'push' new active button
  949.                 //
  950.                 lpBWalk = lpDrvButtonRoot;
  951.                 nCount = MM_DRIVE_NUM;
  952.                 while( lpBWalk->lpDrive != (LPDINFO)lParam){
  953.                     lpBWalk = lpBWalk->next;
  954.                     nCount++;
  955.                 }
  956.  
  957.                 nActiveDrvIndex = nCount;
  958.  
  959.                 lpBWalk->fButtonDown = TRUE;
  960.  
  961.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  962.  
  963.                 break;
  964.               }
  965.  
  966.               //
  967.               // Changes drive of active child.  ButtonID in lParam.
  968.               //
  969.               case MM_DRIVE_NUM:{
  970.  
  971.                 LPBINFO lpBWalk = lpDrvButtonRoot;
  972.                 int     nCount = 0;
  973.                 TCHAR    szDrvBuff[DIRECTORY_STRING_SIZE];
  974.  
  975.                 //
  976.                 // if drive chosen is already current drive, leave.
  977.                 //
  978.                 if( nActiveDrvIndex == (int)lParam )
  979.                     break;
  980.  
  981.                 //
  982.                 // unpush' old active button
  983.                 //
  984.                 for( nCount = MM_DRIVE_NUM; nCount < nActiveDrvIndex; nCount++)
  985.                     lpBWalk = lpBWalk->next;
  986.                 lpBWalk->fButtonDown = FALSE;
  987.  
  988.                 //
  989.                 // change active drive to new before redrawing old.
  990.                 //
  991.                 nActiveDrvIndex = (int)lParam;
  992.  
  993.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  994.  
  995.                 //
  996.                 // 'push' new active button
  997.                 //
  998.                 lpBWalk = lpDrvButtonRoot;
  999.  
  1000.                 for( nCount = MM_DRIVE_NUM; nCount < nActiveDrvIndex; nCount++)
  1001.                     lpBWalk = lpBWalk->next;
  1002.                 lpBWalk->fButtonDown = TRUE;
  1003.  
  1004.                 InvalidateRect(lpBWalk->hButton, NULL, FALSE);
  1005.  
  1006.                 GetWindowText(lpBWalk->hButton, szDrvBuff,
  1007.                               DIRECTORY_STRING_SIZE);
  1008.  
  1009.                 if( !ChangeDrive(szDrvBuff, (DWORD)nActiveDrvIndex) ){
  1010.                     LoadString(ghModule, IDS_CHNGDRVERR, lpBuffer, sizeof(lpBuffer));
  1011.                     ErrorMsg(lpBuffer);
  1012.                     return(0);
  1013.                 }
  1014.  
  1015.                 break;
  1016.               }
  1017.             }
  1018.             return(1);
  1019.         }
  1020.  
  1021.         //
  1022.         // Sent by all created buttons for initialization purposes.
  1023.         //
  1024.         case WM_MEASUREITEM:{
  1025.             LPMEASUREITEMSTRUCT lpMIS;
  1026.  
  1027.             lpMIS = (LPMEASUREITEMSTRUCT)lParam;
  1028.  
  1029.             lpMIS->CtlType = ODT_BUTTON;
  1030.             lpMIS->CtlID = (UINT)wParam;
  1031.             lpMIS->itemWidth = DRIVE_BITMAP_WIDTH;
  1032.             lpMIS->itemHeight = DRIVE_BITMAP_HEIGHT;
  1033.  
  1034.             return(1);
  1035.         }
  1036.  
  1037.         //
  1038.         // Sent by owner draw drive buttons when needing redrawing.
  1039.         //
  1040.         case WM_DRAWITEM:{
  1041.             LPBINFO lpBWalk = lpDrvButtonRoot;
  1042.             int     nCount;
  1043.             int     nBmpIndex;
  1044.             HDC     hDC;
  1045.             HDC     hCompatDC;
  1046.             HGDIOBJ hOldBitmap;
  1047.             TCHAR    szDrvBuff[DIRECTORY_STRING_SIZE];
  1048.             LPDRAWITEMSTRUCT    lpDIS;
  1049.  
  1050.             lpDIS = (LPDRAWITEMSTRUCT)lParam;
  1051.  
  1052.             for( nCount = MM_DRIVE_NUM; nCount < (int)wParam; nCount++)
  1053.                 lpBWalk = lpBWalk->next;
  1054.  
  1055.             //
  1056.             // If not the current selected button, handle button stuff.
  1057.             //
  1058.             if( (int)wParam != nActiveDrvIndex ){
  1059.                 //
  1060.                 // mousebutton is down...
  1061.                 //
  1062.                 if( lpDIS->itemAction & ODA_SELECT ){
  1063.                     //
  1064.                     // left button region, 'unpush' button
  1065.                     //
  1066.                     if( lpDIS->itemState == (UINT)ODS_FOCUS )
  1067.                         lpBWalk->fButtonDown = FALSE;
  1068.                     //
  1069.                     // clicked on a button, draw 'pushed' button
  1070.                     //
  1071.                     if( lpDIS->itemState == (UINT)(ODS_SELECTED | ODS_FOCUS))
  1072.                         lpBWalk->fButtonDown = TRUE;
  1073.                 }
  1074.             }
  1075.  
  1076.             //
  1077.             // draw current state of button.
  1078.             //
  1079.             GetWindowText(lpDIS->hwndItem, szDrvBuff,
  1080.                           DIRECTORY_STRING_SIZE);
  1081.  
  1082.             szDrvBuff[1] = TEXT('\0');
  1083.  
  1084.             hCompatDC = CreateCompatibleDC(lpDIS->hDC);
  1085.             hOldBitmap = CreateCompatibleBitmap(hCompatDC,
  1086.                                                 DRIVE_BITMAP_WIDTH,
  1087.                                                 DRIVE_BITMAP_HEIGHT);
  1088.  
  1089.             nBmpIndex = GetDriveBitmap(lpBWalk);
  1090.  
  1091.             SelectObject( hCompatDC, hDrvBmp[nBmpIndex] );
  1092.  
  1093.             if( !hOldBitmap ) {
  1094.                 LoadString(ghModule, IDS_SELOBJERR, lpBuffer, sizeof(lpBuffer));
  1095.                 ErrorMsg(lpBuffer);
  1096.             }
  1097.             if( !BitBlt(lpDIS->hDC, lpDIS->rcItem.left, lpDIS->rcItem.top,
  1098.                    DRIVE_BITMAP_WIDTH,
  1099.                    DRIVE_BITMAP_HEIGHT,
  1100.                    hCompatDC, 0, 0, SRCCOPY) ) {
  1101.                 LoadString(ghModule, IDS_BITBLTERR, lpBuffer, sizeof(lpBuffer));
  1102.                 ErrorMsg(lpBuffer);
  1103.             }
  1104.  
  1105.             SelectObject( hCompatDC, hOldBitmap);
  1106.             DeleteDC(hCompatDC);
  1107.  
  1108.             hDC = GetDC(hwnd);
  1109.             SetBkMode(hDC, TRANSPARENT);
  1110.             SetTextColor(hDC, GetSysColor(COLOR_BTNTEXT) );
  1111.             SetBkColor(hDC, GetSysColor(COLOR_BTNSHADOW) );
  1112.  
  1113.             // Allow for a different aesthetic for Japanese systems
  1114.             if (GetUserDefaultLangID() == LANG_JAPANESE) 
  1115.                 TextOut(hDC,
  1116.                         ((int)(wParam - MM_DRIVE_NUM) * nDrvEntryWidth) +
  1117.                             DRIVE_BITMAP_SPACING + DRIVE_BITMAP_WIDTH +
  1118.                             DRIVE_LETTER_SPACING,
  1119.                         GetSystemMetrics(SM_CYBORDER)/2,
  1120.                         szDrvBuff, 1);
  1121.             else
  1122.                 TextOut(hDC,
  1123.                         ((int)(wParam - MM_DRIVE_NUM) * nDrvEntryWidth) +
  1124.                             DRIVE_BITMAP_SPACING + DRIVE_BITMAP_WIDTH +
  1125.                             DRIVE_LETTER_SPACING,
  1126.                         (GetSystemMetrics(SM_CYBORDER) + 6)/2,
  1127.                         szDrvBuff, 1);
  1128.  
  1129.             SetBkMode(hDC, OPAQUE);
  1130.  
  1131.             ReleaseDC(hwnd, hDC);
  1132.  
  1133.             break;
  1134.         }
  1135.  
  1136.  
  1137.         case WM_PAINT:{
  1138.             HDC     hCompatDC;
  1139.             RECT     rc;
  1140.             PAINTSTRUCT ps;
  1141.  
  1142.             //
  1143.             // Paint btnshadow background.
  1144.             //
  1145.             GetClientRect(hwnd, &rc);
  1146.  
  1147.             BeginPaint(hwnd, &ps);
  1148.  
  1149.             hCompatDC = CreateCompatibleDC(ps.hdc);
  1150.             FillRect(ps.hdc, &rc, hBrush);
  1151.  
  1152.             EndPaint(hwnd, &ps);
  1153.  
  1154.             return(TRUE);
  1155.         }
  1156.  
  1157.         case WM_DESTROY:{
  1158.             DeleteObject(hBrush);
  1159.  
  1160.             for(yVal = 0; yVal < NUM_BITMAPS; yVal++)
  1161.                 DeleteObject(hDrvBmp[yVal]);
  1162.  
  1163.             break;
  1164.         }
  1165.     }
  1166.     return DefWindowProc(hwnd, message, wParam, lParam);
  1167. }
  1168.  
  1169.  
  1170. /***************************************************************************\
  1171. *
  1172. * GetDriveBitmap()
  1173. *
  1174. * Determines the appropriate index into the drive button bitmap array
  1175. *   (hDrvBmp[]), given a pointer to a drive info structure (LPDINFO)
  1176. *
  1177. *   lpWalk          -   pointer to LPDINFO structure.
  1178. *   lpCurrentDrv    -   pointer to current drive of active child.
  1179. *
  1180. *
  1181. * History:
  1182. * 6/16/92
  1183. *   Created.
  1184. *
  1185. \***************************************************************************/
  1186. int GetDriveBitmap(LPBINFO lpBWalk)
  1187. {
  1188.     int nBmpIndex;
  1189.  
  1190.     EnterCriticalSection(&gDrvCS);
  1191.  
  1192.     switch( lpBWalk->lpDrive->DriveType ){
  1193.         case DRIVE_REMOVABLE:{
  1194.           nBmpIndex = UB_FLOPPY1 - UB_BMP_MARKER;
  1195.           break;
  1196.         }
  1197.  
  1198.         case DRIVE_REMOTE:{
  1199.           nBmpIndex = UB_REMOTE1 - UB_BMP_MARKER;
  1200.             break;
  1201.         }
  1202.  
  1203.         case DRIVE_CDROM:{
  1204.           nBmpIndex = UB_CD1 - UB_BMP_MARKER;
  1205.             break;
  1206.         }
  1207.  
  1208.         case DRIVE_FIXED:
  1209.         default:{
  1210.           nBmpIndex = UB_FIXED1 - UB_BMP_MARKER;
  1211.             break;
  1212.         }
  1213.     }
  1214.  
  1215.     LeaveCriticalSection(&gDrvCS);
  1216.  
  1217.     if( lpBWalk->fButtonDown == TRUE )
  1218.         nBmpIndex++;
  1219.  
  1220.     return(nBmpIndex);
  1221. }
  1222.  
  1223.  
  1224. /***************************************************************************\
  1225. *
  1226. * ChangeDrive()
  1227. *
  1228. *   Changes the current drive of the active child.  Called by the MM_DRIVE_NUM
  1229. *     cases in MainWndProc and DriveBarProc.  This is caused by choosing a
  1230. *     Drive menu item or selecting a drive button from the drive toolbar.
  1231. *
  1232. *     lpszDriveName -   points to a buffer containing the name of the drive
  1233. *     DriveID       -   points to the ID of the Menu item or button, which
  1234. *                         corresponds to the index into the drives linked list
  1235. *                         of the new drive.
  1236. *
  1237. * History:
  1238. * 6/20/92
  1239. *   Created.
  1240. *
  1241. \***************************************************************************/
  1242. BOOL ChangeDrive(LPTSTR lpszDriveName, DWORD DriveIndex)
  1243. {
  1244.     LPCINFO     lpCInfo;
  1245.     LPDINFO     lpWalk;
  1246.     DWORD       dwLoop;
  1247.     UINT        nDriveType;
  1248.     TCHAR       lpBuffer[128];
  1249.  
  1250.     //
  1251.     // Retrieve active child handle.
  1252.     //
  1253.     if( (ghActiveChild != ghwndDrv1) &&
  1254.         (ghActiveChild != ghwndDrv2) ){
  1255.         LoadString(ghModule, IDS_DRVNOTACTVE, lpBuffer, sizeof(lpBuffer));
  1256.         ErrorMsg(lpBuffer);
  1257.         return(0);
  1258.     }
  1259.  
  1260.     //
  1261.     // Retrieving the child window's DRVCHILDINFO data
  1262.     //
  1263.     lpCInfo = (LPCINFO)GetWindowLong(ghActiveChild, GWL_USERDATA);
  1264.  
  1265.     //
  1266.     // Enter Drive list critical section
  1267.     //
  1268.     EnterCriticalSection(&gDrvCS);
  1269.  
  1270.     //
  1271.     // if removable drive, check for existing media.
  1272.     //
  1273.     nDriveType = GetDriveType(lpszDriveName);
  1274.     if( nDriveType == DRIVE_REMOVABLE ||
  1275.         nDriveType == DRIVE_CDROM ){
  1276.         dwLoop = (DWORD)IDOK;
  1277.  
  1278.         LoadString(ghModule, IDS_INSRTMEDIA, lpBuffer, sizeof(lpBuffer));
  1279.  
  1280.         while( !CheckRM(lpszDriveName) && (dwLoop == (DWORD)IDOK) ){
  1281.            dwLoop = (DWORD)MessageBox(ghwndMain, lpBuffer, lpszDriveName, MB_OKCANCEL);
  1282.         }
  1283.  
  1284.         if( dwLoop == (DWORD)IDCANCEL ){
  1285.             SendMessage(ghwndDrives, WM_COMMAND, MM_ACTIVEDRV,
  1286.                         (LPARAM)lpCInfo->lpDriveInfo);
  1287.         LeaveCriticalSection(&gDrvCS);
  1288.             return(0);
  1289.         }
  1290.     }
  1291.  
  1292.     //
  1293.     // set lpDriveInfo member to associated drive struct.
  1294.     //
  1295.     lpWalk = glpDrives;
  1296.     for( dwLoop = 0; dwLoop < DriveIndex - MM_DRIVE_NUM;
  1297.          dwLoop++)
  1298.          lpWalk = lpWalk->next;
  1299.  
  1300.     lpCInfo->lpDriveInfo = lpWalk;
  1301.  
  1302.     lstrcpy(lpCInfo->CaptionBarText, lpWalk->DriveName);
  1303.  
  1304.     LeaveCriticalSection(&gDrvCS);
  1305.  
  1306.     //
  1307.     // This will terminate any currently running drive thread.
  1308.     //
  1309.     SendMessage(ghActiveChild, WM_COMMAND, MM_ESCAPE, (LPARAM)0);
  1310.     lpCInfo->fEscape = FALSE;
  1311.  
  1312.     //
  1313.     // enact the drive change.
  1314.     //
  1315.     PostMessage(ghActiveChild, WM_COMMAND, MM_REFRESH, (LPARAM)0);
  1316.  
  1317.     return(1);
  1318. }
  1319.  
  1320.  
  1321. /***************************************************************************\
  1322. *
  1323. * FunctionBarProc
  1324. *
  1325. * ToolBar Window procedure for displaying File I/O functions.
  1326. *   ghwndFunction is the global handle assoc. w/ this Dlg procedure.
  1327. *
  1328. * History:
  1329. * 6/8/92
  1330. *   Created.
  1331. *
  1332. \***************************************************************************/
  1333. LRESULT WINAPI FunctionBarProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1334. {
  1335.     static HBRUSH   hBrush;
  1336.  
  1337.     switch (message){
  1338.       case WM_INITDIALOG:{
  1339.         HWND    hButton;
  1340.         RECT     rc;
  1341.  
  1342.         hButton = GetDlgItem(hDlg, MM_COPY);
  1343.  
  1344.         GetWindowRect(hButton, &rc);
  1345.  
  1346.         SetWindowLong(hDlg, GWL_USERDATA, rc.bottom - rc.top);
  1347.  
  1348.         //
  1349.         // Sets background color of Toolbar non-modal dialog children.
  1350.         //
  1351.         hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  1352.  
  1353.         return(FALSE);
  1354.       }
  1355.  
  1356.       case WM_PAINT:{
  1357.         RECT     rc;
  1358.         PAINTSTRUCT ps;
  1359.  
  1360.         //
  1361.         // Paint btnshadow background.
  1362.         //
  1363.         GetClientRect(hDlg, &rc);
  1364.         InvalidateRect(hDlg, &rc, FALSE);
  1365.  
  1366.         BeginPaint(hDlg, &ps);
  1367.  
  1368.         FillRect(ps.hdc, &rc, hBrush);
  1369.  
  1370.         EndPaint(hDlg, &ps);
  1371.  
  1372.         return(TRUE);
  1373.       }
  1374.  
  1375.       //
  1376.       // Passes button messages ( = file I/O function messages )
  1377.       //   to active Drv child.
  1378.       //
  1379.       case WM_COMMAND:{
  1380.         switch(wParam){
  1381.           case MM_COPY:
  1382.           case MM_MOVE:
  1383.           case MM_DELETE:
  1384.           case MM_RENAME:
  1385.           case MM_MKDIR:{
  1386.             SendMessage(ghActiveChild, message, wParam, lParam);
  1387.             return(TRUE);
  1388.           }
  1389.         }
  1390.       }
  1391.  
  1392.       case WM_DESTROY:{
  1393.           DeleteObject(hBrush);
  1394.           break;
  1395.       }
  1396.     }
  1397.  
  1398.     return(FALSE);
  1399. }
  1400.  
  1401.  
  1402. /***************************************************************************\
  1403. *
  1404. * RunCommandItem()
  1405. *
  1406. *
  1407. * History:
  1408. * 5/26/93
  1409. *   Created.
  1410. *
  1411. \***************************************************************************/
  1412. BOOL RunCommandItem(LPCINFO lpCInfo)
  1413. {
  1414.     TCHAR       szCmdLine[DIRECTORY_STRING_SIZE * 2] = TEXT("cmd ");
  1415.     LPTSTR      lpszHold;
  1416.     TCHAR       lpBuffer[128];
  1417.  
  1418.     STARTUPINFO si;
  1419.     PROCESS_INFORMATION pi;
  1420.  
  1421.     //
  1422.     // Add the CMD.EXE parameter to keep or kill cmd sessions when done.
  1423.     //
  1424.     if( gfKeepCommandWin )
  1425.         lstrcat( szCmdLine, TEXT("/k ") );
  1426.     else
  1427.         lstrcat( szCmdLine, TEXT("/c ") );
  1428.  
  1429.     //
  1430.     // Add command line edit control text.
  1431.     //
  1432.     lpszHold = TStrChr(szCmdLine, TEXT('\0'));
  1433.  
  1434.     if( SendMessage( ghwndCommand, WM_GETTEXT,
  1435.                             DIRECTORY_STRING_SIZE,
  1436.                             (LPARAM)lpszHold) == LB_ERR ){
  1437.         LoadString(ghModule, IDS_SRCSTRNGERR, lpBuffer, sizeof(lpBuffer));
  1438.         ErrorMsg(lpBuffer);
  1439.         return(0);
  1440.     }
  1441.  
  1442.     //
  1443.     // Attempt to spawn command shell with entry as parameter.
  1444.     //
  1445.     si.cb = sizeof(STARTUPINFO);
  1446.     si.lpReserved = NULL;
  1447.     si.lpDesktop = NULL;
  1448.     si.lpTitle = NULL;
  1449.     si.dwFlags = 0;
  1450.     si.cbReserved2 = 0;
  1451.     si.lpReserved2 = NULL;
  1452.  
  1453.     SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  1454.  
  1455.     if( !CreateProcess(NULL, (LPTSTR)szCmdLine, NULL, NULL, FALSE,
  1456.                        CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
  1457.                        NULL, lpCInfo->CaptionBarText, &si, &pi) ){
  1458.         LoadString(ghModule, IDS_CANTSPAWN, lpBuffer, sizeof(lpBuffer));
  1459.         ErrorMsg(lpBuffer);
  1460.         return(0);
  1461.     }
  1462.  
  1463.     CloseHandle( pi.hProcess );
  1464.     CloseHandle( pi.hThread );
  1465.  
  1466.     SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  1467.  
  1468.     return(1);
  1469. }
  1470.  
  1471.  
  1472. /***************************************************************************\
  1473. *
  1474. * UpdateDrivesMenu()
  1475. *
  1476. * Adds current drives from the glpDrives linked list to the TEXT('Drives') menu
  1477. *
  1478. * Input: hDrivesMenu - handle to TEXT('Drives') Menu
  1479. *        hThread    - used to wait for drives thread to terminate
  1480. *
  1481. * History:
  1482. * 5/14/92
  1483. *   Created.
  1484. *
  1485. \***************************************************************************/
  1486. BOOL UpdateDrivesMenu(HMENU hMenu, HANDLE hThread)
  1487. {
  1488.     HMENU   hDrivesMenu;
  1489.     int     NumMenuItems;
  1490.     DWORD   dwLoop;
  1491.     LPDINFO lpWalk;
  1492.     TCHAR   lpBuffer[128];
  1493.  
  1494.     //
  1495.     // Remove list of drive menu items from Drive menu, if any.
  1496.     //
  1497.     hDrivesMenu = GetSubMenu( hMenu, DRIVE_MENU_NUM);
  1498.     if( !hDrivesMenu ){
  1499.         LoadString(ghModule, IDS_MENUERR1, lpBuffer, sizeof(lpBuffer));
  1500.         ErrorMsg(lpBuffer);
  1501.         return(FALSE);
  1502.     }
  1503.  
  1504.     if( (NumMenuItems = GetMenuItemCount(hDrivesMenu)) == -1) {
  1505.         LoadString(ghModule, IDS_MENUERR2, lpBuffer, sizeof(lpBuffer));
  1506.         ErrorMsg(lpBuffer);
  1507.     }
  1508.  
  1509.     //
  1510.     // Delete previous menu items.
  1511.     //
  1512.     for( dwLoop = 0; dwLoop < (DWORD)NumMenuItems; dwLoop++)
  1513.         if( !DeleteMenu( hDrivesMenu, 0,
  1514.                          MF_BYPOSITION) ){
  1515.             LoadString(ghModule, IDS_MENUERR3, lpBuffer, sizeof(lpBuffer));
  1516.             ErrorMsg(lpBuffer);
  1517.             return(FALSE);
  1518.         }
  1519.  
  1520.     //
  1521.     // Wait for Enumdrv Thread to terminate, and
  1522.     //   enter drive list critical section
  1523.     //
  1524.     WaitForSingleObject(hThread, INFINITE);
  1525.     EnterCriticalSection(&gDrvCS);
  1526.  
  1527.     //
  1528.     // Fill drive menu from glpDrives linked list
  1529.     //
  1530.     NumMenuItems = 0;
  1531.     lpWalk = glpDrives;
  1532.  
  1533.     while(lpWalk != NULL){
  1534.         if( !InsertMenu( hDrivesMenu, NumMenuItems, MF_STRING |
  1535.             MF_BYPOSITION | MF_ENABLED, MM_DRIVE_NUM + NumMenuItems,
  1536.             lpWalk->DriveName)) {
  1537.             LoadString(ghModule, IDS_MENUERR4, lpBuffer, sizeof(lpBuffer));            
  1538.             ErrorMsg(lpBuffer);
  1539.         }
  1540.         NumMenuItems++;
  1541.         lpWalk = lpWalk->next;
  1542.     }
  1543.  
  1544.     LeaveCriticalSection(&gDrvCS);
  1545.  
  1546.     return(TRUE);
  1547. }
  1548.  
  1549.  
  1550. /***************************************************************************\
  1551. *
  1552. * ErrorMsg()
  1553. *
  1554. *   Displays a Message Box with a given error message.
  1555. *
  1556. * History:
  1557. * 5/28/92
  1558. *   Created.
  1559. *
  1560. \***************************************************************************/
  1561. void ErrorMsg(LPTSTR szMsg)
  1562. {
  1563.     TCHAR szHold[DIRECTORY_STRING_SIZE + 1];
  1564.  
  1565.     lstrcpy( szHold, szMsg );
  1566.     lstrcat( szHold, TEXT("\n") );
  1567.  
  1568.     OutputDebugString(szHold);
  1569. }
  1570.