home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwplascr.zip / XWPL0208.ZIP / tools / xlvm / xlvm.cpp < prev    next >
C/C++ Source or Header  |  2002-07-21  |  88KB  |  2,414 lines

  1.  
  2. /*
  3.  *@@sourcefile xlvm.cpp:
  4.  *
  5.  *
  6.  *@@header "xlvm.h"
  7.  *@@added V0.9.9 (2001-02-28) [umoeller]
  8.  */
  9.  
  10. /*
  11.  *      Copyright (C) 2001-2002 Ulrich Möller.
  12.  *      This program is free software; you can redistribute it and/or modify
  13.  *      it under the terms of the GNU General Public License as published by
  14.  *      the Free Software Foundation, in version 2 as it comes in the COPYING
  15.  *      file of the XFolder main distribution.
  16.  *      This program is distributed in the hope that it will be useful,
  17.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *      GNU General Public License for more details.
  20.  */
  21.  
  22. #define OS2EMX_PLAIN_CHAR
  23.  
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <setjmp.h>
  28. #include <ctype.h>
  29.  
  30. #define INCL_DOS
  31. #define INCL_DOSERRORS
  32. #define INCL_WIN
  33. #define INCL_GPIPRIMITIVES
  34. #include <os2.h>
  35.  
  36. #include "lvm_intr.h"
  37.  
  38. #include "setup.h"
  39.  
  40. #include "helpers\cnrh.h"
  41. #include "helpers\comctl.h"
  42. #include "helpers\datetime.h"           // date/time helper routines
  43. #include "helpers\dialog.h"
  44. #include "helpers\dosh.h"
  45. #include "helpers\except.h"
  46. #include "helpers\gpih.h"
  47. #include "helpers\linklist.h"
  48. #include "helpers\nls.h"
  49. #include "helpers\prfh.h"
  50. #include "helpers\standards.h"
  51. #include "helpers\stringh.h"
  52. #include "helpers\threads.h"
  53. #include "helpers\tree.h"
  54. #include "helpers\winh.h"
  55. #include "helpers\xstring.h"
  56.  
  57. #include "xlvm.h"
  58.  
  59. #pragma info (nocnv)
  60.  
  61. /* ******************************************************************
  62.  *
  63.  *   Private declarations
  64.  *
  65.  ********************************************************************/
  66.  
  67. /*
  68.  *@@ LVMDRIVEDATA:
  69.  *
  70.  *@@added V0.9.9 (2001-02-28) [umoeller]
  71.  */
  72.  
  73. typedef struct _LVMDRIVEDATA
  74. {
  75.     HWND                        hwndChart,          // chart for this drive
  76.                                 hwndDescription;    // static below
  77.  
  78.     ADDRESS                     DriveHandle;
  79.  
  80.     Drive_Control_Record        *pControlRecord;
  81.                 // do not free this, this points to an item in the
  82.                 // DriveData array
  83.     /*
  84.     typedef struct _Drive_Control_Record {
  85.     CARDINAL32   Drive_Number;                   // OS/2 Drive Number for this drive.
  86.     CARDINAL32   Drive_Size;                     // The total number of sectors on the drive.
  87.     DoubleWord   Drive_Serial_Number;            // The serial number assigned to this drive.  For info. purposes only.
  88.     ADDRESS      Drive_Handle;                   // Handle used for operations on the disk that this record corresponds to.
  89.     CARDINAL32   Cylinder_Count;                 // The number of cylinders on the drive.
  90.     CARDINAL32   Heads_Per_Cylinder;             // The number of heads per cylinder for this drive.
  91.     CARDINAL32   Sectors_Per_Track;              // The number of sectors per track for this drive.
  92.     BOOLEAN      Drive_Is_PRM;                   // Set to TRUE if this drive is a PRM.
  93.     BYTE         Reserved[3];                    // Alignment.
  94.     } Drive_Control_Record;
  95.     */
  96.  
  97.     Drive_Information_Record    InfoRecord;
  98.                 // full struct, no pointer
  99.  
  100.     /*
  101.     typedef struct _Drive_Information_Record {
  102.     CARDINAL32   Total_Available_Sectors;        // The number of sectors on the disk which are not currently assigned to a partition.
  103.     CARDINAL32   Largest_Free_Block_Of_Sectors;  // The number of sectors in the largest contiguous block of available sectors.
  104.     BOOLEAN      Corrupt_Partition_Table;        // If TRUE, then the partitioning information found on the drive is incorrect!
  105.     BOOLEAN      Unusable;                       // If TRUE, the drive's MBR is not accessible and the drive can not be partitioned.
  106.     BOOLEAN      IO_Error;                       // If TRUE, then the last I/O operation on this drive failed!
  107.     BOOLEAN      Is_Big_Floppy;                  // If TRUE, then the drive is a PRM formatted as a big floppy (i.e. the old style removable media support).
  108.     char         Drive_Name[DISK_NAME_SIZE];     // User assigned name for this disk drive.
  109.     } Drive_Information_Record;
  110.     */
  111.  
  112.     Partition_Information_Array PartitionsArray;
  113.                 // member array pointer is freed for each node
  114.                 // in FreeLVMData
  115.  
  116.     /* typedef struct _Partition_Information_Array {
  117.     Partition_Information_Record * Partition_Array; // An array of Partition_Information_Records.
  118.     CARDINAL32                     Count;           // The number of entries in the Partition_Array.
  119.     } Partition_Information_Array; */
  120.  
  121. } LVMDRIVEDATA, *PLVMDRIVEDATA;
  122.  
  123. /*
  124.  *@@ LVMDATA:
  125.  *      structure holding the current LVM information.
  126.  *
  127.  *      Allocated and filled once; refreshed after
  128.  *      the LVM setup has been changed.
  129.  *
  130.  *@@added V0.9.14 (2001-08-03) [umoeller]
  131.  */
  132.  
  133. typedef struct _LVMDATA
  134. {
  135.     HWND                    hwndClient;
  136.  
  137.     BOOL                    fLVMOpened;
  138.  
  139.     BOOL                    fDirty;
  140.                     // if this becomes TRUE, changes have been made and the
  141.                     // user should be prompted for whether those should be
  142.                     // committed
  143.  
  144.     Drive_Control_Array     DriveData;
  145.                     // opened by Get_Drive_Control_Data, is freed in
  146.                     // FreeLVMData
  147.  
  148.     LINKLIST                llDriveData;
  149.                     // linked list of drive data;
  150.                     // points to LVMDRIVEDATA structs
  151.                     // (no auto-free, must each be freed)
  152.  
  153.     LINKLIST                llPartitions;
  154.                     // linked list to all partitions in the LVMDRIVEDATA structs;
  155.                     // must not be freed
  156.  
  157.     Partition_Information_Record *pPartitionSource;
  158.                     // partition which currently has source emphasis or NULL if none
  159.  
  160. } LVMDATA, *PLVMDATA;
  161.  
  162. /* ******************************************************************
  163.  *
  164.  *   Global variables
  165.  *
  166.  ********************************************************************/
  167.  
  168. FILE        *G_LogFile = NULL;
  169.  
  170. HWND        G_hwndStatusBar = NULLHANDLE;
  171.  
  172. // context menus
  173. HWND        G_hwndWhitespaceMenu = NULLHANDLE,
  174.             G_hwndFreeSpaceMenu = NULLHANDLE,
  175.             G_hwndPartitionMenu = NULLHANDLE,
  176.             G_hwndVolumeMenu = NULLHANDLE;
  177.  
  178. ULONG       G_ulViewStyle = IDMI_VIEW_BARCHART;
  179.  
  180. HWND        G_hwndMenuShowing = NULLHANDLE; // only while menu is showing
  181. EMPHASISNOTIFY G_CurrentEmphasis;
  182.  
  183. PFNWP       G_fnwpFrameOrig = NULL;
  184.  
  185. HPOINTER    G_hptrDrive = NULLHANDLE,
  186.             G_hptrPartition = NULLHANDLE;
  187.  
  188. const char  *INIAPP              = "XWorkplace:xlvm";
  189. const char  *INIKEY_MAINWINPOS   = "WinPos";
  190. const char  *INIKEY_OPENDLG      = "FileOpenDlgPath";
  191.  
  192. const char  *APPTITLE            = "xlvm";
  193.  
  194. #define XM_INSERTDATA       WM_USER
  195. #define XM_LVMERROR         (WM_USER + 1)
  196. #define XM_ENABLEITEMS      (WM_USER + 2)
  197.  
  198. #define MB_FROM_SECTORS(ulSize) ((((ulSize) / 2) + 512) / 1024)
  199.  
  200. // LVM data
  201.  
  202. COUNTRYSETTINGS         G_CountrySettings;
  203.  
  204. /* ******************************************************************
  205.  *
  206.  *   Load LVM Data
  207.  *
  208.  ********************************************************************/
  209.  
  210. /*
  211.  *@@ LVMError:
  212.  *
  213.  *@@added V0.9.12 (2001-05-03) [umoeller]
  214.  */
  215.  
  216. VOID LVMError(HWND hwndClient,
  217.               ULONG ulrc,
  218.               const char *pcszContext)
  219. {
  220.     fprintf(G_LogFile,
  221.             "LVMError: %s returned %d\n",
  222.             pcszContext,
  223.             ulrc);
  224.     WinPostMsg(hwndClient,
  225.                XM_LVMERROR,
  226.                (MPARAM)ulrc,
  227.                (MPARAM)pcszContext);
  228. }
  229.  
  230. PCSZ DescribeLVMError(ULONG ulrc)
  231. {
  232.     switch (ulrc)
  233.     {
  234.         case LVM_ENGINE_NO_ERROR: return "NO_ERROR";
  235.         case LVM_ENGINE_OUT_OF_MEMORY: return "OUT_OF_MEMORY";
  236.         case LVM_ENGINE_IO_ERROR: return "IO_ERROR";
  237.         case LVM_ENGINE_BAD_HANDLE: return "BAD_HANDLE";
  238.         case LVM_ENGINE_INTERNAL_ERROR: return "INTERNAL_ERROR";
  239.         case LVM_ENGINE_ALREADY_OPEN: return "ALREADY_OPEN";
  240.         case LVM_ENGINE_NOT_OPEN: return "NOT_OPEN";
  241.         case LVM_ENGINE_NAME_TOO_BIG: return "NAME_TOO_BIG";
  242.         case LVM_ENGINE_OPERATION_NOT_ALLOWED: return "OPERATION_NOT_ALLOWED";
  243.         case LVM_ENGINE_DRIVE_OPEN_FAILURE: return "DRIVE_OPEN_FAILURE";
  244.         case LVM_ENGINE_BAD_PARTITION: return "BAD_PARTITION";
  245.         case LVM_ENGINE_CAN_NOT_MAKE_PRIMARY_PARTITION: return "CAN_NOT_MAKE_PRIMARY_PARTITION";
  246.         case LVM_ENGINE_TOO_MANY_PRIMARY_PARTITIONS: return "TOO_MANY_PRIMARY_PARTITIONS";
  247.         case LVM_ENGINE_CAN_NOT_MAKE_LOGICAL_DRIVE: return "CAN_NOT_MAKE_LOGICAL_DRIVE";
  248.         case LVM_ENGINE_REQUESTED_SIZE_TOO_BIG: return "REQUESTED_SIZE_TOO_BIG";
  249.         case LVM_ENGINE_1024_CYLINDER_LIMIT: return "1024_CYLINDER_LIMIT";
  250.         case LVM_ENGINE_PARTITION_ALIGNMENT_ERROR: return "PARTITION_ALIGNMENT_ERROR";
  251.         case LVM_ENGINE_REQUESTED_SIZE_TOO_SMALL: return "REQUESTED_SIZE_TOO_SMALL";
  252.         case LVM_ENGINE_NOT_ENOUGH_FREE_SPACE: return "NOT_ENOUGH_FREE_SPACE";
  253.         case LVM_ENGINE_BAD_ALLOCATION_ALGORITHM: return "BAD_ALLOCATION_ALGORITHM";
  254.         case LVM_ENGINE_DUPLICATE_NAME: return "DUPLICATE_NAME";
  255.         case LVM_ENGINE_BAD_NAME: return "BAD_NAME";
  256.         case LVM_ENGINE_BAD_DRIVE_LETTER_PREFERENCE: return "BAD_DRIVE_LETTER_PREFERENCE";
  257.         case LVM_ENGINE_NO_DRIVES_FOUND: return "NO_DRIVES_FOUND";
  258.         case LVM_ENGINE_WRONG_VOLUME_TYPE: return "WRONG_VOLUME_TYPE";
  259.         case LVM_ENGINE_VOLUME_TOO_SMALL: return "VOLUME_TOO_SMALL";
  260.         case LVM_ENGINE_BOOT_MANAGER_ALREADY_INSTALLED: return "BOOT_MANAGER_ALREADY_INSTALLED";
  261.         case LVM_ENGINE_BOOT_MANAGER_NOT_FOUND: return "BOOT_MANAGER_NOT_FOUND";
  262.         case LVM_ENGINE_INVALID_PARAMETER: return "INVALID_PARAMETER";
  263.         case LVM_ENGINE_BAD_FEATURE_SET: return "BAD_FEATURE_SET";
  264.         case LVM_ENGINE_TOO_MANY_PARTITIONS_SPECIFIED: return "TOO_MANY_PARTITIONS_SPECIFIED";
  265.         case LVM_ENGINE_LVM_PARTITIONS_NOT_BOOTABLE: return "LVM_PARTITIONS_NOT_BOOTABLE";
  266.         case LVM_ENGINE_PARTITION_ALREADY_IN_USE: return "PARTITION_ALREADY_IN_USE";
  267.         case LVM_ENGINE_SELECTED_PARTITION_NOT_BOOTABLE: return "SELECTED_PARTITION_NOT_BOOTABLE";
  268.         case LVM_ENGINE_VOLUME_NOT_FOUND: return "VOLUME_NOT_FOUND";
  269.         case LVM_ENGINE_DRIVE_NOT_FOUND: return "DRIVE_NOT_FOUND";
  270.         case LVM_ENGINE_PARTITION_NOT_FOUND: return "PARTITION_NOT_FOUND";
  271.         case LVM_ENGINE_TOO_MANY_FEATURES_ACTIVE: return "TOO_MANY_FEATURES_ACTIVE";
  272.         case LVM_ENGINE_PARTITION_TOO_SMALL: return "PARTITION_TOO_SMALL";
  273.         case LVM_ENGINE_MAX_PARTITIONS_ALREADY_IN_USE: return "MAX_PARTITIONS_ALREADY_IN_USE";
  274.         case LVM_ENGINE_IO_REQUEST_OUT_OF_RANGE: return "IO_REQUEST_OUT_OF_RANGE";
  275.         case LVM_ENGINE_SPECIFIED_PARTITION_NOT_STARTABLE: return "SPECIFIED_PARTITION_NOT_STARTABLE";
  276.         case LVM_ENGINE_SELECTED_VOLUME_NOT_STARTABLE: return "SELECTED_VOLUME_NOT_STARTABLE";
  277.         case LVM_ENGINE_EXTENDFS_FAILED: return "EXTENDFS_FAILED";
  278.         case LVM_ENGINE_REBOOT_REQUIRED: return "REBOOT_REQUIRED";
  279.         case LVM_ENGINE_CAN_NOT_OPEN_LOG_FILE: return "CAN_NOT_OPEN_LOG_FILE";
  280.         case LVM_ENGINE_CAN_NOT_WRITE_TO_LOG_FILE: return "CAN_NOT_WRITE_TO_LOG_FILE";
  281.         case LVM_ENGINE_REDISCOVER_FAILED: return "REDISCOVER_FAILED";
  282.         case LVM_ENGINE_INTERNAL_VERSION_FAILURE: return "INTERNAL_VERSION_FAILURE";
  283.         case LVM_ENGINE_PLUGIN_OPERATION_INCOMPLETE: return "PLUGIN_OPERATION_INCOMPLETE";
  284.         case LVM_ENGINE_BAD_FEATURE_ID: return "BAD_FEATURE_ID";
  285.         case LVM_ENGINE_NO_INIT_DATA: return "NO_INIT_DATA";
  286.         case LVM_ENGINE_NO_CONTEXT_DATA: return "NO_CONTEXT_DATA";
  287.         case LVM_ENGINE_WRONG_CLASS_FOR_FEATURE: return "WRONG_CLASS_FOR_FEATURE";
  288.         case LVM_ENGINE_INCOMPATIBLE_FEATURES_SELECTED: return "INCOMPATIBLE_FEATURES_SELECTED";
  289.         case LVM_ENGINE_NO_CHILDREN: return "NO_CHILDREN";
  290.         case LVM_ENGINE_FEATURE_NOT_SUPPORTED_BY_INTERFACE: return "FEATURE_NOT_SUPPORTED_BY_INTERFACE";
  291.         case LVM_ENGINE_NO_PARENT: return "NO_PARENT";
  292.         case LVM_ENGINE_VOLUME_HAS_NOT_BEEN_COMMITTED_YET: return "VOLUME_HAS_NOT_BEEN_COMMITTED_YET";
  293.         case LVM_ENGINE_UNABLE_TO_REFERENCE_VOLUME: return "UNABLE_TO_REFERENCE_VOLUME";
  294.         case LVM_ENGINE_PARSING_ERROR: return "PARSING_ERROR";
  295.         case LVM_ENGINE_INTERNAL_FEATURE_ERROR: return "INTERNAL_FEATURE_ERROR";
  296.         case LVM_ENGINE_VOLUME_NOT_CONVERTED: return "VOLUME_NOT_CONVERTED";
  297.     }
  298.  
  299.     return "unknown code";
  300. }
  301.  
  302. /*
  303.  *@@ fntLoadLVMData:
  304.  *      fills an LVMDATA struct with the LVM data so that
  305.  *      we can retrieve them more quickly.
  306.  *
  307.  *      THREADINFO.ulData must be a pointer to the
  308.  *      LVMDATA to fill.
  309.  *
  310.  *@@added V0.9.9 (2001-02-28) [umoeller]
  311.  */
  312.  
  313. VOID _Optlink fntLoadLVMData(PTHREADINFO ptiMyself)
  314. {
  315.     CARDINAL32 Error = 0;
  316.  
  317.     TRY_LOUD(excpt1)
  318.     {
  319.         PLVMDATA pData = (PLVMDATA)ptiMyself->ulData;
  320.  
  321.         fprintf(G_LogFile, __FUNCTION__ ": entering\n");
  322.  
  323.         if (!pData->fLVMOpened)
  324.         {
  325.             // first call: open LVM
  326.             Open_LVM_Engine(FALSE,
  327.                             &Error);
  328.  
  329.             if (Error)
  330.                 LVMError(pData->hwndClient, Error, "Open_LVM_Engine");
  331.             else
  332.                 pData->fLVMOpened = TRUE;
  333.         }
  334.  
  335.         if (pData->fLVMOpened)
  336.         {
  337.             pData->DriveData = Get_Drive_Control_Data(&Error);
  338.  
  339.             if (Error)
  340.                 LVMError(pData->hwndClient, Error, "Get_Drive_Control_Data");
  341.             else
  342.             {
  343.                 // go through drives
  344.                 BOOL fExit = FALSE;
  345.                 ULONG ul;
  346.                 for (ul = 0;
  347.                      (ul < pData->DriveData.Count) && (!fExit);
  348.                      ul++)
  349.                 {
  350.                     PLVMDRIVEDATA pDriveData = NEW(LVMDRIVEDATA);
  351.                     ZERO(pDriveData);
  352.  
  353.                     pDriveData->pControlRecord = &pData->DriveData.Drive_Control_Data[ul];
  354.                     // copy handle for quick access
  355.                     pDriveData->DriveHandle = pDriveData->pControlRecord->Drive_Handle;
  356.                     pDriveData->InfoRecord = Get_Drive_Status(pDriveData->DriveHandle,
  357.                                                               &Error);
  358.  
  359.                     if (Error)
  360.                     {
  361.                         LVMError(pData->hwndClient, Error, "Get_Drive_Status");
  362.                         fExit = TRUE;
  363.                     }
  364.                     else
  365.                     {
  366.                         // now get the partitions for this drive
  367.                         pDriveData->PartitionsArray = Get_Partitions(pDriveData->DriveHandle,
  368.                                                                      &Error);
  369.  
  370.                         if (Error)
  371.                         {
  372.                             LVMError(pData->hwndClient, Error, "Get_Partitions");
  373.                             fExit = TRUE;
  374.                         }
  375.                         else
  376.                         {
  377.                             // go thru partitions
  378.                             ULONG ul2;
  379.                             for (ul2 = 0;
  380.                                  ul2 < pDriveData->PartitionsArray.Count;
  381.                                  ul2++)
  382.                             {
  383.                                 Partition_Information_Record *pBarItem
  384.                                     = &pDriveData->PartitionsArray.Partition_Array[ul2];
  385.  
  386.                                 // store partition in global list of all partitions
  387.                                 lstAppendItem(&pData->llPartitions,
  388.                                               pBarItem);
  389.                             }
  390.  
  391.                             // store drive in global list
  392.                             lstAppendItem(&pData->llDriveData,
  393.                                           pDriveData);
  394.                         }
  395.                     }
  396.                 }
  397.             }
  398.         }
  399.  
  400.         fprintf(G_LogFile, __FUNCTION__ ": leaving\n"
  401.                    );
  402.     }
  403.     CATCH(excpt1)
  404.     {
  405.  
  406.     } END_CATCH();
  407.  
  408.     WinPostMsg(ptiMyself->hwndNotify,
  409.                WM_USER,
  410.                (MPARAM)Error,
  411.                0);
  412. }
  413.  
  414. /*
  415.  *@@ FreeLVMData:
  416.  *      frees allocated memory.
  417.  *
  418.  *      If (fCloseEngine == TRUE), the engine is closed
  419.  *      unconditionally, and all changes are lost.
  420.  *
  421.  *      Called on WM_CLOSE with fCloseEngine == TRUE.
  422.  *      Called during program execution if the display
  423.  *      needs to be refreshed.
  424.  *
  425.  *@@added V0.9.14 (2001-08-03) [umoeller]
  426.  */
  427.  
  428. VOID FreeLVMData(PLVMDATA pData,
  429.                  BOOL fCloseEngine)
  430. {
  431.     // clean up
  432.     if (pData->DriveData.Drive_Control_Data)
  433.         Free_Engine_Memory(pData->DriveData.Drive_Control_Data);
  434.  
  435.     // clear list of partition pointers into drive data
  436.     PLISTNODE pNode = lstQueryFirstNode(&pData->llDriveData);
  437.     while (pNode)
  438.     {
  439.         PLVMDRIVEDATA pDriveData = (PLVMDRIVEDATA)pNode->pItemData;
  440.  
  441.         if (pDriveData->hwndChart)
  442.         {
  443.             WinDestroyWindow(pDriveData->hwndChart);
  444.             pDriveData->hwndChart = NULLHANDLE;
  445.         }
  446.         if (pDriveData->hwndDescription)
  447.         {
  448.             WinDestroyWindow(pDriveData->hwndDescription);
  449.             pDriveData->hwndDescription = NULLHANDLE;
  450.         }
  451.  
  452.         if (pDriveData->PartitionsArray.Partition_Array)
  453.             Free_Engine_Memory(pDriveData->PartitionsArray.Partition_Array);
  454.  
  455.         free(pDriveData);
  456.  
  457.         pNode = pNode->pNext;
  458.     }
  459.  
  460.     lstClear(&pData->llDriveData);
  461.  
  462.     // clear list of partition pointers into drive data too
  463.     lstClear(&pData->llPartitions);
  464.  
  465.     if (    (pData->fLVMOpened)
  466.          && (fCloseEngine)
  467.        )
  468.     {
  469.         // close LVM
  470.         Close_LVM_Engine();
  471.  
  472.         pData->fLVMOpened = FALSE;
  473.         pData->fDirty = FALSE;
  474.     }
  475. }
  476.  
  477. /* ******************************************************************
  478.  *
  479.  *   Helpers
  480.  *
  481.  ********************************************************************/
  482.  
  483. /*
  484.  *@@ MessageBox:
  485.  *
  486.  *@@added V0.9.12 (2001-05-03) [umoeller]
  487.  */
  488.  
  489. ULONG MessageBox(HWND hwndOwner,
  490.                  XSTRING *pstr,
  491.                  ULONG fl)
  492. {
  493.     static MSGBOXSTRINGS MsgBoxStrings =
  494.         {
  495.             "~Yes",
  496.             "~No",
  497.             "~OK",
  498.             "~Cancel",
  499.             "~Abort",
  500.             "~Retry",
  501.             "~Ignore",
  502.             "~Enter",
  503.             "Yes to ~all"
  504.         };
  505.  
  506.     return (dlghMessageBox(hwndOwner,
  507.                            G_hptrDrive,
  508.                            APPTITLE,
  509.                            pstr->psz,
  510.                            NULL,
  511.                            fl,
  512.                            "9.WarpSans",
  513.                            &MsgBoxStrings));
  514.     /* return (WinMessageBox(HWND_DESKTOP,
  515.                           G_hwndMain,
  516.                           pcszText,
  517.                           APPTITLE,
  518.                           0,
  519.                           fl | MB_MOVEABLE)); */
  520. }
  521.  
  522. /*
  523.  *@@ SetChartStyle:
  524.  *
  525.  *@@added V0.9.18 (2002-03-23) [umoeller]
  526.  */
  527.  
  528. VOID SetChartStyle(HWND hwndChart)
  529. {
  530.     CHARTSTYLE cs;
  531.     if (G_ulViewStyle == IDMI_VIEW_BARCHART)
  532.         // bar chart:
  533.         cs.ulStyle =    CHS_BARCHART
  534.                       | CHS_3D_DARKEN
  535.                       | CHS_DESCRIPTIONS
  536.                       | CHS_DRAWLINES
  537.                       | CHS_SELECTIONS
  538.                       ;
  539.     else
  540.         // pie chart:
  541.         cs.ulStyle =    CHS_PIECHART
  542.                       | CHS_3D_DARKEN
  543.                       | CHS_DESCRIPTIONS
  544.                       | CHS_DRAWLINES
  545.                       | CHS_SELECTIONS
  546.                       ;
  547.  
  548.     cs.ulThickness = 20;
  549.     cs.dPieSize = .8;
  550.     cs.dDescriptions = .8;
  551.     WinSendMsg(hwndChart, CHTM_SETCHARTSTYLE, &cs, NULL);
  552. }
  553.  
  554. /*
  555.  *@@ RefreshViewMenu:
  556.  *
  557.  *@@added V0.9.18 (2002-03-23) [umoeller]
  558.  */
  559.  
  560. VOID RefreshViewMenu(HWND hwndMain)
  561. {
  562.     HWND hwndMenu;
  563.     if (hwndMenu = WinWindowFromID(hwndMain, FID_MENU))
  564.     {
  565.         WinCheckMenuItem(hwndMenu,
  566.                          IDMI_VIEW_BARCHART,
  567.                          (G_ulViewStyle == IDMI_VIEW_BARCHART));
  568.         WinCheckMenuItem(hwndMenu,
  569.                          IDMI_VIEW_PIECHART,
  570.                          (G_ulViewStyle == IDMI_VIEW_PIECHART));
  571.     }
  572. }
  573.  
  574. /* ******************************************************************
  575.  *
  576.  *   Command handlers
  577.  *
  578.  ********************************************************************/
  579.  
  580. #define IDDI_CREATE_PARTITION_CHBX              1101
  581. #define IDDI_CREATE_PARTITION_MAINGRP           1102
  582. #define IDDI_CREATE_PARTITIONSIZE_TXT           1103
  583. #define IDDI_CREATE_PARTITIONSIZE_SPIN          1104
  584. #define IDDI_CREATE_PARTITIONSIZE_MB            1105
  585. #define IDDI_CREATE_PARTITIONNAME_TXT           1106
  586. #define IDDI_CREATE_PARTITIONNAME_EF            1107
  587. #define IDDI_CREATE_PARTITIONTYPE_GRP           1108
  588. #define IDDI_CREATE_PARTITION_PRIMARY_CHBX      1109
  589. #define IDDI_CREATE_PARTITION_LOGICAL_CHBX      1110
  590. #define IDDI_CREATE_PARTITIONALLOC_GRP          1111
  591. #define IDDI_CREATE_PARTITION_ALLOCSTART_CHBX   1112
  592. #define IDDI_CREATE_PARTITION_ALLOCEND_CHBX     1113
  593. #define IDDI_CREATE_VOLUME_MAINGRP              1114
  594. #define IDDI_CREATE_VOLUME_CHBX                 1115
  595. #define IDDI_CREATE_VOLUMENAME_TXT              1116
  596. #define IDDI_CREATE_VOLUMENAME_EF               1117
  597.  
  598. /* #define IDDI_DELETE_VOLUME_CHBX                 1201
  599. #define IDDI_DELETE_PARTITION_CHBX              1202 */
  600.  
  601. /*
  602.  *@@ fnwpConfirmCreateDlg:
  603.  *
  604.  *@@added V0.9.14 (2001-08-03) [umoeller]
  605.  */
  606.  
  607. MRESULT EXPENTRY fnwpConfirmCreateDlg(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
  608. {
  609.     MRESULT mrc = 0;
  610.  
  611.     PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndDlg, QWL_USER);
  612.  
  613.     switch (msg)
  614.     {
  615.         case WM_INITDLG:
  616.             WinSetWindowPtr(hwndDlg, QWL_USER, mp2);
  617.         break;
  618.  
  619.         case WM_CONTROL:
  620.         {
  621.             SHORT usid = SHORT1FROMMP(mp1),
  622.                   uscode = SHORT2FROMMP(mp1);
  623.             switch (usid)
  624.             {
  625.                 case IDDI_CREATE_PARTITIONSIZE_SPIN:
  626.                     winhAdjustDlgItemSpinData(hwndDlg,
  627.                                               IDDI_CREATE_PARTITIONSIZE_SPIN,
  628.                                               // jump in steps of 1 MB == 2048 sectors
  629.                                               -2048,
  630.                                               uscode);
  631.                     WinSendMsg(hwndDlg, XM_ENABLEITEMS, 0, 0);
  632.                 break;
  633.  
  634.                 case IDDI_CREATE_PARTITION_CHBX:
  635.                 case IDDI_CREATE_VOLUME_CHBX:
  636.                     WinSendMsg(hwndDlg, XM_ENABLEITEMS, 0, 0);
  637.                 break;
  638.             }
  639.         }
  640.         break;
  641.  
  642.         case XM_ENABLEITEMS:
  643.         {
  644.             CHAR    szMB[100],
  645.                     szTemp[100];
  646.  
  647.             LONG lSectors = winhAdjustDlgItemSpinData(hwndDlg,
  648.                                                       IDDI_CREATE_PARTITIONSIZE_SPIN,
  649.                                                       0,        // no grid
  650.                                                       0);
  651.             sprintf(szMB,
  652.                     "%s MB",
  653.                     nlsThousandsULong(szTemp,
  654.                                       MB_FROM_SECTORS(lSectors),
  655.                                       G_CountrySettings.cThousands));
  656.  
  657.             WinSetDlgItemText(hwndDlg, IDDI_CREATE_PARTITIONSIZE_MB, szMB);
  658.  
  659.             BOOL fEnable = winhIsDlgItemChecked(hwndDlg, IDDI_CREATE_PARTITION_CHBX);
  660.             USHORT ausPartitionIDs[]
  661.                 = {
  662.                         IDDI_CREATE_PARTITIONSIZE_TXT,
  663.                         // IDDI_CREATE_PARTITION_MAINGRP,
  664.                         IDDI_CREATE_PARTITIONSIZE_SPIN,
  665.                         IDDI_CREATE_PARTITIONSIZE_MB,
  666.                         IDDI_CREATE_PARTITIONNAME_TXT,
  667.                         IDDI_CREATE_PARTITIONNAME_EF,
  668.                         IDDI_CREATE_PARTITIONTYPE_GRP,
  669.                         IDDI_CREATE_PARTITION_PRIMARY_CHBX,
  670.                         IDDI_CREATE_PARTITION_LOGICAL_CHBX,
  671.                         IDDI_CREATE_PARTITIONALLOC_GRP,
  672.                         IDDI_CREATE_PARTITION_ALLOCSTART_CHBX,
  673.                         IDDI_CREATE_PARTITION_ALLOCEND_CHBX,
  674.                   };
  675.  
  676.             ULONG ul = 0;
  677.  
  678.             for (;
  679.                  ul < ARRAYITEMCOUNT(ausPartitionIDs);
  680.                  ul++)
  681.                 WinEnableControl(hwndDlg, ausPartitionIDs[ul], fEnable);
  682.  
  683.             // enable volume if create partition is checked
  684.             // or if we have a partition already
  685.             BOOL fCanCreateVolume = (    (fEnable)
  686.                                       || (pData->pPartitionSource->Partition_Type)
  687.                                     ),
  688.                  fVolumeChecked = FALSE;
  689.  
  690.             WinEnableControl(hwndDlg, IDDI_CREATE_VOLUME_CHBX,
  691.                              fCanCreateVolume);
  692.             if (!fCanCreateVolume)
  693.                 winhSetDlgItemChecked(hwndDlg, IDDI_CREATE_VOLUME_CHBX, FALSE);
  694.             else
  695.                 fVolumeChecked = !!winhIsDlgItemChecked(hwndDlg, IDDI_CREATE_VOLUME_CHBX);
  696.  
  697.             USHORT ausVolumeIDs[]
  698.                 = {
  699.                         IDDI_CREATE_VOLUMENAME_TXT,
  700.                         IDDI_CREATE_VOLUMENAME_EF
  701.                   };
  702.             for (ul = 0;
  703.                  ul < ARRAYITEMCOUNT(ausVolumeIDs);
  704.                  ul++)
  705.                 WinEnableControl(hwndDlg, ausVolumeIDs[ul], fVolumeChecked);
  706.  
  707.             WinEnableControl(hwndDlg,
  708.                              DID_OK,
  709.                              (    (fVolumeChecked)
  710.                                || (fEnable)
  711.                              ));
  712.         }
  713.         break;
  714.  
  715.         default:
  716.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  717.     }
  718.  
  719.     return (mrc);
  720. }
  721.  
  722. /*
  723.  *@@ ConfirmCreate:
  724.  *
  725.  *      pData->pPartitionSource _must_ contain the
  726.  *      current partition on which to work.
  727.  *
  728.  *      Returns TRUE if the partition was created and
  729.  *      the given LVMDATA must be refreshed.
  730.  *
  731.  *@@added V0.9.12 (2001-05-10) [umoeller]
  732.  */
  733.  
  734. VOID ConfirmCreate(PLVMDATA pData)
  735. {
  736.     CHAR    szPartitionName[100],
  737.             szVolumeName[100];
  738.  
  739.     CONTROLDEF
  740.             Partition = CONTROLDEF_AUTOCHECKBOX(
  741.                                             "Create ~partition",
  742.                                             IDDI_CREATE_PARTITION_CHBX,
  743.                                             SZL_AUTOSIZE,
  744.                                             SZL_AUTOSIZE),
  745.             PartitionMainGroup = CONTROLDEF_GROUP(
  746.                                             "Partition data",
  747.                                             IDDI_CREATE_PARTITION_MAINGRP,
  748.                                             SZL_AUTOSIZE,
  749.                                             SZL_AUTOSIZE),
  750.             PartitionSizeText = CONTROLDEF_TEXT(
  751.                                             "Partition si~ze (sectors):",
  752.                                             IDDI_CREATE_PARTITIONSIZE_TXT,
  753.                                             170,
  754.                                             SZL_AUTOSIZE),
  755.             PartitionSizeSpin = CONTROLDEF_SPINBUTTON(
  756.                                             IDDI_CREATE_PARTITIONSIZE_SPIN,
  757.                                             150,
  758.                                             SZL_AUTOSIZE),
  759.             PartitionSizeText2 = CONTROLDEF_TEXT(
  760.                                             "xxx MB",
  761.                                             IDDI_CREATE_PARTITIONSIZE_MB,
  762.                                             80,
  763.                                             SZL_AUTOSIZE),    // size
  764.             PartitionNameText = CONTROLDEF_TEXT(
  765.                                             "Partition ~name:",
  766.                                             IDDI_CREATE_PARTITIONNAME_TXT,
  767.                                             170,
  768.                                             SZL_AUTOSIZE),      // size
  769.             PartitionNameEF = CONTROLDEF_ENTRYFIELD(
  770.                                             szPartitionName,
  771.                                             IDDI_CREATE_PARTITIONNAME_EF,
  772.                                             150,
  773.                                             SZL_AUTOSIZE),
  774.  
  775.             PartitionTypeGroup = CONTROLDEF_GROUP(
  776.                                             "Partition type",
  777.                                             IDDI_CREATE_PARTITIONTYPE_GRP,
  778.                                             SZL_AUTOSIZE,
  779.                                             SZL_AUTOSIZE),
  780.             PartitionTypePrimary = CONTROLDEF_FIRST_AUTORADIO(
  781.                                             "P~rimary partition",
  782.                                             IDDI_CREATE_PARTITION_PRIMARY_CHBX,
  783.                                             SZL_AUTOSIZE,
  784.                                             SZL_AUTOSIZE),
  785.             PartitionTypeLogical = CONTROLDEF_NEXT_AUTORADIO(
  786.                                             "~Logical drive",
  787.                                             IDDI_CREATE_PARTITION_LOGICAL_CHBX,
  788.                                             SZL_AUTOSIZE,
  789.                                             SZL_AUTOSIZE),
  790.  
  791.             PartitionAlloc = CONTROLDEF_GROUP(
  792.                                             "~Allocation",
  793.                                             IDDI_CREATE_PARTITIONALLOC_GRP,
  794.                                             SZL_AUTOSIZE,
  795.                                             SZL_AUTOSIZE),
  796.             PartitionAllocStart = CONTROLDEF_FIRST_AUTORADIO(
  797.                                             "Allocate from ~start of free space",
  798.                                             IDDI_CREATE_PARTITION_ALLOCSTART_CHBX,
  799.                                             SZL_AUTOSIZE,
  800.                                             SZL_AUTOSIZE),
  801.             PartitionAllocEnd = CONTROLDEF_NEXT_AUTORADIO(
  802.                                             "Allocate from ~end of free space",
  803.                                             IDDI_CREATE_PARTITION_ALLOCEND_CHBX,
  804.                                             SZL_AUTOSIZE,
  805.                                             SZL_AUTOSIZE),
  806.  
  807.             VolumeMainGroup = CONTROLDEF_GROUP(
  808.                                             "Volume data",
  809.                                             IDDI_CREATE_VOLUME_MAINGRP,
  810.                                             SZL_AUTOSIZE,
  811.                                             SZL_AUTOSIZE),
  812.             Volume = CONTROLDEF_AUTOCHECKBOX(
  813.                                             "Create ~volume",
  814.                                             IDDI_CREATE_VOLUME_CHBX,
  815.                                             SZL_AUTOSIZE,
  816.                                             SZL_AUTOSIZE),
  817.             VolumeNameText = CONTROLDEF_TEXT(
  818.                                             "Volume na~me:",
  819.                                             IDDI_CREATE_VOLUMENAME_TXT,
  820.                                             170,
  821.                                             SZL_AUTOSIZE),      // size
  822.             VolumeNameEF = CONTROLDEF_ENTRYFIELD(
  823.                                             szVolumeName,
  824.                                             IDDI_CREATE_VOLUMENAME_EF,
  825.                                             150,
  826.                                             SZL_AUTOSIZE),
  827.  
  828.             OkButton = CONTROLDEF_DEFPUSHBUTTON(
  829.                                             "~OK",
  830.                                             DID_OK,
  831.                                             100, 30),
  832.             CancelButton = CONTROLDEF_PUSHBUTTON(
  833.                                             "~Cancel",
  834.                                             DID_CANCEL,
  835.                                             100, 30);
  836.  
  837.     DLGHITEM dlgTemplate[] =
  838.                     {
  839.                         START_TABLE,
  840.                             START_ROW(ROW_VALIGN_TOP),
  841.                                 START_GROUP_TABLE(&PartitionMainGroup),
  842.                                     START_ROW(ROW_VALIGN_CENTER),
  843.                                         CONTROL_DEF(&Partition),
  844.                                     START_ROW(ROW_VALIGN_CENTER),
  845.                                         CONTROL_DEF(&PartitionSizeText),
  846.                                         CONTROL_DEF(&PartitionSizeSpin),
  847.                                         CONTROL_DEF(&PartitionSizeText2),
  848.                                     START_ROW(ROW_VALIGN_CENTER),
  849.                                         CONTROL_DEF(&PartitionNameText),
  850.                                         CONTROL_DEF(&PartitionNameEF),
  851.                                     START_ROW(0),
  852.                                         START_GROUP_TABLE(&PartitionTypeGroup),
  853.                                             START_ROW(0),
  854.                                                 CONTROL_DEF(&PartitionTypePrimary),
  855.                                             START_ROW(0),
  856.                                                 CONTROL_DEF(&PartitionTypeLogical),
  857.                                         END_TABLE,
  858.                                         START_GROUP_TABLE(&PartitionAlloc),
  859.                                             START_ROW(0),
  860.                                                 CONTROL_DEF(&PartitionAllocStart),
  861.                                             START_ROW(0),
  862.                                                 CONTROL_DEF(&PartitionAllocEnd),
  863.                                         END_TABLE,
  864.                                 END_TABLE,
  865.                             START_ROW(0),
  866.                                 START_GROUP_TABLE(&VolumeMainGroup),
  867.                                     START_ROW(0),
  868.                                         CONTROL_DEF(&Volume),
  869.                                     START_ROW(ROW_VALIGN_CENTER),
  870.                                         CONTROL_DEF(&VolumeNameText),
  871.                                         CONTROL_DEF(&VolumeNameEF),
  872.                                 END_TABLE,
  873.                             START_ROW(0),
  874.                                 CONTROL_DEF(&OkButton),
  875.                                 CONTROL_DEF(&CancelButton),
  876.                         END_TABLE
  877.                     };
  878.  
  879.     if (pData->pPartitionSource)
  880.     {
  881.         HWND hwndDlg;
  882.  
  883.         // if this is free space, enable "create partition"
  884.         if (pData->pPartitionSource->Partition_Type == 0)
  885.         {
  886.         }
  887.  
  888.         strcpy(szPartitionName,
  889.                pData->pPartitionSource->Partition_Name);
  890.                         // this is preset by LVM
  891.         sprintf(szVolumeName,
  892.                 "[ Volume %d ]",
  893.                 lstIndexFromItem(&pData->llPartitions,
  894.                                  pData->pPartitionSource));
  895.  
  896.                // pData->pPartitionSource->Volume_Name);
  897.  
  898.         if (!dlghCreateDlg(&hwndDlg,
  899.                            pData->hwndClient,
  900.                            FCF_TITLEBAR | FCF_SYSMENU | FCF_DLGBORDER | FCF_NOBYTEALIGN,
  901.                            fnwpConfirmCreateDlg,
  902.                            "Create partition/volume",
  903.                            dlgTemplate,
  904.                            ARRAYITEMCOUNT(dlgTemplate),
  905.                            pData,
  906.                            "9.WarpSans"))
  907.         {
  908.             if (pData->pPartitionSource->Partition_Type == 0)
  909.                 // no partition yet: check "partition"
  910.                 winhSetDlgItemChecked(hwndDlg, IDDI_CREATE_PARTITION_CHBX, TRUE);
  911.             else
  912.             {
  913.                 // we have a partition already: check "volume"
  914.                 winhSetDlgItemChecked(hwndDlg, IDDI_CREATE_VOLUME_CHBX, TRUE);
  915.                 // and disable "Partition"
  916.                 winhSetDlgItemChecked(hwndDlg, IDDI_CREATE_PARTITION_CHBX, FALSE);
  917.                 WinEnableControl(hwndDlg, IDDI_CREATE_PARTITION_CHBX, FALSE);
  918.             }
  919.  
  920.             winhSetDlgItemChecked(hwndDlg, IDDI_CREATE_PARTITION_LOGICAL_CHBX, TRUE);
  921.             winhSetDlgItemChecked(hwndDlg, IDDI_CREATE_PARTITION_ALLOCSTART_CHBX, TRUE);
  922.  
  923.             winhSetDlgItemSpinData(hwndDlg,
  924.                                    IDDI_CREATE_PARTITIONSIZE_SPIN,
  925.                                    10,     // min sectors =
  926.                                    pData->pPartitionSource->Usable_Partition_Size,
  927.                                    pData->pPartitionSource->Usable_Partition_Size);
  928.  
  929.             // enable the items
  930.             WinPostMsg(hwndDlg, XM_ENABLEITEMS, 0, 0);
  931.  
  932.             winhCenterWindow(hwndDlg);
  933.             WinProcessDlg(hwndDlg);
  934.  
  935.  
  936.  
  937.  
  938.             WinDestroyWindow(hwndDlg);
  939.         }
  940.     }
  941. }
  942.  
  943. /*
  944.  *@@ CreateVolumeString:
  945.  *
  946.  *@@added V0.9.18 (2002-03-23) [umoeller]
  947.  */
  948.  
  949. PCSZ CreateVolumeString(PSZ pszBuf,
  950.                         PLVMDATA pData)
  951. {
  952.     if (pData->pPartitionSource->Volume_Handle)
  953.     {
  954.         // the volume can be hidden and have no drive letter
  955.         if (pData->pPartitionSource->Volume_Drive_Letter)
  956.             sprintf(pszBuf,
  957.                     "the volume %c: -- \"%s\" (which is "
  958.                     "assigned to partition %d -- \"%s\")",
  959.                     pData->pPartitionSource->Volume_Drive_Letter,
  960.                     pData->pPartitionSource->Volume_Name,
  961.                     lstIndexFromItem(&pData->llPartitions,
  962.                                      pData->pPartitionSource),
  963.                     pData->pPartitionSource->Partition_Name);
  964.         else
  965.             sprintf(pszBuf,
  966.                     "the hidden volume \"%s\" (which is "
  967.                     "assigned to partition %d -- \"%s\")",
  968.                     pData->pPartitionSource->Volume_Name,
  969.                     lstIndexFromItem(&pData->llPartitions,
  970.                                      pData->pPartitionSource),
  971.                     pData->pPartitionSource->Partition_Name);
  972.     }
  973.     else
  974.         // no volume:
  975.         sprintf(pszBuf,
  976.                 "the partition \"%s\" (which is "
  977.                 "currently not assigned to any volume)",
  978.                 pData->pPartitionSource->Volume_Name,
  979.                 lstIndexFromItem(&pData->llPartitions,
  980.                                  pData->pPartitionSource),
  981.                 pData->pPartitionSource->Partition_Name);
  982.  
  983.     return pszBuf;
  984. }
  985.  
  986. /*
  987.  *@@ ConfirmDelete:
  988.  *      displays a confirmation box and deletes
  989.  *      the specified partition/volume.
  990.  *
  991.  *      pData->pPartitionSource _must_ contain the
  992.  *      current partition on which to work.
  993.  *
  994.  *      If the current selection is a volume,
  995.  *      this deletes the entire volume, including
  996.  *      all partitions that belong to it
  997.  *      (LVM Delete_Volume call).
  998.  *
  999.  *      If the current selection is a partition
  1000.  *      that is not part of a volume, this deletes
  1001.  *      the partition only.
  1002.  *
  1003.  *@@added V0.9.12 (2001-05-10) [umoeller]
  1004.  */
  1005.  
  1006. VOID ConfirmDelete(PLVMDATA pData)
  1007. {
  1008.     XSTRING str;
  1009.     xstrInit(&str, 0);
  1010.  
  1011.     if (pData->pPartitionSource)
  1012.     {
  1013.         if (pData->pPartitionSource->Volume_Handle)
  1014.         {
  1015.             // the volume can be hidden and have no drive letter
  1016.             if (pData->pPartitionSource->Volume_Drive_Letter)
  1017.                 xstrPrintf(&str,
  1018.                         "You have selected to delete the volume %c: -- \"%s\", which is "
  1019.                         "assigned to partition %d -- \"%s\". "
  1020.                         "Deleting the volume will completely erase all the data that is "
  1021.                         "presently stored on it, including the partition that it was assigned to. "
  1022.                         "This cannot be undone once xlvm commits your changes to disk on exit. "
  1023.                         "\n\nAre you sure you want to do this?",
  1024.                         pData->pPartitionSource->Volume_Drive_Letter,
  1025.                         pData->pPartitionSource->Volume_Name,
  1026.                         lstIndexFromItem(&pData->llPartitions,
  1027.                                          pData->pPartitionSource),
  1028.                         pData->pPartitionSource->Partition_Name);
  1029.             else
  1030.                 xstrPrintf(&str,
  1031.                         "You have selected to delete the hidden volume \"%s\", which is "
  1032.                         "assigned to partition %d -- \"%s\". "
  1033.                         "Even though the data on this volume is currently not visible to OS/2, "
  1034.                         "deleting the volume will completely erase all the data that is "
  1035.                         "presently stored on it, including the partition that it was assigned to. "
  1036.                         "This cannot be undone once xlvm commits your changes to disk on exit. "
  1037.                         "\n\nAre you sure you want to do this?",
  1038.                         pData->pPartitionSource->Volume_Name,
  1039.                         lstIndexFromItem(&pData->llPartitions,
  1040.                                          pData->pPartitionSource),
  1041.                         pData->pPartitionSource->Partition_Name);
  1042.         }
  1043.         else
  1044.             // no volume:
  1045.             xstrPrintf(&str,
  1046.                     "You have selected to delete the partition \"%s\", which is "
  1047.                     "currently not assigned to any volume. "
  1048.                     "Even though the data on this partition is currently not visible to OS/2, "
  1049.                     "deleting the partition will completely erase all the data that is "
  1050.                     "presently stored on it. "
  1051.                     "This cannot be undone once xlvm commits your changes to disk on exit. "
  1052.                     "\n\nAre you sure you want to do this?",
  1053.                     pData->pPartitionSource->Volume_Name,
  1054.                     lstIndexFromItem(&pData->llPartitions,
  1055.                                      pData->pPartitionSource),
  1056.                     pData->pPartitionSource->Partition_Name);
  1057.  
  1058.         if (MBID_YES == MessageBox(pData->hwndClient,
  1059.                                    &str,
  1060.                                    MB_YESNO | MB_DEFBUTTON2))
  1061.         {
  1062.             CARDINAL32 Error = 0;
  1063.  
  1064.             // we can't delete partitions if they're part of a volume,
  1065.             // so check volume first
  1066.             if (pData->pPartitionSource->Volume_Handle)
  1067.             {
  1068.                 Delete_Volume(pData->pPartitionSource->Volume_Handle,
  1069.                               &Error);
  1070.                 if (Error)
  1071.                     LVMError(pData->hwndClient, Error, "Delete_Volume");
  1072.             }
  1073.             else
  1074.             {
  1075.                 // no volume, but partition:
  1076.                 Delete_Partition(pData->pPartitionSource->Partition_Handle,
  1077.                                  &Error);
  1078.  
  1079.                 if (Error)
  1080.                     LVMError(pData->hwndClient, Error, "Delete_Partition");
  1081.             }
  1082.  
  1083.             if (Changes_Pending())
  1084.                 pData->fDirty = TRUE;
  1085.  
  1086.             // refresh display
  1087.             WinPostMsg(pData->hwndClient, XM_INSERTDATA, 0, 0);
  1088.         }
  1089.     }
  1090.  
  1091.     xstrClear(&str);
  1092. }
  1093.  
  1094. /*
  1095.  *@@ ConfirmHideVolume:
  1096.  *
  1097.  *@@added V0.9.18 (2002-03-23) [umoeller]
  1098.  */
  1099.  
  1100. VOID ConfirmHideVolume(PLVMDATA pData)
  1101. {
  1102.     CARDINAL32 Error = 0;
  1103.     XSTRING str;
  1104.     xstrInit(&str, 0);
  1105.     if (pData->pPartitionSource)
  1106.     {
  1107.         xstrPrintf(&str,
  1108.                 "This will make volume %c: (\"%s\") inaccessible to OS/2. "
  1109.                 "Even though no data will be deleted, "
  1110.                 "the drive letter that was assigned will no longer exist, and "
  1111.                 "all files on that drive can no longer be seen from OS/2. "
  1112.                 "\n\nAre you sure you want to do this?",
  1113.                 pData->pPartitionSource->Volume_Drive_Letter,
  1114.                 pData->pPartitionSource->Volume_Name);
  1115.         if (MBID_YES == MessageBox(pData->hwndClient,
  1116.                                    &str,
  1117.                                    MB_YESNO | MB_DEFBUTTON2))
  1118.         {
  1119.             Hide_Volume(pData->pPartitionSource->Volume_Handle,
  1120.                         &Error);
  1121.             if (Error)
  1122.                 LVMError(pData->hwndClient,
  1123.                          Error,
  1124.                          "Hide_Volume");
  1125.             else
  1126.                 // if (Changes_Pending())       this is not reported!!!
  1127.                     pData->fDirty = TRUE;
  1128.  
  1129.             // refresh display
  1130.             WinPostMsg(pData->hwndClient, XM_INSERTDATA, 0, 0);
  1131.         }
  1132.     }
  1133.  
  1134.     xstrClear(&str);
  1135. }
  1136.  
  1137. /*
  1138.  *@@ ConfirmAddToBootMgr:
  1139.  *
  1140.  *@@added V0.9.18 (2002-03-23) [umoeller]
  1141.  */
  1142.  
  1143. VOID ConfirmAddToBootMgr(PLVMDATA pData)
  1144. {
  1145.     CARDINAL32 Error = 0;
  1146.     XSTRING str;
  1147.     CHAR sz2[1000];
  1148.     xstrInit(&str, 0);
  1149.  
  1150.     if (pData->pPartitionSource)
  1151.     {
  1152.         xstrPrintf(&str,
  1153.                 "This will add %s to the boot manager menu. "
  1154.                 "\n\nAre you sure you want to do this?",
  1155.                 CreateVolumeString(sz2, pData));
  1156.         if (MBID_YES == MessageBox(pData->hwndClient,
  1157.                                    &str,
  1158.                                    MB_YESNO | MB_DEFBUTTON2))
  1159.         {
  1160.             Add_To_Boot_Manager(// pData->pPartitionSource->Partition_Handle,
  1161.                                 pData->pPartitionSource->Volume_Handle,
  1162.                                 &Error);
  1163.             if (Error)
  1164.                 LVMError(pData->hwndClient,
  1165.                          Error,
  1166.                          "Add_To_Boot_Manager");
  1167.  
  1168.             if (Changes_Pending())
  1169.                 pData->fDirty = TRUE;
  1170.         }
  1171.     }
  1172.  
  1173.     xstrClear(&str);
  1174. }
  1175.  
  1176. /*
  1177.  *@@ ConfirmRemoveFromBootMgr:
  1178.  *
  1179.  *@@added V0.9.18 (2002-03-23) [umoeller]
  1180.  */
  1181.  
  1182. VOID ConfirmRemoveFromBootMgr(PLVMDATA pData)
  1183. {
  1184.     CARDINAL32 Error = 0;
  1185.     XSTRING str;
  1186.     CHAR sz2[1000];
  1187.     xstrInit(&str, 0);
  1188.  
  1189.     if (pData->pPartitionSource)
  1190.     {
  1191.         xstrPrintf(&str,
  1192.                 "This will remove %s from the boot manager menu. "
  1193.                 "\n\nAre you sure you want to do this?",
  1194.                 CreateVolumeString(sz2, pData));
  1195.         if (MBID_YES == MessageBox(WinQueryWindow(pData->hwndClient, QW_OWNER),
  1196.                                    &str,
  1197.                                    MB_YESNO | MB_DEFBUTTON2))
  1198.         {
  1199.             Remove_From_Boot_Manager(// pData->pPartitionSource->Partition_Handle,
  1200.                                      pData->pPartitionSource->Volume_Handle,
  1201.                                      &Error);
  1202.             if (Error)
  1203.                 LVMError(pData->hwndClient,
  1204.                          Error,
  1205.                          "Remove_From_Boot_Manager");
  1206.  
  1207.             if (Changes_Pending())
  1208.                 pData->fDirty = TRUE;
  1209.         }
  1210.     }
  1211.  
  1212.     xstrClear(&str);
  1213. }
  1214.  
  1215. /*
  1216.  *@@ ClientCommand:
  1217.  *      command dispatcher for WM_COMMAND in fnwpClient.
  1218.  *
  1219.  *@@added V0.9.12 (2001-05-03) [umoeller]
  1220.  */
  1221.  
  1222. VOID ClientCommand(HWND hwndClient,
  1223.                    MPARAM mp1)
  1224. {
  1225.     PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndClient, QWL_USER);
  1226.  
  1227.     SHORT sCommand =  SHORT1FROMMP(mp1);
  1228.     switch (sCommand)
  1229.     {
  1230.         // "file" menu
  1231.         case IDMI_EXIT:
  1232.             WinPostMsg(WinQueryWindow(hwndClient, QW_OWNER),
  1233.                        WM_SYSCOMMAND,
  1234.                        (MPARAM)SC_CLOSE,
  1235.                        0);
  1236.         break;
  1237.  
  1238.         // "view" menu
  1239.         case IDMI_VIEW_BARCHART:
  1240.         case IDMI_VIEW_PIECHART:
  1241.         {
  1242.             G_ulViewStyle = sCommand;
  1243.  
  1244.             PLISTNODE pNode;
  1245.             for (pNode = lstQueryFirstNode(&pData->llDriveData);
  1246.                  pNode;
  1247.                  pNode = pNode->pNext)
  1248.             {
  1249.                 PLVMDRIVEDATA pDriveData = (PLVMDRIVEDATA)pNode->pItemData;
  1250.                 if (pDriveData->hwndChart)
  1251.                 {
  1252.                     SetChartStyle(pDriveData->hwndChart);
  1253.                 }
  1254.             }
  1255.  
  1256.             RefreshViewMenu(WinQueryWindow(hwndClient, QW_PARENT));
  1257.         }
  1258.         break;
  1259.  
  1260.         case IDMI_VIEW_REFRESH:
  1261.             WinPostMsg(hwndClient,
  1262.                        XM_INSERTDATA,
  1263.                        0,
  1264.                        0);
  1265.         break;
  1266.  
  1267.         // whitespace context menu
  1268.         case IDMI_INSTALLBMGR:
  1269.         break;
  1270.  
  1271.         case IDMI_REMOVEBMGR:
  1272.         break;
  1273.  
  1274.         case IDMI_SETMGRVALUES:
  1275.         break;
  1276.  
  1277.         /*
  1278.          * IDMI_CREATE:
  1279.          *      can come from
  1280.          *
  1281.          *      --  free space
  1282.          *
  1283.          *      --  partition (no volume assigned)
  1284.          */
  1285.  
  1286.         case IDMI_CREATE:
  1287.             ConfirmCreate(pData);
  1288.         break;
  1289.  
  1290.         /*
  1291.          * IDMI_DELETE:
  1292.          *      can come from
  1293.          *
  1294.          *      --  partition (no volume assigned)
  1295.          *
  1296.          *      --  volume
  1297.          */
  1298.  
  1299.         case IDMI_DELETE:
  1300.             ConfirmDelete(pData);
  1301.         break;
  1302.  
  1303.         case IDMI_RENAME:
  1304.         break;
  1305.  
  1306.         // volume context menu
  1307.         case IDMI_EXPANDVOLUME:
  1308.         break;
  1309.  
  1310.         case IDMI_HIDEVOLUME:
  1311.             ConfirmHideVolume(pData);
  1312.         break;
  1313.  
  1314.         case IDMI_CHANGELETTER:
  1315.         break;
  1316.  
  1317.         case IDMI_RENAMEPARTITION_VOLUME:
  1318.         break;
  1319.  
  1320.         case IDMI_SETSTARTABLE:
  1321.         break;
  1322.  
  1323.         case IDMI_ADDTOBMGR:
  1324.             ConfirmAddToBootMgr(pData);
  1325.         break;
  1326.  
  1327.         case IDMI_REMOVEFROMBMGR:
  1328.             ConfirmRemoveFromBootMgr(pData);
  1329.         break;
  1330.     }
  1331. }
  1332.  
  1333. /* ******************************************************************
  1334.  *
  1335.  *   Client window proc
  1336.  *
  1337.  ********************************************************************/
  1338.  
  1339. /*
  1340.  *@@ GetPartitionColor:
  1341.  *      returns a color according to the partition type.
  1342.  *
  1343.  *@@added V0.9.12 (2001-05-03) [umoeller]
  1344.  */
  1345.  
  1346. LONG GetPartitionColor(ULONG ulType,
  1347.                        Partition_Information_Record *pBarItem, // in: partition info
  1348.                        PSZ pszType)       // out: if != NULL, description
  1349. {
  1350.     switch (ulType)
  1351.     {
  1352.         case 0:     // free
  1353.             if (pszType)
  1354.                 strcpy(pszType, "Free space");
  1355.             return RGBCOL_DARKGRAY;
  1356.         break;
  1357.  
  1358.         case 0x14:
  1359.         case 0x06:
  1360.         case 0x01:
  1361.         case 0x04:
  1362.         case 0x84:  // FAT
  1363.             if (pszType)
  1364.                 strcpy(pszType, "FAT16");
  1365.             return RGBCOL_DARKGREEN;
  1366.         break;
  1367.  
  1368.         case 0x07: // compatibility volume
  1369.         case 0x35:  // LVM volume
  1370.             if (pszType)
  1371.             {
  1372.                 if (    (pBarItem)
  1373.                      && (pBarItem->Volume_Drive_Letter)
  1374.                      && (!doshQueryDiskFSType(toupper(pBarItem->Volume_Drive_Letter) - 'A' + 1,
  1375.                                               pszType,
  1376.                                               20))
  1377.                    )
  1378.                     ;
  1379.                 else
  1380.                     strcpy(pszType, "unknown");
  1381.             }
  1382.  
  1383.             if (ulType == 0x07)
  1384.                 return RGBCOL_DARKBLUE;
  1385.  
  1386.             return RGBCOL_BLUE;
  1387.         break;
  1388.  
  1389.         case 0x0b:
  1390.         case 0x0c:  // FAT32
  1391.             if (pszType)
  1392.                 strcpy(pszType, "FAT32");
  1393.             return RGBCOL_DARKYELLOW;
  1394.         break;
  1395.  
  1396.         case 0x82:
  1397.             if (pszType)
  1398.                 strcpy(pszType, "Linux swap");
  1399.             return RGBCOL_DARKRED;
  1400.  
  1401.         case 0x83:  // linux
  1402.             if (pszType)
  1403.                 strcpy(pszType, "Linux ext2fs");
  1404.             return RGBCOL_DARKRED;
  1405.         break;
  1406.  
  1407.         case 0x0a:  // boot manager
  1408.             if (pszType)
  1409.                 strcpy(pszType, "IBM boot manager");
  1410.             return RGBCOL_DARKCYAN;
  1411.         break;
  1412.  
  1413.     }
  1414.  
  1415.     // unknown:
  1416.     if (pszType)
  1417.         strcpy(pszType, "unknown");
  1418.     return RGBCOL_DARKGRAY;
  1419. }
  1420.  
  1421. /*
  1422.  *@@ SetControlsData:
  1423.  *      creates and sets up the chart controls in the client.
  1424.  *
  1425.  *      The chart controls maintain full copies of the display
  1426.  *      data, so there's nothing to free here afterwards.
  1427.  *
  1428.  *@@added V0.9.12 (2001-05-03) [umoeller]
  1429.  */
  1430.  
  1431. VOID SetControlsData(HWND hwndClient)
  1432. {
  1433.     PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndClient, QWL_USER);
  1434.  
  1435.     // count drives; we need to divide the remaining space
  1436.     ULONG   cDrives = lstCountItems(&pData->llDriveData);
  1437.     ULONG   ulCurrentID = 1000;
  1438.  
  1439.     if (cDrives)        // avoid division by zero
  1440.     {
  1441.         // drives loop
  1442.         PLISTNODE pNode = lstQueryFirstNode(&pData->llDriveData);
  1443.         while (pNode)
  1444.         {
  1445.             PLVMDRIVEDATA pDriveData = (PLVMDRIVEDATA)pNode->pItemData;
  1446.  
  1447.             ULONG ulDriveNo = pDriveData->pControlRecord->Drive_Number;
  1448.  
  1449.             // create a chart control for this
  1450.             if (!pDriveData->hwndChart)
  1451.             {
  1452.                 LONG lColor = RGBCOL_WHITE;
  1453.                 pDriveData->hwndChart = winhCreateControl(hwndClient,
  1454.                                                           WC_STATIC,
  1455.                                                           "chart",
  1456.                                                           SS_TEXT | DT_LEFT | DT_VCENTER
  1457.                                                             | WS_VISIBLE,
  1458.                                                           // ID:
  1459.                                                           ulCurrentID++);
  1460.                 WinSetPresParam(pDriveData->hwndChart,
  1461.                                 PP_FOREGROUNDCOLOR,
  1462.                                 sizeof(lColor),
  1463.                                 &lColor);
  1464.                 lColor = WinQuerySysColor(HWND_DESKTOP,
  1465.                                           SYSCLR_APPWORKSPACE,
  1466.                                           0);
  1467.                 WinSetPresParam(pDriveData->hwndDescription,
  1468.                                 PP_BACKGROUNDCOLOR,
  1469.                                 sizeof(lColor),
  1470.                                 &lColor);
  1471.                 ctlChartFromStatic(pDriveData->hwndChart);
  1472.  
  1473.                 SetChartStyle(pDriveData->hwndChart);
  1474.             }
  1475.  
  1476.             // and a description static
  1477.             if (!pDriveData->hwndDescription)
  1478.             {
  1479.                 pDriveData->hwndDescription = winhCreateControl(hwndClient,
  1480.                                                                 WC_STATIC,
  1481.                                                                 "descr",
  1482.                                                                 SS_TEXT | DT_LEFT | DT_VCENTER
  1483.                                                                     | WS_VISIBLE,
  1484.                                                                 0);
  1485.                 LONG lColor = WinQuerySysColor(HWND_DESKTOP,
  1486.                                                SYSCLR_APPWORKSPACE,
  1487.                                                0);
  1488.                 WinSetPresParam(pDriveData->hwndDescription,
  1489.                                 PP_BACKGROUNDCOLOR,
  1490.                                 sizeof(lColor),
  1491.                                 &lColor);
  1492.             }
  1493.  
  1494.             // set drive description text
  1495.             ULONG ulMB =    MB_FROM_SECTORS(pDriveData->pControlRecord->Drive_Size);
  1496.             CHAR sz[1000], sz2[50], sz3[50];
  1497.             LONG lSectorsOnDrive = pDriveData->pControlRecord->Drive_Size;
  1498.  
  1499.             sprintf(sz,
  1500.                     "Drive %d: \"%s\", %s MBytes, %s sectors (CHS: %d/%d/%d)",
  1501.                     ulDriveNo,
  1502.                     pDriveData->InfoRecord.Drive_Name,
  1503.                     nlsThousandsULong(sz2,
  1504.                                       ulMB,
  1505.                                       G_CountrySettings.cThousands),
  1506.                     nlsThousandsULong(sz3,
  1507.                                       lSectorsOnDrive,
  1508.                                       G_CountrySettings.cThousands),
  1509.                     pDriveData->pControlRecord->Cylinder_Count,
  1510.                     pDriveData->pControlRecord->Heads_Per_Cylinder,
  1511.                     pDriveData->pControlRecord->Sectors_Per_Track);
  1512.             WinSetWindowText(pDriveData->hwndDescription, sz);
  1513.  
  1514.             // set chart data
  1515.             ULONG cPartitionsThis = pDriveData->PartitionsArray.Count;
  1516.             CHARTDATA       cd;
  1517.             ZERO(&cd);
  1518.             cd.usStartAngle = 90 + 45/2;
  1519.             cd.usSweepAngle = 360 -  45;
  1520.             cd.cValues = cPartitionsThis; // array count
  1521.             cd.padValues = (double*)malloc(sizeof(double) * cPartitionsThis);
  1522.             cd.palColors = (long*)malloc(sizeof(long) * cPartitionsThis);
  1523.             cd.papszDescriptions = (PSZ*)malloc(sizeof(PSZ) * cPartitionsThis);
  1524.  
  1525.             LONG lMinSize = (lSectorsOnDrive / 1000) * 2 / 100;
  1526.  
  1527.             ULONG ul;
  1528.             for (ul = 0;
  1529.                  ul < cPartitionsThis;
  1530.                  ul++)
  1531.             {
  1532.                 Partition_Information_Record *pBarItem
  1533.                             = &pDriveData->PartitionsArray.Partition_Array[ul];
  1534.  
  1535.                 LONG lSizeThis = pBarItem->True_Partition_Size / 1000;
  1536.                 // if this is a small partition (less than 2% of the disk
  1537.                 // size), enlarge it to 2% of the disk size
  1538.                 if (lSizeThis < lMinSize)
  1539.                     lSizeThis = lMinSize;
  1540.  
  1541.                 cd.padValues[ul] = (double)lSizeThis;
  1542.  
  1543.                 // set color
  1544.                 ULONG ulType = 0;
  1545.                 if (pBarItem->Partition_Type != 0)
  1546.                     ulType = pBarItem->OS_Flag;
  1547.                 cd.palColors[ul] = GetPartitionColor(ulType, NULL, NULL);
  1548.  
  1549.                 // set text
  1550.                 sprintf(sz,
  1551.                         "%u",
  1552.                         lstIndexFromItem(&pData->llPartitions, pBarItem));
  1553.                 if (pBarItem->Volume_Drive_Letter)
  1554.                     sprintf(sz + strlen(sz),
  1555.                             "\n%c:",
  1556.                             pBarItem->Volume_Drive_Letter);
  1557.  
  1558.                 cd.papszDescriptions[ul] = strdup(sz);
  1559.             }
  1560.  
  1561.             // cd.papszDescriptions = &apszDescriptions[0];
  1562.             WinSendMsg(pDriveData->hwndChart, CHTM_SETCHARTDATA, &cd, NULL);
  1563.  
  1564.             free(cd.padValues);
  1565.             free(cd.palColors);
  1566.             for (ul = 0;
  1567.                  ul < cPartitionsThis;
  1568.                  ul++)
  1569.                 free(cd.papszDescriptions[ul]);
  1570.             free(cd.papszDescriptions);
  1571.  
  1572.             // next drive
  1573.             pNode = pNode->pNext;
  1574.         }
  1575.     }
  1576. }
  1577.  
  1578. /*
  1579.  *@@ PositionChartsInClient:
  1580.  *
  1581.  *@@added V0.9.12 (2001-05-03) [umoeller]
  1582.  */
  1583.  
  1584. VOID PositionChartsInClient(HWND hwndClient)
  1585. {
  1586.     PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndClient, QWL_USER);
  1587.  
  1588.     RECTL rclClient;
  1589.  
  1590.     WinQueryWindowRect(hwndClient,
  1591.                        &rclClient); // exclusive
  1592.  
  1593.     #define OUTER_SPACING 20
  1594.     #define INNER_SPACING 10
  1595.     #define DESCR_HEIGHT  20
  1596.  
  1597.     // reduce the rect by 20
  1598.     gpihInflateRect(&rclClient, -OUTER_SPACING);
  1599.  
  1600.     // count drives; we need to divide the remaining space
  1601.     ULONG cDrives = lstCountItems(&pData->llDriveData);
  1602.  
  1603.     if (cDrives)        // avoid division by zero
  1604.     {
  1605.         LONG cyPaint = rclClient.yTop - rclClient.yBottom;
  1606.         // leave another 20 pixels space between the drives
  1607.         cyPaint -= (INNER_SPACING * (cDrives - 1));
  1608.         LONG cyPerDrive = cyPaint / cDrives;
  1609.  
  1610.         // start with drive 1 on top
  1611.         LONG yTop = rclClient.yTop;
  1612.  
  1613.         // drives loop
  1614.         PLISTNODE pNode = lstQueryFirstNode(&pData->llDriveData);
  1615.         while (pNode)
  1616.         {
  1617.             PLVMDRIVEDATA pDriveData = (PLVMDRIVEDATA)pNode->pItemData;
  1618.  
  1619.             WinSetWindowPos(pDriveData->hwndChart,
  1620.                             0,
  1621.                             rclClient.xLeft,
  1622.                             yTop - cyPerDrive + INNER_SPACING + DESCR_HEIGHT,
  1623.                             rclClient.xRight - rclClient.xLeft,
  1624.                             cyPerDrive - INNER_SPACING - DESCR_HEIGHT,
  1625.                             SWP_MOVE | SWP_SIZE);
  1626.  
  1627.             WinSetWindowPos(pDriveData->hwndDescription,
  1628.                             0,
  1629.                             rclClient.xLeft,
  1630.                             yTop - cyPerDrive,
  1631.                             rclClient.xRight - rclClient.xLeft,
  1632.                             DESCR_HEIGHT,
  1633.                             SWP_MOVE | SWP_SIZE);
  1634.  
  1635.             // next drive
  1636.             pNode = pNode->pNext;
  1637.             // go down for next drive
  1638.             yTop -= cyPerDrive;
  1639.             yTop -= INNER_SPACING;
  1640.         }
  1641.     }
  1642. }
  1643.  
  1644. /*
  1645.  *@@ GetVolumeDescription:
  1646.  *      describes the given volume.
  1647.  *
  1648.  *@@added V0.9.12 (2001-05-03) [umoeller]
  1649.  */
  1650.  
  1651. VOID GetVolumeDescription(PLVMDATA pData,
  1652.                           PSZ psz,      // out: description string
  1653.                           Partition_Information_Record *pBarItem) // in: partition info
  1654. {
  1655.     *psz = '\0';
  1656.  
  1657.     psz += sprintf(psz,
  1658.                    "Partition %u",
  1659.                    lstIndexFromItem(&pData->llPartitions, pBarItem));
  1660.  
  1661.     if (pBarItem->Partition_Type == 0)
  1662.         psz += sprintf(psz, ": free space");
  1663.     else
  1664.     {
  1665.         if (pBarItem->Volume_Drive_Letter)
  1666.             psz += sprintf(psz, ": drive %c:", pBarItem->Volume_Drive_Letter);
  1667.         else
  1668.             psz += sprintf(psz, ": hidden");
  1669.  
  1670.         if (strlen(pBarItem->Volume_Name))
  1671.             psz += sprintf(psz,
  1672.                            " (Volume name \"%s\") ",
  1673.                            pBarItem->Volume_Name);
  1674.  
  1675.         if (pBarItem->Primary_Partition)
  1676.             psz += sprintf(psz, ", primary partition");
  1677.  
  1678.         CHAR szDesc[100];
  1679.         GetPartitionColor(pBarItem->OS_Flag, pBarItem, szDesc);
  1680.  
  1681.         if (pBarItem->OS_Flag)
  1682.             psz += sprintf(psz,
  1683.                            ", type 0x%lX (%s)",
  1684.                            pBarItem->OS_Flag,
  1685.                            szDesc);
  1686.     }
  1687.  
  1688.     CHAR sz2[200], sz3[200];
  1689.  
  1690.     psz += sprintf(psz,
  1691.                    ", %s MB (%s sectors)",
  1692.                    nlsThousandsULong(sz2,
  1693.                                      MB_FROM_SECTORS(pBarItem->True_Partition_Size),
  1694.                                      G_CountrySettings.cThousands),
  1695.                    nlsThousandsULong(sz3,
  1696.                                      pBarItem->True_Partition_Size,
  1697.                                      G_CountrySettings.cThousands));
  1698. }
  1699.  
  1700. /*
  1701.  *@@ ShowContextMenu:
  1702.  *      builds and shows a context menu for the
  1703.  *      selected partition.
  1704.  *
  1705.  *@@added V0.9.12 (2001-05-03) [umoeller]
  1706.  */
  1707.  
  1708. VOID ShowContextMenu(PLVMDATA pData,
  1709.                      PEMPHASISNOTIFY pen,
  1710.                      Partition_Information_Record *pBarItem)
  1711. {
  1712.     HWND hwndMenu = 0;
  1713.  
  1714.     if (!pBarItem)
  1715.         hwndMenu = G_hwndWhitespaceMenu;
  1716.     else
  1717.         if (pBarItem->Partition_Type == 0)
  1718.         {
  1719.             hwndMenu = G_hwndFreeSpaceMenu;
  1720.  
  1721.             // now enable/disable the items that don't apply
  1722.             CARDINAL32 Error = 0;
  1723.             ULONG ulOptions = Get_Valid_Options(pBarItem->Partition_Handle,
  1724.                                                 &Error);
  1725.  
  1726.             WinEnableMenuItem(hwndMenu,
  1727.                               IDMI_CREATE,
  1728.                               (    ulOptions
  1729.                                    & (CREATE_PRIMARY_PARTITION | CREATE_LOGICAL_DRIVE))
  1730.                               != 0);
  1731.         }
  1732.         else
  1733.         {
  1734.             if (pBarItem->Volume_Handle)
  1735.             {
  1736.                 // this partition is part of a volume:
  1737.                 hwndMenu = G_hwndVolumeMenu;
  1738.  
  1739.                 // now enable/disable the items that don't apply
  1740.                 CARDINAL32 Error = 0;
  1741.                 ULONG ulOptions = Get_Valid_Options(pBarItem->Volume_Handle,
  1742.                                                           &Error);
  1743.  
  1744.                 WinEnableMenuItem(hwndMenu,
  1745.                                   IDMI_EXPANDVOLUME,
  1746.                                   (ulOptions & EXPAND_VOLUME) != 0);
  1747.                 WinEnableMenuItem(hwndMenu,
  1748.                                   IDMI_DELETE,
  1749.                                   (ulOptions & DELETE_VOLUME) != 0);
  1750.                 WinEnableMenuItem(hwndMenu,
  1751.                                   IDMI_HIDEVOLUME,
  1752.                                   (ulOptions & HIDE_VOLUME) != 0);
  1753.                 WinEnableMenuItem(hwndMenu,
  1754.                                   IDMI_CHANGELETTER,
  1755.                                   (ulOptions & ASSIGN_DRIVE_LETTER) != 0);
  1756.  
  1757.                 // rename partition/volume is always enabled
  1758.  
  1759.                 WinEnableMenuItem(hwndMenu,
  1760.                                   IDMI_SETSTARTABLE,
  1761.                                   (ulOptions & SET_STARTABLE) != 0);
  1762.                 WinEnableMenuItem(hwndMenu,
  1763.                                   IDMI_ADDTOBMGR,
  1764.                                   (ulOptions & ADD_TO_BOOT_MANAGER_MENU) != 0);
  1765.                 WinEnableMenuItem(hwndMenu,
  1766.                                   IDMI_REMOVEFROMBMGR,
  1767.                                   (ulOptions & REMOVE_FROM_BOOT_MANAGER_MENU) != 0);
  1768.             }
  1769.             else
  1770.                 // partition not currently assigned to a volume:
  1771.                 hwndMenu = G_hwndPartitionMenu;
  1772.         }
  1773.  
  1774.     if (hwndMenu)
  1775.     {
  1776.         pData->pPartitionSource = pBarItem;
  1777.         G_hwndMenuShowing = hwndMenu;       // to remove source emphasis later
  1778.  
  1779.         POINTL ptl = {pen->ptl.x, pen->ptl.y};
  1780.         // map to desktop
  1781.         WinMapWindowPoints(pen->hwndSource,     // from chart ctl
  1782.                            HWND_DESKTOP,
  1783.                            &ptl,
  1784.                            1);
  1785.  
  1786.         // add source emphasis
  1787.         WinSendMsg(pen->hwndSource,
  1788.                    CHTM_SETEMPHASIS,
  1789.                    (MPARAM)1,           // source emphasis
  1790.                    (MPARAM)pen->lIndex);
  1791.  
  1792.         // store emphasis data
  1793.         memcpy(&G_CurrentEmphasis, pen, sizeof(EMPHASISNOTIFY));
  1794.  
  1795.         WinPopupMenu(HWND_DESKTOP,
  1796.                      pData->hwndClient,
  1797.                      hwndMenu,
  1798.                      ptl.x,
  1799.                      ptl.y,
  1800.                      0,
  1801.                      PU_HCONSTRAIN | PU_VCONSTRAIN | PU_MOUSEBUTTON1
  1802.                         | PU_MOUSEBUTTON2 | PU_KEYBOARD);
  1803.     }
  1804. }
  1805.  
  1806. /*
  1807.  *@@ ConfirmCommit:
  1808.  *
  1809.  *@@added V0.9.18 (2002-03-23) [umoeller]
  1810.  */
  1811.  
  1812. BOOL ConfirmCommit(HWND hwndClient)
  1813. {
  1814.     BOOL fClose = FALSE;
  1815.  
  1816.     XSTRING str;
  1817.     xstrInitCopy(&str,
  1818.                  "Changes have been made to the disk setup. "
  1819.                  "At this point, none of the changes have been written to the disk(s) yet. "
  1820.                  "Writing the changes will make them permanent. "
  1821.                  "\n\nShould all pending changes be written to disk now?",
  1822.                  0);
  1823.  
  1824.     ULONG ulrc = MessageBox(hwndClient,
  1825.                             &str,
  1826.                             MB_YESNOCANCEL | MB_DEFBUTTON2);
  1827.     switch (ulrc)
  1828.     {
  1829.         case MBID_YES:
  1830.         {
  1831.             // commit:
  1832.             CARDINAL32 Error;
  1833.             if (Commit_Changes(&Error))
  1834.                 fClose = TRUE;
  1835.             else
  1836.                 LVMError(hwndClient,
  1837.                          Error,
  1838.                          "Commit_Changes");
  1839.         }
  1840.         break;
  1841.  
  1842.         case MBID_NO:
  1843.             fClose = TRUE;
  1844.         break;
  1845.     }
  1846.  
  1847.     xstrClear(&str);
  1848.  
  1849.     return fClose;
  1850. }
  1851.  
  1852. /*
  1853.  *@@ fnwpClient:
  1854.  *      client window proc.
  1855.  */
  1856.  
  1857. MRESULT EXPENTRY fnwpClient(HWND hwndClient, ULONG msg, MPARAM mp1, MPARAM mp2)
  1858. {
  1859.     MRESULT mrc = 0;
  1860.  
  1861.     switch (msg)
  1862.     {
  1863.         case WM_CREATE:
  1864.         {
  1865.             PLVMDATA pData = NEW(LVMDATA);
  1866.             ZERO(pData);
  1867.  
  1868.             lstInit(&pData->llDriveData, FALSE);
  1869.             lstInit(&pData->llPartitions, FALSE);
  1870.  
  1871.             pData->hwndClient = hwndClient;
  1872.  
  1873.             WinSetWindowPtr(hwndClient, QWL_USER, pData);
  1874.  
  1875.             WinPostMsg(hwndClient,
  1876.                        XM_INSERTDATA,
  1877.                        0,
  1878.                        0);
  1879.         }
  1880.         break;
  1881.  
  1882.         /*
  1883.          * XM_INSERTDATA:
  1884.          *      posted on startup to load the LVM data.
  1885.          *
  1886.          *      No parameters.
  1887.          */
  1888.  
  1889.         case XM_INSERTDATA:
  1890.         {
  1891.             ULONG ulError = 0;
  1892.             PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndClient, QWL_USER);
  1893.  
  1894.             fprintf(G_LogFile, __FUNCTION__ ": processing XM_INSERTDATA\n"
  1895.                        );
  1896.  
  1897.             // clean up if not first post
  1898.             FreeLVMData(pData,
  1899.                         FALSE);         // do not free engine yet
  1900.  
  1901.             if (!(ulError = thrRunSync(WinQueryAnchorBlock(hwndClient),
  1902.                                        fntLoadLVMData,
  1903.                                        "loadLVMData",
  1904.                                        (ULONG)pData)))
  1905.             {
  1906.                 fprintf(G_LogFile, __FUNCTION__ ": calling SetControlsData\n");
  1907.  
  1908.                 // update controls with the data
  1909.                 SetControlsData(hwndClient);
  1910.  
  1911.                 fprintf(G_LogFile, __FUNCTION__ ": calling PositionChartsInClient\n");
  1912.  
  1913.                 // position the controls in the client
  1914.                 PositionChartsInClient(hwndClient);
  1915.  
  1916.                 WinSetWindowText(G_hwndStatusBar,
  1917.                                  "xlvm is ready.");
  1918.  
  1919.                 fprintf(G_LogFile, __FUNCTION__ ": done processing XM_INSERTDATA\n");
  1920.             }
  1921.             else
  1922.             {
  1923.                 WinSetWindowText(G_hwndStatusBar,
  1924.                                  "An error occured loading the LVM data.");
  1925.             }
  1926.         }
  1927.         break;
  1928.  
  1929.         /*
  1930.          *@@ XM_LVMERROR:
  1931.          *      mp1 has error code
  1932.          *      mp2 has context
  1933.          */
  1934.  
  1935.         case XM_LVMERROR:
  1936.         {
  1937.             XSTRING str;
  1938.             xstrInit(&str, 0);
  1939.             xstrPrintf(&str,
  1940.                     "An error returned in the LVM engine. %s returned error code %d (%s).",
  1941.                     mp2,
  1942.                     mp1,
  1943.                     DescribeLVMError((ULONG)mp1));
  1944.             MessageBox(hwndClient,
  1945.                        &str,
  1946.                        MB_OK);
  1947.             xstrClear(&str);
  1948.         }
  1949.         break;
  1950.  
  1951.         /*
  1952.          * WM_PAINT:
  1953.          *
  1954.          */
  1955.  
  1956.         case WM_PAINT:
  1957.         {
  1958.             fprintf(G_LogFile, __FUNCTION__ ": processing WM_PAINT\n");
  1959.  
  1960.             RECTL rclClient;
  1961.             HPS hps = WinBeginPaint(hwndClient, NULLHANDLE, NULL);
  1962.             WinQueryWindowRect(hwndClient, &rclClient);
  1963.             gpihSwitchToRGB(hps);
  1964.             WinFillRect(hps,
  1965.                         &rclClient,
  1966.                         WinQuerySysColor(HWND_DESKTOP,
  1967.                                          SYSCLR_APPWORKSPACE,
  1968.                                          0));
  1969.             WinEndPaint(hps);
  1970.  
  1971.             fprintf(G_LogFile, __FUNCTION__ ": done processing WM_PAINT\n");
  1972.         }
  1973.         break;
  1974.  
  1975.         case WM_SIZE:
  1976.             fprintf(G_LogFile, __FUNCTION__ ": processing WM_SIZE\n");
  1977.             PositionChartsInClient(hwndClient);
  1978.             fprintf(G_LogFile, __FUNCTION__ ": done processing WM_SIZE\n");
  1979.         break;
  1980.  
  1981.         /*
  1982.          * WM_COMMAND:
  1983.          *
  1984.          */
  1985.  
  1986.         case WM_COMMAND:
  1987.             fprintf(G_LogFile, __FUNCTION__ ": processing WM_COMMAND 0x%lX\n", SHORT1FROMMP(mp1));
  1988.             ClientCommand(hwndClient, mp1);
  1989.             fprintf(G_LogFile, __FUNCTION__ ": done processing WM_COMMAND 0x%lX\n", SHORT1FROMMP(mp1));
  1990.         break;
  1991.  
  1992.         /*
  1993.          * WM_CONTROL:
  1994.          *
  1995.          */
  1996.  
  1997.         case WM_CONTROL:
  1998.         {
  1999.             fprintf(G_LogFile, __FUNCTION__ ": processing WM_CONTROL 0x%lX\n", SHORT1FROMMP(mp1));
  2000.  
  2001.             SHORT usid = SHORT1FROMMP(mp1),
  2002.                   uscode = SHORT2FROMMP(mp1);
  2003.             if (usid >= 1000)        // chart controls have 1000 + drive no.
  2004.             {
  2005.                 switch (uscode)
  2006.                 {
  2007.                     case CHTN_EMPHASISCHANGED:
  2008.                     case CHTN_CONTEXTMENU:
  2009.                     case CHTN_SETFOCUS:  // V0.9.20 (2002-07-17) [pr]
  2010.                     {
  2011.                         PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndClient, QWL_USER);
  2012.  
  2013.                         PLVMDRIVEDATA pDriveData
  2014.                                 = (PLVMDRIVEDATA)lstItemFromIndex(&pData->llDriveData,
  2015.                                                                   usid - 1000);
  2016.                         if (pDriveData)
  2017.                         {
  2018.                             // now we got the drive where a new volume
  2019.                             // was selected: get the volume then from
  2020.                             // the chart control data given to us
  2021.                             PEMPHASISNOTIFY pen = (PEMPHASISNOTIFY)mp2;
  2022.                             if (pen)
  2023.                             {
  2024.                                 if (   (   (uscode == CHTN_EMPHASISCHANGED)
  2025.                                         && (pen->ulEmphasis == 0)      // selection changed
  2026.                                        )
  2027.                                     || (uscode == CHTN_SETFOCUS)  // V0.9.20 (2002-07-17) [pr]
  2028.                                    )
  2029.                                 {
  2030.                                     if (pen->lIndex == -1)
  2031.                                         // deselected:
  2032.                                         WinSetWindowText(G_hwndStatusBar, "");
  2033.                                     else if (pen->lIndex < pDriveData->PartitionsArray.Count)
  2034.                                     {
  2035.                                         // selection changed:
  2036.                                         Partition_Information_Record *pBarItem
  2037.                                             = &pDriveData->PartitionsArray.Partition_Array[pen->lIndex];
  2038.                                         CHAR sz[1000] = "?";
  2039.                                         GetVolumeDescription(pData, sz, pBarItem);
  2040.                                         WinSetWindowText(G_hwndStatusBar, sz);
  2041.                                     }
  2042.                                 }
  2043.                                 else
  2044.                                     if (    (pen->lIndex < pDriveData->PartitionsArray.Count)
  2045.                                          && (uscode == CHTN_CONTEXTMENU)
  2046.                                        )
  2047.                                     {
  2048.                                         Partition_Information_Record *pBarItem
  2049.                                             = &pDriveData->PartitionsArray.Partition_Array[pen->lIndex];
  2050.                                         {
  2051.                                             ShowContextMenu(pData,
  2052.                                                             pen,
  2053.                                                             pBarItem);
  2054.                                         }
  2055.                                     }
  2056.                             }
  2057.                         }
  2058.                     }
  2059.                     break;
  2060.  
  2061.                 } // end switch
  2062.             }
  2063.  
  2064.             fprintf(G_LogFile, __FUNCTION__ ": done processing WM_CONTROL 0x%lX\n", SHORT1FROMMP(mp1));
  2065.         }
  2066.         break;
  2067.  
  2068.         /*
  2069.          * WM_MENUEND:
  2070.          *      remove source emphasis when context menu goes
  2071.          *      away.
  2072.          */
  2073.  
  2074.         case WM_MENUEND:
  2075.             if (    (G_hwndMenuShowing)
  2076.                  && ((HWND)mp2 == G_hwndMenuShowing)
  2077.                )
  2078.             {
  2079.                 WinSendMsg(G_CurrentEmphasis.hwndSource,
  2080.                            CHTM_SETEMPHASIS,
  2081.                            (MPARAM)1,           // source emphasis
  2082.                            (MPARAM)-1);         // remove
  2083.             }
  2084.         break;
  2085.  
  2086.         /*
  2087.          * WM_CLOSE:
  2088.          *
  2089.          */
  2090.  
  2091.         case WM_CLOSE:
  2092.         {
  2093.             PLVMDATA pData = (PLVMDATA)WinQueryWindowPtr(hwndClient, QWL_USER);
  2094.  
  2095.             fprintf(G_LogFile, __FUNCTION__ ": processing WM_CLOSE\n");
  2096.             BOOL fClose = FALSE;
  2097.  
  2098.             if (!pData->fDirty)
  2099.                 fClose = TRUE;
  2100.             else
  2101.             {
  2102.                 // dirty:
  2103.                 fClose = ConfirmCommit(hwndClient);
  2104.             }
  2105.  
  2106.             if (fClose)
  2107.             {
  2108.                 winhSaveWindowPos(WinQueryWindow(hwndClient, QW_OWNER),
  2109.                                   HINI_USER,
  2110.                                   INIAPP,
  2111.                                   INIKEY_MAINWINPOS);
  2112.                 WinSetWindowText(G_hwndStatusBar,
  2113.                                  "Cleaning up...");
  2114.  
  2115.                 fprintf(G_LogFile, __FUNCTION__ ":   posting WM_QUIT\n");
  2116.  
  2117.                 WinPostMsg(hwndClient, WM_QUIT, 0, 0);
  2118.  
  2119.                 FreeLVMData(pData,
  2120.                             TRUE);      // close engine
  2121.             }
  2122.  
  2123.             fprintf(G_LogFile, __FUNCTION__ ": done processing WM_CLOSE\n");
  2124.         }
  2125.         break;
  2126.  
  2127.         default:
  2128.             mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
  2129.     }
  2130.  
  2131.     return (mrc);
  2132. }
  2133.  
  2134. /* ******************************************************************
  2135.  *
  2136.  *   Frame window proc
  2137.  *
  2138.  ********************************************************************/
  2139.  
  2140. /*
  2141.  *@@ winhCreateStatusBar:
  2142.  *
  2143.  *@@added V0.9.5 (2000-08-13) [umoeller]
  2144.  */
  2145.  
  2146. HWND winhCreateStatusBar(HWND hwndFrame,
  2147.                          HWND hwndOwner,
  2148.                          USHORT usID,
  2149.                          PSZ pszFont,
  2150.                          LONG lColor)
  2151. {
  2152.     // create status bar
  2153.     HWND        hwndReturn = NULLHANDLE;
  2154.     PPRESPARAMS ppp = NULL;
  2155.     winhStorePresParam(&ppp, PP_FONTNAMESIZE, strlen(pszFont)+1, pszFont);
  2156.     lColor = WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0);
  2157.     winhStorePresParam(&ppp, PP_BACKGROUNDCOLOR, sizeof(lColor), &lColor);
  2158.     lColor = CLR_BLACK;
  2159.     winhStorePresParam(&ppp, PP_FOREGROUNDCOLOR, sizeof(lColor), &lColor);
  2160.     hwndReturn = WinCreateWindow(hwndFrame,
  2161.                                  WC_STATIC,
  2162.                                  "Loading LVM data, please wait...",
  2163.                                  SS_TEXT | DT_VCENTER | WS_VISIBLE,
  2164.                                  0, 0, 0, 0,
  2165.                                  hwndOwner,
  2166.                                  HWND_TOP,
  2167.                                  usID,
  2168.                                  NULL,
  2169.                                  ppp);
  2170.     free(ppp);
  2171.     return (hwndReturn);
  2172. }
  2173.  
  2174. /*
  2175.  *@@ winh_fnwpFrameWithStatusBar:
  2176.  *      subclassed frame window proc.
  2177.  *
  2178.  *@@added V0.9.5 (2000-08-13) [umoeller]
  2179.  */
  2180.  
  2181. MRESULT EXPENTRY winh_fnwpFrameWithStatusBar(HWND hwndFrame, ULONG msg, MPARAM mp1, MPARAM mp2)
  2182. {
  2183.     MRESULT mrc = 0;
  2184.  
  2185.     switch (msg)
  2186.     {
  2187.         case WM_QUERYFRAMECTLCOUNT:
  2188.         {
  2189.             // query the standard frame controls count
  2190.             ULONG ulrc = (ULONG)(G_fnwpFrameOrig(hwndFrame, msg, mp1, mp2));
  2191.  
  2192.             // if we have a status bar, increment the count
  2193.             ulrc++;
  2194.  
  2195.             mrc = (MPARAM)ulrc;
  2196.         }
  2197.         break;
  2198.  
  2199.         case WM_FORMATFRAME:
  2200.         {
  2201.             //  query the number of standard frame controls
  2202.             ULONG ulCount = (ULONG)(G_fnwpFrameOrig(hwndFrame, msg, mp1, mp2));
  2203.  
  2204.             // we have a status bar:
  2205.             // format the frame
  2206.             ULONG       ul;
  2207.             PSWP        swpArr = (PSWP)mp1;
  2208.  
  2209.             for (ul = 0; ul < ulCount; ul++)
  2210.             {
  2211.                 if (WinQueryWindowUShort( swpArr[ul].hwnd, QWS_ID ) == 0x8008 )
  2212.                                                                  // FID_CLIENT
  2213.                 {
  2214.                     POINTL      ptlBorderSizes;
  2215.                     ULONG       ulStatusBarHeight = 20;
  2216.                     WinSendMsg(hwndFrame,
  2217.                                WM_QUERYBORDERSIZE,
  2218.                                (MPARAM)&ptlBorderSizes,
  2219.                                0);
  2220.  
  2221.                     // first initialize the _new_ SWP for the status bar.
  2222.                     // Since the SWP array for the std frame controls is
  2223.                     // zero-based, and the standard frame controls occupy
  2224.                     // indices 0 thru ulCount-1 (where ulCount is the total
  2225.                     // count), we use ulCount for our static text control.
  2226.                     swpArr[ulCount].fl = SWP_MOVE | SWP_SIZE | SWP_NOADJUST | SWP_ZORDER;
  2227.                     swpArr[ulCount].x  = ptlBorderSizes.x;
  2228.                     swpArr[ulCount].y  = ptlBorderSizes.y;
  2229.                     swpArr[ulCount].cx = swpArr[ul].cx;  // same as cnr's width
  2230.                     swpArr[ulCount].cy = ulStatusBarHeight;
  2231.                     swpArr[ulCount].hwndInsertBehind = HWND_BOTTOM; // HWND_TOP;
  2232.                     swpArr[ulCount].hwnd = G_hwndStatusBar;
  2233.  
  2234.                     // adjust the origin and height of the container to
  2235.                     // accomodate our static text control
  2236.                     swpArr[ul].y  += swpArr[ulCount].cy;
  2237.                     swpArr[ul].cy -= swpArr[ulCount].cy;
  2238.                 }
  2239.             }
  2240.  
  2241.             // increment the number of frame controls
  2242.             // to include our status bar
  2243.             mrc = (MRESULT)(ulCount + 1);
  2244.         }
  2245.         break;
  2246.  
  2247.         case WM_CALCFRAMERECT:
  2248.             mrc = G_fnwpFrameOrig(hwndFrame, msg, mp1, mp2);
  2249.  
  2250.             // we have a status bar: calculate its rectangle
  2251.             // CalcFrameRect(mp1, mp2);
  2252.         break;
  2253.  
  2254.         default:
  2255.             mrc = G_fnwpFrameOrig(hwndFrame, msg, mp1, mp2);
  2256.     }
  2257.  
  2258.     return (mrc);
  2259. }
  2260.  
  2261. /* ******************************************************************
  2262.  *
  2263.  *   main
  2264.  *
  2265.  ********************************************************************/
  2266.  
  2267. #define WC_XLVMCLIENT "xlvmClientClass"
  2268.  
  2269. /*
  2270.  *@@ main:
  2271.  *
  2272.  */
  2273.  
  2274. int main(int argc, char* argv[])
  2275. {
  2276.     HAB         hab;
  2277.     HMQ         hmq;
  2278.     QMSG        qmsg;
  2279.  
  2280.     if (!(hab = WinInitialize(0)))
  2281.         return FALSE;
  2282.  
  2283.     if (!(hmq = WinCreateMsgQueue(hab, 0)))
  2284.         return FALSE;
  2285.  
  2286.     DosError(FERR_DISABLEHARDERR | FERR_ENABLEEXCEPTION);
  2287.  
  2288.     nlsQueryCountrySettings(&G_CountrySettings);
  2289.  
  2290.     TRY_LOUD(excpt1)
  2291.     {
  2292.         const char *p = strrchr(argv[0], '\\');
  2293.         if (p)
  2294.         {
  2295.             char sz[300];
  2296.             strhncpy0(sz, argv[0], p - argv[0]);
  2297.             strcat(sz, "\\xlvm.log");
  2298.             G_LogFile = fopen(sz, "w");
  2299.  
  2300.             fprintf(G_LogFile, "xlvm log\n");
  2301.         }
  2302.  
  2303.         G_hptrDrive = WinLoadPointer(HWND_DESKTOP,
  2304.                                      NULLHANDLE,
  2305.                                      IDP_DRIVE);
  2306.  
  2307.         G_hptrPartition = WinLoadPointer(HWND_DESKTOP,
  2308.                                          NULLHANDLE,
  2309.                                          IDP_PARTITION);
  2310.  
  2311.         G_hwndWhitespaceMenu = WinLoadMenu(HWND_OBJECT, NULLHANDLE, IDM_WHITESPACE);
  2312.         G_hwndFreeSpaceMenu = WinLoadMenu(HWND_OBJECT, NULLHANDLE, IDM_FREESPACE);
  2313.         G_hwndPartitionMenu = WinLoadMenu(HWND_OBJECT, NULLHANDLE, IDM_PARTITION);
  2314.         G_hwndVolumeMenu = WinLoadMenu(HWND_OBJECT, NULLHANDLE, IDM_VOLUME);
  2315.  
  2316.         // register client
  2317.         if (!WinRegisterClass(hab,
  2318.                               WC_XLVMCLIENT,
  2319.                               fnwpClient,
  2320.                               CS_SIZEREDRAW | CS_CLIPCHILDREN,
  2321.                               4))
  2322.             fprintf(G_LogFile, "WinRegisterClass failed.\n");
  2323.         else
  2324.         {
  2325.             // create frame and container
  2326.             HWND    hwndClient = NULLHANDLE,
  2327.                     hwndMain = winhCreateStdWindow(HWND_DESKTOP,
  2328.                                                    0,
  2329.                                                    FCF_TITLEBAR
  2330.                                                       | FCF_SYSMENU
  2331.                                                       | FCF_MINMAX
  2332.                                                       | FCF_SIZEBORDER
  2333.                                                       | FCF_ICON
  2334.                                                       | FCF_MENU
  2335.                                                       | FCF_TASKLIST,
  2336.                                                    0,
  2337.                                                    APPTITLE,      // xmlview
  2338.                                                    1,             // icon resource
  2339.                                                    WC_XLVMCLIENT, // client class
  2340.                                                    WS_VISIBLE,
  2341.                                                    0,
  2342.                                                    NULL,
  2343.                                                    &hwndClient);
  2344.  
  2345.             fprintf(G_LogFile, "G_hwndMain is 0x%lX, G_hwndClient is 0x%lX\n",
  2346.                         hwndMain, hwndClient);
  2347.  
  2348.             if ((hwndMain) && (hwndClient))
  2349.             {
  2350.                 // create status bar as child of the frame
  2351.                 G_hwndStatusBar = winhCreateStatusBar(hwndMain,
  2352.                                                       hwndClient,
  2353.                                                       0,
  2354.                                                       "9.WarpSans",
  2355.                                                       CLR_BLACK);
  2356.                 fprintf(G_LogFile, "G_hwndStatusBar is 0x%lX\n",
  2357.                             G_hwndStatusBar);
  2358.  
  2359.                 // subclass frame for supporting status bar and msgs
  2360.                 G_fnwpFrameOrig = WinSubclassWindow(hwndMain,
  2361.                                                     winh_fnwpFrameWithStatusBar);
  2362.  
  2363.                 fprintf(G_LogFile, "G_fnwpFrameOrig is 0x%lX\n",
  2364.                             G_fnwpFrameOrig);
  2365.  
  2366.                 winhSetWindowFont(hwndClient, "9.WarpSans");
  2367.  
  2368.                 RefreshViewMenu(hwndMain);
  2369.  
  2370.                 if (!winhRestoreWindowPos(hwndMain,
  2371.                                           HINI_USER,
  2372.                                           INIAPP,
  2373.                                           INIKEY_MAINWINPOS,
  2374.                                           SWP_SHOW | SWP_ACTIVATE | SWP_MOVE | SWP_SIZE))
  2375.                 {
  2376.                     fprintf(G_LogFile, "restore winpos failed, setting explicit window pos\n"
  2377.                                 );
  2378.                     WinSetWindowPos(hwndMain,
  2379.                                     HWND_TOP,
  2380.                                     10, 10, 500, 500,
  2381.                                     SWP_SHOW | SWP_ACTIVATE | SWP_MOVE | SWP_SIZE);
  2382.                 }
  2383.  
  2384.                 fprintf(G_LogFile, "posting XM_INSERTDATA\n"
  2385.                            );
  2386.  
  2387.                 fprintf(G_LogFile, __FUNCTION__ ": entering msg loop\n"
  2388.                            );
  2389.  
  2390.                 //  standard PM message loop
  2391.                 while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
  2392.                 {
  2393.                     WinDispatchMsg(hab, &qmsg);
  2394.                 }
  2395.  
  2396.                 fprintf(G_LogFile, __FUNCTION__ ": leaving msg loop\n"
  2397.                            );
  2398.  
  2399.                 WinDestroyWindow(hwndMain);
  2400.             }
  2401.         }
  2402.     }
  2403.     CATCH(excpt1)
  2404.     {
  2405.     } END_CATCH();
  2406.  
  2407.     // clean up on the way out
  2408.     WinDestroyMsgQueue(hmq);
  2409.     WinTerminate(hab);
  2410.  
  2411.     return (0);
  2412. }
  2413.  
  2414.