util.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 10k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * util.c - Utility routines.
  3.  */
  4. /* Headers
  5.  **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. /****************************** Public Functions *****************************/
  9. #ifdef WINNT
  10. //
  11. //  These are some helper functions for handling Unicode strings
  12. //
  13. /*----------------------------------------------------------
  14. Purpose: This function converts a wide-char string to a multi-byte
  15.          string.
  16.          If pszBuf is non-NULL and the converted string can fit in 
  17.          pszBuf, then *ppszAnsi will point to the given buffer.
  18.          Otherwise, this function will allocate a buffer that can
  19.          hold the converted string.
  20.          If pszWide is NULL, then *ppszAnsi will be freed.  Note
  21.          that pszBuf must be the same pointer between the call
  22.          that converted the string and the call that frees the 
  23.          string.
  24. Returns: TRUE 
  25.          FALSE (if out of memory)
  26. Cond:    --
  27. */
  28. PRIVATE_CODE 
  29. BOOL 
  30. AnsiFromUnicode(
  31.     LPSTR * ppszAnsi,
  32.     LPCWSTR pwszWide,        // NULL to clean up
  33.     LPSTR pszBuf,
  34.     int cchBuf)
  35.     {
  36.     BOOL bRet;
  37.     // Convert the string?
  38.     if (pwszWide)
  39.         {
  40.         // Yes; determine the converted string length
  41.         int cch;
  42.         LPSTR psz;
  43.         cch = WideCharToMultiByte(CP_ACP, 0, pwszWide, -1, NULL, 0, NULL, NULL);
  44.         // String too big, or is there no buffer?
  45.         if (cch > cchBuf || NULL == pszBuf)
  46.             {
  47.             // Yes; allocate space
  48.             cchBuf = cch + 1;
  49.             psz = (LPSTR)LocalAlloc(LPTR, CbFromCchA(cchBuf));
  50.             }
  51.         else
  52.             {
  53.             // No; use the provided buffer
  54.             ASSERT(pszBuf);
  55.             psz = pszBuf;
  56.             }
  57.         if (psz)
  58.             {
  59.             // Convert the string
  60.             cch = WideCharToMultiByte(CP_ACP, 0, pwszWide, -1, psz, cchBuf, NULL, NULL);
  61.             bRet = (0 < cch);
  62.             }
  63.         else
  64.             {
  65.             bRet = FALSE;
  66.             }
  67.         *ppszAnsi = psz;
  68.         }
  69.     else
  70.         {
  71.         // No; was this buffer allocated?
  72.         if (*ppszAnsi && pszBuf != *ppszAnsi)
  73.             {
  74.             // Yes; clean up
  75.             LocalFree((HLOCAL)*ppszAnsi);
  76.             *ppszAnsi = NULL;
  77.             }
  78.         bRet = TRUE;
  79.         }
  80.     return bRet;
  81.     }
  82. /*----------------------------------------------------------
  83. Purpose: Wide-char wrapper for StrToIntExA.
  84. Returns: see StrToIntExA
  85. Cond:    --
  86. */
  87. PUBLIC_CODE
  88. BOOL 
  89. StrToIntExW(
  90.     LPCWSTR   pwszString,
  91.     DWORD     dwFlags,          // STIF_ bitfield 
  92.     int FAR * piRet)
  93.     {
  94.     CHAR szBuf[MAX_BUF];
  95.     LPSTR pszString;
  96.     BOOL bRet = AnsiFromUnicode(&pszString, pwszString, szBuf, SIZECHARS(szBuf));
  97.     if (bRet)
  98.         {
  99.         bRet = StrToIntExA(pszString, dwFlags, piRet);
  100.         AnsiFromUnicode(&pszString, NULL, szBuf, 0);
  101.         }
  102.     return bRet;
  103.     }
  104. /*----------------------------------------------------------
  105. Purpose: Returns an integer value specifying the length of
  106.          the substring in psz that consists entirely of 
  107.          characters in pszSet.  If psz begins with a character
  108.          not in pszSet, then this function returns 0.
  109.          This is a DBCS-safe version of the CRT strspn().  
  110. Returns: see above
  111. Cond:    --
  112. */
  113. PUBLIC_CODE
  114. int
  115. StrSpnW(
  116.     LPCWSTR psz,
  117.     LPCWSTR pszSet)
  118.     {
  119.     LPCWSTR pszT;
  120.     LPCWSTR pszSetT;
  121.     ASSERT(psz);
  122.     ASSERT(pszSet);
  123.     // Go thru the string to be inspected 
  124.     for (pszT = psz; *pszT; pszT++)
  125.         {
  126.         // Go thru the char set
  127.         for (pszSetT = pszSet; *pszSetT != *pszT; pszSetT++)
  128.             {
  129.             if (0 == *pszSetT)
  130.                 {
  131.                 // Reached end of char set without finding a match
  132.                 return (int)(pszT - psz);
  133.                 }
  134.             }
  135.         }
  136.     return (int)(pszT - psz);
  137.     }
  138. /*----------------------------------------------------------
  139. Purpose: Returns a pointer to the first occurrence of a character
  140.          in psz that belongs to the set of characters in pszSet.
  141.          The search does not include the null terminator.
  142. Returns: see above
  143. Cond:    --
  144. */
  145. PUBLIC_CODE
  146. LPWSTR
  147. StrPBrkW(
  148.     IN LPCWSTR psz,
  149.     IN LPCWSTR pszSet)
  150.     {
  151.     LPCWSTR pszSetT;
  152.     ASSERT(psz);
  153.     ASSERT(pszSet);
  154.     // Go thru the string to be inspected 
  155.     while (*psz)
  156.         {
  157.         // Go thru the char set
  158.         for (pszSetT = pszSet; *pszSetT; pszSetT++)
  159.             {
  160.             if (*psz == *pszSetT)
  161.                 {
  162.                 // Found first character that matches
  163.                 return (LPWSTR)psz;     // Const -> non-const
  164.                 }
  165.             }
  166.         psz++;
  167.         }
  168.     return NULL;
  169.     }
  170. #endif // WINNT
  171. /*----------------------------------------------------------
  172. Purpose: Special verion of atoi.  Supports hexadecimal too.
  173.          If this function returns FALSE, *piRet is set to 0.
  174. Returns: TRUE if the string is a number, or contains a partial number
  175.          FALSE if the string is not a number
  176. Cond:    --
  177. */
  178. PUBLIC_CODE
  179. BOOL 
  180. StrToIntExA(
  181.     LPCSTR    pszString,
  182.     DWORD     dwFlags,          // STIF_ bitfield 
  183.     int FAR * piRet)
  184.     {
  185.     #define IS_DIGIT(ch)    InRange(ch, '0', '9')
  186.     BOOL bRet;
  187.     int n;
  188.     BOOL bNeg = FALSE;
  189.     LPCSTR psz;
  190.     LPCSTR pszAdj;
  191.     // Skip leading whitespace
  192.     //
  193.     for (psz = pszString; *psz == ' ' || *psz == 'n' || *psz == 't'; psz = CharNextA(psz))
  194.         ;
  195.       
  196.     // Determine possible explicit signage
  197.     //  
  198.     if (*psz == '+' || *psz == '-')
  199.         {
  200.         bNeg = (*psz == '+') ? FALSE : TRUE;
  201.         psz++;
  202.         }
  203.     // Or is this hexadecimal?
  204.     //
  205.     pszAdj = CharNextA(psz);
  206.     if ((STIF_SUPPORT_HEX & dwFlags) &&
  207.         *psz == '0' && (*pszAdj == 'x' || *pszAdj == 'X'))
  208.         {
  209.         // Yes
  210.         // (Never allow negative sign with hexadecimal numbers)
  211.         bNeg = FALSE;   
  212.         psz = CharNextA(pszAdj);
  213.         pszAdj = psz;
  214.         // Do the conversion
  215.         //
  216.         for (n = 0; ; psz = CharNextA(psz))
  217.             {
  218.             if (IS_DIGIT(*psz))
  219.                 n = 0x10 * n + *psz - '0';
  220.             else
  221.                 {
  222.                 CHAR ch = *psz;
  223.                 int n2;
  224.                 if (ch >= 'a')
  225.                     ch -= 'a' - 'A';
  226.                 n2 = ch - 'A' + 0xA;
  227.                 if (n2 >= 0xA && n2 <= 0xF)
  228.                     n = 0x10 * n + n2;
  229.                 else
  230.                     break;
  231.                 }
  232.             }
  233.         // Return TRUE if there was at least one digit
  234.         bRet = (psz != pszAdj);
  235.         }
  236.     else
  237.         {
  238.         // No
  239.         pszAdj = psz;
  240.         // Do the conversion
  241.         for (n = 0; IS_DIGIT(*psz); psz = CharNextA(psz))
  242.             n = 10 * n + *psz - '0';
  243.         // Return TRUE if there was at least one digit
  244.         bRet = (psz != pszAdj);
  245.         }
  246.     *piRet = bNeg ? -n : n;
  247.     return bRet;
  248.     }    
  249. /*----------------------------------------------------------
  250. Purpose: Returns an integer value specifying the length of
  251.          the substring in psz that consists entirely of 
  252.          characters in pszSet.  If psz begins with a character
  253.          not in pszSet, then this function returns 0.
  254.          This is a DBCS-safe version of the CRT strspn().  
  255. Returns: see above
  256. Cond:    --
  257. */
  258. PUBLIC_CODE
  259. int
  260. StrSpnA(
  261.     LPCSTR psz,
  262.     LPCSTR pszSet)
  263.     {
  264.     LPCSTR pszT;
  265.     LPCSTR pszSetT;
  266.     // Go thru the string to be inspected 
  267.     for (pszT = psz; *pszT; pszT = CharNextA(pszT))
  268.         {
  269.         // Go thru the char set
  270.         for (pszSetT = pszSet; *pszSetT; pszSetT = CharNextA(pszSetT))
  271.             {
  272.             if (*pszSetT == *pszT)
  273.                 {
  274.                 if ( !IsDBCSLeadByte(*pszSetT) )
  275.                     {
  276.                     break;      // Chars match
  277.                     }
  278.                 else if (pszSetT[1] == pszT[1])
  279.                     {
  280.                     break;      // Chars match
  281.                     }
  282.                 }
  283.             }
  284.         // End of char set?
  285.         if (0 == *pszSetT)
  286.             {
  287.             break;      // Yes, no match on this inspected char
  288.             }
  289.         }
  290.     return (int)(pszT - psz);
  291.     }
  292. /*----------------------------------------------------------
  293. Purpose: Returns a pointer to the first occurrence of a character
  294.          in psz that belongs to the set of characters in pszSet.
  295.          The search does not include the null terminator.
  296.          If psz contains no characters that are in the set of
  297.          characters in pszSet, this function returns NULL.
  298.          This function is DBCS-safe.
  299. Returns: see above
  300. Cond:    --
  301. */
  302. PUBLIC_CODE
  303. LPSTR
  304. StrPBrkA(
  305.     LPCSTR psz,
  306.     LPCSTR pszSet)
  307.     {
  308.     LPCSTR pszSetT;
  309.     ASSERT(psz);
  310.     ASSERT(pszSet);
  311.     while (*psz)
  312.         {
  313.         for (pszSetT = pszSet; *pszSetT; pszSetT = CharNextA(pszSetT))
  314.             {
  315.             if (*psz == *pszSetT)
  316.                 {
  317.                 // Found first character that matches
  318.                 return (LPSTR)psz;      // Const -> non-const
  319.                 }
  320.             }
  321.         psz = CharNextA(psz);
  322.         }
  323.     return NULL;
  324.     }
  325. PUBLIC_CODE BOOL IsPathDirectory(PCSTR pcszPath)
  326. {
  327.    DWORD dwAttr;
  328.    ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  329.    dwAttr = GetFileAttributes(pcszPath);
  330.    return(dwAttr != -1 &&
  331.           IS_FLAG_SET(dwAttr, FILE_ATTRIBUTE_DIRECTORY));
  332. }
  333. PUBLIC_CODE BOOL KeyExists(HKEY hkeyRoot, PCSTR pcszSubKey)
  334. {
  335.    BOOL bExists;
  336.    HKEY hkey;
  337.    ASSERT(IS_VALID_HANDLE(hkeyRoot, KEY));
  338.    ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR));
  339.    bExists = (RegOpenKey(hkeyRoot, pcszSubKey, &hkey) == ERROR_SUCCESS);
  340.    if (bExists)
  341.       EVAL(RegCloseKey(hkey) == ERROR_SUCCESS);
  342.    return(bExists);
  343. }
  344. #ifdef DEBUG
  345. PUBLIC_CODE BOOL IsStringContained(PCSTR pcszBigger, PCSTR pcszSuffix)
  346. {
  347.    ASSERT(IS_VALID_STRING_PTR(pcszBigger, CSTR));
  348.    ASSERT(IS_VALID_STRING_PTR(pcszSuffix, CSTR));
  349.    return(pcszSuffix >= pcszBigger &&
  350.           pcszSuffix <= pcszBigger + lstrlen(pcszBigger));
  351. }
  352. #endif