home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / stock / ea.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  8.0 KB  |  309 lines

  1. /***    ea.c - layer for EA support
  2.  *
  3.  *    Author:
  4.  *        Benjamin W. Slivka
  5.  *        (c) 1990
  6.  *        Microsoft Corporation
  7.  *
  8.  *    History:
  9.  *        08-Feb-1990 bens    Initial version (Subset from EA.EXE sources)
  10.  *        02-May-1990 bens    Added SetEAValue (copied from ea.exe)
  11.  *        01-Jun-1990 bens    Support binary EAs
  12.  */
  13.  
  14. #define INCL_DOSERRORS
  15. #define INCL_DOSFILEMGR
  16. #define INCL_NOPM
  17.  
  18. #include <os2.h>
  19.  
  20. #include <ctype.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <memory.h>
  25.  
  26. #include "ea.h"
  27. #include "mem.h"
  28.  
  29.  
  30. #ifdef CHECKASSERTS
  31. #define dbg(a)    a
  32. #else
  33. #define dbg(a)
  34. #endif
  35.  
  36. // Buffer sizes for EA API calls
  37. #define CB_GEAL       400        // Enough for one GEA in list
  38. #define CB_FEAL      2000        // Enough for large file list
  39.  
  40.  
  41. char *        TranslateValue(char *pbValue,USHORT cbValue,USHORT *pcbValue);
  42.  
  43.  
  44. /***    EAQueryValue - Get text EA value from file
  45.  *
  46.  *    Entry
  47.  *        pszFile - File path
  48.  *        pszName - EA name
  49.  *        pcbValue - USHORT to receive value length
  50.  *
  51.  *    Exit-Success
  52.  *        returns non-zero pointer to value; Caller must free this!
  53.  *        If value is ASCII
  54.  *            *pcbValue == 0;
  55.  *        If value is BINARY
  56.  *            *pcbValue == length of value;
  57.  *
  58.  *    Exit-Failure
  59.  *        returns NULL
  60.  */
  61. char *EAQueryValue(char *pszFile,char *pszName,USHORT *pcbValue)
  62. {
  63.     USHORT    cb;
  64.     EAOP    eaop;
  65.     FEA *    pfea;
  66.     FEA *    pfeaEnd;
  67.     FEALIST *    pFEAList;
  68.     GEA *    pgea;
  69.     GEALIST *    pGEAList;
  70.     char *    psz;
  71.     char *    pszValue;
  72.     USHORT    rc;
  73.  
  74.     //
  75.     // Alloc GEAList and FEAList
  76.     //
  77.     pGEAList = MemAlloc(CB_GEAL);
  78.     if (pGEAList == NULL) {
  79.     return NULL;
  80.     }
  81.  
  82.     pFEAList = MemAlloc(CB_FEAL);
  83.     if (pFEAList == NULL) {
  84.     MemFree(pGEAList);
  85.     return NULL;
  86.     }
  87.  
  88.     // Build GEA List with one GEA
  89.  
  90.     pgea = pGEAList->list;        // Point at first GEA
  91.     cb = strlen(pszName);
  92.     pgea->cbName = (UCHAR)cb;        // Set length
  93.     memcpy(pgea->szName,pszName,cb+1);    // Copy name and NUL
  94.     pgea = (GEA *)((char *)pgea + cb + sizeof(GEA));
  95.     pGEAList->cbList = (char *)pgea - (char *)pGEAList; // Set buffer size
  96.  
  97.     // Get attribute value
  98.  
  99.     pFEAList->cbList = CB_FEAL;     // Set size of FEA list
  100.     eaop.fpGEAList = pGEAList;
  101.     eaop.fpFEAList = pFEAList;
  102.  
  103.     rc = DosQPathInfo(pszFile,        // File path
  104.               FIL_QUERYEASFROMLIST, // info level
  105.               (PBYTE)&eaop,    // EAOP structure
  106.               sizeof(eaop),    // Size of EAOP
  107.               0L);        // Reserved
  108.     pfea = (FEA *)pFEAList->list;    // Point at FEA
  109.  
  110.     //    NOTE: DosQPathInfo only fails if there is an inconsistency in
  111.     //          one of its parameters.  It DOES NOT fail if the EA is
  112.     //          not present.  Rather, on a file system that does not
  113.     //          support EAs, it appears to return pFEAList->cbList ==
  114.     //          sizeof(pFEAList->cbList), indicating no FEAs are present.
  115.     //          If the file system *does* support EAs, but the particular
  116.     //          EA is not present, pFEA->cbValue == 0.
  117.  
  118.     if ((rc == 0) &&            // Call succeeded,...
  119.     ((pFEAList->cbList) > sizeof(pFEAList->cbList)) && // FEA is there,...
  120.     (pfea->cbValue > 0)) {        // and file has EA value!
  121.     // Parse EA value
  122.     cb = pfea->cbName;
  123.     psz = (char *)pfea + sizeof(FEA); // Point at name
  124.     pszValue = psz + cb + 1;    // Point at value
  125.     psz = TranslateValue(pszValue,pfea->cbValue,pcbValue);
  126.     }
  127.     else
  128.        psz = NULL;            // EA not present, or too big
  129.  
  130.     MemFree(pFEAList);
  131.     MemFree(pGEAList);
  132.     return psz;
  133. }
  134.  
  135.  
  136. /***    TranslateValue - produce printable representation of EA value
  137.  *
  138.  *    Entry
  139.  *        pbValue  - Value buffer
  140.  *        cbValue  - Length of value buffer
  141.  *        pcbValue - USHORT to receive actual value length
  142.  *
  143.  *    Exit-Success
  144.  *        Returns non-zero pointer to value; caller MUST free!
  145.  *        If value is ASCII
  146.  *            *pcbValue == 0;
  147.  *        If value is BINARY
  148.  *            *pcbValue == length of value;
  149.  *
  150.  *    Exit-Failure
  151.  *        Returns NULL
  152.  *
  153.  *
  154.  *  EAT_MVMT - Multi-value, Multi-type
  155.  *
  156.  *    +------+----------+-------+------+--------+-------+---+---+---+---+
  157.  *    | Type | Codepage | Count | Type | Length | Value |...| T | L | V |
  158.  *    +------+----------+-------+------+--------+-------+---+---+---+---+
  159.  *       us        us         us      us      us       ?
  160.  *    \________________________/ \_____________________/     \_________/
  161.  *       MVMT header              Value 1         Value N
  162.  *
  163.  */
  164. char * TranslateValue(char *pbValue,USHORT cbValue,USHORT *pcbValue)
  165. {
  166.     USHORT cb=cbValue;
  167.     USHORT codePage;
  168.     USHORT cValue;
  169.     char * pbDst;
  170.     char * pbSrc;
  171.     char * pszNew;
  172.     USHORT type;
  173.  
  174.     // Parse MVMT header, if present
  175.  
  176.     pbSrc = pbValue;
  177.  
  178.     type = *(USHORT *)pbSrc;        // Get EA value type
  179.     if (type == EAT_MVMT) {
  180.     pbSrc += sizeof(USHORT);    // Skip type
  181.     codePage = *((USHORT*)pbSrc)++; // Get code page
  182.     cValue = *((USHORT*)pbSrc)++;    // Get count of values
  183.     if (cValue != 1)        // Not exactly one value
  184.         return NULL;        //  Fail
  185.     type = *(USHORT *)pbSrc;    // Get EA value type
  186.     }
  187.  
  188.  
  189.     // Parse value
  190.  
  191.     if ( (type == EAT_ASCII) || (type == EAT_BINARY) ) {
  192.     pbSrc += sizeof(USHORT);    // Skip type
  193.     cb = *((USHORT *)pbSrc)++;    // Get data length
  194.  
  195.     // Allocate buffer for data
  196.  
  197.     pszNew = MemAlloc(cb+1);    // Leave room for NUL, in ASCII case
  198.     if (pszNew == NULL)
  199.         return NULL;
  200.     pbDst = pszNew;
  201.  
  202.     // Copy data
  203.  
  204.     memcpy(pbDst,pbSrc,cb);     // Copy value
  205.     pbDst += cb;            // Advance destination pointer
  206.  
  207.     if (type == EAT_ASCII) {
  208.         *pbDst++ = '\0';        // Terminate ASCIIZ string
  209.         *pcbValue = 0;        // Indicate value is ASCIIZ
  210.     }
  211.     else
  212.         *pcbValue = cb;        // Indicate value is binary
  213.     return pszNew;            // Return value
  214.     }
  215.     else
  216.     return NULL;            //  Fail
  217. }
  218.  
  219.  
  220. /***    EASetValue - Create/Change/Delete an EA
  221.  *
  222.  *    Entry
  223.  *        pszFile  - file path
  224.  *        pszName  - EA name
  225.  *        cbValue  - EA length; 0 => pszValue is ASCIIZ
  226.  *        pszValue - EA value; NULL to delete EA
  227.  *
  228.  *    Exit-Success
  229.  *        returns TRUE
  230.  *
  231.  *    Exit-Failure
  232.  *        returns FALSE
  233.  *
  234.  */
  235. BOOL EASetValue(char *pszFile,char *pszName,USHORT cbValue,char *pszValue)
  236. {
  237.     USHORT    cbName;
  238.     EAOP    eaop;
  239.     FEA *    pfea;
  240.     FEALIST *    pFEAList;
  241.     char *    psz;
  242.     USHORT    rc;
  243.     USHORT    type;
  244.  
  245.     // Determine operation
  246.  
  247.     if (pszValue == NULL) {        // Delete this EA
  248.     type = EAT_ASCII;
  249.     cbValue = 0;
  250.     }
  251.     else if (cbValue == 0) {        // Create/Change value
  252.     type = EAT_ASCII;
  253.     cbValue = strlen(pszValue);    // Compute length (do not count NUL!)
  254.     }
  255.     else {                // Create/Change Binary value
  256.     type = EAT_BINARY;
  257.     }
  258.  
  259.     //
  260.     // Alloc FEA List
  261.     //
  262.     pFEAList = MemAlloc(CB_FEAL);
  263.     if (pFEAList == NULL)
  264.     return FALSE;
  265.  
  266.     cbName = strlen(pszName);
  267.  
  268.     //
  269.     // Build EA structure
  270.     //
  271.     pfea = (FEA *)pFEAList->list;    // Point at first FEA
  272.     pfea->fEA = 0;            // No flag settings
  273.     pfea->cbName = (UCHAR)cbName;    // Set name length
  274.     pfea->cbValue = cbValue;        // Set value length
  275.  
  276.     psz = (char *)pfea + sizeof(FEA);    // Point at location for name
  277.     memcpy(psz,pszName,cbName+1);    // Copy Name *and* NUL
  278.     psz += cbName+1;            // Point at location for value
  279.     if (cbValue > 0) {            // Edit/Create EA
  280.     *((USHORT *)psz)++ = EAT_MVMT;    // Set MVMT type (to record code page!)
  281.     *((USHORT *)psz)++ = NULL;    // Set codepage
  282.     *((USHORT *)psz)++ = 1;     // Only one TLV record
  283.     *((USHORT *)psz)++ = type;    // Set EA type
  284.     *((USHORT *)psz)++ = cbValue;    // Set ASCII length
  285.  
  286.     pfea->cbValue += 5*sizeof(USHORT); // MVMT header and type and length
  287.     memcpy(psz,pszValue,cbValue);    // Copy Value
  288.     }
  289.     pfea = (FEA *)(psz + cbValue);    // Point at byte after FEA
  290.  
  291.     //
  292.     // Set size of FEA List (only one FEA)
  293.     //
  294.  
  295.     pFEAList->cbList = (char *)pfea - (char *)pFEAList;
  296.  
  297.     eaop.fpGEAList = NULL;
  298.     eaop.fpFEAList = pFEAList;
  299.  
  300.     rc = DosSetPathInfo(pszFile,        // File path
  301.             FIL_QUERYEASIZE,    // Set EA
  302.             (PBYTE)&eaop,        // EAOP structure
  303.             sizeof(eaop),        // Size of EAOP
  304.             0,            // Options
  305.             0L);            // Reserved
  306.     MemFree(pFEAList);
  307.     return (rc == 0);
  308. }
  309.