home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwplascr.zip / XWPL0208.ZIP / src / startshut / archives.c < prev    next >
C/C++ Source or Header  |  2002-06-02  |  48KB  |  1,311 lines

  1.  
  2. /*
  3.  *@@sourcefile archives.c:
  4.  *      the purpose of this code is to examine the WPS's status
  5.  *      by evaluating dates, directory and system INI file contents.
  6.  *      We can then draw the conclusion (depending on user settings)
  7.  *      whether the WPS backup functionality should be enabled.
  8.  *
  9.  *      These checks are performed in arcCheckIfBackupNeeded, which
  10.  *      gets called during Desktop startup.
  11.  *
  12.  *      This file is ALL new with V0.9.0.
  13.  *
  14.  *      This is based on ideas in the WPSArcO code which has kindly
  15.  *      been provided by Stefan Milcke (Stefan.Milcke@t-online.de).
  16.  *
  17.  *      All funtions in this file have the arc* prefix.
  18.  *
  19.  *      Note that the ARCHIVINGSETTINGS are only manipulated by the
  20.  *      new Desktop "Archives" notebook page, whose code is
  21.  *      in xfdesk.c. For the archiving settings, we do not use
  22.  *      the global settings (as the rest of XWorkplace does), but
  23.  *      this separate structure instead. See arcQuerySettings.
  24.  *
  25.  *@@added V0.9.0 [umoeller]
  26.  *@@header "startshut\archives.h"
  27.  */
  28.  
  29. /*
  30.  *      Copyright (C) 1999-2002 Ulrich Möller.
  31.  *      This file is part of the XWorkplace source package.
  32.  *      XWorkplace is free software; you can redistribute it and/or modify
  33.  *      it under the terms of the GNU General Public License as published
  34.  *      by the Free Software Foundation, in version 2 as it comes in the
  35.  *      "COPYING" file of the XWorkplace main distribution.
  36.  *      This program is distributed in the hope that it will be useful,
  37.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  38.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39.  *      GNU General Public License for more details.
  40.  */
  41.  
  42. /*
  43.  *@@todo:
  44.  *  csm:
  45.          Ok, no guarantee, but this is what I found out:
  46.              Offset 0x00: (int32)    "Nummer des Archives nach Restore"
  47.                                          (Ist immer 0, wenn ein Backup gemacht wurde.
  48.                                           Nach einem Restore ist hier die Nummer des Archives zu finden)
  49.              Offset 0xCF: (int32)    "Dateien bei jedem Systemstart aktivieren"
  50.                                          (0 = off, 1 = on/selected)
  51.              Offset 0xD7: (int32)    "Anzahl der zu sichernden Archive"
  52.              Offset 0xD9: (int32)    "Anzeige der Optionen bei jedem Neustart"
  53.                                          (0 = off, 2 = on/selected)
  54.              Offset 0xDD: (int32)    "Zeitsperre fuer Anzeigen der Optionen"
  55.                                          (0 to 999)
  56.          The rest of the file I don't know (besides the path
  57.          beginning at offset 0x06, 200 bytes long)
  58.  */
  59.  
  60. #pragma strings(readonly)
  61.  
  62. /*
  63.  *  Suggested #include order:
  64.  *  1)  os2.h
  65.  *  2)  C library headers
  66.  *  3)  setup.h (code generation and debugging options)
  67.  *  4)  headers in helpers\
  68.  *  5)  at least one SOM implementation header (*.ih)
  69.  *  6)  dlgids.h, headers in shared\ (as needed)
  70.  *  7)  headers in implementation dirs (e.g. filesys\, as needed)
  71.  *  8)  #pragma hdrstop and then more SOM headers which crash with precompiled headers
  72.  */
  73.  
  74. #define INCL_DOSDATETIME
  75. #define INCL_DOSERRORS
  76.  
  77. #define INCL_WINDIALOGS
  78. #define INCL_WINBUTTONS
  79. #define INCL_WINSTATICS
  80. #define INCL_WINSTDSPIN
  81. #define INCL_WINSHELLDATA       // Prf* functions
  82. #include <os2.h>
  83.  
  84. #include <string.h>
  85. #include <stdio.h>
  86. #include <io.h>
  87. #include <fcntl.h>
  88. #include <sys\stat.h>
  89. #include <time.h>
  90. #include <process.h>
  91. #include <math.h>
  92.  
  93. // generic headers
  94. #include "setup.h"                      // code generation and debugging options
  95.  
  96. // headers in /helpers
  97. #include "helpers\datetime.h"           // date/time helpers
  98. #include "helpers\dialog.h"             // dialog helpers
  99. #include "helpers\dosh.h"
  100. #include "helpers\prfh.h"
  101. #include "helpers\standards.h"          // some standard macros
  102. #include "helpers\stringh.h"
  103. #include "helpers\winh.h"               // PM helper routines
  104. #include "helpers\wphandle.h"           // file-system object handles
  105. #include "helpers\xstring.h"            // extended string helpers
  106.  
  107. // SOM headers which don't crash with prec. header files
  108. #include "xfdesk.ih"
  109.  
  110. // XWorkplace implementation headers
  111. #include "dlgids.h"                     // all the IDs that are shared with NLS
  112. #include "shared\common.h"              // the majestic XWorkplace include file
  113. #include "shared\notebook.h"            // generic XWorkplace notebook handling
  114.  
  115. #include "startshut\archives.h"         // archiving declarations
  116.  
  117. // other SOM headers
  118. #pragma hdrstop                 // VAC++ keeps crashing otherwise
  119.  
  120. /********************************************************************
  121.  *
  122.  *   Global variables
  123.  *
  124.  ********************************************************************/
  125.  
  126. static ARCHIVINGSETTINGS   G_ArcSettings;
  127. static DATETIME            G_dtLastArchived;
  128. static BOOL                G_fSettingsLoaded = FALSE;
  129.  
  130. static CHAR                G_szArcBaseFilename[CCHMAXPATH] = "";
  131.  
  132. #define ARCOFS_JUSTRESTORED             0x00000
  133. #define ARCOFS_ARCHIVINGENABLED         0x000CF
  134. #define ARCOFS_MAXARCHIVES              0x000D7
  135.  
  136. /********************************************************************
  137.  *
  138.  *   "Archives" page replacement in WPDesktop
  139.  *
  140.  ********************************************************************/
  141.  
  142. // PSZ's for percentage spinbutton
  143. static PCSZ     G_apcszPercentages[] =
  144.     {
  145.         "0.010",
  146.         "0.025",
  147.         "0.050",
  148.         "0.075",
  149.         "0.100",
  150.         "0.250",
  151.         "0.500",
  152.         "0.750",
  153.         "1.000",
  154.         "2.500",
  155.         "5.000"
  156.     };
  157.  
  158. #define SPIN_WIDTH      40
  159. #define SPIN_HEIGHT     STD_SPIN_HEIGHT
  160.  
  161. static const CONTROLDEF
  162.     ArcCriteriaGroup = LOADDEF_GROUP(ID_XSDI_ARC_CRITERIA_GROUP, DEFAULT_TABLE_WIDTH),
  163.     EnableArchiveCB = LOADDEF_AUTOCHECKBOX(ID_XSDI_ARC_ENABLE),
  164.     ArcAlwaysCB = LOADDEF_AUTOCHECKBOX(ID_XSDI_ARC_ALWAYS),
  165.     ArcNextCB = LOADDEF_AUTOCHECKBOX(ID_XSDI_ARC_NEXT),
  166.     ArcINICB = LOADDEF_AUTOCHECKBOX(ID_XSDI_ARC_INI),
  167.     ArcINISpin =
  168.         {
  169.             WC_SPINBUTTON,
  170.             NULL,
  171.             WS_VISIBLE | WS_TABSTOP
  172.                 | SPBS_MASTER | SPBS_JUSTLEFT | SPBS_JUSTRIGHT | SPBS_JUSTCENTER
  173.                 | SPBS_FASTSPIN,
  174.             ID_XSDI_ARC_INI_SPIN,
  175.             CTL_COMMON_FONT,
  176.             0,
  177.             { SPIN_WIDTH, SPIN_HEIGHT },     // size
  178.             COMMON_SPACING,
  179.         },
  180.     ArcINITxt2 = LOADDEF_TEXT(ID_XSDI_ARC_INI_SPINTXT1),
  181.     ArcDaysCB = LOADDEF_AUTOCHECKBOX(ID_XSDI_ARC_DAYS),
  182.     ArcDaysSpin =
  183.         {
  184.             WC_SPINBUTTON,
  185.             NULL,
  186.             WS_VISIBLE | WS_TABSTOP
  187.                 | SPBS_MASTER | SPBS_JUSTLEFT | SPBS_JUSTRIGHT | SPBS_JUSTCENTER
  188.                 | SPBS_FASTSPIN,
  189.             ID_XSDI_ARC_DAYS_SPIN,
  190.             CTL_COMMON_FONT,
  191.             0,
  192.             { SPIN_WIDTH, SPIN_HEIGHT },     // size
  193.             COMMON_SPACING,
  194.         },
  195.     ArcDaysTxt2 = LOADDEF_TEXT(ID_XSDI_ARC_DAYS_SPINTXT1),
  196.     ArcShowStatusCB = LOADDEF_AUTOCHECKBOX(ID_XSDI_ARC_SHOWSTATUS),
  197.     Arc2Group = LOADDEF_GROUP(ID_XSDI_ARC_ARCHIVES_GROUP, DEFAULT_TABLE_WIDTH),
  198.     ArcNoTxt1 = LOADDEF_TEXT(ID_XSDI_ARC_ARCHIVES_NO_TXT1),
  199.     ArcNoSpin =
  200.         {
  201.             WC_SPINBUTTON,
  202.             NULL,
  203.             WS_VISIBLE | WS_TABSTOP
  204.                 | SPBS_MASTER | SPBS_JUSTLEFT | SPBS_JUSTRIGHT | SPBS_JUSTCENTER,
  205.             ID_XSDI_ARC_ARCHIVES_NO_SPIN,
  206.             CTL_COMMON_FONT,
  207.             0,
  208.             { SPIN_WIDTH, SPIN_HEIGHT },     // size
  209.             COMMON_SPACING,
  210.         },
  211.     ArcNoTxt2 = LOADDEF_TEXT(ID_XSDI_ARC_ARCHIVES_NO_TXT2);
  212.  
  213. static const DLGHITEM dlgArchives[] =
  214.     {
  215.         START_TABLE,            // root table, required
  216.             START_ROW(0),       // row 1 in the root table, required
  217.                 // create group on top
  218.                 START_GROUP_TABLE(&ArcCriteriaGroup),
  219.                     START_ROW(ROW_VALIGN_CENTER),
  220.                         CONTROL_DEF(&EnableArchiveCB),
  221.                     START_ROW(ROW_VALIGN_CENTER),
  222.                         CONTROL_DEF(&G_Spacing),    // notebook.c
  223.                         CONTROL_DEF(&ArcAlwaysCB),
  224.                     START_ROW(ROW_VALIGN_CENTER),
  225.                         CONTROL_DEF(&G_Spacing),    // notebook.c
  226.                         CONTROL_DEF(&ArcNextCB),
  227.                     START_ROW(ROW_VALIGN_CENTER),
  228.                         CONTROL_DEF(&G_Spacing),    // notebook.c
  229.                         CONTROL_DEF(&ArcINICB),
  230.                         CONTROL_DEF(&ArcINISpin),
  231.                         CONTROL_DEF(&ArcINITxt2),
  232.                     START_ROW(ROW_VALIGN_CENTER),
  233.                         CONTROL_DEF(&G_Spacing),    // notebook.c
  234.                         CONTROL_DEF(&ArcDaysCB),
  235.                         CONTROL_DEF(&ArcDaysSpin),
  236.                         CONTROL_DEF(&ArcDaysTxt2),
  237.                     START_ROW(ROW_VALIGN_CENTER),
  238.                         CONTROL_DEF(&ArcShowStatusCB),
  239.                 END_TABLE,
  240.             START_ROW(0),       // row 2 in the root table
  241.                 START_GROUP_TABLE(&Arc2Group),
  242.                     START_ROW(ROW_VALIGN_CENTER),
  243.                         CONTROL_DEF(&ArcNoTxt1),
  244.                         CONTROL_DEF(&ArcNoSpin),
  245.                         CONTROL_DEF(&ArcNoTxt2),
  246.                 END_TABLE,
  247.             START_ROW(0),       // notebook buttons (will be moved)
  248.                 CONTROL_DEF(&G_UndoButton),         // common.c
  249.                 CONTROL_DEF(&G_DefaultButton),      // common.c
  250.                 CONTROL_DEF(&G_HelpButton),         // common.c
  251.         END_TABLE
  252.     };
  253.  
  254. /*
  255.  * arcArchivesInitPage:
  256.  *      notebook callback function (notebook.c) for the
  257.  *      "Archives" page replacement in the Desktop's settings
  258.  *      notebook.
  259.  *      Sets the controls on the page according to the
  260.  *      Global Settings.
  261.  *
  262.  *@@added V0.9.0 [umoeller]
  263.  *@@changed V0.9.9 (2001-04-07) [pr]: fixed Undo/Default
  264.  *@@changed V0.9.16 (2001-11-22) [umoeller]: now using dlg formatter
  265.  */
  266.  
  267. VOID arcArchivesInitPage(PNOTEBOOKPAGE pnbp,   // notebook info struct
  268.                           ULONG flFlags)        // CBI_* flags (notebook.h)
  269. {
  270.     PARCHIVINGSETTINGS pArcSettings = arcQuerySettings();
  271.  
  272.     if (flFlags & CBI_INIT)
  273.     {
  274.         // first call: backup archive settings for "Undo" button;
  275.         // this memory will be freed automatically by the
  276.         // common notebook window function (notebook.c) when
  277.         // the notebook page is destroyed
  278.         if (pnbp->pUser = malloc(sizeof(ARCHIVINGSETTINGS)))
  279.             memcpy(pnbp->pUser, pArcSettings, sizeof(ARCHIVINGSETTINGS));
  280.  
  281.         // insert the controls using the dialog formatter
  282.         // V0.9.16 (2001-11-22) [umoeller]
  283.         ntbFormatPage(pnbp->hwndDlgPage,
  284.                       dlgArchives,
  285.                       ARRAYITEMCOUNT(dlgArchives));
  286.  
  287.         WinSendDlgItemMsg(pnbp->hwndDlgPage, ID_XSDI_ARC_INI_SPIN,
  288.                           SPBM_SETARRAY,
  289.                           (MPARAM)&G_apcszPercentages,
  290.                           (MPARAM)ARRAYITEMCOUNT(G_apcszPercentages));
  291.     }
  292.  
  293.     if (flFlags & CBI_SET)
  294.     {
  295.         ULONG       ul = 0;
  296.  
  297.         winhSetDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_ENABLE,
  298.                               (pArcSettings->ulArcFlags & ARCF_ENABLED) != 0);
  299.         winhSetDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_ALWAYS,
  300.                               (pArcSettings->ulArcFlags & ARCF_ALWAYS) != 0);
  301.         winhSetDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_NEXT,
  302.                               (pArcSettings->ulArcFlags & ARCF_NEXT) != 0);
  303.         winhSetDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_INI,
  304.                               (pArcSettings->ulArcFlags & ARCF_INI) != 0);
  305.  
  306.         // INI files percentage:
  307.         // go thru the spin button array and find
  308.         // percentage that matches
  309.         for (ul = 0; ul < ARRAYITEMCOUNT(G_apcszPercentages); ul++)
  310.         {
  311.             float dTemp;
  312.             // CHAR szTempx[100];
  313.             // convert current array item to float
  314.             sscanf(G_apcszPercentages[ul], "%f", &dTemp);
  315.  
  316.             // same?
  317.             if (fabs(dTemp - pArcSettings->dIniFilesPercent) < 0.00001)
  318.                                 // prevent rounding errors
  319.             {
  320.                 // yes: set this spin button array item
  321.                 WinSendDlgItemMsg(pnbp->hwndDlgPage, ID_XSDI_ARC_INI_SPIN,
  322.                                   SPBM_SETCURRENTVALUE,
  323.                                   (MPARAM)ul,
  324.                                   (MPARAM)NULL);
  325.                 break;
  326.             }
  327.         }
  328.  
  329.         // every xxx days
  330.         winhSetDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_DAYS,
  331.                               (pArcSettings->ulArcFlags & ARCF_DAYS) != 0);
  332.         winhSetDlgItemSpinData(pnbp->hwndDlgPage, ID_XSDI_ARC_DAYS_SPIN,
  333.                                1, 50,       // spin button limits
  334.                                pArcSettings->ulEveryDays);
  335.  
  336.         // status
  337.         winhSetDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_SHOWSTATUS,
  338.                               pArcSettings->fShowStatus);
  339.  
  340.         // no. of archives
  341.         arcSetNumArchives(&pArcSettings->cArchivesCount,
  342.                           FALSE);       // query
  343.         winhSetDlgItemSpinData(pnbp->hwndDlgPage, ID_XSDI_ARC_ARCHIVES_NO_SPIN,
  344.                                1, 9,        // spin button limits
  345.                                pArcSettings->cArchivesCount);
  346.     }
  347.  
  348.     if (flFlags & CBI_ENABLE)
  349.     {
  350.         BOOL    fEnabled = ((pArcSettings->ulArcFlags & ARCF_ENABLED) != 0),
  351.                 fAlways = ((pArcSettings->ulArcFlags & ARCF_ALWAYS) != 0),
  352.                 fINI = winhIsDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_INI),
  353.                 fDays = winhIsDlgItemChecked(pnbp->hwndDlgPage, ID_XSDI_ARC_DAYS);
  354.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_ALWAYS,
  355.                           fEnabled);
  356.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_NEXT,
  357.                           fEnabled && !fAlways);
  358.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_INI,
  359.                           fEnabled && !fAlways);
  360.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_INI_SPIN,
  361.                           ( (fEnabled) && (fINI) ) && !fAlways);
  362.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_INI_SPINTXT1,
  363.                           ( (fEnabled) && (fINI) ) && !fAlways);
  364.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_DAYS,
  365.                           fEnabled && !fAlways);
  366.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_DAYS_SPIN,
  367.                           ( (fEnabled) && (fDays) ) && !fAlways);
  368.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_DAYS_SPINTXT1,
  369.                           ( (fEnabled) && (fDays) ) && !fAlways);
  370.  
  371.         WinEnableControl(pnbp->hwndDlgPage, ID_XSDI_ARC_SHOWSTATUS,
  372.                           fEnabled);
  373.     }
  374. }
  375.  
  376. /*
  377.  * arcArchivesItemChanged:
  378.  *      notebook callback function (notebook.c) for the
  379.  *      "Archives" page replacement in the Desktop's settings
  380.  *      notebook.
  381.  *      Reacts to changes of any of the dialog controls.
  382.  *
  383.  *@@added V0.9.0 [umoeller]
  384.  *@@changed V0.9.9 (2001-04-07) [pr]: fixed Undo/Default
  385.  */
  386.  
  387. MRESULT arcArchivesItemChanged(PNOTEBOOKPAGE pnbp,
  388.                                ULONG ulItemID,
  389.                                USHORT usNotifyCode,
  390.                                ULONG ulExtra)      // for checkboxes: contains new state
  391. {
  392.     PARCHIVINGSETTINGS pArcSettings = arcQuerySettings();
  393.     ULONG           ulSetFlags = 0;
  394.     BOOL            fSave = TRUE;
  395.  
  396.     switch (ulItemID)
  397.     {
  398.         case ID_XSDI_ARC_ENABLE:
  399.             ulSetFlags |= ARCF_ENABLED;
  400.         break;
  401.  
  402.         case ID_XSDI_ARC_ALWAYS:
  403.             ulSetFlags |= ARCF_ALWAYS;
  404.         break;
  405.  
  406.         case ID_XSDI_ARC_NEXT:
  407.             ulSetFlags |= ARCF_NEXT;
  408.         break;
  409.  
  410.         case ID_XSDI_ARC_INI:
  411.             ulSetFlags |= ARCF_INI;
  412.         break;
  413.  
  414.         case ID_XSDI_ARC_INI_SPIN:
  415.             if (    (pnbp->flPage & NBFL_PAGE_INITED)       // skip this during initialization
  416.                  && (usNotifyCode == SPBN_CHANGE)
  417.                )
  418.             {
  419.                 CHAR    szTemp[100];
  420.                 float   flTemp = 0;
  421.                 // query current spin button array
  422.                 // item as a string
  423.                 WinSendDlgItemMsg(pnbp->hwndDlgPage, ulItemID,
  424.                                   SPBM_QUERYVALUE,
  425.                                   (MPARAM)szTemp,
  426.                                   MPFROM2SHORT(sizeof(szTemp),
  427.                                                SPBQ_ALWAYSUPDATE));
  428.                 sscanf(szTemp, "%f", &flTemp);
  429.                 pArcSettings->dIniFilesPercent = (double)flTemp;
  430.             }
  431.         break;
  432.  
  433.         case ID_XSDI_ARC_DAYS:
  434.             ulSetFlags |= ARCF_DAYS;
  435.         break;
  436.  
  437.         case ID_XSDI_ARC_DAYS_SPIN:
  438.             pArcSettings->ulEveryDays = winhAdjustDlgItemSpinData(pnbp->hwndDlgPage,
  439.                                                                   ulItemID,
  440.                                                                   0,              // no grid
  441.                                                                   usNotifyCode);
  442.         break;
  443.  
  444.         case ID_XSDI_ARC_SHOWSTATUS:
  445.             pArcSettings->fShowStatus = ulExtra;
  446.         break;
  447.  
  448.         case ID_XSDI_ARC_ARCHIVES_NO_SPIN:
  449.             pArcSettings->cArchivesCount = (CHAR)winhAdjustDlgItemSpinData(pnbp->hwndDlgPage,
  450.                                                                            ulItemID,
  451.                                                                            0,              // no grid
  452.                                                                            usNotifyCode);
  453.             arcSetNumArchives(&pArcSettings->cArchivesCount,
  454.                               TRUE);        // set
  455.             fSave = FALSE;
  456.         break;
  457.  
  458.         case DID_UNDO:
  459.         {
  460.             // "Undo" button: get pointer to backed-up archive settings
  461.             PARCHIVINGSETTINGS pWASBackup = (PARCHIVINGSETTINGS)(pnbp->pUser);
  462.  
  463.             // and restore the settings for this page
  464.             pArcSettings->ulArcFlags = pWASBackup->ulArcFlags;
  465.             pArcSettings->dIniFilesPercent = pWASBackup->dIniFilesPercent;
  466.             pArcSettings->ulEveryDays = pWASBackup->ulEveryDays;
  467.             pArcSettings->fShowStatus = pWASBackup->fShowStatus;
  468.             pArcSettings->cArchivesCount = pWASBackup->cArchivesCount;
  469.             arcSetNumArchives(&pArcSettings->cArchivesCount,
  470.                               TRUE);        // set
  471.  
  472.             // update the display by calling the INIT callback
  473.             pnbp->inbp.pfncbInitPage(pnbp, CBI_SET | CBI_ENABLE);
  474.         }
  475.         break;
  476.  
  477.         case DID_DEFAULT:
  478.             // set the default settings for this settings page
  479.             arcSetDefaultSettings();
  480.             arcSetNumArchives(&pArcSettings->cArchivesCount,
  481.                               TRUE);        // set
  482.             // update the display by calling the INIT callback
  483.             pnbp->inbp.pfncbInitPage(pnbp, CBI_SET | CBI_ENABLE);
  484.         break;
  485.  
  486.         default:
  487.             fSave = FALSE;
  488.     }
  489.  
  490.     if (ulSetFlags)
  491.     {
  492.         if (ulExtra)    // checkbox checked
  493.             pArcSettings->ulArcFlags |= ulSetFlags;
  494.         else            // checkbox unchecked
  495.             pArcSettings->ulArcFlags &= ~ulSetFlags;
  496.         // re-enable dlg items by calling the INIT callback
  497.         pnbp->inbp.pfncbInitPage(pnbp, CBI_ENABLE);
  498.     }
  499.  
  500.     if (fSave)
  501.         // enable/disable items
  502.         arcSaveSettings();
  503.  
  504.     return ((MPARAM)0);
  505. }
  506.  
  507. /********************************************************************
  508.  *
  509.  *   Archiving settings
  510.  *
  511.  ********************************************************************/
  512.  
  513. /*
  514.  *@@ arcSetDefaultSettings:
  515.  *      this initializes the global ARCHIVINGSETTINGS
  516.  *      structure with default values.
  517.  *
  518.  *@@changed V0.9.9 (2001-04-07) [pr]: fixed Undo/Default
  519.  */
  520.  
  521. VOID arcSetDefaultSettings(VOID)
  522. {
  523.     #ifdef DEBUG_STARTUP
  524.         _Pmpf(("**** Settings defaults"));
  525.     #endif
  526.     G_ArcSettings.ulArcFlags = 0;
  527.     G_ArcSettings.dIniFilesPercent = .1;
  528.     G_ArcSettings.ulEveryDays = 1;
  529.     G_ArcSettings.fShowStatus = TRUE;
  530.     G_ArcSettings.cArchivesCount = 3;
  531. }
  532.  
  533. /*
  534.  *@@ arcQuerySettings:
  535.  *      this returns the global ARCHIVINGSETTINGS
  536.  *      structure, which is filled with the data
  537.  *      from OS2.INI if this is queried for the
  538.  *      first time.
  539.  *
  540.  *@@changed V0.9.9 (2001-04-07) [pr]: fixed Undo/Default
  541.  */
  542.  
  543. PARCHIVINGSETTINGS arcQuerySettings(VOID)
  544. {
  545.     if (!G_fSettingsLoaded)
  546.     {
  547.         ULONG   cbData = sizeof(G_ArcSettings);
  548.         BOOL    brc = FALSE;
  549.         // first call:
  550.         G_fSettingsLoaded = TRUE;
  551.         // load settings
  552.         brc = PrfQueryProfileData(HINI_USER,
  553.                                   (PSZ)INIAPP_XWORKPLACE,
  554.                                   (PSZ)INIKEY_ARCHIVE_SETTINGS,
  555.                                   &G_ArcSettings,
  556.                                   &cbData);
  557.         if ((!brc) || cbData != sizeof(G_ArcSettings))
  558.             // data not found:
  559.         {
  560.             G_ArcSettings.dAppsSizeLast = 0;
  561.             G_ArcSettings.dKeysSizeLast = 0;
  562.             G_ArcSettings.dDataSumLast = 0;
  563.             arcSetDefaultSettings();
  564.         }
  565.  
  566.         cbData = sizeof(G_dtLastArchived);
  567.         brc = PrfQueryProfileData(HINI_USER,
  568.                                   (PSZ)INIAPP_XWORKPLACE,
  569.                                   (PSZ)INIKEY_ARCHIVE_LASTBACKUP,
  570.                                   &G_dtLastArchived,
  571.                                   &cbData);
  572.         if ((!brc) || cbData != sizeof(G_dtLastArchived))
  573.         {
  574.             // data not found:
  575.             DosGetDateTime(&G_dtLastArchived);
  576.             G_dtLastArchived.year = 1990;       // enfore backup then
  577.         }
  578.  
  579.         // initialize szArcBaseFilename
  580.         sprintf(G_szArcBaseFilename,
  581.                 "%c:\\OS2\\BOOT\\ARCHBASE.$$$",
  582.                 doshQueryBootDrive());
  583.     }
  584.  
  585.     return (&G_ArcSettings);
  586. }
  587.  
  588. /*
  589.  *@@ arcSaveSettings:
  590.  *      this writes the ARCHIVINGSETTINGS structure
  591.  *      back to OS2.INI.
  592.  */
  593.  
  594. BOOL arcSaveSettings(VOID)
  595. {
  596.     return (PrfWriteProfileData(HINI_USER,
  597.                                 (PSZ)INIAPP_XWORKPLACE,
  598.                                 (PSZ)INIKEY_ARCHIVE_SETTINGS,
  599.                                 &G_ArcSettings,
  600.                                 sizeof(G_ArcSettings)));
  601. }
  602.  
  603. /********************************************************************
  604.  *
  605.  *   Archiving Enabling
  606.  *
  607.  ********************************************************************/
  608.  
  609. /*
  610.  *@@ arcSetArchiveByte:
  611.  *      writes byte "byte" to offset "offset" in ARCHBASE.$$$.
  612.  *
  613.  *@@added V0.9.13 (2001-06-14) [umoeller]
  614.  */
  615.  
  616. APIRET arcSetArchiveByte(UCHAR byte,        // in: byte to write
  617.                          LONG offset)
  618. {
  619.     APIRET arc = NO_ERROR;
  620.     // ULONG ulAttr;
  621.     // file is always write protected, so disable this
  622.     // before writing
  623.     if (!(arc = doshSetPathAttr(G_szArcBaseFilename,
  624.                                 FILE_ARCHIVED)))
  625.     {
  626.         // open the file for write access then
  627.         PXFILE pFile = NULL;
  628.         ULONG cb = 0;
  629.         if (!(arc = doshOpen(G_szArcBaseFilename,
  630.                              XOPEN_READWRITE_EXISTING,
  631.                              &cb,
  632.                              &pFile)))
  633.         {
  634.             arc = doshWriteAt(pFile,
  635.                               offset,
  636.                               1,
  637.                               &byte);
  638.  
  639.             doshClose(&pFile);
  640.         }
  641.  
  642.         doshSetPathAttr(G_szArcBaseFilename,
  643.                         FILE_ARCHIVED | FILE_READONLY);
  644.     }
  645.  
  646.     if (arc)
  647.         cmnLog(__FILE__, __LINE__, __FUNCTION__,
  648.                "Got error %d");
  649.  
  650.     return arc;
  651. }
  652.  
  653. /*
  654.  *@@ arcQueryArchiveByte:
  655.  *      gets byte pointed to by "pByte" from offset "offset"
  656.  *      in ARCHBASE.$$$.
  657.  *
  658.  *@@added V0.9.13 (2001-06-14) [umoeller]
  659.  */
  660.  
  661. APIRET arcQueryArchiveByte(UCHAR *pByte,        // out: read byte
  662.                            LONG offset)
  663. {
  664.     APIRET arc = NO_ERROR;
  665.  
  666.     // open the file then
  667.     PXFILE pFile;
  668.     ULONG cbFile = 0;
  669.     if (!(arc = doshOpen(G_szArcBaseFilename,
  670.                          XOPEN_READ_EXISTING,
  671.                          &cbFile,
  672.                          &pFile)))
  673.     {
  674.         ULONG cb = 1;
  675.         arc = doshReadAt(pFile,
  676.                          offset,
  677.                          &cb,
  678.                          pByte,
  679.                          0);
  680.  
  681.         doshClose(&pFile);
  682.     }
  683.  
  684.     if (arc)
  685.         cmnLog(__FILE__, __LINE__, __FUNCTION__,
  686.                "Got error %d");
  687.  
  688.     return arc;
  689. }
  690.  
  691. /*
  692.  *@@ arcForceNoArchiving:
  693.  *      enforces that all archiving is disabled, both in
  694.  *      XWP and the WPS.
  695.  *
  696.  *@@added V0.9.16 (2001-10-25) [umoeller]
  697.  */
  698.  
  699. VOID arcForceNoArchiving(VOID)
  700. {
  701.     // force loading of settings
  702.     arcQuerySettings();
  703.     arcSwitchArchivingOn(FALSE);
  704.     G_ArcSettings.ulArcFlags &= ~ARCF_ENABLED;
  705.     arcSaveSettings();
  706. }
  707.  
  708. #define ID_XFDI_GENERICDLGTEXT          221
  709.  
  710. static CONTROLDEF
  711.     ArcStatusIcon = CONTROLDEF_ICON(
  712.                             NULLHANDLE,     // replaced below
  713.                             ID_ICONDLG),
  714.     ArcStatusText = CONTROLDEF_TEXT_WORDBREAK(
  715.                             "1\n2\n3",   // room for three lines, replaced below
  716.                             ID_XFDI_GENERICDLGTEXT,
  717.                             200);
  718.  
  719. static const DLGHITEM dlgArcStatus[] =
  720.     {
  721.         START_TABLE,            // root table, required
  722.             START_ROW(ROW_VALIGN_CENTER),
  723.                 CONTROL_DEF(&ArcStatusIcon),
  724.                 CONTROL_DEF(&ArcStatusText),
  725.         END_TABLE
  726.     };
  727.  
  728. /*
  729.  *@@ ShowStatus:
  730.  *
  731.  *@@added V0.9.16 (2001-11-25) [umoeller]
  732.  */
  733.  
  734. static VOID ShowStatus(HWND hwndStatus,
  735.                        PCSZ pcszText)
  736. {
  737.     WinSetDlgItemText(hwndStatus, ID_XFDI_GENERICDLGTEXT,
  738.                       pcszText);
  739.     WinSetWindowPos(hwndStatus,
  740.                     HWND_TOP,
  741.                     50,
  742.                     50,
  743.                     0,
  744.                     0,
  745.                     SWP_MOVE | SWP_ZORDER | SWP_SHOW);
  746.                             // but no activate
  747. }
  748.  
  749. /*
  750.  *@@ arcCheckIfBackupNeeded:
  751.  *      this checks the system according to the settings
  752.  *      in ARCHIVINGSETTINGS (i.e. always, next bootup,
  753.  *      date, INI changes -- see arcCheckINIFiles),
  754.  *      and calls arcSwitchArchivingOn according to the
  755.  *      result of these checks.
  756.  *
  757.  *      This gets called from initMain
  758.  *      while the WPS is booting up (see remarks there).
  759.  *      If we enable Desktop archiving here, the WPS will
  760.  *      archive the Desktop soon afterwards.
  761.  *
  762.  *      If (ARCHIVINGSETTINGS.fShowStatus == TRUE), hwndNotify
  763.  *      will receive a msg with the value ulMsg and the
  764.  *      HWND of the notification window in mp1 to be able
  765.  *      to destroy it later.
  766.  *
  767.  *      initMain sets this to the XWorkplace
  768.  *      Thread-1 object window (krn_fnwpThread1Object), which in
  769.  *      turn starts a timer to destroy the window later.
  770.  *
  771.  *@@changed V0.9.4 (2000-07-22) [umoeller]: archiving wasn't always disabled if turned off completely; fixed
  772.  *@@changed V0.9.13 (2001-06-14) [umoeller]: no longer using archive marker file, thanks Stefan Milcke
  773.  *@@changed V0.9.16 (2001-11-19) [umoeller]: now using dialog formatter for status window
  774.  */
  775.  
  776. BOOL arcCheckIfBackupNeeded(HWND hwndNotify,        // in: window to notify
  777.                             ULONG ulMsg)            // in: msg to post to hwndNotify
  778. {
  779.     BOOL    fBackup = FALSE,
  780.             fDisableArchiving = FALSE;
  781.     CHAR    szTemp[300];
  782.  
  783.     // force loading of settings
  784.     arcQuerySettings();
  785.  
  786.     if (G_ArcSettings.ulArcFlags & ARCF_ENABLED)
  787.     {
  788.         HWND    hwndStatus = NULLHANDLE;
  789.         XSTRING strMsg;
  790.  
  791.         CHAR    lRestoredArchiveNumber = 0;
  792.  
  793.         xstrInit(&strMsg, 300);
  794.  
  795.         if (G_ArcSettings.fShowStatus)
  796.         {
  797.             ArcStatusIcon.pcszText = (PCSZ)cmnQueryDlgIcon();
  798.  
  799.             // format the status window
  800.             // V0.9.16 (2001-11-19) [umoeller]
  801.             dlghCreateDlg(&hwndStatus,
  802.                           NULLHANDLE,
  803.                           FCF_TITLEBAR | /* FCF_SYSMENU | */ FCF_DLGBORDER | FCF_NOBYTEALIGN,
  804.                           WinDefDlgProc,
  805.                           cmnGetString(ID_XFD_ARCHIVINGSTATUS),
  806.                           dlgArcStatus,
  807.                           ARRAYITEMCOUNT(dlgArcStatus),
  808.                           NULL,
  809.                           cmnQueryDefaultFont());
  810.         }
  811.  
  812.         // changed V0.9.13 (2001-06-14) [umoeller]:
  813.         // get the "restored archive" byte
  814.         arcQueryArchiveByte(&lRestoredArchiveNumber,
  815.                             ARCOFS_JUSTRESTORED);
  816.  
  817.         if (lRestoredArchiveNumber)
  818.         {
  819.             // archive was just restored:
  820.             // disable archiving then
  821.             sprintf(szTemp,
  822.                     cmnGetString(ID_XSSI_ARCRESTORED),      // archive %d was restored
  823.                     lRestoredArchiveNumber);
  824.             xstrcpy(&strMsg, szTemp, 0);
  825.             fBackup = FALSE;
  826.             fDisableArchiving = TRUE;
  827.             arcSetArchiveByte(0, ARCOFS_JUSTRESTORED);
  828.         } // end V0.9.13 (2001-06-14) [umoeller]
  829.         else
  830.         {
  831.             // no archive was just restored:
  832.             if (G_ArcSettings.ulArcFlags & ARCF_ALWAYS)
  833.             {
  834.                 fBackup = TRUE;
  835.  
  836.                 if (G_ArcSettings.fShowStatus)
  837.                     ShowStatus(hwndStatus,
  838.                                cmnGetString(ID_XSSI_ARCENABLED));
  839.             }
  840.             else
  841.             {
  842.                 BOOL    fCheckINIs = (G_ArcSettings.ulArcFlags & ARCF_INI);
  843.  
  844.                 if (G_ArcSettings.ulArcFlags & ARCF_NEXT)
  845.                 {
  846.                     if (G_ArcSettings.fShowStatus)
  847.                         ShowStatus(hwndStatus,
  848.                                    cmnGetString(ID_XSSI_ARCENABLEDONCE));
  849.  
  850.                     fBackup = TRUE;
  851.                     fCheckINIs = FALSE;     // not necessary
  852.  
  853.                     // unset this settings flag for next time
  854.                     G_ArcSettings.ulArcFlags &= ~ARCF_NEXT;
  855.                     arcSaveSettings();
  856.                 }
  857.                 else if (G_ArcSettings.ulArcFlags & ARCF_DAYS)
  858.                 {
  859.                     // days-based:
  860.                     DATETIME    dtNow;
  861.                     LONG        lDaysNow,
  862.                                 lDaysLast,
  863.                                 lDaysPassed;
  864.  
  865.                     DosGetDateTime(&dtNow);
  866.                     lDaysNow = dtDate2Scalar(dtNow.year,
  867.                                              dtNow.month,
  868.                                              dtNow.day);
  869.                     lDaysLast= dtDate2Scalar(G_dtLastArchived.year,
  870.                                              G_dtLastArchived.month,
  871.                                              G_dtLastArchived.day);
  872.                     lDaysPassed = lDaysNow - lDaysLast;
  873.  
  874.                     if (lDaysPassed >= G_ArcSettings.ulEveryDays)
  875.                     {
  876.                         fBackup = TRUE;
  877.                         fCheckINIs = FALSE;     // not necessary
  878.                     }
  879.  
  880.                     if (G_ArcSettings.fShowStatus)
  881.                     {
  882.                         sprintf(szTemp,
  883.                                 cmnGetString(ID_XSSI_ARCDAYSPASSED),  // "%d days passed since last backup." // pszArcDaysPassed
  884.                                 lDaysPassed);
  885.                         xstrcpy(&strMsg, szTemp, 0);
  886.                         xstrcatc(&strMsg, '\n');
  887.                         sprintf(szTemp,
  888.                                 cmnGetString(ID_XSSI_ARCDAYSLIMIT),  // "Limit: %d days." // pszArcDaysLimit
  889.                                 G_ArcSettings.ulEveryDays);
  890.                         xstrcat(&strMsg, szTemp, 0);
  891.                         xstrcatc(&strMsg, '\n');
  892.                     }
  893.                 }
  894.  
  895.                 if (fCheckINIs)
  896.                 {
  897.                     // INI-based:
  898.                     double  dMaxDifferencePercent = 0;
  899.  
  900.                     if (G_ArcSettings.fShowStatus)
  901.                     {
  902.                         sprintf(szTemp,
  903.                                 "%s\n",
  904.                                 cmnGetString(ID_XSSI_ARCINICHECKING)) ; // pszArcINIChecking
  905.                         ShowStatus(hwndStatus,
  906.                                    szTemp);
  907.                     }
  908.  
  909.                     fBackup = arcCheckINIFiles(&G_ArcSettings.dIniFilesPercent,
  910.                                                (PSZ)INIAPP_XWORKPLACE,  // ignore this
  911.                                                &G_ArcSettings.dAppsSizeLast,
  912.                                                &G_ArcSettings.dKeysSizeLast,
  913.                                                &G_ArcSettings.dDataSumLast,
  914.                                                &dMaxDifferencePercent);
  915.  
  916.                     if (G_ArcSettings.fShowStatus)
  917.                     {
  918.                         sprintf(szTemp,
  919.                                 cmnGetString(ID_XSSI_ARCINICHANGED),  // "INI files changed %f %%", // pszArcINIChanged
  920.                                 dMaxDifferencePercent);
  921.                         xstrcpy(&strMsg, szTemp, 0);
  922.                         xstrcatc(&strMsg, '\n');
  923.                         sprintf(szTemp,
  924.                                 cmnGetString(ID_XSSI_ARCINILIMIT),  // "Limit: %f %%." // pszArcINILimit
  925.                                 G_ArcSettings.dIniFilesPercent);
  926.                         xstrcat(&strMsg, szTemp, 0);
  927.                         xstrcatc(&strMsg, '\n');
  928.                     }
  929.                 } // end if (fCheckINIs)
  930.             } // end else if (G_ArcSettings.ulArcFlags & ARCF_ALWAYS)
  931.         } // else if (fWasJustRestored)
  932.  
  933.         if (strMsg.ulLength)
  934.         {
  935.             if (G_ArcSettings.fShowStatus)
  936.             {
  937.                 if (fBackup)
  938.                 {
  939.                     // archiving to be turned on:
  940.                     // save "last app" etc. data so we won't get this twice
  941.                     arcSaveSettings();
  942.                     xstrcat(&strMsg,
  943.                             cmnGetString(ID_XSSI_ARCENABLED),  // "Desktop archiving enabled"
  944.                             0);
  945.                 }
  946.                 else
  947.                     xstrcat(&strMsg,
  948.                             cmnGetString(ID_XSSI_ARCNOTNECC),  // "Desktop archiving not necessary"
  949.                             0);
  950.  
  951.                 ShowStatus(hwndStatus,
  952.                            strMsg.psz);
  953.             }
  954.         }
  955.  
  956.         xstrClear(&strMsg);
  957.  
  958.         if (G_ArcSettings.fShowStatus)
  959.             WinPostMsg(hwndNotify, ulMsg, (MPARAM)hwndStatus, (MPARAM)NULL);
  960.     }
  961.  
  962.     arcSwitchArchivingOn(fBackup); // moved V0.9.4 (2000-07-22) [umoeller]
  963.  
  964.     if (fDisableArchiving)
  965.     {
  966.         G_ArcSettings.ulArcFlags &= ~ARCF_ENABLED;
  967.         arcSaveSettings();
  968.         cmnMessageBoxExt(NULLHANDLE,
  969.                          116,
  970.                          NULL, 0,
  971.                          188,
  972.                          MB_OK);
  973.     }
  974.  
  975.     return (fBackup);
  976. }
  977.  
  978. /*
  979.  *@@ arcSwitchArchivingOn:
  980.  *      depending on fSwitchOn, this switches Desktop archiving on or off
  981.  *      by manipulating the \OS2\BOOT\ARCHBASE.$$$ file.
  982.  *
  983.  *      In addition, this stores the date of the last archive in OS2.INI
  984.  *      and creates a file on the desktop to mark this as an archive.
  985.  *
  986.  *      This should only be called by arcCheckIfBackupNeeded.
  987.  *
  988.  *@@changed V0.9.13 (2001-06-14) [umoeller]: optimized
  989.  *@@changed V0.9.13 (2001-06-14) [smilcke]: when archiving is switched on we have to clear the restore flag
  990.  */
  991.  
  992. APIRET arcSwitchArchivingOn(BOOL fSwitchOn)
  993. {
  994.     APIRET arc = NO_ERROR;
  995.  
  996.     if (fSwitchOn)
  997.     {
  998.         if (!(arc = arcSetArchiveByte(1, ARCOFS_ARCHIVINGENABLED)))
  999.         {
  1000.             // reset the restore flag V0.9.13 (2001-06-14) [smilcke]
  1001.             arc = arcSetArchiveByte(0, ARCOFS_JUSTRESTORED);
  1002.  
  1003.             #ifdef DEBUG_STARTUP
  1004.              _Pmpf(("WPS Archiving activated"));
  1005.             #endif
  1006.  
  1007.             // store date of backup in OS2.INI
  1008.             DosGetDateTime(&G_dtLastArchived);
  1009.             PrfWriteProfileData(HINI_USER,
  1010.                                 (PSZ)INIAPP_XWORKPLACE,
  1011.                                 (PSZ)INIKEY_ARCHIVE_LASTBACKUP,
  1012.                                 &G_dtLastArchived,
  1013.                                 sizeof(G_dtLastArchived));
  1014.         }
  1015.     }
  1016.     else
  1017.     {
  1018.         arc = arcSetArchiveByte(0, ARCOFS_ARCHIVINGENABLED);
  1019.  
  1020.         #ifdef DEBUG_STARTUP
  1021.         _Pmpf(("WPS Archiving deactivated"));
  1022.         #endif
  1023.     }
  1024.  
  1025.     if (arc)
  1026.         cmnLog(__FILE__, __LINE__, __FUNCTION__,
  1027.                "Got error %d");
  1028.  
  1029.     return arc;
  1030. }
  1031.  
  1032. /*
  1033.  *@@ arcSetNumArchives:
  1034.  *      queries or sets the maximum no. of archives
  1035.  *      which are maintained by the WPS.
  1036.  *
  1037.  *      If (fSet == TRUE), the number of archives is set
  1038.  *      to *pcArchives. This must be > 0 and < 10, otherwise
  1039.  *      FALSE is returned.
  1040.  *
  1041.  *      If (fSet == FALSE), the current number of archives
  1042.  *      is queried and written into *pcArchives, but not
  1043.  *      changed.
  1044.  *
  1045.  *@@changed V0.9.12 (2001-05-24) [smilcke]: code optimized to use arcSetByte/arcGetByte
  1046.  */
  1047.  
  1048. BOOL arcSetNumArchives(PCHAR pcArchives,        // in/out: number of archives
  1049.                        BOOL fSet)               // if TRUE, archive number is set
  1050. {
  1051.     BOOL            brc = FALSE;
  1052.  
  1053.     if (pcArchives)
  1054.         if (    (fSet)
  1055.              && (    (*pcArchives < 0)
  1056.                   || (*pcArchives > 9)
  1057.                 )
  1058.            )
  1059.         {
  1060.             brc = FALSE;
  1061.         }
  1062.         else
  1063.         {
  1064.             CHAR cArchives = 0;
  1065.             arcQueryArchiveByte(&cArchives,
  1066.                                 ARCOFS_MAXARCHIVES);
  1067.             if (fSet)
  1068.                 arcSetArchiveByte(*pcArchives,
  1069.                                   ARCOFS_MAXARCHIVES);
  1070.             *pcArchives = cArchives;
  1071.         }
  1072.  
  1073.     return brc;
  1074. }
  1075.  
  1076. /*
  1077.  *@@ arcCheckINIFiles:
  1078.  *      this function goes thru both OS2.INI and OS2SYS.INI and
  1079.  *      checks for changes. This gets called from arcCheckIfBackupNeeded.
  1080.  *
  1081.  *      To find this out, we check the following data:
  1082.  *      --  the size of the applications list;
  1083.  *      --  the size of the keys list;
  1084.  *      --  the actual profile data, for which all values are summed up.
  1085.  *
  1086.  *      If any of these values differs more than cPercent from the old
  1087.  *      data passed to this function, we update that data and return TRUE,
  1088.  *      which means that Desktop archiving should be turned on.
  1089.  *
  1090.  *      Otherwise FALSE is returned, and the data is not changed.
  1091.  *
  1092.  *      In any case, *pcMaxDifferencePercent is set to the maximum
  1093.  *      percentage of difference which was computed.
  1094.  *
  1095.  *      If (cPercent == 0), all data is checked for, and TRUE is always
  1096.  *      returned. This might be useful for retrieving the "last app" etc.
  1097.  *      data once.
  1098.  *
  1099.  *      NOTE: It is the responsibility of the caller to save the
  1100.  *      old data somewhere. This function does _not_ check the
  1101.  *      INI files.
  1102.  *
  1103.  *      Set pszIgnoreApp to any INI application which should be ignored
  1104.  *      when checking for changes. This is useful if the "last app" etc.
  1105.  *      data is stored in the profiles too. If (pszIgnoreApp == NULL),
  1106.  *      all applications are checked for.
  1107.  */
  1108.  
  1109. BOOL arcCheckINIFiles(double* pdPercent,
  1110.                       PSZ pszIgnoreApp,        // in: this application will not be checked
  1111.                       double* pdAppsSizeLast,
  1112.                       double* pdKeysSizeLast,
  1113.                       double* pdDataSumLast,
  1114.                       double* pdMaxDifferencePercent) // out: maximum difference found
  1115. {
  1116.     BOOL            brc = FALSE;        // return value
  1117.     double          dDataSum = 0,
  1118.                     dTotalAppsSize = 0,
  1119.                     dTotalKeysSize = 0;
  1120.     double          dMaxDifferencePercent = 0;
  1121.  
  1122.     // 1) Applications loop
  1123.     APIRET          arc;
  1124.     PSZ pszAppsList = NULL;
  1125.  
  1126.     #ifdef DEBUG_STARTUP
  1127.         _Pmpf(("Checking INI files"));
  1128.     #endif
  1129.  
  1130.     if (!(arc = prfhQueryKeysForApp(HINI_PROFILE, // both OS2.INI and OS2SYS.INI
  1131.                                     NULL,        // return applications
  1132.                                     &pszAppsList)))
  1133.     {
  1134.         PSZ pApp2 = pszAppsList;
  1135.  
  1136.         while (*pApp2 != 0)
  1137.         {
  1138.             BOOL    fIgnore = FALSE;
  1139.             // pApp2 has the current app now
  1140.  
  1141.             // ignore this app?
  1142.             if (pszIgnoreApp)
  1143.                 if (!strcmp(pszIgnoreApp, pApp2))
  1144.                     fIgnore = TRUE;
  1145.  
  1146.             if (!fIgnore)
  1147.             {
  1148.                 // 2) keys loop for this app
  1149.                 PSZ pszKeysList = NULL;
  1150.                 if (!(arc = prfhQueryKeysForApp(HINI_PROFILE, // both OS2.INI and OS2SYS.INI
  1151.                                                 pApp2,        // return keys
  1152.                                                 &pszKeysList)))
  1153.                 {
  1154.                     PSZ pKey2 = pszKeysList;
  1155.  
  1156.                     while (*pKey2 != 0)
  1157.                     {
  1158.                         // pKey2 has the current key now
  1159.  
  1160.                         // 3) get key data
  1161.                         ULONG   cbData = 0;
  1162.                         PSZ pszData = prfhQueryProfileData(HINI_PROFILE,
  1163.                                                            pApp2,
  1164.                                                            pKey2,
  1165.                                                            &cbData);
  1166.                         if (pszData)
  1167.                         {
  1168.                             // sum up all values
  1169.                             PSZ     p = pszData;
  1170.                             ULONG   ul = 0;
  1171.                             for (ul = 0;
  1172.                                  ul < cbData;
  1173.                                  ul++, p++)
  1174.                                 dDataSum += (double)*p;
  1175.  
  1176.                             free(pszData);
  1177.                         }
  1178.  
  1179.                         pKey2 += strlen(pKey2)+1; // next key
  1180.                     } // end while (*pKey2 != 0)
  1181.  
  1182.                     // add size of keys list to total size
  1183.                     dTotalKeysSize += (pKey2 - pszKeysList);
  1184.  
  1185.                     free(pszKeysList);
  1186.                 } // end if (pszKeysList)
  1187.             } // end if (!fIgnore)
  1188.  
  1189.             pApp2 += strlen(pApp2)+1; // next app
  1190.         } // end while (*pApp2 != 0)
  1191.  
  1192.         // add size of apps list to total size
  1193.         dTotalAppsSize += (pApp2 - pszAppsList);
  1194.  
  1195.         free(pszAppsList);
  1196.     } // end if (pszAppsList)
  1197.  
  1198.     if (*pdPercent != 0)
  1199.     {
  1200.         #ifdef DEBUG_STARTUP
  1201.             CHAR szTemp[1000];
  1202.  
  1203.             _Pmpf(("Last, now"));
  1204.             sprintf(szTemp, "Apps size: %f, %f", *pdAppsSizeLast, dTotalAppsSize);
  1205.             _Pmpf(("%s", szTemp));
  1206.             sprintf(szTemp, "Keys size: %f, %f", *pdKeysSizeLast, dTotalKeysSize);
  1207.             _Pmpf(("%s", szTemp));
  1208.             sprintf(szTemp, "Data sum: %f, %f", *pdDataSumLast, dDataSum);
  1209.             _Pmpf(("%s", szTemp));
  1210.         #endif
  1211.  
  1212.         if ((*pdAppsSizeLast) && (dTotalAppsSize))
  1213.         {
  1214.             // if so, check if more than the given percentage of application strings
  1215.             // where modified
  1216.             double dPercentThis =
  1217.                         fabs(dTotalAppsSize - *pdAppsSizeLast)     // difference (we need fabs, abs returns 0 always)
  1218.                         * 100                               // in percent
  1219.                         / *pdAppsSizeLast;
  1220.  
  1221.             #ifdef DEBUG_STARTUP
  1222.                 sprintf(szTemp, "%f", dPercentThis);
  1223.                 _Pmpf(("dPercent Apps: %s", szTemp));
  1224.             #endif
  1225.  
  1226.             if (dPercentThis > *pdPercent)
  1227.             {
  1228.                 // yes: store new value (for later writing to log-file)
  1229.                 // and switch archiving on
  1230.                 *pdAppsSizeLast = dTotalAppsSize;
  1231.                 brc = TRUE;
  1232.             }
  1233.  
  1234.             if (dPercentThis > dMaxDifferencePercent)
  1235.                 dMaxDifferencePercent = dPercentThis;
  1236.         }
  1237.  
  1238.         // same logic for keys size
  1239.         if ((*pdKeysSizeLast) && (dTotalKeysSize))
  1240.         {
  1241.             double dPercentThis =
  1242.                         fabs(dTotalKeysSize - *pdKeysSizeLast)     // difference (we need fabs, abs returns 0 always)
  1243.                         * 100                               // in percent
  1244.                         / *pdKeysSizeLast;
  1245.  
  1246.             #ifdef DEBUG_STARTUP
  1247.                 sprintf(szTemp, "%f", dPercentThis);
  1248.                 _Pmpf(("dPercent Keys: %s", szTemp));
  1249.             #endif
  1250.  
  1251.             if (dPercentThis > *pdPercent)
  1252.             {
  1253.                 // yes: store new value (for later writing to log-file)
  1254.                 // and switch archiving on
  1255.                 *pdKeysSizeLast = dTotalKeysSize;
  1256.                 brc = TRUE;
  1257.             }
  1258.  
  1259.             if (dPercentThis > dMaxDifferencePercent)
  1260.                 dMaxDifferencePercent = dPercentThis;
  1261.         }
  1262.  
  1263.         // same logic for profile data
  1264.         if ((*pdDataSumLast) && (dDataSum))
  1265.         {
  1266.             double dPercentThis =
  1267.                         fabs(dDataSum - *pdDataSumLast)     // difference (we need fabs, abs returns 0 always)
  1268.                         * 100                               // in percent
  1269.                         / *pdDataSumLast;
  1270.  
  1271.             #ifdef DEBUG_STARTUP
  1272.                 sprintf(szTemp, "%f", dPercentThis);
  1273.                 _Pmpf(("dPercent Data: %s", szTemp));
  1274.             #endif
  1275.  
  1276.             if (dPercentThis > *pdPercent)
  1277.             {
  1278.                 // yes: store new value (for later writing to log-file)
  1279.                 // and switch archiving on
  1280.                 *pdDataSumLast = dDataSum;
  1281.                 brc = TRUE;
  1282.             }
  1283.  
  1284.             if (dPercentThis > dMaxDifferencePercent)
  1285.                 dMaxDifferencePercent = dPercentThis;
  1286.         }
  1287.  
  1288.         if (pdMaxDifferencePercent)
  1289.             *pdMaxDifferencePercent = dMaxDifferencePercent;
  1290.  
  1291.     } // end if (cPercent)
  1292.  
  1293.     // check if any size is 0 so the values MUST be written and archiving MUST
  1294.     // be switched on
  1295.     if (!*pdAppsSizeLast || !*pdKeysSizeLast || !*pdDataSumLast)
  1296.     {
  1297.         *pdAppsSizeLast = dTotalAppsSize;
  1298.         *pdKeysSizeLast = dTotalKeysSize;
  1299.         *pdDataSumLast = dDataSum;
  1300.         brc = TRUE;
  1301.     }
  1302.  
  1303.     #ifdef DEBUG_STARTUP
  1304.         _Pmpf(("  Done checking INI files, returning %d", brc));
  1305.     #endif
  1306.  
  1307.     return brc;
  1308. }
  1309.  
  1310.  
  1311.