
/*
 *@@sourcefile prfh.c:
 *      contains those Presentation Manager helper functions
 *      which deal with Profile (Prf*) functions. These can be
 *      used w/out the rest of the XFolder source in any PM
 *      program.
 *      This file is new with V0.82.
 *
 *      Function prefixes:
 *      --  prfh*   Prf (profile, INI) helper functions
 *
 *@@include #define INCL_WINWINDOWMGR
 *@@include #define INCL_WINSHELLDATA
 *@@include #include <os2.h>
 *@@include #include "prfh.h"
 */

/*
 *      Copyright (C) 1997-99 Ulrich M”ller.
 *      This file is part of the XFolder source package.
 *      XFolder is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published
 *      by the Free Software Foundation, in version 2 as it comes in the
 *      "COPYING" file of the XFolder main distribution.
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 */

#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WIN
#include <os2.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "dosh.h"

#include "prfh.h"

/*
 *@@ prfhQueryKeysForApp:
 *      returns the keys list for an INI application. This
 *      list is copied into a newly allocated buffer, of which
 *      the address is returned.  You should free() this buffer
 *      when you're done. Returns NULL upon errors.
 */

PSZ prfhQueryKeysForApp(HINI hIni,      // in: INI handle
                        PSZ pszApp)     // in: application to query
{
    PSZ     pKeys = NULL;
    ULONG   ulSizeOfKeysList = 0;

    // get size of keys list for pszApp
    if (PrfQueryProfileSize(hIni, pszApp, NULL, &ulSizeOfKeysList))
    {
        pKeys = (PSZ)malloc(ulSizeOfKeysList);
        if (!PrfQueryProfileData(hIni, pszApp, NULL, pKeys, &ulSizeOfKeysList)) {
            free(pKeys);
            pKeys = NULL;
        }
    }
    return (pKeys);
}

/*
 * prfhINIError:
 *      this is called whenever an error occurs saving a
 *      profile. This will compose an error string and
 *      all the callback func fncbError.
 */

ULONG prfhINIError(ULONG ulOptions, HAB hab, HFILE hfLog, PFNWP fncbError, PSZ pszErrorString)
{
    ULONG ulrc;
    CHAR szError2[2000];

    if (fncbError) {
        if (ulOptions == MB_ABORTRETRYIGNORE)
            sprintf(szError2, "%s"
                              "\nWinGetLastError: 0x%lX"
                              "\nPress 'Abort' to abort saving the INI files. This will restart the WPS to avoid loss of data."
                              "\nPress 'Retry' to attempt saving this INI file again. "
                              "\nPress 'Ignore' to ignore this error. This might help, but "
                              "also lead to more errors or loss of the currently processed data.",
                              pszErrorString,
                              WinGetLastError(hab));
        else
            sprintf(szError2, "%s\nPress 'Cancel' to abort shutdown. ", pszErrorString);
        ulrc = ( (ULONG)(*fncbError)(0, 0, szError2, (MPARAM)ulOptions) );

    } else
        ulrc = (MBID_ABORT);

    if (hfLog) {
        CHAR szLog[2000];
        sprintf(szLog, "    Error occured: %s\n    Return code: %s (%d)\n    WinGetLastError: %lX\n",
                pszErrorString,
                    (ulrc == MBID_ABORT) ? "MBID_ABORT"
                    : (ulrc == MBID_IGNORE) ? "MBID_IGNORE"
                    : (ulrc == MBID_RETRY) ? "MBID_RETRY"
                    : "unknown",
                ulrc,
                WinGetLastError(hab));
        doshWriteToLogFile(hfLog, szLog);
    }
    return (ulrc);
}

/*
 * prfhINIError2:
 *      like the previous func, but with additional info
 *      for the error string.
 */

ULONG prfhINIError2(ULONG ulOptions, PSZ pszINI, HAB hab, HFILE hfLog, PFNWP fncbError, PSZ pszErrorString)
{
    CHAR szError2[2000];
    sprintf(szError2, "An error occured copying the profile %s: \n%s",
            pszINI, pszErrorString);
    return (prfhINIError(ulOptions, hab, hfLog, fncbError, szError2));
}

/*
 *@@ prfhCopyProfile:
 *      this function copies a given profile into a
 *      new file. hOld is the handle, pszOld the filename
 *      of the profile to be copied (e.g. HINI_USERPROFILE
 *      and "?:\OS2\OS2.INI"; pszNew must point to a
 *      buffer which will contain the new filename ending
 *      in ".XFL" after prfhCopyProfile returns
 *      (e.g. "?:\OS2\OS2.XFL").
 *      You may specify a Callback procedure which gets
 *      called upon every copied application in the INI
 *      file; this way, you can provide a progress bar.
 *      fncbError gets called upon errors.
 */

BOOL prfhCopyProfile(HAB hab,               // in:  anchor block
                     HFILE hfLog,           // in:  logfile handle
                                            // or NULLHANDLE for no log
                     HINI hOld,             // in:  HINI to copy
                     PSZ pszOld,            // in:  fully qualif. filename of hOld
                     PSZ pszNew,            // out: new filename
                     PFNWP fncbUpdate,      // in:  progress callback
                     HWND hwnd, ULONG msg, ULONG ulCount, ULONG ulMax,
                                            // in:  passed to fncbUpdate
                     PFNWP fncbError,       // in:  error callback
                     PULONG pulFunc2)       // in:  passed to fncbError
{
    // BOOL    rc = TRUE;
    HINI    hNew;
    PSZ     pApps, pKeys, pData,
            pApp2, pKey2;
    ULONG   ulSizeOfAppsList, ulSizeOfKeysList, ulSizeOfData;
    CHAR    szLog[1000];
    #define MBID_NOERROR 999
    ULONG   ulErrorStatus = MBID_NOERROR;
    PSZ     p_;
    CHAR    szError2[2000];

    *pulFunc2 = 20000;
    if (hfLog) {
        sprintf(szLog, "    Entering prfhCopyProfile, params: "
                    "hiniOld 0x%lX, pszOld %s, pfnwpCallback 0x%lX, "
                    "hwnd 0x%lX, msg 0x%lX, ulCount 0x%lX, ulMax 0x%lX\n",
                    hOld, pszOld, fncbUpdate, hwnd, msg, ulCount, ulMax);
        doshWriteToLogFile(hfLog, szLog);
    }

    *pulFunc2 = 20010;
    if ( (!pszOld) || (!pszNew) )
        ulErrorStatus = prfhINIError2(MB_CANCEL, pszOld, hab, hfLog, fncbError,
                "Invalid name buffers given.");

    *pulFunc2 = 20020;
    if (ulErrorStatus == MBID_NOERROR) {
        strupr(pszOld);
        strcpy(pszNew, pszOld);
        p_ = strstr(pszNew, ".INI");
        if (!p_)
            ulErrorStatus = prfhINIError2(MB_CANCEL, pszNew, hab, hfLog, fncbError,
                    "Error composing new filename.");
    }

    *pulFunc2 = 20030;
    if (ulErrorStatus == MBID_NOERROR) {
        strcpy(p_, ".XFL");
        if (hfLog) {
            sprintf(szLog, "    DEL %s\n", pszNew);
            doshWriteToLogFile(hfLog, szLog);
        }
        DosDelete(pszNew);

        if (hfLog) {
            sprintf(szLog, "    PrfOpenProfile %s\n", pszNew);
            doshWriteToLogFile(hfLog, szLog);
        }

        *pulFunc2 = 20040;
        hNew = PrfOpenProfile(hab, pszNew);
        if (!hNew)
            ulErrorStatus = prfhINIError2(MB_CANCEL, pszNew, hab, hfLog, fncbError,
                    "Error creating temporary profile.");
    }

    // get size of applications list
    *pulFunc2 = 20100;
    if (ulErrorStatus == MBID_NOERROR) {
        if (!PrfQueryProfileSize(hOld, NULL, NULL, &ulSizeOfAppsList))
            ulErrorStatus = prfhINIError2(MB_CANCEL, pszNew, hab, hfLog, fncbError,
                    "Error querying applications list size.");
        else
        if (ulSizeOfAppsList == 0)
            ulErrorStatus = prfhINIError2(MB_CANCEL, pszNew, hab, hfLog, fncbError,
                "Size of applications list cannot be 0.");
    }

    if (ulErrorStatus == MBID_NOERROR) {

        // do-while loop in case of MBID_RETRY
        do {
            ulErrorStatus = MBID_NOERROR; // if we have a retry in the do-while loop

            // get applications list
            *pulFunc2 = 20110;
            pApps = (PSZ)malloc(ulSizeOfAppsList);
            pApp2 = pApps;
            if (!PrfQueryProfileData(hOld, NULL, NULL, pApps, &ulSizeOfAppsList))
                ulErrorStatus = prfhINIError2(MB_CANCEL, pszNew, hab, hfLog, fncbError,
                            "Could not query application list.");

            // applications loop

            *pulFunc2 = 20200;
            while (   (*pApp2 != 0)
                   && (ulErrorStatus == MBID_NOERROR)
                  )
            {
                *pulFunc2 = 20210;
                if (hfLog) {
                    sprintf(szLog, "    Copying app %s... ", pApp2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // get size of keys list for pApp2
                *pulFunc2 = 20220;
                if (!PrfQueryProfileSize(hOld, pApp2, NULL, &ulSizeOfKeysList)) {
                    sprintf(szError2, "Error querying size of keys list for \"%s\".",
                            pApp2);
                    ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                            szError2);
                }
                else if (ulSizeOfKeysList == 0) {
                    sprintf(szError2, "Size of keys list for \"%s\" should not be 0.",
                            pApp2);
                    ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                                szError2);
                }

                if (ulErrorStatus == MBID_NOERROR) {
                    *pulFunc2 = 20250;
                    pKeys = (PSZ)malloc(ulSizeOfKeysList);
                    pKey2 = pKeys;
                    if (!PrfQueryProfileData(hOld, pApp2, NULL, pKeys, &ulSizeOfKeysList)) {
                        sprintf(szError2, "Error querying keys list for %s (size: %d bytes).",
                                pApp2, ulSizeOfKeysList);
                        ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                                szError2);
                    }

                    // keys loop

                    *pulFunc2 = 20300;
                    while (   (*pKey2 != 0)
                           && (ulErrorStatus == MBID_NOERROR)
                                // if "ignore" was pressed on error, the whole
                                // application is skipped
                          )
                    {
                        *pulFunc2 = 20310;
                        if (!PrfQueryProfileSize(hOld, pApp2, pKey2, &ulSizeOfData)) {
                            sprintf(szError2, "Error querying data size of \"%s\"/\"%s\".",
                                    pApp2, pKey2);
                            ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                                    szError2);
                        }

                        if (ulErrorStatus == MBID_NOERROR) {

                            // finally, copy data

                            if (ulSizeOfData != 0)
                            {
                                // valid data:
                                *pulFunc2 = 20400;
                                pData = (PSZ)malloc(ulSizeOfData);
                                if (!pData) {
                                    sprintf(szError2, "Error allocating memory for data from key %s (app %s, size %d bytes).",
                                            pKey2, pApp2, ulSizeOfData);
                                    ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                                            szError2);
                                }

                                if (ulErrorStatus == MBID_NOERROR) {
                                    *pulFunc2 = 20410;
                                    if (    (!PrfQueryProfileData(hOld, pApp2, pKey2,
                                                    pData, &ulSizeOfData))
                                         // || (TRUE) // *** debug!!!
                                       )
                                    {
                                        sprintf(szError2, "Error reading data from app \"%s\", key \"%s\" (size %d bytes).",
                                                pApp2, pKey2, ulSizeOfData);
                                        ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                                                szError2);
                                    }
                                }
                            } else {
                                // data size == 0: this shouldn't really happen,
                                // but if it does, we'll just create a NULL string.
                                // Users have reported that some INI files seem to
                                // contain those "empty" keys. I don't see how these
                                // can exist, but they seem to...
                                pData = (PSZ)malloc(1);
                                *pData = 0;
                            }

                            if (ulErrorStatus == MBID_NOERROR) {
                                *pulFunc2 = 20420;
                                if (!PrfWriteProfileData(hNew, pApp2, pKey2, pData, ulSizeOfData)) {
                                    sprintf(szError2, "Error writing data to app \"%s\", key \"%s\" (size %d bytes).",
                                            pApp2, pKey2, ulSizeOfData);
                                    ulErrorStatus = prfhINIError2(MB_ABORTRETRYIGNORE, pszNew, hab, hfLog, fncbError,
                                            szError2);
                                }
                            }

                            *pulFunc2 = 20430;
                            if (pData)
                                free(pData);
                        }

                        // go for next key
                        *pulFunc2 = 20490;
                        pKey2 += strlen(pKey2)+1;
                        *pulFunc2 = 20491;

                        if (ulErrorStatus == MBID_IGNORE)
                            // skip this key
                            ulErrorStatus = MBID_NOERROR;

                    } // end while (*pKey2 != 0)

                    *pulFunc2 = 20500;
                    if (pKeys)
                        free(pKeys);

                    if (ulErrorStatus == MBID_NOERROR) {
                        *pulFunc2 = 20510;
                        if (hfLog)
                            doshWriteToLogFile(hfLog, "OK\n");
                    }

                } // end if (ulErrorOccured == MBID_NOERROR)

                *pulFunc2 = 20520;
                if (fncbUpdate) {
                    ULONG ulNow2, ulMax2;
                    ulNow2 = ((1000*(pApp2-pApps))/ulSizeOfAppsList) + (ulCount*1000);
                    ulMax2 = (ulMax+1)*1000; // ulAppsSize;
                    (*fncbUpdate)(hwnd, msg, (MPARAM)ulNow2, (MPARAM)ulMax2);
                }

                *pulFunc2 = 20530;
                // go for next app
                pApp2 += strlen(pApp2)+1;
                *pulFunc2 = 20531;

                if (ulErrorStatus == MBID_IGNORE)
                    // skip this app
                    ulErrorStatus = MBID_NOERROR;

            } // end while (*pApp2 != 0)

            *pulFunc2 = 20610;
            if (pApps)
                free(pApps);

            if (hfLog) {
                sprintf(szLog, "    Done copying apps\n");
                doshWriteToLogFile(hfLog, szLog);
            }
        } while (ulErrorStatus == MBID_RETRY);
    } // end if (ulErrorOccured == MBID_NOERROR)

    *pulFunc2 = 20620;
    if (hfLog) {
        sprintf(szLog, "    PrfCloseProfile %s\n", pszNew);
        doshWriteToLogFile(hfLog, szLog);
    }

    *pulFunc2 = 20630;
    PrfCloseProfile(hNew);
    *pulFunc2 = 20640;
    if (fncbUpdate)
        (*fncbUpdate)(hwnd, msg, (MPARAM)(ulCount+1), (MPARAM)(ulMax+1));

    *pulFunc2 = 20650;
    if (hfLog)
        doshWriteToLogFile(hfLog, "    Exiting prfhCopyProfile.\n");

    *pulFunc2 = 20660;

    return (ulErrorStatus == MBID_NOERROR); // FALSE if error occured
}

/*
 *@@ prfhSaveINIs:
 *      this will enforce saving of OS2.INI and OS2SYS.INI
 *      by calling prfhCopyProfile (above) on them; the therefrom
 *      resulting ".XFL" files will replace the original
 *      ".INI" files.
 *      Specify fncbUpdate and fncbError like in prfhCopyProfile.
 */

APIRET prfhSaveINIs(HAB hab,                // in:  anchor block
                     HFILE hfLog,           // in:  logfile handle or NULLHANDLE for no log
                     PFNWP fncbUpdate,      // in:  progress callback
                     HWND hwnd, ULONG msg,  // in:  params passed to fncbUpdate
                     PFNWP fncbError,       // in:  error callback
                     PULONG pulFunc2)       // in:  passed to fncbError
{
    PRFPROFILE Profiles;
    APIRET  arc = NO_ERROR, arc2;
    BOOL    brc = TRUE;

    // FILESTATUS3 fs3;
    CHAR    szSysNew[CCHMAXPATH],
            szUserNew[CCHMAXPATH],
            szSysBackup[CCHMAXPATH],
            szUserBackup[CCHMAXPATH],
            szLog[1000];

    // PSZ     p;

    // the following flag may be one of the following:
    //        MBID_NOERROR--- everything's fine, continue
    //        MBID_IGNORE --- error occured, but ignore
    //        MBID_RETRY  --- error occured, but retry
    //        MBID_ABORT  --- error occured, abort saving
    ULONG   ulErrorOccured = MBID_IGNORE;

    // DosEnterCritSec();

    *pulFunc2 = 10000;

    if (hfLog)
        doshWriteToLogFile(hfLog, "  Entering prfhSaveINIs...\n");

    Profiles.cchUserName = Profiles.cchSysName = 0;
    brc = PrfQueryProfile(hab, &Profiles);

    *pulFunc2 = 10010;
    if (!brc) {
        ulErrorOccured = prfhINIError(MB_CANCEL, hab, hfLog, fncbError,
                "Error querying system profiles size.");
    }

    *pulFunc2 = 10020;
    if (ulErrorOccured == MBID_IGNORE) {
        Profiles.pszUserName  = (PSZ)malloc(Profiles.cchUserName);
        Profiles.pszSysName  = (PSZ)malloc(Profiles.cchSysName);
        if (    (Profiles.pszSysName == NULL)
             || (Profiles.pszUserName == NULL)
           )
            ulErrorOccured = prfhINIError(MB_CANCEL, hab, hfLog, fncbError,
                    "Error allocating memory (1).");
    }

    *pulFunc2 = 10030;
    if (ulErrorOccured == MBID_IGNORE) {
        if (!PrfQueryProfile(hab, &Profiles))
            ulErrorOccured = prfhINIError(MB_CANCEL, hab, hfLog, fncbError,
                    "Error querying profiles (2).");
    }

    *pulFunc2 = 10040;
    if (ulErrorOccured == MBID_IGNORE) {
        if (hfLog) {
            sprintf(szLog, "  System profiles are %s, %s\n",
                    Profiles.pszUserName, Profiles.pszSysName);
            doshWriteToLogFile(hfLog, szLog);
        }

        // create filenames
        strcpy(szSysBackup, Profiles.pszSysName);
        strcpy(strstr(szSysBackup, ".INI"), ".BAK");
        strcpy(szUserBackup, Profiles.pszUserName);
        strcpy(strstr(szUserBackup, ".INI"), ".BAK");

        *pulFunc2 = 10050;
        // create OS2SYS.XFL
        if (hfLog) {
            sprintf(szLog, "  Storing %s in *.XFL\n",
                    Profiles.pszSysName);
            doshWriteToLogFile(hfLog, szLog);
        }
        if (!prfhCopyProfile(hab, hfLog, HINI_SYSTEMPROFILE,
                Profiles.pszSysName, szSysNew,
                fncbUpdate, hwnd, msg, 0, 1,
                fncbError, pulFunc2))
        {
            // abort, since prfhCopyProfile already has error handling
            ulErrorOccured = MBID_ABORT;
        }
    }

    *pulFunc2 = 10060;
    if (ulErrorOccured == MBID_IGNORE) {
        // create OS2.XFL
        if (hfLog) {
            sprintf(szLog, "  Storing %s in *.XFL\n",
                    Profiles.pszUserName);
            doshWriteToLogFile(hfLog, szLog);
        }
        if (!prfhCopyProfile(hab, hfLog,
                HINI_USERPROFILE, Profiles.pszUserName, szUserNew,
                fncbUpdate, hwnd, msg, 1, 1,
                fncbError, pulFunc2))
        {
            // abort, since prfhCopyProfile already has error handling
            ulErrorOccured = MBID_ABORT;
        }
    }

    /*
     * renaming stuff for OS2SYS.INI
     *
     */

    if (ulErrorOccured == MBID_IGNORE) {
        do {
            ulErrorOccured = MBID_IGNORE; // if we have a retry in the do-while loop

            *pulFunc2 = 10070;
            if (ulErrorOccured == MBID_IGNORE) {
                // attrib -r -s -h -a OS2SYS.BAK
                if (hfLog) {
                    sprintf(szLog, "  ATTRIB -R -S -H -A %s\n",
                            szSysBackup);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc2 = doshSetPathAttr(szSysBackup, FILE_NORMAL);
                if (hfLog) {
                    sprintf(szLog, "    rc2: %d\n", arc2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // delete OS2SYS.BAK
                if (hfLog) {
                    sprintf(szLog, "  DEL %s\n",
                            szSysBackup);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc2 = DosDelete(szSysBackup);
                if (hfLog) {
                    sprintf(szLog, "    rc2: %d\n", arc2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // attrib -r -s -h -a OS2SYS.INI
                if (hfLog) {
                    sprintf(szLog, "  ATTRIB -R -S -H -A %s\n",
                            Profiles.pszSysName);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc2 = doshSetPathAttr(Profiles.pszSysName, FILE_NORMAL);
                if (hfLog) {
                    sprintf(szLog, "    rc2: %d\n", arc2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // move OS2SYS.INI OS2SYS.BAK
                if (hfLog) {
                    sprintf(szLog, "  MOVE %s %s\n",
                            Profiles.pszSysName, szSysBackup);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc = DosMove(Profiles.pszSysName, szSysBackup);
                if (hfLog) {
                    sprintf(szLog, "    rc: %d\n", arc);
                    doshWriteToLogFile(hfLog, szLog);
                }

                if (arc)
                    ulErrorOccured = prfhINIError(MB_ABORTRETRYIGNORE, hab, hfLog, fncbError, "Error moving original system profile to backup.");
            }

            *pulFunc2 = 10200;
            if (ulErrorOccured == MBID_IGNORE) {
                if (hfLog) {
                    sprintf(szLog, "  MOVE %s %s\n",
                            szSysNew, Profiles.pszSysName);
                    doshWriteToLogFile(hfLog, szLog);
                }
                *pulFunc2 = 10210;
                arc = DosMove(szSysNew, Profiles.pszSysName);
                if (hfLog) {
                    sprintf(szLog, "    rc: %d\n", arc);
                    doshWriteToLogFile(hfLog, szLog);
                }
                if (arc)
                    ulErrorOccured = prfhINIError(MB_ABORTRETRYIGNORE, hab, hfLog, fncbError, "Error moving newly created profile to system profile.");
            }
        } while (ulErrorOccured == MBID_RETRY);
    }

    /*
     * renaming stuff for OS2.INI
     *
     */

    if (ulErrorOccured == MBID_IGNORE) {
        do {
            ulErrorOccured = MBID_IGNORE; // if we have a retry in the do-while loop

            *pulFunc2 = 10300;
            if (ulErrorOccured == MBID_IGNORE) {
                // attrib -r -s -h -a OS2.BAK
                if (hfLog) {
                    sprintf(szLog, "  ATTRIB -R -S -H -A %s\n",
                            szUserBackup);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc2 = doshSetPathAttr(szUserBackup, FILE_NORMAL);
                if (hfLog) {
                    sprintf(szLog, "    rc2: %d\n", arc2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // delete OS2.BAK
                *pulFunc2 = 10310;
                if (hfLog) {
                    sprintf(szLog, "  DEL %s\n",
                            szUserBackup);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc2 = DosDelete(szUserBackup);
                if (hfLog) {
                    sprintf(szLog, "    rc2: %d\n", arc2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // attrib -r -s -h -a OS2.INI
                if (hfLog) {
                    sprintf(szLog, "  ATTRIB -R -S -H -A %s\n",
                            Profiles.pszUserName);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc2 = doshSetPathAttr(Profiles.pszUserName, FILE_NORMAL);
                if (hfLog) {
                    sprintf(szLog, "    rc2: %d\n", arc2);
                    doshWriteToLogFile(hfLog, szLog);
                }

                // move OS2.INI OS2.BAK
                if (hfLog) {
                    sprintf(szLog, "  MOVE %s %s\n",
                            Profiles.pszUserName, szUserBackup);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc = DosMove(Profiles.pszUserName, szUserBackup);
                if (hfLog) {
                    sprintf(szLog, "    rc: %d\n", arc);
                    doshWriteToLogFile(hfLog, szLog);
                }

                if (arc)
                    ulErrorOccured = prfhINIError(MB_ABORTRETRYIGNORE, hab, hfLog, fncbError, "Error moving original user profile to backup.");
            }

            *pulFunc2 = 10350;
            if (ulErrorOccured == MBID_IGNORE) {
                // move OS2.XFL OS2.INI
                if (hfLog) {
                    sprintf(szLog, "  MOVE %s %s\n",
                            szUserNew, Profiles.pszUserName);
                    doshWriteToLogFile(hfLog, szLog);
                }
                arc = DosMove(szUserNew, Profiles.pszUserName);
                if (hfLog) {
                    sprintf(szLog, "    rc: %d\n", arc);
                    doshWriteToLogFile(hfLog, szLog);
                }

                if (arc)
                    ulErrorOccured = prfhINIError(MB_ABORTRETRYIGNORE, hab, hfLog, fncbError, "Error moving newly created profile to user profile.");
            }
        } while (ulErrorOccured == MBID_RETRY);
    }

    // DosExitCritSec();

    *pulFunc2 = 10400;
    if (ulErrorOccured != MBID_IGNORE) {
        DosMove(szSysBackup, Profiles.pszSysName);
        DosMove(szUserBackup, Profiles.pszUserName);
    }

    *pulFunc2 = 10410;
    if (    (Profiles.pszSysName)
         && (Profiles.pszUserName)
       )
    {
        *pulFunc2 = 10420;
        free(Profiles.pszSysName);
        *pulFunc2 = 10430;
        free(Profiles.pszUserName);
    }

    *pulFunc2 = 10430;
    if (hfLog) {
        doshWriteToLogFile(hfLog, "  Done with prfhSaveINIs\n");
    }

    if (ulErrorOccured != MBID_IGNORE)
        return (999);
    else
        return (NO_ERROR);
}

/*
 *@@ prfhQueryColor:
 *      returns a system color in OS2.INI's PM_Colors as a LONG.
 */

LONG prfhQueryColor(PSZ pszKeyName, PSZ pszDefault)
{
    CHAR szColor[30];
    LONG r, g, b;
    PrfQueryProfileString(
                HINI_USER,
                "PM_Colors",
                pszKeyName,
                pszDefault,
                szColor,
                sizeof(szColor)-1);
    sscanf(szColor, "%d %d %d ", &r, &g, &b);
    return (r*0x10000 + g*0x100 + b);
}


