Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
6.1 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. CStringPI.cpp
  5. Abstract:
  6. Win32 API wrappers for CString
  7. Created:
  8. 02/27/2001 robkenny Created
  9. 08/14/2001 robkenny Moved code inside the ShimLib namespace.
  10. --*/
  11. #include "ShimLib.h"
  12. #include "Shlobj.h"
  13. namespace ShimLib
  14. {
  15. /*====================================================================================*/
  16. /*++
  17. Read a registry value into this CString.
  18. REG_EXPAND_SZ is automatically expanded and the type is changed to REG_SZ
  19. If the type is not REG_SZ or REG_EXPAND_SZ, then csRegValue.GetLength()
  20. is the number of *bytes* in the string.
  21. This should, really, only be used to read REG_SZ/REG_EXPAND_SZ registry values.
  22. --*/
  23. LONG RegQueryValueExW(
  24. CString & csValue,
  25. HKEY hKeyRoot,
  26. const WCHAR * lpszKey,
  27. const WCHAR * lpszValue,
  28. LPDWORD lpType)
  29. {
  30. LONG success;
  31. HKEY hKey;
  32. success = RegOpenKeyW(hKeyRoot, lpszKey, &hKey);
  33. if (success == ERROR_SUCCESS)
  34. {
  35. DWORD dwSizeBytes;
  36. success = ::RegQueryValueExW(hKey, lpszValue, 0, lpType, NULL, &dwSizeBytes);
  37. if (success == ERROR_SUCCESS)
  38. {
  39. int nChars = dwSizeBytes / sizeof(WCHAR);
  40. nChars -= 1; // size included null
  41. WCHAR * lpszBuffer = csValue.GetBuffer(nChars);
  42. success = ::RegQueryValueExW(hKey, lpszValue, 0, lpType, (BYTE*)lpszBuffer, &dwSizeBytes);
  43. if (success == ERROR_SUCCESS)
  44. {
  45. csValue.ReleaseBuffer(nChars);
  46. if (*lpType == REG_EXPAND_SZ)
  47. {
  48. csValue.ExpandEnvironmentStringsW();
  49. *lpType = REG_SZ;
  50. }
  51. }
  52. else
  53. {
  54. csValue.ReleaseBuffer(0);
  55. }
  56. }
  57. ::RegCloseKey(hKey);
  58. }
  59. if (success != ERROR_SUCCESS)
  60. {
  61. csValue.Truncate(0);
  62. }
  63. return success;
  64. }
  65. /*====================================================================================*/
  66. BOOL SHGetSpecialFolderPathW(
  67. CString & csFolder,
  68. int nFolder,
  69. HWND hwndOwner
  70. )
  71. {
  72. // Force the size to MAX_PATH because there is no way to determine necessary buffer size.
  73. WCHAR * lpsz = csFolder.GetBuffer(MAX_PATH);
  74. BOOL bSuccess = ::SHGetSpecialFolderPathW(hwndOwner, lpsz, nFolder, FALSE);
  75. csFolder.ReleaseBuffer(-1); // Don't know the length of the resulting string
  76. return bSuccess;
  77. }
  78. /*====================================================================================*/
  79. CStringToken::CStringToken(const CString & csToken, const CString & csDelimit)
  80. {
  81. m_nPos = 0;
  82. m_csToken = csToken;
  83. m_csDelimit = csDelimit;
  84. }
  85. /*++
  86. Grab the next token
  87. --*/
  88. BOOL CStringToken::GetToken(CString & csNextToken, int & nPos) const
  89. {
  90. // Already reached the end of the string
  91. if (nPos > m_csToken.GetLength())
  92. {
  93. csNextToken.Truncate(0);
  94. return FALSE;
  95. }
  96. int nNextToken;
  97. // Skip past all the leading seperators
  98. nPos = m_csToken.FindOneNotOf(m_csDelimit, nPos);
  99. if (nPos < 0)
  100. {
  101. // Nothing but seperators
  102. csNextToken.Truncate(0);
  103. nPos = m_csToken.GetLength() + 1;
  104. return FALSE;
  105. }
  106. // Find the next seperator
  107. nNextToken = m_csToken.FindOneOf(m_csDelimit, nPos);
  108. if (nNextToken < 0)
  109. {
  110. // Did not find a seperator, return remaining string
  111. m_csToken.Mid(nPos, csNextToken);
  112. nPos = m_csToken.GetLength() + 1;
  113. return TRUE;
  114. }
  115. // Found a seperator, return the string
  116. m_csToken.Mid(nPos, nNextToken - nPos, csNextToken);
  117. nPos = nNextToken;
  118. return TRUE;
  119. }
  120. /*++
  121. Grab the next token
  122. --*/
  123. BOOL CStringToken::GetToken(CString & csNextToken)
  124. {
  125. return GetToken(csNextToken, m_nPos);
  126. }
  127. /*++
  128. Count the number of remaining tokens.
  129. --*/
  130. int CStringToken::GetCount() const
  131. {
  132. int nTokenCount = 0;
  133. int nNextToken = m_nPos;
  134. CString csTok;
  135. while (GetToken(csTok, nNextToken))
  136. {
  137. nTokenCount += 1;
  138. }
  139. return nTokenCount;
  140. }
  141. /*====================================================================================*/
  142. /*====================================================================================*/
  143. /*++
  144. A simple class to assist in command line parsing
  145. --*/
  146. CStringParser::CStringParser(const WCHAR * lpszCl, const WCHAR * lpszSeperators)
  147. {
  148. m_ncsArgList = 0;
  149. m_csArgList = NULL;
  150. if (!lpszCl || !*lpszCl)
  151. {
  152. return; // no command line == no tokens
  153. }
  154. CString csCl(lpszCl);
  155. CString csSeperator(lpszSeperators);
  156. if (csSeperator[0] == L' ')
  157. {
  158. // Special processing for blank seperated cl
  159. SplitWhite(csCl);
  160. }
  161. else
  162. {
  163. SplitSeperator(csCl, csSeperator);
  164. }
  165. }
  166. CStringParser::~CStringParser()
  167. {
  168. if (m_csArgList)
  169. {
  170. delete [] m_csArgList;
  171. }
  172. }
  173. /*++
  174. Split up the command line based on the seperators
  175. --*/
  176. void CStringParser::SplitSeperator(const CString & csCl, const CString & csSeperator)
  177. {
  178. CStringToken csParser(csCl, csSeperator);
  179. CString csTok;
  180. m_ncsArgList = csParser.GetCount();
  181. m_csArgList = new CString[m_ncsArgList];
  182. if (!m_csArgList)
  183. {
  184. CSTRING_THROW_EXCEPTION
  185. }
  186. // Break the command line into seperate tokens
  187. for (int i = 0; i < m_ncsArgList; ++i)
  188. {
  189. csParser.GetToken(m_csArgList[i]);
  190. }
  191. }
  192. /*++
  193. Split up the command line based on whitespace,
  194. this works exactly like the CMD's command line.
  195. --*/
  196. void CStringParser::SplitWhite(const CString & csCl)
  197. {
  198. LPWSTR * argv = _CommandLineToArgvW(csCl, &m_ncsArgList);
  199. if (!argv)
  200. {
  201. CSTRING_THROW_EXCEPTION
  202. }
  203. m_csArgList = new CString[m_ncsArgList];
  204. if (!m_csArgList)
  205. {
  206. CSTRING_THROW_EXCEPTION
  207. }
  208. for (int i = 0; i < m_ncsArgList; ++i)
  209. {
  210. m_csArgList[i] = argv[i];
  211. }
  212. LocalFree(argv);
  213. }
  214. /*====================================================================================*/
  215. /*====================================================================================*/
  216. }; // end of namespace ShimLib