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.

1594 lines
42 KiB

  1. // --------------------------------------------------------------------------
  2. // Strutil.cpp
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // Steven J. Bailey
  5. // --------------------------------------------------------------------------
  6. #include "pch.hxx"
  7. #include <iert.h>
  8. #include "dllmain.h"
  9. #include "oertpriv.h"
  10. #include <wininet.h>
  11. #include <shlwapi.h>
  12. #include <shlwapip.h>
  13. #include <qstrcmpi.h>
  14. #include <shlwapi.h>
  15. #include "unicnvrt.h"
  16. #include <BadStrFunctions.h>
  17. // conversion from 'int' to 'unsigned short', possible loss of data
  18. #pragma warning (disable:4244)
  19. // --------------------------------------------------------------------------
  20. // g_szMonths
  21. // --------------------------------------------------------------------------
  22. static const LPSTR g_szMonths[] = {
  23. "Jan", "Feb", "Mar",
  24. "Apr", "May", "Jun",
  25. "Jul", "Aug", "Sep",
  26. "Oct", "Nov", "Dec"
  27. };
  28. // --------------------------------------------------------------------------
  29. // g_szDays
  30. // --------------------------------------------------------------------------
  31. static const LPSTR g_szDays[] = {
  32. "Sun",
  33. "Mon",
  34. "Tue",
  35. "Wed",
  36. "Thu",
  37. "Fri",
  38. "Sat"
  39. };
  40. // --------------------------------------------------------------------------
  41. // g_rgZones
  42. // --------------------------------------------------------------------------
  43. static const INETTIMEZONE g_rgZones[] = {
  44. { "UT", 0, 0 },
  45. { "GMT", 0, 0 },
  46. { "EST", 5, 0 },
  47. { "EDT", 4, 0 },
  48. { "CST", 6, 0 },
  49. { "CDT", 5, 0 },
  50. { "MST", 7, 0 },
  51. { "MDT", 6, 0 },
  52. { "PST", 8, 0 },
  53. { "PDT", 7, 0 },
  54. { "KST", -9, 0 },
  55. { "JST", -9, 0 },
  56. { NULL, 0, 0 }
  57. };
  58. // --------------------------------------------------------------------------------
  59. // How big is the thread local storage string buffer
  60. // -------------------------------------------------------------------------------
  61. #define CBMAX_THREAD_TLS_BUFFER 512
  62. // --------------------------------------------------------------------------------
  63. // ThreadAllocateTlsMsgBuffer
  64. // -------------------------------------------------------------------------------
  65. void ThreadAllocateTlsMsgBuffer(void)
  66. {
  67. if (g_dwTlsMsgBuffIndex != 0xffffffff)
  68. TlsSetValue(g_dwTlsMsgBuffIndex, NULL);
  69. }
  70. // --------------------------------------------------------------------------------
  71. // ThreadFreeTlsMsgBuffer
  72. // -------------------------------------------------------------------------------
  73. void ThreadFreeTlsMsgBuffer(void)
  74. {
  75. if (g_dwTlsMsgBuffIndex != 0xffffffff)
  76. {
  77. LPSTR psz = (LPSTR)TlsGetValue(g_dwTlsMsgBuffIndex);
  78. SafeMemFree(psz);
  79. SideAssert(0 != TlsSetValue(g_dwTlsMsgBuffIndex, NULL));
  80. }
  81. }
  82. // --------------------------------------------------------------------------------
  83. // PszGetTlsBuffer
  84. // -------------------------------------------------------------------------------
  85. LPSTR PszGetTlsBuffer(void)
  86. {
  87. // Get the buffer
  88. LPSTR pszBuffer = (LPSTR)TlsGetValue(g_dwTlsMsgBuffIndex);
  89. // If buffer has not been allocated
  90. if (NULL == pszBuffer)
  91. {
  92. // Allocate it
  93. pszBuffer = (LPSTR)g_pMalloc->Alloc(CBMAX_THREAD_TLS_BUFFER);
  94. // Store it
  95. Assert(pszBuffer);
  96. SideAssert(0 != TlsSetValue(g_dwTlsMsgBuffIndex, pszBuffer));
  97. }
  98. // Done
  99. return pszBuffer;
  100. }
  101. // --------------------------------------------------------------------------------
  102. // _MSG - Used to build a string from variable length args, thread-safe
  103. // -------------------------------------------------------------------------------
  104. OESTDAPI_(LPCSTR) _MSG(LPSTR pszFormat, ...)
  105. {
  106. // Locals
  107. va_list arglist;
  108. LPSTR pszBuffer=NULL;
  109. // I use tls to hold the buffer
  110. if (g_dwTlsMsgBuffIndex != 0xffffffff)
  111. {
  112. // Setup the arglist
  113. va_start(arglist, pszFormat);
  114. // Get the Buffer
  115. pszBuffer = PszGetTlsBuffer();
  116. // If we have a buffer
  117. if (pszBuffer)
  118. {
  119. // Format the data
  120. wvnsprintf(pszBuffer, (CBMAX_THREAD_TLS_BUFFER - sizeof(pszBuffer[0])), pszFormat, arglist);
  121. }
  122. // End the arglist
  123. va_end(arglist);
  124. }
  125. return ((LPCSTR)pszBuffer);
  126. }
  127. // --------------------------------------------------------------------------
  128. // StrChrExA
  129. // --------------------------------------------------------------------------
  130. OESTDAPI_(LPCSTR) StrChrExA(UINT codepage, LPCSTR pszString, CHAR ch)
  131. {
  132. // Locals
  133. LPSTR pszT=(LPSTR)pszString;
  134. // Loop for ch in pszString
  135. while(*pszT)
  136. {
  137. // Lead Byte
  138. if (IsDBCSLeadByteEx(codepage, *pszT))
  139. pszT++;
  140. else if (*pszT == ch)
  141. return pszT;
  142. pszT++;
  143. }
  144. // Not Found
  145. return NULL;
  146. }
  147. // --------------------------------------------------------------------------
  148. // PszDayFromIndex
  149. // --------------------------------------------------------------------------
  150. OESTDAPI_(LPCSTR) PszDayFromIndex(ULONG ulIndex)
  151. {
  152. // Invalid Arg
  153. Assert(ulIndex <= 6);
  154. // Adjust ulIndex
  155. ulIndex = (ulIndex > 6) ? 0 : ulIndex;
  156. // Return
  157. return g_szDays[ulIndex];
  158. }
  159. // --------------------------------------------------------------------------
  160. // PszMonthFromIndex (ulIndex is one-based)
  161. // --------------------------------------------------------------------------
  162. OESTDAPI_(LPCSTR) PszMonthFromIndex(ULONG ulIndex)
  163. {
  164. // Invalid Arg
  165. Assert(ulIndex >= 1 && ulIndex <= 12);
  166. // Adjust ulIndex
  167. ulIndex = (ulIndex < 1 || ulIndex > 12) ? 0 : ulIndex - 1;
  168. // Return
  169. return g_szMonths[ulIndex];
  170. }
  171. // --------------------------------------------------------------------------
  172. // HrFindInetTimeZone
  173. // --------------------------------------------------------------------------
  174. OESTDAPI_(HRESULT) HrFindInetTimeZone(LPCSTR pszTimeZone, LPINETTIMEZONE pTimeZone)
  175. {
  176. // Invalid Arg
  177. Assert(pszTimeZone && pTimeZone);
  178. // Loop timezone table
  179. for (ULONG iZoneCode=0; g_rgZones[iZoneCode].lpszZoneCode!=NULL; iZoneCode++)
  180. {
  181. // Is this the code...
  182. if (lstrcmpi(pszTimeZone, g_rgZones[iZoneCode].lpszZoneCode) == 0)
  183. {
  184. CopyMemory(pTimeZone, &g_rgZones[iZoneCode], sizeof(INETTIMEZONE));
  185. return S_OK;
  186. }
  187. }
  188. // Not Found
  189. return E_FAIL;
  190. }
  191. // --------------------------------------------------------------------------
  192. // HrIndexOfMonth
  193. // --------------------------------------------------------------------------
  194. OESTDAPI_(HRESULT) HrIndexOfMonth(LPCSTR pszMonth, ULONG *pulIndex)
  195. {
  196. // Invalid Arg
  197. Assert(pszMonth && pulIndex);
  198. // Loop the Months
  199. for (ULONG iMonth=0; iMonth < ARRAYSIZE(g_szMonths); iMonth++)
  200. {
  201. // Is this the month
  202. if (OEMstrcmpi(pszMonth, g_szMonths[iMonth]) == 0)
  203. {
  204. // Set It
  205. *pulIndex = (iMonth + 1);
  206. // Validate
  207. AssertSz(*pulIndex >= 1 && *pulIndex <= 12, "HrIndexOfMonth - Bad Month");
  208. // Done
  209. return S_OK;
  210. }
  211. }
  212. *pulIndex = 0;
  213. // Not Found
  214. return E_FAIL;
  215. }
  216. // --------------------------------------------------------------------------
  217. // HrIndexOfWeek
  218. // --------------------------------------------------------------------------
  219. OESTDAPI_(HRESULT) HrIndexOfWeek(LPCSTR pszDay, ULONG *pulIndex)
  220. {
  221. // Invalid Arg
  222. Assert(pszDay && pulIndex);
  223. // Loop the Days
  224. for (ULONG iDayOfWeek=0; iDayOfWeek < ARRAYSIZE(g_szDays); iDayOfWeek++)
  225. {
  226. // Is this the day
  227. if (OEMstrcmpi(pszDay, g_szDays[iDayOfWeek]) == 0)
  228. {
  229. // Set Day Of Week
  230. *pulIndex = iDayOfWeek;
  231. // Validate
  232. AssertSz(((int) *pulIndex) >= 0 && ((int) *pulIndex) <= 6, "HrIndexOfDay - Bad day of week");
  233. // Done
  234. return S_OK;
  235. }
  236. }
  237. *pulIndex = 0;
  238. // Failure
  239. return E_FAIL;
  240. }
  241. // --------------------------------------------------------------------------
  242. // PszEscapeMenuStringA
  243. //
  244. // Escapes & characters with another & so that they show up correctly when shown
  245. // in a menu.
  246. // --------------------------------------------------------------------------------
  247. OESTDAPI_(LPSTR) PszEscapeMenuStringA(LPCSTR pszSource, LPSTR pszQuoted, int cchMax)
  248. {
  249. LPSTR pszT=pszQuoted;
  250. int cch = 1; // 1 is intentional
  251. Assert(pszSource);
  252. Assert(pszQuoted);
  253. while((cch < cchMax) && (*pszSource))
  254. {
  255. if (IsDBCSLeadByte(*pszSource))
  256. {
  257. cch++;
  258. // Is there only space for lead byte?
  259. if (cch == cchMax)
  260. // Yes, don't write it
  261. break;
  262. else
  263. *pszT++ = *pszSource++;
  264. }
  265. else if ('&' == *pszSource)
  266. {
  267. cch++;
  268. if (cch == cchMax)
  269. break;
  270. else
  271. *pszT++ = '&';
  272. }
  273. // Only way this could fail is if there was a DBCSLeadByte with no trail byte
  274. Assert(*pszSource);
  275. *pszT++ = *pszSource++;
  276. cch++;
  277. }
  278. *pszT = 0;
  279. return pszQuoted;
  280. }
  281. // --------------------------------------------------------------------------------
  282. // PszSkipWhiteA
  283. // --------------------------------------------------------------------------
  284. OESTDAPI_(LPSTR) PszSkipWhiteA(LPSTR psz)
  285. {
  286. while(*psz && (*psz == ' ' || *psz == '\t'))
  287. psz++;
  288. return psz;
  289. }
  290. OESTDAPI_(LPWSTR) PszSkipWhiteW(LPWSTR psz)
  291. {
  292. while(*psz && (*psz == L' ' || *psz == L'\t'))
  293. psz++;
  294. return psz;
  295. }
  296. // --------------------------------------------------------------------------
  297. // PszScanToWhiteA
  298. // --------------------------------------------------------------------------
  299. OESTDAPI_(LPSTR) PszScanToWhiteA(LPSTR psz)
  300. {
  301. while(*psz && ' ' != *psz && '\t' != *psz)
  302. psz++;
  303. return psz;
  304. }
  305. // --------------------------------------------------------------------------
  306. // PszScanToCharA
  307. // --------------------------------------------------------------------------
  308. OESTDAPI_(LPSTR) PszScanToCharA(LPSTR psz, CHAR ch)
  309. {
  310. while(*psz && ch != *psz)
  311. psz++;
  312. return psz;
  313. }
  314. // --------------------------------------------------------------------------
  315. // PszDupLenA
  316. // duplicates a string with upto cchMax characters in (and a null term)
  317. // --------------------------------------------------------------------------
  318. OESTDAPI_(LPSTR) PszDupLenA(LPCSTR pcszSource, int cchMax)
  319. {
  320. // Locals
  321. LPSTR pszDup=NULL;
  322. // No Source
  323. if (pcszSource == NULL || cchMax == 0)
  324. goto exit;
  325. // the amount to copy if the min of the max and the
  326. // source
  327. cchMax = min(lstrlen(pcszSource), cchMax);
  328. // Allocate the String
  329. pszDup = PszAllocA(cchMax+1); // +1 for null term
  330. if (!pszDup)
  331. goto exit;
  332. // Copy the data, leave room for the null-term
  333. CopyMemory(pszDup, pcszSource, cchMax);
  334. // null terminate
  335. pszDup[cchMax] = 0;
  336. exit:
  337. // Done
  338. return pszDup;
  339. }
  340. // --------------------------------------------------------------------------
  341. // PszFromANSIStreamA - pstm is assumed to be an ANSI stream
  342. // --------------------------------------------------------------------------
  343. OESTDAPI_(LPSTR) PszFromANSIStreamA(LPSTREAM pstm)
  344. {
  345. // Locals
  346. HRESULT hr;
  347. LPSTR psz=NULL;
  348. ULONG cb;
  349. // Get stream size
  350. hr = HrGetStreamSize(pstm, &cb);
  351. if (FAILED(hr))
  352. {
  353. Assert(FALSE);
  354. return NULL;
  355. }
  356. // Rewind the stream
  357. HrRewindStream(pstm);
  358. // Allocate a buffer
  359. if ((psz = PszAllocA(cb + 1)) != NULL)
  360. {
  361. // Read a buffer from stream
  362. hr = pstm->Read(psz, cb, NULL);
  363. if (FAILED(hr))
  364. {
  365. Assert(FALSE);
  366. MemFree(psz);
  367. return NULL;
  368. }
  369. // Null Terminate
  370. *(psz + cb) = '\0';
  371. }
  372. // Done
  373. return psz;
  374. }
  375. // --------------------------------------------------------------------------
  376. // PszFromANSIStreamW - pstm is assumed to be an ANSI stream
  377. // --------------------------------------------------------------------------
  378. LPWSTR PszFromANSIStreamW(UINT cp, LPSTREAM pstm)
  379. {
  380. // Get ANSI string
  381. LPSTR psz = PszFromANSIStreamA(pstm);
  382. if (NULL == psz)
  383. return NULL;
  384. // Convert to unicode
  385. LPWSTR pwsz = PszToUnicode(cp, psz);
  386. // Done
  387. return pwsz;
  388. }
  389. // --------------------------------------------------------------------------
  390. // ConvertFromHex - Converts a hexdigit into a numerica value
  391. // --------------------------------------------------------------------------
  392. OESTDAPI_(CHAR) ChConvertFromHex (CHAR ch)
  393. {
  394. if (ch >= '0' && ch <= '9')
  395. return CHAR((ch - '0'));
  396. else if (ch >= 'A'&& ch <= 'F')
  397. return CHAR(((ch - 'A') + 10));
  398. else if (ch >= 'a' && ch <= 'f')
  399. return CHAR(((ch - 'a') + 10));
  400. else
  401. return ((CHAR)(BYTE)255);
  402. }
  403. // --------------------------------------------------------------------------
  404. // FIsValidRegKeyNameA
  405. // --------------------------------------------------------------------------
  406. BOOL FIsValidRegKeyNameA(LPSTR pszKey)
  407. {
  408. // Locals
  409. LPSTR psz=pszKey;
  410. // If Empty...
  411. if (FIsEmptyA(pszKey))
  412. return FALSE;
  413. // Check for backslashes
  414. while(*psz)
  415. {
  416. if (*psz == '\\')
  417. return FALSE;
  418. psz = CharNextA(psz);
  419. }
  420. // Its ok
  421. return TRUE;
  422. }
  423. // --------------------------------------------------------------------------
  424. // FIsValidRegKeyNameW
  425. // --------------------------------------------------------------------------
  426. BOOL FIsValidRegKeyNameW(LPWSTR pwszKey)
  427. {
  428. // Locals
  429. LPWSTR pwsz=pwszKey;
  430. // If Empty...
  431. if (FIsEmptyW(pwszKey))
  432. return FALSE;
  433. // Check for backslashes
  434. while(*pwsz)
  435. {
  436. if (*pwsz == L'\\')
  437. return FALSE;
  438. pwsz = CharNextW(pwsz);
  439. }
  440. // Its ok
  441. return TRUE;
  442. }
  443. // --------------------------------------------------------------------------
  444. // FIsSpaceA
  445. // --------------------------------------------------------------------------
  446. OESTDAPI_(BOOL) FIsSpaceA(LPSTR psz)
  447. {
  448. WORD wType = 0;
  449. if (IsDBCSLeadByte(*psz))
  450. SideAssert(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  451. else
  452. SideAssert(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  453. return (wType & C1_SPACE);
  454. }
  455. // --------------------------------------------------------------------------
  456. // FIsSpaceW
  457. // --------------------------------------------------------------------------
  458. OESTDAPI_(BOOL) FIsSpaceW(LPWSTR pwsz)
  459. {
  460. BOOL result = FALSE;
  461. if (S_OK == IsPlatformWinNT())
  462. {
  463. WORD wType = 0;
  464. SideAssert(GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, pwsz, 1, &wType));
  465. result = (wType & C1_SPACE);
  466. }
  467. else
  468. {
  469. LPSTR psz = PszToANSI(CP_ACP, pwsz);
  470. if (psz)
  471. result = FIsSpaceA(psz);
  472. MemFree(psz);
  473. }
  474. return result;
  475. }
  476. // --------------------------------------------------------------------------
  477. // FIsEmptyA
  478. // --------------------------------------------------------------------------
  479. OESTDAPI_(BOOL) FIsEmptyA(LPCSTR pcszString)
  480. {
  481. // Locals
  482. LPSTR psz;
  483. // Bad Pointer
  484. if (!pcszString)
  485. return TRUE;
  486. // Check for All spaces
  487. psz = (LPSTR)pcszString;
  488. while (*psz)
  489. {
  490. if (FIsSpaceA(psz) == FALSE)
  491. return FALSE;
  492. psz++;
  493. }
  494. // Done
  495. return TRUE;
  496. }
  497. // --------------------------------------------------------------------------
  498. // FIsEmptyW
  499. // --------------------------------------------------------------------------
  500. OESTDAPI_(BOOL) FIsEmptyW(LPCWSTR pcwszString)
  501. {
  502. // Locals
  503. LPWSTR pwsz;
  504. // Bad Pointer
  505. if (!pcwszString)
  506. return TRUE;
  507. // Check for All spaces
  508. pwsz = (LPWSTR)pcwszString;
  509. while (*pwsz)
  510. {
  511. if (FIsSpaceW(pwsz) == FALSE)
  512. return FALSE;
  513. pwsz++;
  514. }
  515. // Done
  516. return TRUE;
  517. }
  518. // --------------------------------------------------------------------------
  519. // PszAllocA
  520. // --------------------------------------------------------------------------
  521. OESTDAPI_(LPSTR) PszAllocA(INT nLen)
  522. {
  523. // Locals
  524. LPSTR psz=NULL;
  525. // Empty ?
  526. if (nLen == 0)
  527. goto exit;
  528. // Allocate
  529. if (FAILED(HrAlloc((LPVOID *)&psz, (nLen + 1) * sizeof (CHAR))))
  530. goto exit;
  531. exit:
  532. // Done
  533. return psz;
  534. }
  535. // --------------------------------------------------------------------------
  536. // PszAllocW
  537. // --------------------------------------------------------------------------
  538. OESTDAPI_(LPWSTR) PszAllocW(INT nLen)
  539. {
  540. // Locals
  541. LPWSTR pwsz=NULL;
  542. // Empty ?
  543. if (nLen == 0)
  544. goto exit;
  545. // Allocate
  546. if (FAILED(HrAlloc((LPVOID *)&pwsz, (nLen + 1) * sizeof (WCHAR))))
  547. goto exit;
  548. exit:
  549. // Done
  550. return pwsz;
  551. }
  552. // --------------------------------------------------------------------------
  553. // PszToUnicode
  554. // --------------------------------------------------------------------------
  555. OESTDAPI_(LPWSTR) PszToUnicode(UINT cp, LPCSTR pcszSource)
  556. {
  557. // Locals
  558. INT cchNarrow,
  559. cchWide;
  560. LPWSTR pwszDup=NULL;
  561. // No Source
  562. if (pcszSource == NULL)
  563. goto exit;
  564. // Length
  565. cchNarrow = lstrlenA(pcszSource) + 1;
  566. // Determine how much space is needed for translated widechar
  567. cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, NULL, 0);
  568. // Error
  569. if (cchWide == 0)
  570. goto exit;
  571. // Alloc temp buffer
  572. pwszDup = PszAllocW(cchWide + 1);
  573. if (!pwszDup)
  574. goto exit;
  575. // Do the actual translation
  576. cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, pwszDup, cchWide+1);
  577. // Error
  578. if (cchWide == 0)
  579. {
  580. SafeMemFree(pwszDup);
  581. goto exit;
  582. }
  583. exit:
  584. // Done
  585. return pwszDup;
  586. }
  587. // --------------------------------------------------------------------------
  588. // PszToANSI
  589. // --------------------------------------------------------------------------
  590. OESTDAPI_(LPSTR) PszToANSI(UINT cp, LPCWSTR pcwszSource)
  591. {
  592. // Locals
  593. INT cchNarrow,
  594. cchWide;
  595. LPSTR pszDup=NULL;
  596. // No Source
  597. if (pcwszSource == NULL)
  598. goto exit;
  599. // Length
  600. cchWide = lstrlenW(pcwszSource)+1;
  601. // Determine how much space is needed for translated widechar
  602. cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, NULL, 0, NULL, NULL);
  603. // Error
  604. if (cchNarrow == 0)
  605. goto exit;
  606. // Alloc temp buffer
  607. pszDup = PszAllocA(cchNarrow + 1);
  608. if (!pszDup)
  609. goto exit;
  610. // Do the actual translation
  611. cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, pszDup, cchNarrow+1, NULL, NULL);
  612. // Error
  613. if (cchNarrow == 0)
  614. {
  615. SafeMemFree(pszDup);
  616. goto exit;
  617. }
  618. exit:
  619. // Done
  620. return pszDup;
  621. }
  622. // --------------------------------------------------------------------------
  623. // PszDupA
  624. // --------------------------------------------------------------------------
  625. OESTDAPI_(LPSTR) PszDupA(LPCSTR pcszSource)
  626. {
  627. // Locals
  628. INT nLen;
  629. LPSTR pszDup=NULL;
  630. // No Source
  631. if (pcszSource == NULL)
  632. goto exit;
  633. // Get String Length
  634. nLen = lstrlenA(pcszSource) + 1;
  635. // Allocate the String
  636. pszDup = PszAllocA(nLen);
  637. if (!pszDup)
  638. goto exit;
  639. // Copy the data
  640. CopyMemory(pszDup, pcszSource, nLen);
  641. exit:
  642. // Done
  643. return pszDup;
  644. }
  645. // --------------------------------------------------------------------------
  646. // PszDupW
  647. // --------------------------------------------------------------------------
  648. OESTDAPI_(LPWSTR) PszDupW(LPCWSTR pcwszSource)
  649. {
  650. // Locals
  651. INT nLen;
  652. LPWSTR pwszDup=NULL;
  653. // No Source
  654. if (pcwszSource == NULL)
  655. goto exit;
  656. // Get String Length
  657. nLen = lstrlenW(pcwszSource) + 1;
  658. // Allocate the String
  659. pwszDup = PszAllocW(nLen);
  660. if (!pwszDup)
  661. goto exit;
  662. // Copy the data
  663. CopyMemory(pwszDup, pcwszSource, nLen * sizeof(WCHAR));
  664. exit:
  665. // Done
  666. return pwszDup;
  667. }
  668. // --------------------------------------------------------------------------
  669. // StripCRLF
  670. // --------------------------------------------------------------------------
  671. OESTDAPI_(void) StripCRLF(LPSTR lpsz, ULONG *pcb)
  672. {
  673. // Null ?
  674. AssertSz (lpsz && pcb, "NULL Parameter");
  675. // If length is zero, then return
  676. if (!lpsz || !pcb || (*pcb == 0))
  677. {
  678. Assert(0);
  679. return;
  680. }
  681. // Check last three characters of the string, last char might or might not be a null-term
  682. LONG iLast = (*pcb) - 2;
  683. if (iLast < 0)
  684. iLast = 0;
  685. for (LONG i=(*pcb); i>=iLast; i--)
  686. {
  687. // Is end character a '\n'
  688. if (lpsz[i] == chLF)
  689. {
  690. lpsz[i] = '\0';
  691. (*pcb)--;
  692. }
  693. // Is end character a '\r'
  694. if (lpsz[i] == chCR)
  695. {
  696. lpsz[i] = '\0';
  697. (*pcb)--;
  698. }
  699. }
  700. return;
  701. }
  702. // --------------------------------------------------------------------------
  703. // ToUpper
  704. // --------------------------------------------------------------------------
  705. TCHAR ToUpper(TCHAR c)
  706. {
  707. return (TCHAR)LOWORD(CharUpper(MAKEINTRESOURCE(c)));
  708. }
  709. // --------------------------------------------------------------------------
  710. // IsPrint
  711. // --------------------------------------------------------------------------
  712. OESTDAPI_(int) IsPrint(LPSTR psz)
  713. {
  714. WORD wType;
  715. if (IsDBCSLeadByte(*psz))
  716. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  717. else
  718. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  719. return !(wType & C1_CNTRL);
  720. }
  721. // --------------------------------------------------------------------------
  722. // IsDigit
  723. // --------------------------------------------------------------------------
  724. OESTDAPI_(int) IsDigit(LPSTR psz)
  725. {
  726. WORD wType;
  727. if (IsDBCSLeadByte(*psz))
  728. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  729. else
  730. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  731. return (wType & C1_DIGIT);
  732. }
  733. // --------------------------------------------------------------------------
  734. // IsXDigit
  735. // --------------------------------------------------------------------------
  736. int IsXDigit(LPSTR psz)
  737. {
  738. WORD wType;
  739. if (IsDBCSLeadByte(*psz))
  740. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  741. else
  742. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  743. return (wType & C1_XDIGIT);
  744. }
  745. // --------------------------------------------------------------------------
  746. // IsUpper
  747. // --------------------------------------------------------------------------
  748. OESTDAPI_(INT) IsUpper(LPSTR psz)
  749. {
  750. WORD wType;
  751. if (IsDBCSLeadByte(*psz))
  752. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  753. else
  754. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  755. return (wType & C1_UPPER);
  756. }
  757. // --------------------------------------------------------------------------
  758. // IsAlpha
  759. // --------------------------------------------------------------------------
  760. int IsAlpha(LPSTR psz)
  761. {
  762. WORD wType;
  763. if (IsDBCSLeadByte(*psz))
  764. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  765. else
  766. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  767. return (wType & C1_ALPHA);
  768. }
  769. // --------------------------------------------------------------------------
  770. // IsPunct
  771. // --------------------------------------------------------------------------
  772. int IsPunct(LPSTR psz)
  773. {
  774. WORD wType;
  775. if (IsDBCSLeadByte(*psz))
  776. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  777. else
  778. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  779. return (wType & C1_PUNCT);
  780. }
  781. // --------------------------------------------------------------------------
  782. // strsave
  783. // --------------------------------------------------------------------------
  784. char *strsave(char *s)
  785. {
  786. char *p;
  787. if (!s)
  788. return NULL;
  789. DWORD cchSize = (lstrlen(s)+1);
  790. if (MemAlloc((LPVOID*)&p, cchSize * sizeof(p[0])))
  791. {
  792. StrCpyN(p, s, cchSize);
  793. }
  794. return p;
  795. }
  796. // --------------------------------------------------------------------------
  797. // strtrim
  798. // --------------------------------------------------------------------------
  799. OESTDAPI_(LPSTR) strtrim(char *s)
  800. {
  801. char *p;
  802. for (p = s; *p; p++)
  803. ;
  804. for (--p ; (p>=s) && StrChr(" \t\r\n",*p); --p)
  805. *p = '\0';
  806. while (*s && StrChr(" \t\r\n",*s))
  807. ++s;
  808. return s;
  809. }
  810. OESTDAPI_(LPWSTR) strtrimW(WCHAR *s)
  811. {
  812. WCHAR *p;
  813. for (p = s; *p; p++)
  814. ;
  815. for (--p ; (p>=s) && StrChrW(L" \t\r\n",*p); --p)
  816. *p = '\0';
  817. while (*s && StrChrW(L" \t\r\n",*s))
  818. ++s;
  819. return s;
  820. }
  821. // --------------------------------------------------------------------------
  822. // strappend
  823. // --------------------------------------------------------------------------
  824. void strappend(char **pp, char *s)
  825. {
  826. char *p;
  827. Assert(pp);
  828. if (!s)
  829. return;
  830. if (!*pp)
  831. {
  832. DWORD cchSize = (lstrlen(s)+1);
  833. if (!MemAlloc((LPVOID*)&p, cchSize * sizeof(p[0])))
  834. return;
  835. StrCpyNA(p, s, cchSize);
  836. }
  837. else
  838. {
  839. DWORD cchSize = (lstrlen(s) + lstrlen(*pp) + 2);
  840. if (!MemAlloc((LPVOID*)&p, cchSize * sizeof(p[0])))
  841. return;
  842. StrCpyNA(p, *pp, cchSize);
  843. StrCatBuffA(p, "\r", cchSize);
  844. StrCatBuffA(p, s, cchSize);
  845. MemFree(*pp);
  846. }
  847. *pp = p;
  848. }
  849. OESTDAPI_(ULONG) UlStripWhitespace(LPTSTR lpsz, BOOL fLeading, BOOL fTrailing, ULONG *pcb)
  850. {
  851. // Locals
  852. ULONG cb;
  853. LPTSTR psz;
  854. Assert(lpsz != NULL);
  855. Assert(fLeading || fTrailing);
  856. // Did the user pass in the length
  857. if (pcb)
  858. cb = *pcb;
  859. else
  860. cb = lstrlen (lpsz);
  861. if (cb == 0)
  862. return cb;
  863. if (fLeading)
  864. {
  865. psz = lpsz;
  866. while (FIsSpace(psz))
  867. {
  868. psz++;
  869. cb--;
  870. }
  871. if (psz != lpsz)
  872. // get the NULL at the end too
  873. MoveMemory(lpsz, psz, (cb + 1) * sizeof(TCHAR));
  874. }
  875. if (fTrailing)
  876. {
  877. psz = lpsz + cb;
  878. while (cb > 0)
  879. {
  880. if (!FIsSpace(psz-1))
  881. break;
  882. psz--;
  883. cb--;
  884. }
  885. // NULL Term
  886. *psz = '\0';
  887. }
  888. // Set String Size
  889. if (pcb)
  890. *pcb = cb;
  891. // Done
  892. return cb;
  893. }
  894. OESTDAPI_(ULONG) UlStripWhitespaceW(LPWSTR lpwsz, BOOL fLeading, BOOL fTrailing, ULONG *pcb)
  895. {
  896. // Locals
  897. ULONG cb;
  898. LPWSTR pwsz;
  899. Assert(lpwsz != NULL);
  900. Assert(fLeading || fTrailing);
  901. // Did the user pass in the length
  902. if (pcb)
  903. cb = *pcb;
  904. else
  905. cb = lstrlenW(lpwsz)* sizeof(WCHAR) ; // multiply by sizeof(WCHAR) to get correct byte size.
  906. if (cb == 0)
  907. return cb;
  908. if (fLeading)
  909. {
  910. pwsz = lpwsz;
  911. while (FIsSpaceW(pwsz))
  912. {
  913. pwsz++;
  914. cb -= sizeof(*pwsz);
  915. }
  916. if (pwsz != lpwsz)
  917. // get the NULL at the end too
  918. MoveMemory(lpwsz, pwsz, cb + sizeof(WCHAR));
  919. }
  920. if (fTrailing)
  921. {
  922. pwsz = lpwsz + cb / sizeof(WCHAR); // Divided by size of WCHAR to get right pointer
  923. while (cb > 0)
  924. {
  925. if (!FIsSpaceW(pwsz - 1))
  926. break;
  927. pwsz--;
  928. cb -= sizeof(*pwsz);
  929. }
  930. // NULL Term
  931. *pwsz = L'\0';
  932. }
  933. // Set String Size
  934. if (pcb)
  935. *pcb = cb;
  936. // Done
  937. return cb;
  938. }
  939. // =============================================================================================
  940. // Converts first two characters of lpcsz to a WORD
  941. // =============================================================================================
  942. SHORT ASCII_NFromSz (LPCSTR lpcsz)
  943. {
  944. char acWordStr[3];
  945. Assert (lpcsz);
  946. CopyMemory (acWordStr, lpcsz, 2 * sizeof (char));
  947. acWordStr[2] = '\0';
  948. return ((SHORT) (StrToInt (acWordStr)));
  949. }
  950. // =================================================================================
  951. // Adjust the time at lpSysTime by adding the given lHoursToAdd &
  952. // lMinutesToAdd. Returns the adjusted time at lpFileTime.
  953. // =================================================================================
  954. HRESULT HrAdjustTime (LPSYSTEMTIME lpSysTime, LONG lHoursToAdd, LONG lMinutesToAdd, LPFILETIME lpFileTime)
  955. {
  956. // Locals
  957. HRESULT hr = S_OK;
  958. BOOL bResult = FALSE;
  959. LONG lUnitsToAdd = 0;
  960. LARGE_INTEGER liTime;
  961. LONGLONG liHoursToAdd = 1i64, liMinutesToAdd = 1i64;
  962. // Check Params
  963. AssertSz (lpSysTime && lpFileTime, "Null Parameter");
  964. // Convert sys time to file time
  965. if (!SystemTimeToFileTime (lpSysTime, lpFileTime))
  966. {
  967. hr = TRAPHR (E_FAIL);
  968. DebugTrace( "SystemTimeToFileTime() failed, dwError=%d.\n", GetLastError());
  969. goto Exit;
  970. }
  971. // Init
  972. liTime.LowPart = lpFileTime->dwLowDateTime;
  973. liTime.HighPart = lpFileTime->dwHighDateTime;
  974. // Adjust the hour
  975. if (lHoursToAdd != 0)
  976. {
  977. lUnitsToAdd = lHoursToAdd * 3600;
  978. liHoursToAdd *= lUnitsToAdd;
  979. liHoursToAdd *= 10000000i64;
  980. liTime.QuadPart += liHoursToAdd;
  981. }
  982. // Adjust the minutes
  983. if (lMinutesToAdd != 0)
  984. {
  985. lUnitsToAdd = lMinutesToAdd * 60;
  986. liMinutesToAdd *= lUnitsToAdd;
  987. liMinutesToAdd *= 10000000i64;
  988. liTime.QuadPart += liMinutesToAdd;
  989. }
  990. // Assign the result to FILETIME
  991. lpFileTime->dwLowDateTime = liTime.LowPart;
  992. lpFileTime->dwHighDateTime = liTime.HighPart;
  993. Exit:
  994. return hr;
  995. }
  996. // =================================================================================
  997. // Addjust the time at lpSysTime according to the given Zone info,
  998. // Returns the adjusted time at lpFileTime.
  999. // =================================================================================
  1000. BOOL ProcessZoneInfo (LPSTR lpszZoneInfo, INT *lpcHoursToAdd, INT *lpcMinutesToAdd)
  1001. {
  1002. // Locals
  1003. ULONG cbZoneInfo;
  1004. BOOL bResult;
  1005. // Init
  1006. *lpcHoursToAdd = 0;
  1007. *lpcMinutesToAdd = 0;
  1008. cbZoneInfo = lstrlen (lpszZoneInfo);
  1009. bResult = TRUE;
  1010. // +hhmm or -hhmm
  1011. if ((*lpszZoneInfo == '-' || *lpszZoneInfo == '+') && cbZoneInfo <= 5)
  1012. {
  1013. // Take off
  1014. cbZoneInfo-=1;
  1015. // determine the hour/minute offset
  1016. if (cbZoneInfo == 4)
  1017. {
  1018. *lpcMinutesToAdd = (INT)StrToInt (lpszZoneInfo+3);
  1019. *(lpszZoneInfo+3) = 0x00;
  1020. *lpcHoursToAdd = (INT)StrToInt(lpszZoneInfo+1);
  1021. }
  1022. // 3
  1023. else if (cbZoneInfo == 3)
  1024. {
  1025. *lpcMinutesToAdd = (INT)StrToInt (lpszZoneInfo+2);
  1026. *(lpszZoneInfo+2) = 0x00;
  1027. *lpcHoursToAdd = (INT)StrToInt (lpszZoneInfo+1);
  1028. }
  1029. // 2
  1030. else if (cbZoneInfo == 2 || cbZoneInfo == 1)
  1031. {
  1032. *lpcMinutesToAdd = 0;
  1033. *lpcHoursToAdd = (INT)StrToInt(lpszZoneInfo+1);
  1034. }
  1035. if (*lpszZoneInfo == '+')
  1036. {
  1037. *lpcHoursToAdd = -*lpcHoursToAdd;
  1038. *lpcMinutesToAdd = -*lpcMinutesToAdd;
  1039. }
  1040. }
  1041. // Xenix conversion: TZ = current time zone or other unknown tz types.
  1042. else if (lstrcmpi (lpszZoneInfo, "TZ") == 0 ||
  1043. lstrcmpi (lpszZoneInfo, "LOCAL") == 0 ||
  1044. lstrcmpi (lpszZoneInfo, "UNDEFINED") == 0)
  1045. {
  1046. TIME_ZONE_INFORMATION tzi ;
  1047. DWORD dwRet = GetTimeZoneInformation (&tzi);
  1048. if (dwRet != 0xFFFFFFFF)
  1049. {
  1050. LONG cMinuteBias = tzi.Bias;
  1051. if (dwRet == TIME_ZONE_ID_STANDARD)
  1052. cMinuteBias += tzi.StandardBias ;
  1053. else if (dwRet == TIME_ZONE_ID_DAYLIGHT)
  1054. cMinuteBias += tzi.DaylightBias ;
  1055. *lpcHoursToAdd = cMinuteBias / 60 ;
  1056. *lpcMinutesToAdd = cMinuteBias % 60 ;
  1057. }
  1058. else
  1059. {
  1060. AssertSz (FALSE, "Why would this happen");
  1061. bResult = FALSE;
  1062. }
  1063. }
  1064. // Loop through known time zone standards
  1065. else
  1066. {
  1067. for (INT i=0; g_rgZones[i].lpszZoneCode!=NULL; i++)
  1068. {
  1069. if (lstrcmpi (lpszZoneInfo, g_rgZones[i].lpszZoneCode) == 0)
  1070. {
  1071. *lpcHoursToAdd = g_rgZones[i].cHourOffset;
  1072. *lpcMinutesToAdd = g_rgZones[i].cMinuteOffset;
  1073. break;
  1074. }
  1075. }
  1076. if (g_rgZones[i].lpszZoneCode == NULL)
  1077. {
  1078. DebugTrace( "Unrecognized zone info: [%s]\n", lpszZoneInfo );
  1079. bResult = FALSE;
  1080. }
  1081. }
  1082. return bResult;
  1083. }
  1084. #define IS_DIGITA(ch) (ch >= '0' && ch <= '9')
  1085. #define IS_DIGITW(ch) (ch >= L'0' && ch <= L'9')
  1086. // ---------------------------------------------------------------------------------------
  1087. // StrToUintA
  1088. // ---------------------------------------------------------------------------------------
  1089. OESTDAPI_(UINT) StrToUintA(LPCSTR lpSrc)
  1090. {
  1091. UINT n = 0;
  1092. Assert(*lpSrc != '-');
  1093. while (IS_DIGITA(*lpSrc))
  1094. {
  1095. n *= 10;
  1096. n += *lpSrc - '0';
  1097. lpSrc++;
  1098. }
  1099. return n;
  1100. }
  1101. // ---------------------------------------------------------------------------------------
  1102. // StrToUintW
  1103. // ---------------------------------------------------------------------------------------
  1104. OESTDAPI_(UINT) StrToUintW(LPCWSTR lpSrc)
  1105. {
  1106. UINT n = 0;
  1107. Assert(*lpSrc != '-');
  1108. while (IS_DIGITW(*lpSrc))
  1109. {
  1110. n *= 10;
  1111. n += *lpSrc - L'0';
  1112. lpSrc++;
  1113. }
  1114. return n;
  1115. }
  1116. // ---------------------------------------------------------------------------------------
  1117. // FIsValidFileNameCharW
  1118. // ---------------------------------------------------------------------------------------
  1119. OESTDAPI_(BOOL) FIsValidFileNameCharW(WCHAR wch)
  1120. {
  1121. // Locals
  1122. LPWSTR pwsz;
  1123. static const WCHAR s_pwszBad[] = L"<>:\"/\\|?*";
  1124. pwsz = (LPWSTR)s_pwszBad;
  1125. while(*pwsz)
  1126. {
  1127. if (wch == *pwsz)
  1128. return FALSE;
  1129. pwsz++;
  1130. }
  1131. // Shouldn't allow any control chars
  1132. if ((wch >= 0x0000) && (wch < 0x0020))
  1133. return FALSE;
  1134. // Done
  1135. return TRUE;
  1136. }
  1137. // --------------------------------------------------------------------------
  1138. // FIsValidFileNameCharA
  1139. // --------------------------------------------------------------------------
  1140. OESTDAPI_(BOOL) FIsValidFileNameCharA(UINT codepage, CHAR ch)
  1141. {
  1142. // Locals
  1143. LPSTR psz;
  1144. static const CHAR s_szBad[] = "<>:\"/\\|?*";
  1145. psz = (LPSTR)s_szBad;
  1146. while(*psz)
  1147. {
  1148. if (IsDBCSLeadByteEx(codepage, *psz))
  1149. psz++;
  1150. else if (ch == *psz)
  1151. return FALSE;
  1152. psz++;
  1153. }
  1154. // Shouldn't allow any control chars
  1155. if ((ch >= 0x00) && (ch < 0x20))
  1156. return FALSE;
  1157. // Done
  1158. return TRUE;
  1159. }
  1160. // --------------------------------------------------------------------------
  1161. // CleanupFileNameInPlaceA
  1162. // --------------------------------------------------------------------------
  1163. OESTDAPI_(ULONG) EXPORT_16 CleanupFileNameInPlaceA(UINT codepage, LPSTR psz)
  1164. {
  1165. UINT ich=0;
  1166. UINT cch=lstrlen(psz);
  1167. // Fixup codepage?
  1168. if (1200 == codepage)
  1169. codepage = CP_ACP;
  1170. // Loop and remove invalid chars
  1171. while (ich < cch)
  1172. {
  1173. // If lead byte, skip it, its leagal
  1174. if (IsDBCSLeadByteEx(codepage, psz[ich]))
  1175. ich+=2;
  1176. // Illeagl file name character ?
  1177. else if (!FIsValidFileNameCharA(codepage, psz[ich]))
  1178. {
  1179. MoveMemory (psz + ich, psz + (ich + 1), cch - ich);
  1180. cch--;
  1181. }
  1182. else
  1183. ich++;
  1184. }
  1185. // Return the Length
  1186. return cch;
  1187. }
  1188. // --------------------------------------------------------------------------
  1189. // CleanupFileNameInPlaceW
  1190. // --------------------------------------------------------------------------
  1191. OESTDAPI_(ULONG) EXPORT_16 CleanupFileNameInPlaceW(LPWSTR pwsz)
  1192. {
  1193. // Locals
  1194. ULONG ich=0;
  1195. ULONG cch=lstrlenW(pwsz);
  1196. // Loop and remove invalids
  1197. while (ich < cch)
  1198. {
  1199. // Illeagl file name character ?
  1200. if (!FIsValidFileNameCharW(pwsz[ich]))
  1201. pwsz[ich]=L'_';
  1202. ich++;
  1203. }
  1204. // Return the length
  1205. return cch;
  1206. }
  1207. // =============================================================================================
  1208. // ReplaceChars
  1209. // =============================================================================================
  1210. OESTDAPI_(INT) EXPORT_16 ReplaceChars(LPCSTR pszString, CHAR chFind, CHAR chReplace)
  1211. {
  1212. // Locals
  1213. LPSTR pszT=(LPSTR)pszString;
  1214. DWORD nCount=0;
  1215. // Loop for ch in pszString
  1216. while(*pszT)
  1217. {
  1218. // Lead Byte
  1219. if (IsDBCSLeadByte(*pszT))
  1220. pszT++;
  1221. else if (*pszT == chFind)
  1222. {
  1223. *pszT = chReplace;
  1224. nCount++;
  1225. }
  1226. pszT++;
  1227. }
  1228. // Not Found
  1229. return nCount;
  1230. }
  1231. OESTDAPI_(INT) EXPORT_16 ReplaceCharsW(LPCWSTR pszString, WCHAR chFind, WCHAR chReplace)
  1232. {
  1233. // Locals
  1234. LPWSTR pszT = (LPWSTR)pszString;
  1235. DWORD nCount=0;
  1236. // Loop for ch in pszString
  1237. while(*pszT)
  1238. {
  1239. if (*pszT == chFind)
  1240. {
  1241. *pszT = chReplace;
  1242. nCount++;
  1243. }
  1244. pszT++;
  1245. }
  1246. // Not Found
  1247. return nCount;
  1248. }
  1249. OESTDAPI_(BOOL) IsValidFileIfFileUrl(LPSTR pszUrl)
  1250. {
  1251. TCHAR rgch[MAX_PATH];
  1252. ULONG cch=ARRAYSIZE(rgch);
  1253. // pathCreate from url execpts a cannonicalised url with file:// infront
  1254. if (UrlCanonicalizeA(pszUrl, rgch, &cch, 0)==S_OK)
  1255. {
  1256. cch = ARRAYSIZE(rgch);
  1257. if (PathCreateFromUrlA(rgch, rgch, &cch, 0)==S_OK &&
  1258. !PathFileExistsA(rgch))
  1259. return FALSE;
  1260. }
  1261. return TRUE;
  1262. }
  1263. OESTDAPI_(BOOL) IsValidFileIfFileUrlW(LPWSTR pwszUrl)
  1264. {
  1265. WCHAR wsz[MAX_PATH];
  1266. ULONG cch=ARRAYSIZE(wsz);
  1267. // pathCreate from url execpts a cannonicalised url with file:// infront
  1268. if (UrlCanonicalizeW(pwszUrl, wsz, &cch, 0)==S_OK)
  1269. {
  1270. cch = ARRAYSIZE(wsz);
  1271. if (PathCreateFromUrlW(wsz, wsz, &cch, 0)==S_OK &&
  1272. !PathFileExistsW(wsz))
  1273. return FALSE;
  1274. }
  1275. return TRUE;
  1276. }
  1277. /***
  1278. *char *StrTokEx(pstring, control) - tokenize string with delimiter in control
  1279. *
  1280. *Purpose:
  1281. * StrTokEx considers the string to consist of a sequence of zero or more
  1282. * text tokens separated by spans of one or more control chars. the first
  1283. * call, with string specified, returns a pointer to the first char of the
  1284. * first token, and will write a null char into pstring immediately
  1285. * following the returned token. when no tokens remain
  1286. * in pstring a NULL pointer is returned. remember the control chars with a
  1287. * bit map, one bit per ascii char. the null char is always a control char.
  1288. *
  1289. *Entry:
  1290. * char **pstring - ptr to ptr to string to tokenize
  1291. * char *control - string of characters to use as delimiters
  1292. *
  1293. *Exit:
  1294. * returns pointer to first token in string,
  1295. * returns NULL when no more tokens remain.
  1296. * pstring points to the beginning of the next token.
  1297. *
  1298. *WARNING!!!
  1299. * upon exit, the first delimiter in the input string will be replaced with '\0'
  1300. *
  1301. *******************************************************************************/
  1302. char * __cdecl StrTokEx (char ** ppszIn, const char * pcszCtrlIn)
  1303. {
  1304. unsigned char *psz;
  1305. const unsigned char *pszCtrl = (const unsigned char *)pcszCtrlIn;
  1306. unsigned char map[32] = {0};
  1307. LPSTR pszToken;
  1308. if(*ppszIn == NULL)
  1309. return NULL;
  1310. /* Set bits in delimiter table */
  1311. do
  1312. {
  1313. map[*pszCtrl >> 3] |= (1 << (*pszCtrl & 7));
  1314. }
  1315. while (*pszCtrl++);
  1316. /* Initialize str. */
  1317. psz = (unsigned char*)*ppszIn;
  1318. /* Find beginning of token (skip over leading delimiters). Note that
  1319. * there is no token if this loop sets str to point to the terminal
  1320. * null (*str == '\0') */
  1321. while ((map[*psz >> 3] & (1 << (*psz & 7))) && *psz)
  1322. psz++;
  1323. pszToken = (LPSTR)psz;
  1324. /* Find the end of the token. If it is not the end of the string,
  1325. * put a null there. */
  1326. for (; *psz ; psz++)
  1327. {
  1328. if (map[*psz >> 3] & (1 << (*psz & 7)))
  1329. {
  1330. *psz++ = '\0';
  1331. break;
  1332. }
  1333. }
  1334. /* string now points to beginning of next token */
  1335. *ppszIn = (LPSTR)psz;
  1336. /* Determine if a token has been found. */
  1337. if (pszToken == (LPSTR)psz)
  1338. return NULL;
  1339. else
  1340. return pszToken;
  1341. }