Leaked source code of windows server 2003
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.

873 lines
22 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. engine.c
  5. Abstract:
  6. Token Generator for Cross Language Migration Tool
  7. Author:
  8. Rerkboon Suwanasuk 01-May-2002 Created
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <Shlwapi.h>
  16. #include "common.h"
  17. //-----------------------------------------------------------------------------
  18. //
  19. // Function: TokenizeMultiSzString
  20. //
  21. // Synopsis: Extract array of strings in buffer. Each pointer in array of
  22. // pointers will point to each string in buffer.
  23. // Strings in buffer are separated by a single '\0'
  24. // End of strings array is indicated by two consecutive "\0\0"
  25. //
  26. // Returns: Number of strings in the buffer
  27. // 0 if no strings in the buffer
  28. // -1 if error occurs
  29. //
  30. // History: 02/07/2002 Rerkboos Created
  31. //
  32. // Notes: none.
  33. //
  34. //-----------------------------------------------------------------------------
  35. LONG TokenizeMultiSzString(
  36. LPCWSTR lpBuffer, // MultiSZ string buffer
  37. DWORD cchBuffer, // Size of buffer (in WCHAR)
  38. LPCWSTR lpToken[], // Array of pointer that will point to each SZ
  39. DWORD dwArrSize // Maximum array size
  40. )
  41. {
  42. DWORD dwTokenIndex;
  43. DWORD i;
  44. if (lpBuffer == NULL || lpToken == NULL)
  45. {
  46. // Invalid parameters
  47. return -1;
  48. }
  49. if (*lpBuffer == TEXT('\0') && *(lpBuffer + 1) == TEXT('\0'))
  50. {
  51. // No SZ in buffer
  52. return 0;
  53. }
  54. dwTokenIndex = 0;
  55. lpToken[dwTokenIndex] = lpBuffer;
  56. for (i = 0 ; i < cchBuffer ; i++)
  57. {
  58. if (*(lpBuffer + i) == TEXT('\0'))
  59. {
  60. // Reach the end of current string, check the next character in buffer
  61. i++;
  62. if (*(lpBuffer + i) == TEXT('\0'))
  63. {
  64. // Two consecutive '\0', it is the end of MultiSz string
  65. // return the number of SZ string in buffer
  66. return (dwTokenIndex + 1);
  67. }
  68. else
  69. {
  70. // Beginning of next string, assign the pointer to next string
  71. dwTokenIndex++;
  72. if (dwTokenIndex < dwArrSize)
  73. {
  74. // Enough pointer in array to use
  75. lpToken[dwTokenIndex] = lpBuffer + i;
  76. }
  77. else
  78. {
  79. // Array of pointer is too small to extract strings from buffer
  80. return -1;
  81. }
  82. }
  83. }
  84. }
  85. // Buffer is not null terminated correctly if we reach here
  86. return -1;
  87. }
  88. //-----------------------------------------------------------------------------
  89. //
  90. // Function: ExtractTokenString
  91. //
  92. // Synopsis: Tokenize the string using caller-supplied separators.
  93. // Each pointer in pointer array will point to the token in source
  94. // string, each token is null terminated.
  95. //
  96. // Returns: Number of token after tokenized
  97. // -1 if error occurs
  98. //
  99. // History: 02/07/2002 Rerkboos Created
  100. //
  101. // Notes: Source string will be modified, caller need to make sure
  102. // that original source string is backed up.
  103. //
  104. //-----------------------------------------------------------------------------
  105. LONG ExtractTokenString(
  106. LPWSTR lpString, // Source string to be tokenized
  107. LPWSTR lpToken[], // Array of pointers to token
  108. LPCWSTR lpSep, // List of separator characters
  109. DWORD nArrSize // Size of token array
  110. )
  111. {
  112. DWORD nTokIndex = 0;
  113. LPWSTR lpTmpToken;
  114. if (NULL == lpString || NULL == lpToken || NULL == lpSep)
  115. {
  116. // Invalid parameters
  117. return -1;
  118. }
  119. // Get first token
  120. lpTmpToken = wcstok(lpString, lpSep);
  121. // Loop until no more token left in the string
  122. while (NULL != lpTmpToken)
  123. {
  124. if (nTokIndex < nArrSize)
  125. {
  126. // Enough pointer in array to use, so get next token
  127. lpToken[nTokIndex] = lpTmpToken;
  128. nTokIndex++;
  129. lpTmpToken = wcstok(NULL, lpSep);
  130. }
  131. else
  132. {
  133. // Array size is too small to handle all the tokens
  134. return -1;
  135. }
  136. }
  137. // nTokIndex hold the number of token at this point
  138. return nTokIndex;
  139. }
  140. //-----------------------------------------------------------------------------
  141. //
  142. // Function: ConcatFilePath
  143. //
  144. // Synopsis:
  145. //
  146. // Returns:
  147. //
  148. // History: 02/07/2002 Rerkboos Created
  149. //
  150. // Notes:
  151. //
  152. //-----------------------------------------------------------------------------
  153. HRESULT ConcatFilePath(
  154. LPCWSTR lpPath,
  155. LPCWSTR lpFile,
  156. LPWSTR lpFilePath,
  157. DWORD cchFilePath
  158. )
  159. {
  160. HRESULT hr = E_FAIL;
  161. DWORD dwPathBackSlashIndex;
  162. LPCWSTR lpFormat;
  163. const WCHAR wszWithSlash[] = TEXT("%s\\%s");
  164. const WCHAR wszWithoutSlash[] = TEXT("%s%s");
  165. if (lpFilePath == NULL)
  166. {
  167. return E_INVALIDARG;
  168. }
  169. dwPathBackSlashIndex = lstrlen(lpPath) - 1;
  170. if (*(lpPath + dwPathBackSlashIndex) == TEXT('\\'))
  171. {
  172. // Path is already ended with a '\'
  173. lpFormat = wszWithoutSlash;
  174. }
  175. else
  176. {
  177. // Path is not ended with a '\', need a '\'
  178. lpFormat = wszWithSlash;
  179. }
  180. hr = StringCchPrintf(lpFilePath,
  181. cchFilePath,
  182. lpFormat,
  183. lpPath,
  184. lpFile);
  185. return hr;
  186. }
  187. //-----------------------------------------------------------------------------
  188. //
  189. // Function:
  190. //
  191. // Synopsis:
  192. //
  193. // Returns:
  194. //
  195. // History: 02/07/2002 Rerkboos Created
  196. //
  197. // Notes:
  198. //
  199. //-----------------------------------------------------------------------------
  200. HRESULT CopyCompressedFile(
  201. LPCWSTR lpCabPath,
  202. LPCWSTR lpCabFile, // Absolute path with CAB file name
  203. LPCWSTR lpFileInCab, // File name in CAB file
  204. LPWSTR lpUncompressedFile,
  205. DWORD cchUncompressedFile
  206. )
  207. {
  208. HRESULT hr = E_FAIL;
  209. BOOL bRet;
  210. DWORD dwRet;
  211. WCHAR wszAppName[MAX_PATH];
  212. WCHAR wszArg[MAX_PATH * 3];
  213. WCHAR wszFullCabFilePath[MAX_PATH];
  214. hr = ConcatFilePath(lpCabPath,
  215. lpCabFile,
  216. wszFullCabFilePath,
  217. ARRAYSIZE(wszFullCabFilePath));
  218. if (FAILED(hr))
  219. {
  220. return hr;
  221. }
  222. if (lpFileInCab == NULL || *lpFileInCab == TEXT('\0'))
  223. {
  224. DWORD dwEnd = lstrlen(lpCabFile);
  225. if (lpCabFile[dwEnd - 1] == TEXT('_'))
  226. {
  227. // Stand alone compressed file
  228. dwRet = ExpandEnvironmentStrings(TEXT("%SystemRoot%\\system32\\Extrac32.exe"),
  229. wszAppName,
  230. ARRAYSIZE(wszAppName));
  231. if (dwRet > 0)
  232. {
  233. hr = ConcatFilePath(g_wszTempFolder,
  234. lpCabFile,
  235. lpUncompressedFile,
  236. cchUncompressedFile);
  237. if (SUCCEEDED(hr))
  238. {
  239. hr = StringCchPrintf(wszArg,
  240. ARRAYSIZE(wszArg),
  241. TEXT("Extrac32.exe /Y \"%s\" \"%s\""),
  242. wszFullCabFilePath,
  243. lpUncompressedFile);
  244. if (SUCCEEDED(hr))
  245. {
  246. hr = LaunchProgram(wszAppName, wszArg);
  247. }
  248. }
  249. }
  250. }
  251. else
  252. {
  253. // Stand alone uncompressed file
  254. hr = ConcatFilePath(g_wszTempFolder,
  255. lpCabFile,
  256. lpUncompressedFile,
  257. cchUncompressedFile);
  258. if (SUCCEEDED(hr))
  259. {
  260. bRet = CopyFile(wszFullCabFilePath,
  261. lpUncompressedFile,
  262. FALSE);
  263. if (bRet)
  264. {
  265. SetFileAttributes(lpUncompressedFile, FILE_ATTRIBUTE_NORMAL);
  266. hr = S_OK;
  267. }
  268. else
  269. {
  270. hr = HRESULT_FROM_WIN32(GetLastError());
  271. }
  272. }
  273. }
  274. }
  275. else
  276. {
  277. // CAB file
  278. dwRet = ExpandEnvironmentStrings(TEXT("%SystemRoot%\\system32\\Expand.exe"),
  279. wszAppName,
  280. ARRAYSIZE(wszAppName));
  281. if (dwRet > 0)
  282. {
  283. hr = ConcatFilePath(g_wszTempFolder,
  284. lpFileInCab,
  285. lpUncompressedFile,
  286. cchUncompressedFile);
  287. if (SUCCEEDED(hr))
  288. {
  289. hr = StringCchPrintf(wszArg,
  290. ARRAYSIZE(wszArg),
  291. TEXT("Expand.exe \"%s\" -F:%s \"%s\""),
  292. wszFullCabFilePath,
  293. lpFileInCab,
  294. g_wszTempFolder);
  295. if (SUCCEEDED(hr))
  296. {
  297. hr = LaunchProgram(wszAppName, wszArg);
  298. }
  299. }
  300. }
  301. }
  302. //
  303. // Double check if the file is uncompressed/copied correctly
  304. //
  305. if (SUCCEEDED(hr))
  306. {
  307. DWORD dwAttr;
  308. dwAttr = GetFileAttributes(lpUncompressedFile);
  309. if (dwAttr == INVALID_FILE_ATTRIBUTES)
  310. {
  311. hr = HRESULT_FROM_WIN32(GetLastError());
  312. }
  313. }
  314. return hr;
  315. }
  316. //-----------------------------------------------------------------------------
  317. //
  318. // Function:
  319. //
  320. // Synopsis:
  321. //
  322. // Returns:
  323. //
  324. // History: 02/07/2002 Rerkboos Created
  325. //
  326. // Notes:
  327. //
  328. //-----------------------------------------------------------------------------
  329. HRESULT LaunchProgram(
  330. LPWSTR lpAppName,
  331. LPWSTR lpCmdLine
  332. )
  333. {
  334. HRESULT hr = E_FAIL;
  335. BOOL bRet = FALSE;
  336. STARTUPINFO si;
  337. PROCESS_INFORMATION pi;
  338. // Construct absolute path to Winnt32.exe
  339. ZeroMemory(&si, sizeof(STARTUPINFO));
  340. si.cb = sizeof(STARTUPINFO);
  341. si.wShowWindow = SW_SHOWMINIMIZED;
  342. // CreateProcess call conforms to security guideline
  343. bRet = CreateProcess(lpAppName,
  344. lpCmdLine,
  345. NULL,
  346. NULL,
  347. FALSE,
  348. CREATE_NO_WINDOW,
  349. NULL,
  350. NULL,
  351. &si,
  352. &pi);
  353. if (bRet)
  354. {
  355. // Wait until Expand.exe finished
  356. hr = S_OK;
  357. WaitForSingleObject(pi.hProcess, INFINITE);
  358. CloseHandle(pi.hProcess);
  359. CloseHandle(pi.hThread);
  360. }
  361. else
  362. {
  363. hr = HRESULT_FROM_WIN32(GetLastError());
  364. }
  365. return hr;
  366. }
  367. //-----------------------------------------------------------------------------
  368. //
  369. // Function:
  370. //
  371. // Synopsis:
  372. //
  373. // Returns:
  374. //
  375. // History: 02/07/2002 Rerkboos Created
  376. //
  377. // Notes:
  378. //
  379. //-----------------------------------------------------------------------------
  380. HRESULT GetPathFromSourcePathName(
  381. LPCWSTR lpSrcPathName,
  382. LPWSTR lpPathBuffer,
  383. DWORD cchPathBuffer
  384. )
  385. {
  386. HRESULT hr = S_FALSE;
  387. DWORD i;
  388. if (lpSrcPathName == NULL || lpPathBuffer == NULL)
  389. {
  390. return E_INVALIDARG;
  391. }
  392. for (i = 0 ; i < g_dwSrcCount ; i++)
  393. {
  394. if (lstrcmpi(lpSrcPathName, g_SrcPath[i].wszSrcName) == LSTR_EQUAL)
  395. {
  396. hr = StringCchCopy(lpPathBuffer,
  397. cchPathBuffer,
  398. g_SrcPath[i].wszPath);
  399. }
  400. }
  401. return S_OK;
  402. }
  403. //-----------------------------------------------------------------------------
  404. //
  405. // Function:
  406. //
  407. // Synopsis:
  408. //
  409. // Returns:
  410. //
  411. // History: 02/07/2002 Rerkboos Created
  412. //
  413. // Notes:
  414. //
  415. //-----------------------------------------------------------------------------
  416. HRESULT GetCabFileName(
  417. LPCWSTR lpFileToken, // File name token from template file
  418. LPWSTR lpCab,
  419. DWORD cchCab,
  420. LPWSTR lpFileInCab,
  421. DWORD cchFileInCab
  422. )
  423. {
  424. HRESULT hr = E_FAIL;
  425. LPWSTR lpBuffer;
  426. LPWSTR lpStart;
  427. DWORD cbBuffer;
  428. if (lpCab == NULL || lpFileInCab == NULL)
  429. {
  430. return E_INVALIDARG;
  431. }
  432. cbBuffer = (lstrlen(lpFileToken) + 1) * sizeof(WCHAR);
  433. lpBuffer = (LPWSTR) MEMALLOC(cbBuffer);
  434. if (lpBuffer)
  435. {
  436. hr = StringCbCopy(lpBuffer, cbBuffer, lpFileToken);
  437. if (SUCCEEDED(hr))
  438. {
  439. lpStart = wcstok(lpBuffer, TEXT("\\"));
  440. if (lpStart)
  441. {
  442. hr = StringCchCopy(lpCab, cchCab, lpStart);
  443. if (SUCCEEDED(hr))
  444. {
  445. lpStart = wcstok(NULL, TEXT("\\"));
  446. if (lpStart)
  447. {
  448. hr = StringCchCopy(lpFileInCab, cchFileInCab, lpStart);
  449. }
  450. else
  451. {
  452. hr = StringCchCopy(lpFileInCab, cchFileInCab, TEXT(""));
  453. }
  454. }
  455. }
  456. }
  457. MEMFREE(lpBuffer);
  458. }
  459. return hr;
  460. }
  461. //-----------------------------------------------------------------------------
  462. //
  463. // Function:
  464. //
  465. // Synopsis:
  466. //
  467. // Returns:
  468. //
  469. // History: 02/07/2002 Rerkboos Created
  470. //
  471. // Notes:
  472. //
  473. //-----------------------------------------------------------------------------
  474. HRESULT GetCabTempDirectory(
  475. LPCWSTR lpCab
  476. )
  477. {
  478. HRESULT hr = S_OK;
  479. return hr;
  480. }
  481. //-----------------------------------------------------------------------------
  482. //
  483. // Function:
  484. //
  485. // Synopsis:
  486. //
  487. // Returns:
  488. //
  489. // History: 02/07/2002 Rerkboos Created
  490. //
  491. // Notes:
  492. //
  493. //-----------------------------------------------------------------------------
  494. HRESULT CreateTempDirectory(
  495. LPWSTR lpName, // Buffer to store temp path
  496. DWORD cchName // Size of buffer (in WCHAR)
  497. )
  498. {
  499. HRESULT hr = E_FAIL;
  500. WCHAR wszTempPath[MAX_PATH];
  501. DWORD cchCopied;
  502. if (lpName == NULL)
  503. {
  504. return FALSE;
  505. }
  506. cchCopied = GetTempPath(cchName, lpName);
  507. if (cchCopied > 0)
  508. {
  509. hr = StringCchCat(lpName, cchName, TEXT_TOKGEN_TEMP_PATH_NAME);
  510. if (SUCCEEDED(hr))
  511. {
  512. if (GetFileAttributes(lpName) == INVALID_FILE_ATTRIBUTES)
  513. {
  514. if (!CreateDirectory(lpName, NULL))
  515. {
  516. hr = HRESULT_FROM_WIN32(GetLastError());
  517. }
  518. }
  519. else
  520. {
  521. hr = S_OK;
  522. }
  523. }
  524. }
  525. return hr;
  526. }
  527. //-----------------------------------------------------------------------------
  528. //
  529. // Function: LTrim
  530. //
  531. // Synopsis: Trim the leading spaces in the string.
  532. //
  533. // Returns: none
  534. //
  535. // History: 02/07/2002 Rerkboos Created
  536. //
  537. // Notes: none
  538. //
  539. //-----------------------------------------------------------------------------
  540. void LTrim(
  541. LPWSTR lpBuffer
  542. )
  543. {
  544. int nIndex = 0;
  545. int nDest = 0;
  546. if (NULL == lpBuffer || TEXT('\0') == *lpBuffer)
  547. return;
  548. while (TEXT(' ') == lpBuffer[nIndex] && TEXT('\0') != lpBuffer[nIndex])
  549. nIndex++;
  550. while (TEXT('\0') != lpBuffer[nIndex])
  551. {
  552. lpBuffer[nDest] = lpBuffer[nIndex];
  553. nDest++;
  554. nIndex++;
  555. }
  556. lpBuffer[nDest] = TEXT('\0');
  557. }
  558. //-----------------------------------------------------------------------------
  559. //
  560. // Function: RTrim
  561. //
  562. // Synopsis: Trim the trailing spaces in the string.
  563. //
  564. // Returns: none
  565. //
  566. // History: 02/07/2002 Rerkboos Created
  567. //
  568. // Notes: none
  569. //
  570. //-----------------------------------------------------------------------------
  571. void RTrim(
  572. LPWSTR lpBuffer
  573. )
  574. {
  575. int nIndex = 0;
  576. int nDest = 0;
  577. if (NULL == lpBuffer || TEXT('\0') == *lpBuffer)
  578. return;
  579. nIndex = lstrlen(lpBuffer) - 1;
  580. while (nIndex >= 0)
  581. {
  582. if (lpBuffer[nIndex] != TEXT(' '))
  583. break;
  584. nIndex--;
  585. }
  586. lpBuffer[nIndex + 1] = TEXT('\0');
  587. }
  588. //-----------------------------------------------------------------------------
  589. //
  590. // Function: Str2KeyPath
  591. //
  592. // Synopsis: Convert string value of root key to HKEY value
  593. //
  594. // Returns: HKEY value
  595. //
  596. // History: 02/07/2002 Rerkboos Created
  597. //
  598. // Notes: none
  599. //
  600. //-----------------------------------------------------------------------------
  601. BOOL Str2KeyPath(
  602. LPCWSTR lpHKeyStr,
  603. PHKEY pHKey,
  604. LPCWSTR* pSubKeyPath
  605. )
  606. {
  607. int i;
  608. LPCWSTR lpStart;
  609. STRING_TO_DATA InfRegSpecTohKey[] = {
  610. TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE,
  611. TEXT("HKLM") , HKEY_LOCAL_MACHINE,
  612. TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT,
  613. TEXT("HKCR") , HKEY_CLASSES_ROOT,
  614. TEXT("HKR") , NULL,
  615. TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER,
  616. TEXT("HKCU") , HKEY_CURRENT_USER,
  617. TEXT("HKEY_USERS") , HKEY_USERS,
  618. TEXT("HKU") , HKEY_USERS,
  619. TEXT("") , NULL
  620. };
  621. PSTRING_TO_DATA Table = InfRegSpecTohKey;
  622. if (NULL == lpHKeyStr)
  623. {
  624. return FALSE;
  625. }
  626. for(i = 0 ; Table[i].String[0] != TEXT('\0') ; i++)
  627. {
  628. lpStart = wcsstr(lpHKeyStr, Table[i].String);
  629. if (lpStart == lpHKeyStr)
  630. {
  631. *pHKey = Table[i].Data;
  632. if (NULL != pSubKeyPath)
  633. {
  634. lpStart += lstrlen(Table[i].String);
  635. if (*lpStart == TEXT('\0'))
  636. {
  637. *pSubKeyPath = lpStart;
  638. }
  639. else
  640. {
  641. *pSubKeyPath = lpStart + 1;
  642. }
  643. }
  644. return TRUE;
  645. }
  646. }
  647. return FALSE;
  648. }
  649. HRESULT StringSubstitute(
  650. LPWSTR lpString, // New string buffer
  651. DWORD cchString, // Size of buffer in WCHAR
  652. LPCWSTR lpOldString, // Old string
  653. LPCWSTR lpOldSubStr, // Old sub string to be substituted
  654. LPCWSTR lpNewSubStr // New sub string
  655. )
  656. {
  657. HRESULT hr = E_FAIL;
  658. LPWSTR lpSubStrBegin;
  659. lpSubStrBegin = StrStrI(lpOldString, lpOldSubStr);
  660. if (lpSubStrBegin)
  661. {
  662. // Sub string found in source string
  663. DWORD cchNewString;
  664. cchNewString = lstrlen(lpOldString)
  665. - lstrlen(lpOldSubStr)
  666. + lstrlen(lpNewSubStr);
  667. if (cchNewString < cchString)
  668. {
  669. DWORD dwStartIndex;
  670. DWORD dwEndIndex;
  671. DWORD i, j;
  672. dwStartIndex = (DWORD) (lpSubStrBegin - lpOldString);
  673. dwEndIndex = dwStartIndex + lstrlen(lpOldSubStr);
  674. for (i = 0 ; i < dwStartIndex ; i++)
  675. {
  676. lpString[i] = lpOldString[i];
  677. }
  678. for (j = 0 ; j < (DWORD) lstrlen(lpNewSubStr) ; i++, j++)
  679. {
  680. lpString[i] = lpNewSubStr[j];
  681. }
  682. for (j = dwEndIndex ; lpOldString[j] != TEXT('\0') ; i++, j++)
  683. {
  684. lpString[i] = lpOldString[j];
  685. }
  686. lpString[i] = TEXT('\0');
  687. hr = S_OK;
  688. }
  689. else
  690. {
  691. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  692. }
  693. }
  694. else
  695. {
  696. // sub string not found
  697. hr = S_FALSE;
  698. }
  699. if (hr == E_FAIL)
  700. {
  701. hr = HRESULT_FROM_WIN32(GetLastError());
  702. }
  703. return hr;
  704. }
  705. HRESULT ExtractSubString(
  706. LPWSTR lpString, // New string buffer
  707. DWORD cchString, // Size of buffer in WCHAR
  708. LPCWSTR lpOldString, // Old string
  709. LPCWSTR lpLeft, // Left delimitor
  710. LPCWSTR lpRight // Right delimitor
  711. )
  712. {
  713. HRESULT hr = E_FAIL;
  714. LPWSTR lpSubStrBegin, lpSubStrEnd;
  715. lpSubStrBegin = StrStrI(lpOldString, lpLeft);
  716. if (lpSubStrBegin)
  717. {
  718. lpSubStrBegin += lstrlen(lpLeft);
  719. lpSubStrEnd = StrStrI(lpSubStrBegin, lpRight);
  720. if (lpSubStrEnd && (DWORD)(lpSubStrEnd-lpSubStrBegin) < cchString)
  721. {
  722. while (lpSubStrBegin < lpSubStrEnd)
  723. {
  724. *lpString = *lpSubStrBegin;
  725. lpString++;
  726. lpSubStrBegin++;
  727. }
  728. *lpString = (WCHAR)'\0';
  729. hr = S_OK;
  730. }
  731. }
  732. return hr;
  733. }
  734. //-----------------------------------------------------------------------------
  735. //
  736. // Function: CompareENGString
  737. //
  738. // Synopsis: Wrapper of CompareString API, to compare English strings.
  739. //
  740. // Returns: Same as CompareString() API
  741. //
  742. // History: 05/06/2002 Rerkboos Created
  743. //
  744. // Notes: none
  745. //
  746. //-----------------------------------------------------------------------------
  747. int CompareEngString(
  748. LPCTSTR lpString1,
  749. LPCTSTR lpString2
  750. )
  751. {
  752. return CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
  753. NORM_IGNORECASE,
  754. lpString1,
  755. -1,
  756. lpString2,
  757. -1);
  758. }