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.

749 lines
26 KiB

  1. //=--------------------------------------------------------------------------=
  2. // WCUtil.H
  3. //=--------------------------------------------------------------------------=
  4. // Copyright (c) 1987-1998, Microsoft Corp.
  5. // All Rights Reserved
  6. // Information Contained Herein Is Proprietary and Confidential.
  7. //=--------------------------------------------------------------------------=
  8. //
  9. // Utitlity Routines for the WebClass Designer
  10. //
  11. #ifndef _WCUTIL_H_
  12. //=--------------------------------------------------------------------------=
  13. //
  14. // inline HRESULT WCU_ANSIFromWideStr(WCHAR * pwszWideStr, char **ppszAnsi)
  15. //
  16. // Converts null terminated WCHAR string to null terminated ANSI string.
  17. // Allocates ANSI string using new operator. If successful, caller must free
  18. // ANSI string with delete operator.
  19. //
  20. //=--------------------------------------------------------------------------=
  21. inline HRESULT WCU_ANSIFromWideStr(WCHAR *pwszWideStr, char **ppszAnsi)
  22. {
  23. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_ANSIFromWideStr"));
  24. HRESULT hr = S_OK;
  25. *ppszAnsi = NULL;
  26. int cchWideStr = (int)::wcslen(pwszWideStr);
  27. int cchConverted = 0;
  28. // get required buffer length
  29. int cchAnsi = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
  30. 0, // performance and mapping flags
  31. pwszWideStr, // address of wide-character string
  32. cchWideStr, // number of characters in string
  33. NULL, // address of buffer for new string
  34. 0, // size of buffer
  35. NULL, // address of default for unmappable characters
  36. NULL // address of flag set when default char. used
  37. );
  38. CSF_CHECK(0 != cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  39. // allocate a buffer for the ANSI string
  40. *ppszAnsi = new char [cchAnsi + 1];
  41. CSF_CHECK(NULL != *ppszAnsi, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  42. // now convert the string and copy it to the buffer
  43. cchConverted = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
  44. 0, // performance and mapping flags
  45. pwszWideStr, // address of wide-character string
  46. cchWideStr, // number of characters in string
  47. *ppszAnsi, // address of buffer for new string
  48. cchAnsi, // size of buffer
  49. NULL, // address of default for unmappable characters
  50. NULL // address of flag set when default char. used
  51. );
  52. CSF_CHECK(cchConverted == cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  53. // add terminating null byte
  54. *( (*ppszAnsi) + cchAnsi ) = '\0';
  55. CLEANUP:
  56. if (FAILED(hr))
  57. {
  58. if (NULL != *ppszAnsi)
  59. {
  60. delete [] *ppszAnsi;
  61. *ppszAnsi = NULL;
  62. }
  63. }
  64. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_ANSIFromWideStr hr = %08.8X"), hr);
  65. return hr;
  66. }
  67. //=--------------------------------------------------------------------------=
  68. //
  69. // inline HRESULT WCU_ANSIFromWideStr(WCHAR * pwszWideStr, char **ppszAnsi)
  70. //
  71. // Converts null terminated WCHAR string to null terminated ANSI string.
  72. // Allocates ANSI string using new operator. If successful, caller must free
  73. // ANSI string with delete operator.
  74. //
  75. //=--------------------------------------------------------------------------=
  76. inline HRESULT WCU_ANSIFromWideStrLen(WCHAR *pwszWideStr, int cchWideStr, char **ppszAnsi)
  77. {
  78. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_ANSIFromWideStr"));
  79. HRESULT hr = S_OK;
  80. *ppszAnsi = NULL;
  81. int cchConverted = 0;
  82. // get required buffer length
  83. int cchAnsi = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
  84. 0, // performance and mapping flags
  85. pwszWideStr, // address of wide-character string
  86. cchWideStr, // number of characters in string
  87. NULL, // address of buffer for new string
  88. 0, // size of buffer
  89. NULL, // address of default for unmappable characters
  90. NULL // address of flag set when default char. used
  91. );
  92. CSF_CHECK(0 != cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  93. // allocate a buffer for the ANSI string
  94. *ppszAnsi = new char [cchAnsi + 1];
  95. CSF_CHECK(NULL != *ppszAnsi, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  96. // now convert the string and copy it to the buffer
  97. cchConverted = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
  98. 0, // performance and mapping flags
  99. pwszWideStr, // address of wide-character string
  100. cchWideStr, // number of characters in string
  101. *ppszAnsi, // address of buffer for new string
  102. cchAnsi, // size of buffer
  103. NULL, // address of default for unmappable characters
  104. NULL // address of flag set when default char. used
  105. );
  106. CSF_CHECK(cchConverted == cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  107. // add terminating null byte
  108. *( (*ppszAnsi) + cchAnsi ) = '\0';
  109. CLEANUP:
  110. if (FAILED(hr))
  111. {
  112. if (NULL != *ppszAnsi)
  113. {
  114. delete [] *ppszAnsi;
  115. *ppszAnsi = NULL;
  116. }
  117. }
  118. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_ANSIFromWideStr hr = %08.8X"), hr);
  119. return hr;
  120. }
  121. //=--------------------------------------------------------------------------=
  122. //
  123. // inline HRESULT WCU_WideStrFromANSI(char *pszAnsi, WCHAR **ppwszWideStr))
  124. //
  125. // Converts null terminated ANSI string to a null terminated WCHAR string.
  126. // Allocates WCHAR string buffer using the new operator. If successful, caller
  127. // must free WCHAR string using the delete operator.
  128. //
  129. //=--------------------------------------------------------------------------=
  130. inline HRESULT WCU_WideStrFromANSI(char *pszAnsi, WCHAR **ppwszWideStr)
  131. {
  132. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_WideStrFromANSI"));
  133. HRESULT hr = S_OK;
  134. *ppwszWideStr = NULL;
  135. int cchANSI = ::strlen(pszAnsi);
  136. int cchConverted = 0;
  137. // get required buffer length
  138. int cchWideStr = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
  139. 0, // performance and mapping flags
  140. pszAnsi, // address of multibyte string
  141. cchANSI, // number of characters in string
  142. NULL, // address of buffer for new string
  143. 0 // size of buffer
  144. );
  145. CSF_CHECK(0 != cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  146. // allocate a buffer for the WCHAR *
  147. *ppwszWideStr = new WCHAR[cchWideStr + 1];
  148. CSF_CHECK(NULL != *ppwszWideStr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  149. // now convert the string and copy it to the buffer
  150. cchConverted = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
  151. 0, // performance and mapping flags
  152. pszAnsi, // address of multibyte string
  153. cchANSI, // number of characters in string
  154. *ppwszWideStr, // address of buffer for new string
  155. cchWideStr // size of buffer
  156. );
  157. CSF_CHECK(cchConverted == cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  158. // add terminating null character
  159. *( (*ppwszWideStr) + cchWideStr ) = L'\0';
  160. CLEANUP:
  161. if (FAILED(hr))
  162. {
  163. if (NULL != *ppwszWideStr)
  164. {
  165. delete [] *ppwszWideStr;
  166. *ppwszWideStr = NULL;
  167. }
  168. }
  169. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_WideStrFromANSI hr = %08.8X"), hr);
  170. return hr;
  171. }
  172. //=--------------------------------------------------------------------------=
  173. //
  174. // inline HRESULT WCU_WideStrFromANSIExtra(char *pszAnsi, WCHAR **ppwszWideStr))
  175. //
  176. // Converts null terminated ANSI string to a null terminated WCHAR string.
  177. // Allocates WCHAR string buffer using the new operator. If successful, caller
  178. // must free WCHAR string using the delete operator.
  179. //
  180. // User can also specify the number of extra bytes to add the returned buffer. The
  181. // actual size of the buffer is returned as well.
  182. //
  183. //=--------------------------------------------------------------------------=
  184. inline HRESULT WCU_WideStrFromANSIExtra
  185. (
  186. HANDLE hHeap,
  187. char *pszAnsi,
  188. int cchANSI,
  189. WCHAR **ppwszWideStr,
  190. DWORD cbExtra,
  191. DWORD* pcbBufferSize,
  192. DWORD* pcchConverted
  193. )
  194. {
  195. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_WideStrFromANSI"));
  196. HRESULT hr = S_OK;
  197. *ppwszWideStr = NULL;
  198. int cchConverted = 0;
  199. DWORD cbBufferSize = 0;
  200. // get required buffer length
  201. int cchWideStr = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
  202. 0, // performance and mapping flags
  203. pszAnsi, // address of multibyte string
  204. cchANSI, // number of characters in string
  205. NULL, // address of buffer for new string
  206. 0 // size of buffer
  207. );
  208. CSF_CHECK(0 != cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  209. cbBufferSize = (cchWideStr + 1 + cbExtra) * sizeof(WCHAR);
  210. // allocate a buffer for the WCHAR *
  211. *ppwszWideStr = (LPWSTR) HeapAlloc(hHeap, NULL, cbBufferSize);
  212. CSF_CHECK(NULL != *ppwszWideStr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  213. // now convert the string and copy it to the buffer
  214. cchConverted = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
  215. 0, // performance and mapping flags
  216. pszAnsi, // address of multibyte string
  217. cchANSI, // number of characters in string
  218. *ppwszWideStr, // address of buffer for new string
  219. cchWideStr // size of buffer
  220. );
  221. CSF_CHECK(cchConverted == cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  222. // add terminating null character
  223. *( (*ppwszWideStr) + cchWideStr ) = L'\0';
  224. *pcbBufferSize = cbBufferSize;
  225. *pcchConverted = cchConverted;
  226. CLEANUP:
  227. if (FAILED(hr))
  228. {
  229. if (NULL != *ppwszWideStr)
  230. {
  231. delete [] *ppwszWideStr;
  232. *ppwszWideStr = NULL;
  233. }
  234. }
  235. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_WideStrFromANSI hr = %08.8X"), hr);
  236. return hr;
  237. }
  238. //=--------------------------------------------------------------------------=
  239. //
  240. // inline HRESULT WCU_WideStrFromANSILen(char *pszAnsi, int nLen, WCHAR **ppwszWideStr))
  241. //
  242. // Converts length specifed ANSI string to a null terminated WCHAR string.
  243. // Allocates WCHAR string buffer using the new operator. If successful, caller
  244. // must free WCHAR string using the delete operator.
  245. //
  246. //=--------------------------------------------------------------------------=
  247. inline HRESULT WCU_WideStrFromANSILen(char *pszAnsi, int nLen, WCHAR **ppwszWideStr)
  248. {
  249. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_WideStrFromANSI"));
  250. HRESULT hr = S_OK;
  251. *ppwszWideStr = NULL;
  252. int cchConverted = 0;
  253. if(nLen == 0)
  254. {
  255. *ppwszWideStr = NULL;
  256. return S_OK;
  257. }
  258. // get required buffer length
  259. int cchWideStr = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
  260. 0, // performance and mapping flags
  261. pszAnsi, // address of multibyte string
  262. nLen, // number of characters in string
  263. NULL, // address of buffer for new string
  264. 0 // size of buffer
  265. );
  266. CSF_CHECK(0 != cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  267. // allocate a buffer for the WCHAR *
  268. *ppwszWideStr = new WCHAR[cchWideStr + 1];
  269. CSF_CHECK(NULL != *ppwszWideStr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  270. // now convert the string and copy it to the buffer
  271. cchConverted = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
  272. 0, // performance and mapping flags
  273. pszAnsi, // address of multibyte string
  274. nLen, // number of characters in string
  275. *ppwszWideStr, // address of buffer for new string
  276. cchWideStr // size of buffer
  277. );
  278. CSF_CHECK(cchConverted == cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  279. // add terminating null character
  280. *( (*ppwszWideStr) + cchWideStr ) = L'\0';
  281. CLEANUP:
  282. if (FAILED(hr))
  283. {
  284. if (NULL != *ppwszWideStr)
  285. {
  286. delete [] *ppwszWideStr;
  287. *ppwszWideStr = NULL;
  288. }
  289. }
  290. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_WideStrFromANSI hr = %08.8X"), hr);
  291. return hr;
  292. }
  293. //=--------------------------------------------------------------------------=
  294. //
  295. // inline HRESULT WCU_ANSIFromBSTR(BSTR bstr, char **ppszAnsi)
  296. //
  297. // Converts BSTR to null terminated ANSI string. Allocates ANSI string using
  298. // new operator. If successful, caller must free ANSI string with delete
  299. // operator.
  300. //
  301. //=--------------------------------------------------------------------------=
  302. inline HRESULT WCU_ANSIFromBSTR(BSTR bstr, char **ppszAnsi)
  303. {
  304. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_ANSIFromBSTR"));
  305. HRESULT hr = S_OK;
  306. *ppszAnsi = NULL;
  307. int cchBstr = (int)::SysStringLen(bstr);
  308. int cchConverted = 0;
  309. // get required buffer length
  310. int cchAnsi = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
  311. 0, // performance and mapping flags
  312. bstr, // address of wide-character string
  313. cchBstr, // number of characters in string
  314. NULL, // address of buffer for new string
  315. 0, // size of buffer
  316. NULL, // address of default for unmappable characters
  317. NULL // address of flag set when default char. used
  318. );
  319. CSF_CHECK(0 != cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  320. // allocate a buffer for the ANSI string
  321. *ppszAnsi = new char [cchAnsi + 1];
  322. CSF_CHECK(NULL != *ppszAnsi, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  323. // now convert the string and copy it to the buffer
  324. cchConverted = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
  325. 0, // performance and mapping flags
  326. bstr, // address of wide-character string
  327. cchBstr, // number of characters in string
  328. *ppszAnsi, // address of buffer for new string
  329. cchAnsi, // size of buffer
  330. NULL, // address of default for unmappable characters
  331. NULL // address of flag set when default char. used
  332. );
  333. CSF_CHECK(cchConverted == cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  334. // add terminating null byte
  335. *( (*ppszAnsi) + cchAnsi ) = '\0';
  336. CLEANUP:
  337. if (FAILED(hr))
  338. {
  339. if (NULL != *ppszAnsi)
  340. {
  341. delete [] *ppszAnsi;
  342. *ppszAnsi = NULL;
  343. }
  344. }
  345. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_ANSIFromBSTR hr = %08.8X"), hr);
  346. return hr;
  347. }
  348. //=--------------------------------------------------------------------------=
  349. //
  350. // inline HRESULT WCU_BSTRFromANSI(char *pszAnsi, BSTR *pbstr))
  351. //
  352. // Converts null terminated ANSI string to a null terminated BSTR. Allocates
  353. // BSTR. If successful, caller must free BSTR using ::SysFreeString().
  354. //
  355. //=--------------------------------------------------------------------------=
  356. inline HRESULT WCU_BSTRFromANSI(char *pszAnsi, BSTR *pbstr)
  357. {
  358. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_BSTRFromANSI"));
  359. HRESULT hr = S_OK;
  360. WCHAR *pwszWideStr = NULL;
  361. // convert to a wide string first
  362. hr = WCU_WideStrFromANSI(pszAnsi, &pwszWideStr);
  363. CSF_CHECK(SUCCEEDED(hr), hr, CSF_TRACE_INTERNAL_ERRORS);
  364. // allocate a BSTR and copy it
  365. *pbstr = ::SysAllocStringLen(pwszWideStr, ::wcslen(pwszWideStr));
  366. CSF_CHECK(NULL != *pbstr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  367. CLEANUP:
  368. if (NULL != pwszWideStr)
  369. {
  370. delete [] pwszWideStr;
  371. }
  372. if (FAILED(hr))
  373. {
  374. if (NULL != *pbstr)
  375. {
  376. ::SysFreeString(*pbstr);
  377. *pbstr = NULL;
  378. }
  379. }
  380. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_BSTRFromANSI hr = %08.8X"), hr);
  381. return hr;
  382. }
  383. //=--------------------------------------------------------------------------=
  384. //
  385. // inline HRESULT WCU_BSTRFromANSILen(char *pszAnsi, int nLen, BSTR *pbstr))
  386. //
  387. // Converts len specified ANSI string to a null terminated BSTR. Allocates
  388. // BSTR. If successful, caller must free BSTR using ::SysFreeString().
  389. //
  390. //=--------------------------------------------------------------------------=
  391. inline HRESULT WCU_BSTRFromANSILen(char *pszAnsi, int nLen, BSTR *pbstr)
  392. {
  393. CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_BSTRFromANSI"));
  394. HRESULT hr = S_OK;
  395. WCHAR *pwszWideStr = NULL;
  396. if(nLen == 0)
  397. {
  398. *pbstr = SysAllocString(L"\0");
  399. CSF_CHECK(*pbstr != NULL, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  400. return S_OK;
  401. }
  402. // convert to a wide string first
  403. hr = WCU_WideStrFromANSILen(pszAnsi, nLen, &pwszWideStr);
  404. CSF_CHECK(SUCCEEDED(hr), hr, CSF_TRACE_INTERNAL_ERRORS);
  405. // allocate a BSTR and copy it
  406. *pbstr = ::SysAllocStringLen(pwszWideStr, nLen);
  407. CSF_CHECK(NULL != *pbstr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  408. CLEANUP:
  409. if (NULL != pwszWideStr)
  410. {
  411. delete [] pwszWideStr;
  412. }
  413. if (FAILED(hr))
  414. {
  415. if (NULL != *pbstr)
  416. {
  417. ::SysFreeString(*pbstr);
  418. *pbstr = NULL;
  419. }
  420. }
  421. CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_BSTRFromANSI hr = %08.8X"), hr);
  422. return hr;
  423. }
  424. inline HRESULT GetIISVersion
  425. (
  426. DWORD* pdwMajor,
  427. DWORD* pdwMinor
  428. )
  429. {
  430. HRESULT hr = S_OK;
  431. TCHAR *pszRegIISParamsKey = { TEXT("SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters") };
  432. TCHAR *pszRegASPParamsKey = { TEXT("SYSTEM\\CurrentControlSet\\Services\\W3SVC\\ASP") };
  433. HKEY hKey = NULL;
  434. long lRet = 0;
  435. DWORD dwType = 0;
  436. DWORD cbSize = sizeof(DWORD);
  437. lRet = ::RegOpenKey(HKEY_LOCAL_MACHINE,
  438. pszRegIISParamsKey,
  439. &hKey);
  440. CSF_CHECK(lRet == ERROR_SUCCESS, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  441. // Now, we can get the size of the value...
  442. lRet = ::RegQueryValueEx(hKey, "MajorVersion", NULL, &dwType, (BYTE*) pdwMajor, &cbSize);
  443. CSF_CHECK(lRet == ERROR_SUCCESS, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  444. // Now, we can get the size of the value...
  445. lRet = ::RegQueryValueEx(hKey, "MinorVersion", NULL, &dwType, (BYTE*) pdwMinor, &cbSize);
  446. CSF_CHECK(lRet == ERROR_SUCCESS, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
  447. // Uggghh! IIS 3.0 never update the registry verison, so we need to check for
  448. // ASP if 1 or 2 was specified...
  449. if(*pdwMajor < 3)
  450. {
  451. ::RegCloseKey(hKey);
  452. lRet = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  453. pszRegASPParamsKey,
  454. 0,
  455. KEY_QUERY_VALUE,
  456. &hKey);
  457. if(lRet == ERROR_SUCCESS)
  458. {
  459. // We found the ASP key so this must be version 3.0...
  460. *pdwMajor = 3;
  461. *pdwMinor = 0;
  462. }
  463. }
  464. CLEANUP:
  465. if(hKey != NULL)
  466. ::RegCloseKey(hKey);
  467. return hr;
  468. }
  469. // TODO: Do we want this this way?
  470. // Maybe just substract 2? No We ain't dynamic casue
  471. // of the tlb anyhow.
  472. inline DWORD IISVersionToASPVersion(DWORD dwIIS)
  473. {
  474. DWORD dwASP = 0;
  475. if(dwIIS == 3)
  476. {
  477. dwASP = 1;
  478. }
  479. else if(dwIIS == 4)
  480. {
  481. dwASP = 2;
  482. }
  483. return dwASP;
  484. }
  485. // Listed from most to least
  486. static WCHAR g_wszMostUniqueCharset[] = {L"~`\\_/{}|[]^!@#$%*():;"};
  487. //----------------------------------------------------------------------------------------
  488. // PickMostUniqueChar
  489. //----------------------------------------------------------------------------------------
  490. // Selects the most unique char in the specified string. We use this to pick the most unique
  491. // char in the user supplied tag prefix. This optimizes searching for those tags
  492. //----------------------------------------------------------------------------------------
  493. inline HRESULT PickMostUniqueChar
  494. (
  495. LPWSTR pwszPrefix, // [in] String to find unique char in
  496. WORD* pwIndex // [out] Index of the most unique char
  497. )
  498. {
  499. LPWSTR pwszRet = NULL;
  500. ASSERT(wcslen(pwszPrefix) < 0xFFFF);
  501. // See if the string contains any of our unique chars
  502. //
  503. pwszRet = wcspbrk(pwszPrefix, g_wszMostUniqueCharset);
  504. if(pwszRet != NULL)
  505. {
  506. *pwIndex = (WORD)(pwszRet - pwszPrefix);
  507. }
  508. else
  509. {
  510. // If not, just use first char in the string
  511. //
  512. *pwIndex = 0;
  513. }
  514. return S_OK;
  515. }
  516. /***
  517. *wchar_t *wcsistr(string1, string2) - search for string2 in string1
  518. * (wide strings)
  519. *
  520. *Purpose:
  521. * finds the first occurrence of string2 in string1 (wide strings)
  522. *
  523. *Entry:
  524. * wchar_t *string1 - string to search in
  525. * wchar_t *string2 - string to search for
  526. *
  527. *Exit:
  528. * returns a pointer to the first occurrence of string2 in
  529. * string1, or NULL if string2 does not occur in string1
  530. *
  531. *Uses:
  532. *
  533. *Exceptions:
  534. *
  535. *******************************************************************************/
  536. //=--------------------------------------------------------------------------=
  537. //
  538. // wchar_t *WCU_wcsistr(string1, string2)
  539. //
  540. // Purpose:
  541. // Finds the first occurrence of string2 in string1 (wide strings.
  542. // Not case sensitive.
  543. // This is a direct copy of C runtime source code from VC5. The only
  544. // addition is the use of the Win32 API CharUpperBuffW() to do a locale
  545. // sensitive conversion of characters to upper case before comparing
  546. // them.
  547. //
  548. // Entry:
  549. // wchar_t *string1 - string to search in
  550. // wchar_t *string2 - string to search for
  551. //
  552. // Exit:
  553. // returns a pointer to the first occurrence of string2 in
  554. // string1, or NULL if string2 does not occur in string1
  555. //
  556. //=--------------------------------------------------------------------------=
  557. inline wchar_t * __cdecl WCU_wcsistr
  558. (
  559. const wchar_t * wcs1,
  560. const wchar_t * wcs2
  561. )
  562. {
  563. wchar_t *cp = (wchar_t *) wcs1;
  564. wchar_t *s1, *s2;
  565. wchar_t c1, c2;
  566. while (*cp)
  567. {
  568. s1 = cp;
  569. s2 = (wchar_t *) wcs2;
  570. // while there are characters left in both strings
  571. while ( *s1 && *s2 )
  572. {
  573. // if the characters are not equal
  574. if (*s1 - *s2)
  575. {
  576. // convert them to uppercase
  577. c1 = *s1;
  578. c2 = *s2;
  579. if ( (CharUpperBuffW(&c1, (DWORD)1) != (DWORD)1) ||
  580. (CharUpperBuffW(&c2, (DWORD)1) != (DWORD)1) )
  581. {
  582. break;
  583. }
  584. // if the upper case characters are not equal then the string
  585. // is not there
  586. if (c1 - c2)
  587. break;
  588. }
  589. s1++, s2++;
  590. }
  591. if (!*s2)
  592. return(cp);
  593. cp++;
  594. }
  595. return(NULL);
  596. }
  597. #define _WCUTIL_H_
  598. #endif // _WCUTIL_H_