home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwphescr.zip / XWPH0208.ZIP / src / helpers / prfh.c < prev    next >
C/C++ Source or Header  |  2002-07-28  |  19KB  |  576 lines

  1.  
  2. /*
  3.  *@@sourcefile prfh.c:
  4.  *      contains those Presentation Manager helper functions
  5.  *      which deal with Profile (Prf*) functions.
  6.  *      This file is new with V0.82.
  7.  *
  8.  *      Usage: All OS/2 programs.
  9.  *
  10.  *      Function prefixes:
  11.  *      --  prfh*   Prf (profile, INI) helper functions
  12.  *
  13.  *      Note: Version numbering in this file relates to XWorkplace version
  14.  *            numbering.
  15.  *
  16.  *@@header "helpers\prfh.h"
  17.  */
  18.  
  19. /*
  20.  *      Copyright (C) 1997-2000 Ulrich Möller.
  21.  *      This file is part of the "XWorkplace helpers" source package.
  22.  *      This is free software; you can redistribute it and/or modify
  23.  *      it under the terms of the GNU General Public License as published
  24.  *      by the Free Software Foundation, in version 2 as it comes in the
  25.  *      "COPYING" file of the XWorkplace main distribution.
  26.  *      This program is distributed in the hope that it will be useful,
  27.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  28.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  29.  *      GNU General Public License for more details.
  30.  */
  31.  
  32. #define OS2EMX_PLAIN_CHAR
  33.     // this is needed for "os2emx.h"; if this is defined,
  34.     // emx will define PSZ as _signed_ char, otherwise
  35.     // as unsigned char
  36.  
  37. #define INCL_DOSERRORS
  38. #define INCL_WINSHELLDATA
  39. #include <os2.h>
  40.  
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44.  
  45. #include "setup.h"                      // code generation and debugging options
  46.  
  47. #define INCLUDE_PRFH_PRIVATE
  48. #include "helpers\prfh.h"
  49.  
  50. #pragma hdrstop
  51.  
  52. /*
  53.  *@@category: Helpers\Profile (INI) helpers
  54.  */
  55.  
  56. /*
  57.  *@@ prfhQueryKeysForApp:
  58.  *      returns the keys list for an INI application. This
  59.  *      list is copied into a newly allocated buffer, of which
  60.  *      the address is returned.
  61.  *
  62.  *      Returns NULL upon errors.
  63.  *
  64.  *      If the return value is != NULL, the PSZ points to a new
  65.  *      buffer which contains all the keys within the pszApp
  66.  *      application. Each key name in the list is terminated with
  67.  *      a null character. The last string in the list is terminated
  68.  *      with two null characters.
  69.  *
  70.  *      The returned buffer should be freed later using free().
  71.  *
  72.  *      <B>Example</B> for iterating over a keys list:
  73.  *
  74.  +          PSZ pszKeysList = prfhQueryKeysForApp(...);
  75.  +          if (pszKeysList)
  76.  +          {
  77.  +              PSZ pKey2 = pszKeysList;
  78.  +
  79.  +              while (*pKey2 != 0)
  80.  +              {
  81.  +                  ...     // pKey2 has the current key now
  82.  +                  pKey2 += strlen(pKey2)+1; // next key
  83.  +              }
  84.  +              free(pszKeysList);
  85.  +          }
  86.  *
  87.  *      You can also use this function to query the applications
  88.  *      list for hIni, if you specifiy pszApp as NULL.
  89.  *
  90.  *@@changed V0.9.12 (2001-05-12) [umoeller]: changed prototypes to return APIRET now
  91.  *@@changed V0.9.19 (2002-04-11) [pr]: Fixed app. with no keys
  92.  */
  93.  
  94. APIRET prfhQueryKeysForApp(HINI hIni,      // in: INI handle (can be HINI_USER or HINI_SYSTEM)
  95.                            const char *pcszApp, // in: application to query list for (or NULL for applications list)
  96.                            PSZ *ppszKeys)   // out: keys list (newly allocated)
  97. {
  98.     APIRET  arc = NO_ERROR;
  99.     PSZ     pKeys = NULL;
  100.     ULONG   ulSizeOfKeysList = 0;
  101.  
  102.     // get size of keys list for pszApp
  103.     if (!PrfQueryProfileSize(hIni, (PSZ)pcszApp, NULL, &ulSizeOfKeysList))
  104.         arc = PRFERR_KEYSLIST;
  105.     else
  106.     {
  107.         if (ulSizeOfKeysList == 0)
  108.             ulSizeOfKeysList = 1;    // V0.9.19 (2002-04-11) [pr]
  109.  
  110.         if (!(pKeys = (PSZ)malloc(ulSizeOfKeysList)))
  111.             arc = ERROR_NOT_ENOUGH_MEMORY;
  112.         else
  113.         {
  114.             *pKeys = 0;
  115.             if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, NULL, pKeys, &ulSizeOfKeysList))
  116.                 arc = PRFERR_KEYSLIST;
  117.         }
  118.     }
  119.  
  120.     if (!arc)       // V0.9.12 (2001-05-12) [umoeller]
  121.         *ppszKeys = pKeys;
  122.     else
  123.         if (pKeys)
  124.             free(pKeys);
  125.  
  126.     return arc;
  127. }
  128.  
  129. #ifdef __DEBUG_MALLOC_ENABLED__ // setup.h, helpers\memdebug.c
  130.  
  131. /*
  132.  *@@ prfhQueryProfileDataDebug:
  133.  *      debug version of prfhQueryProfileData, which is
  134.  *      automatically mapped to if __XWPMEMDEBUG__ is defined.
  135.  *
  136.  *@@added V0.9.1 (99-12-20) [umoeller]
  137.  *@@changed V0.9.3 (2000-04-20) [umoeller]: this called malloc(0) if the key existed, but was empty. Fixed.
  138.  */
  139.  
  140. PSZ (prfhQueryProfileDataDebug)(HINI hIni,      // in: INI handle (can be HINI_USER or HINI_SYSTEM)
  141.                               const char *pcszApp,      // in: application to query
  142.                               const char *pcszKey,      // in: key to query
  143.                               PULONG pcbBuf,   // out: size of the returned buffer
  144.                               const char *file,
  145.                               unsigned long line,
  146.                               const char *function)
  147. {
  148.     PSZ     pData = NULL;
  149.     ULONG   ulSizeOfData = 0;
  150.  
  151.     // get size of data for pszApp/pszKey
  152.     if (PrfQueryProfileSize(hIni, (PSZ)pcszApp, (PSZ)pcszKey, &ulSizeOfData))
  153.     {
  154.         if (ulSizeOfData)
  155.         {
  156.             pData = (PSZ)memdMalloc(ulSizeOfData, file, line, function);
  157.             if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, (PSZ)pcszKey, pData, &ulSizeOfData))
  158.             {
  159.                 free(pData);
  160.                 pData = NULL;
  161.             }
  162.         }
  163.     }
  164.  
  165.     if (pcbBuf)
  166.         *pcbBuf = ulSizeOfData;
  167.  
  168.     return (pData);
  169. }
  170.  
  171. #else
  172.  
  173. /*
  174.  *@@ prfhQueryProfileData:
  175.  *      similar to PrfQueryProfileData, but this one copies
  176.  *      the data into a newly allocated buffer, of which the
  177.  *      address is returned.
  178.  *
  179.  *      Returns NULL upon errors, for example if the specified
  180.  *      key doesn't exist or doesn't contain any data.
  181.  *
  182.  *      If pcbBuf != NULL, this func will write the size of
  183.  *      the allocated buffer into *pcbBuf.
  184.  *
  185.  *      The returned buffer should be freed later using free().
  186.  *
  187.  *@@added V0.9.0 [umoeller]
  188.  *@@changed V0.9.3 (2000-04-20) [umoeller]: this called malloc(0) if the key existed, but was empty. Fixed.
  189.  */
  190.  
  191. PSZ (prfhQueryProfileData)(HINI hIni,           // in: INI handle (can be HINI_USER or HINI_SYSTEM)
  192.                          const char *pcszApp,   // in: application to query
  193.                          const char *pcszKey,   // in: key to query
  194.                          PULONG pcbBuf)         // out: size of the returned buffer; ptr can be NULL
  195. {
  196.     PSZ     pData = NULL;
  197.     ULONG   ulSizeOfData;
  198.  
  199.     // get size of data for pszApp/pszKey
  200.     if (    (PrfQueryProfileSize(hIni, (PSZ)pcszApp, (PSZ)pcszKey, &ulSizeOfData))
  201.          && (ulSizeOfData)
  202.          && (pData = (PSZ)malloc(ulSizeOfData))
  203.        )
  204.     {
  205.         if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, (PSZ)pcszKey, pData, &ulSizeOfData))
  206.         {
  207.             free(pData);
  208.             pData = NULL;
  209.         }
  210.     }
  211.  
  212.     if (pcbBuf)
  213.         *pcbBuf = ulSizeOfData;
  214.  
  215.     return (pData);
  216. }
  217.  
  218. #endif
  219.  
  220. /*
  221.  *@@ prfhQueryProfileChar:
  222.  *      this query the first character of profile data.
  223.  *      This is mostly useful with the PM country settings
  224.  *      in OS2.INI:
  225.  *      -- date separator: "PM_National", "sDate"
  226.  *      -- time separator: "PM_National", "sTime"
  227.  */
  228.  
  229. CHAR prfhQueryProfileChar(HINI hini,        // in: INI handle (can be HINI_USER or HINI_SYSTEM)
  230.                           const char *pcszApp,       // in: application to query
  231.                           const char *pcszKey,       // in: key to query
  232.                           CHAR cDefault)    // in: default to return if not found
  233. {
  234.     CHAR    szTemp[5],
  235.             szDefault[5];
  236.     szDefault[0] = cDefault;
  237.     szDefault[1] = 0;
  238.     PrfQueryProfileString(HINI_USER, (PSZ)pcszApp, (PSZ)pcszKey,
  239.                           szDefault,
  240.                           szTemp, sizeof(szTemp)-1);
  241.     return (szTemp[0]);
  242. }
  243.  
  244. /*
  245.  *@@ prfhQueryColor:
  246.  *      returns a system color in OS2.INI's PM_Colors as a LONG.
  247.  */
  248.  
  249. LONG prfhQueryColor(const char *pcszKeyName,
  250.                     const char *pcszDefault)
  251. {
  252.     CHAR szColor[30];
  253.     ULONG r, g, b;
  254.     PrfQueryProfileString(
  255.                 HINI_USER,
  256.                 "PM_Colors",
  257.                 (PSZ)pcszKeyName,
  258.                 (PSZ)pcszDefault,
  259.                 szColor,
  260.                 sizeof(szColor)-1);
  261.     sscanf(szColor, "%lu %lu %lu ", &r, &g, &b);
  262.     return (LONG)(r*0x10000 + g*0x100 + b);
  263. }
  264.  
  265. /*
  266.  *@@ prfhCopyKey:
  267.  *      this copies one key from the given profile and application
  268.  *      to another one.
  269.  *
  270.  *      pszTargetApp may be in the same profile (and must be
  271.  *      different from pszSourceApp then) or in a different
  272.  *      profile (and can be the same then).
  273.  *
  274.  *      You must specify all parameters. You cannot specify pszKey
  275.  *      as NULL to have a whole application copied. Use prfhCopyApp
  276.  *      for that.
  277.  *      No check is made for this.
  278.  *
  279.  *      Returns:
  280.  *      --  0: no error
  281.  *
  282.  *      --  PRFERR_DATASIZE: couldn't query data size for key
  283.  *
  284.  *      --  PRFERR_MEMORY: couldn't allocate memory
  285.  *
  286.  *      --  PRFERR_READ: couldn't read data from source (PrfQueryProfileData error)
  287.  *
  288.  *      --  PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
  289.  *
  290.  *@@added V0.9.0 [umoeller]
  291.  */
  292.  
  293. APIRET prfhCopyKey(HINI hiniSource,       // in: source profile (can be HINI_USER or HINI_SYSTEM)
  294.                    const char *pcszSourceApp,      // in: source application
  295.                    const char *pcszKey,            // in: source/target key
  296.                    HINI hiniTarget,       // in: target profile (can be HINI_USER or HINI_SYSTEM)
  297.                    const char *pcszTargetApp)      // in: target app
  298. {
  299.     ULONG   ulSizeOfData = 0,
  300.             ulrc = 0;       // return: no error
  301.  
  302.     if (PrfQueryProfileSize(hiniSource, (PSZ)pcszSourceApp, (PSZ)pcszKey, &ulSizeOfData))
  303.     {
  304.         PSZ pData = 0;
  305.  
  306.         // copy data
  307.         if (ulSizeOfData == 0)
  308.         {
  309.             // data size == 0: this shouldn't really happen,
  310.             // but if it does, we'll just create a NULL string.
  311.             // Users have reported that some INI files seem to
  312.             // contain those "empty" keys. I don't see how these
  313.             // can exist, but they seem to...
  314.             pData = (PSZ)malloc(1);
  315.             *pData = 0;
  316.         }
  317.         else
  318.             pData = (PSZ)malloc(ulSizeOfData);
  319.  
  320.         if (pData)
  321.         {
  322.             if (PrfQueryProfileData(hiniSource,
  323.                                     (PSZ)pcszSourceApp,
  324.                                     (PSZ)pcszKey,
  325.                                     pData,
  326.                                     &ulSizeOfData))
  327.             {
  328.                 if (!PrfWriteProfileData(hiniTarget,
  329.                                          (PSZ)pcszTargetApp,
  330.                                          (PSZ)pcszKey,
  331.                                          pData,
  332.                                          ulSizeOfData))
  333.                     ulrc = PRFERR_WRITE;
  334.             }
  335.             else
  336.                 ulrc = PRFERR_READ;
  337.  
  338.             free(pData);
  339.         }
  340.         else
  341.             ulrc = ERROR_NOT_ENOUGH_MEMORY;
  342.     }
  343.     else
  344.         ulrc = PRFERR_DATASIZE;
  345.  
  346.     return (ulrc);
  347. }
  348.  
  349. /*
  350.  *@@ prfhCopyApp:
  351.  *      this copies one key from the given profile and application
  352.  *      to another one.
  353.  *
  354.  *      You can use this function in several contexts:
  355.  *
  356.  *      -- copy one application within the same profile
  357.  *         (i.e. hiniSource == hiniTarget);
  358.  *         in this case, pszSourceApp must be != pszTargetApp;
  359.  *
  360.  *      -- copy an application from one profile to another
  361.  *         (i.e. hiniSource != hiniTarget);
  362.  *         in this case, pszSourceApp can be == pszTargetApp
  363.  *         (but can be different also).
  364.  *
  365.  *      WARNING: This does _not_ check for whether the target
  366.  *      application exists already. This has two consequences:
  367.  *
  368.  *      --  existing data will be overwritten without warning;
  369.  *
  370.  *      --  if the existing target application has keys that are
  371.  *          not in the source application, they are not deleted.
  372.  *          As a result, you might end up with more keys than
  373.  *          in the source application.
  374.  *
  375.  *      So you should delete the target application before
  376.  *      calling this function, like this:
  377.  *
  378.  +          PrfWriteProfileString(hiniTarget, pszTargetApp, NULL, NULL);
  379.  *
  380.  *      You must specify all parameters. You cannot specify pszApp
  381.  *      as NULL to have a whole profile copied. Use prfhCopyProfile
  382.  *      for that.
  383.  *      No check is made for this.
  384.  *
  385.  *      Returns:
  386.  *
  387.  *      --  0: no error
  388.  *
  389.  *      --  PRFERR_KEYSLIST: couldn't query keys for pszSourceApp
  390.  *
  391.  *      --  PRFERR_DATASIZE: couldn't query data size for key
  392.  *
  393.  *      --  PRFERR_MEMORY: couldn't allocate memory
  394.  *
  395.  *      --  PRFERR_READ: couldn't read data from source (PrfQueryProfileData error)
  396.  *
  397.  *      --  PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
  398.  *
  399.  *@@added V0.9.0 [umoeller]
  400.  */
  401.  
  402. APIRET prfhCopyApp(HINI hiniSource,   // in: source profile (can be HINI_USER or HINI_SYSTEM)
  403.                    const char *pcszSourceApp,  // in: source application
  404.                    HINI hiniTarget,   // in: target profile (can be HINI_USER or HINI_SYSTEM)
  405.                    const char *pcszTargetApp,  // in: name of pszSourceApp in hiniTarget
  406.                    PSZ pszErrorKey)   // out: failing key in case of error; ptr can be NULL
  407. {
  408.     APIRET  arc = NO_ERROR;
  409.     PSZ     pszKeysList = NULL;
  410.  
  411.     if (pszErrorKey)
  412.         *pszErrorKey = 0;
  413.  
  414.     if (!(arc = prfhQueryKeysForApp(hiniSource,
  415.                                     (PSZ)pcszSourceApp,
  416.                                     &pszKeysList)))
  417.     {
  418.         PSZ pKey2 = pszKeysList;
  419.  
  420.         while (*pKey2 != 0)
  421.         {
  422.             // copy this key
  423.             arc = prfhCopyKey(hiniSource,
  424.                               pcszSourceApp,
  425.                               pKey2,
  426.                               hiniTarget,
  427.                               pcszTargetApp);
  428.             if (arc)
  429.             {
  430.                 // error: copy failing key to buffer
  431.                 if (pszErrorKey)
  432.                     strcpy(pszErrorKey, pKey2);
  433.                 break;
  434.             }
  435.             pKey2 += strlen(pKey2)+1;
  436.         } // end while (*pKey2 != 0)
  437.  
  438.         free (pszKeysList);
  439.     }
  440.  
  441.     return arc;
  442. }
  443.  
  444. /*
  445.  *@@ prfhRenameKey:
  446.  *      renames a key in an INI file.
  447.  *
  448.  *      Since there's no such thing as a PrfRename,
  449.  *      what we do here is load the old data, write
  450.  *      it under a new key, and delete the old data.
  451.  *
  452.  *      Returns:
  453.  *
  454.  *      --  0: no error
  455.  *
  456.  *      --  PRFERR_INVALID_KEY: pcszApp or pcszOldKey do not exist.
  457.  *
  458.  *      --  PRFERR_KEY_EXISTS: pcszNewApp/pcszNewKey is already occupied.
  459.  *
  460.  *      --  PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
  461.  *
  462.  *@@added V0.9.9 (2001-02-06) [umoeller]
  463.  */
  464.  
  465. ULONG prfhRenameKey(HINI hini,
  466.                     const char *pcszOldApp,
  467.                     const char *pcszOldKey, // in: key to rename
  468.                     const char *pcszNewApp, // in: new app (if NULL, pcszOldApp is used)
  469.                     const char *pcszNewKey) // in: new name for pcszOldKey
  470. {
  471.     ULONG ulrc = 0;
  472.  
  473.     ULONG   cbData = 0;
  474.     PSZ pszData = prfhQueryProfileData(hini,
  475.                                        pcszOldApp,
  476.                                        pcszOldKey,
  477.                                        &cbData);
  478.     if (!pszData)
  479.         // not found:
  480.         ulrc = PRFERR_INVALID_KEY;
  481.     else
  482.     {
  483.         ULONG   cb;
  484.  
  485.         if (!pcszNewApp)
  486.             // is NULL:
  487.             pcszNewApp = pcszOldApp;
  488.  
  489.         // make sure target doesn't exist
  490.         if (    (PrfQueryProfileSize(hini,
  491.                                      (PSZ)pcszNewApp,
  492.                                      (PSZ)pcszNewKey,
  493.                                      &cb))
  494.              && (cb)
  495.            )
  496.             ulrc = PRFERR_KEY_EXISTS;
  497.         else
  498.         {
  499.             if (!PrfWriteProfileData(hini,
  500.                                      (PSZ)pcszNewApp,
  501.                                      (PSZ)pcszNewKey,
  502.                                      pszData,
  503.                                      cbData))
  504.                 ulrc = PRFERR_WRITE;
  505.             else
  506.             {
  507.                 // success writing:
  508.                 // delete old
  509.                 PrfWriteProfileData(hini,
  510.                                     (PSZ)pcszOldApp,
  511.                                     (PSZ)pcszOldKey,
  512.                                     NULL,
  513.                                     0);
  514.             }
  515.         }
  516.  
  517.         free(pszData);
  518.     }
  519.  
  520.     return (ulrc);
  521. }
  522.  
  523. /*
  524.  *@@ prfhSetUserProfile:
  525.  *      calls PrfReset to change the current user
  526.  *      profile (normally OS2.INI) to the specified
  527.  *      INI file.
  528.  *
  529.  *@@added V0.9.4 (2000-07-19) [umoeller]
  530.  *@@changed V0.9.19 (2002-04-02) [umoeller]: now returning APIRET
  531.  */
  532.  
  533. APIRET prfhSetUserProfile(HAB hab,
  534.                           const char *pcszUserProfile)     // in: new user profile (.INI)
  535. {
  536.     APIRET arc = NO_ERROR;
  537.  
  538.     // find out current profile names
  539.     PRFPROFILE Profiles;
  540.     Profiles.cchUserName = Profiles.cchSysName = 0;
  541.     // first query their file name lengths
  542.     if (PrfQueryProfile(hab, &Profiles))
  543.     {
  544.         // allocate memory for filenames
  545.         Profiles.pszUserName  = (PSZ)malloc(Profiles.cchUserName);
  546.         Profiles.pszSysName  = (PSZ)malloc(Profiles.cchSysName);
  547.  
  548.         if ((Profiles.pszSysName) && (Profiles.pszUserName))
  549.         {
  550.             // get filenames
  551.             if (PrfQueryProfile(hab, &Profiles))
  552.             {
  553.                 // _Pmpf(("Old user profile: %s", Profiles.pszUserName));
  554.  
  555.                 // change INIs
  556.                 free(Profiles.pszUserName);
  557.                 Profiles.pszUserName = (PSZ)pcszUserProfile;
  558.                 Profiles.cchUserName = strlen(pcszUserProfile) + 1;
  559.                 if (!PrfReset(hab, &Profiles))
  560.                     arc = PRFERR_RESET;
  561.                 free(Profiles.pszSysName);
  562.             }
  563.             else
  564.                 arc = PRFERR_QUERY;
  565.         }
  566.         else
  567.             arc = PRFERR_QUERY;
  568.     }
  569.     else
  570.         arc = PRFERR_QUERY;
  571.  
  572.     return arc;
  573. }
  574.  
  575.  
  576.