FILER.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:49k
源码类别:

Windows编程

开发平台:

Visual C++

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