ReactOS 0.4.15-dev-7788-g1ad9096
string.c
Go to the documentation of this file.
1/*
2 * Shlwapi string functions
3 *
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2002 Jon Griffiths
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include "config.h"
23#include "wine/port.h"
24
25#include <math.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <string.h>
29
30#define NONAMELESSUNION
31
32#include "windef.h"
33#include "winbase.h"
34#define NO_SHLWAPI_REG
35#define NO_SHLWAPI_STREAM
36#include "shlwapi.h"
37#include "wingdi.h"
38#include "winuser.h"
39#include "shlobj.h"
40#include "mlang.h"
41#include "ddeml.h"
42#include "wine/unicode.h"
43#include "wine/debug.h"
44
45#include "resource.h"
46
48
50
53
54
55static void FillNumberFmt(NUMBERFMTW *fmt, LPWSTR decimal_buffer, int decimal_bufwlen,
56 LPWSTR thousand_buffer, int thousand_bufwlen)
57{
58 WCHAR grouping[64];
59 WCHAR *c;
60
61 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_ILZERO|LOCALE_RETURN_NUMBER, (LPWSTR)&fmt->LeadingZero, sizeof(fmt->LeadingZero)/sizeof(WCHAR));
62 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER|LOCALE_RETURN_NUMBER, (LPWSTR)&fmt->LeadingZero, sizeof(fmt->NegativeOrder)/sizeof(WCHAR));
63 fmt->NumDigits = 0;
64 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, decimal_buffer, decimal_bufwlen);
65 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousand_buffer, thousand_bufwlen);
66 fmt->lpThousandSep = thousand_buffer;
67 fmt->lpDecimalSep = decimal_buffer;
68
69 /*
70 * Converting grouping string to number as described on
71 * http://blogs.msdn.com/oldnewthing/archive/2006/04/18/578251.aspx
72 */
73 fmt->Grouping = 0;
74 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, grouping, sizeof(grouping)/sizeof(WCHAR));
75 for (c = grouping; *c; c++)
76 if (*c >= '0' && *c < '9')
77 {
78 fmt->Grouping *= 10;
79 fmt->Grouping += *c - '0';
80 }
81
82 if (fmt->Grouping % 10 == 0)
83 fmt->Grouping /= 10;
84 else
85 fmt->Grouping *= 10;
86}
87
88/*************************************************************************
89 * FormatInt [internal]
90 *
91 * Format an integer according to the current locale
92 *
93 * RETURNS
94 * The number of characters written on success or 0 on failure
95 */
96static int FormatInt(LONGLONG qdwValue, LPWSTR pszBuf, int cchBuf)
97{
99 WCHAR decimal[8], thousand[8];
100 WCHAR buf[24];
101 WCHAR *c;
102 BOOL neg = (qdwValue < 0);
103
104 FillNumberFmt(&fmt, decimal, sizeof decimal / sizeof (WCHAR),
105 thousand, sizeof thousand / sizeof (WCHAR));
106
107 c = &buf[24];
108 *(--c) = 0;
109 do
110 {
111 *(--c) = '0' + (qdwValue%10);
112 qdwValue /= 10;
113 } while (qdwValue > 0);
114 if (neg)
115 *(--c) = '-';
116
117 return GetNumberFormatW(LOCALE_USER_DEFAULT, 0, c, &fmt, pszBuf, cchBuf);
118}
119
120/*************************************************************************
121 * FormatDouble [internal]
122 *
123 * Format an integer according to the current locale. Prints the specified number of digits
124 * after the decimal point
125 *
126 * RETURNS
127 * The number of characters written on success or 0 on failure
128 */
129static int FormatDouble(double value, int decimals, LPWSTR pszBuf, int cchBuf)
130{
131 static const WCHAR flfmt[] = {'%','f',0};
132 WCHAR buf[64];
134 WCHAR decimal[8], thousand[8];
135
136 snprintfW(buf, 64, flfmt, value);
137
138 FillNumberFmt(&fmt, decimal, sizeof decimal / sizeof (WCHAR),
139 thousand, sizeof thousand / sizeof (WCHAR));
140 fmt.NumDigits = decimals;
141 return GetNumberFormatW(LOCALE_USER_DEFAULT, 0, buf, &fmt, pszBuf, cchBuf);
142}
143
144/*************************************************************************
145 * SHLWAPI_ChrCmpHelperA
146 *
147 * Internal helper for SHLWAPI_ChrCmpA/ChrCMPIA.
148 *
149 * NOTES
150 * Both this function and its Unicode counterpart are very inefficient. To
151 * fix this, CompareString must be completely implemented and optimised
152 * first. Then the core character test can be taken out of that function and
153 * placed here, so that it need never be called at all. Until then, do not
154 * attempt to optimise this code unless you are willing to test that it
155 * still performs correctly.
156 */
158{
159 char str1[3], str2[3];
160
161 str1[0] = LOBYTE(ch1);
162 if (IsDBCSLeadByte(str1[0]))
163 {
164 str1[1] = HIBYTE(ch1);
165 str1[2] = '\0';
166 }
167 else
168 str1[1] = '\0';
169
170 str2[0] = LOBYTE(ch2);
171 if (IsDBCSLeadByte(str2[0]))
172 {
173 str2[1] = HIBYTE(ch2);
174 str2[2] = '\0';
175 }
176 else
177 str2[1] = '\0';
178
179 return CompareStringA(GetThreadLocale(), dwFlags, str1, -1, str2, -1) - CSTR_EQUAL;
180}
181
182/*************************************************************************
183 * SHLWAPI_ChrCmpA
184 *
185 * Internal helper function.
186 */
188{
189 return SHLWAPI_ChrCmpHelperA(ch1, ch2, 0);
190}
191
192/*************************************************************************
193 * ChrCmpIA (SHLWAPI.385)
194 *
195 * Compare two characters, ignoring case.
196 *
197 * PARAMS
198 * ch1 [I] First character to compare
199 * ch2 [I] Second character to compare
200 *
201 * RETURNS
202 * FALSE, if the characters are equal.
203 * Non-zero otherwise.
204 */
206{
207 TRACE("(%d,%d)\n", ch1, ch2);
208
209 return SHLWAPI_ChrCmpHelperA(ch1, ch2, NORM_IGNORECASE);
210}
211
212/*************************************************************************
213 * ChrCmpIW [SHLWAPI.386]
214 *
215 * See ChrCmpIA.
216 */
218{
219 return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL;
220}
221
222/*************************************************************************
223 * StrChrA [SHLWAPI.@]
224 *
225 * Find a given character in a string.
226 *
227 * PARAMS
228 * lpszStr [I] String to search in.
229 * ch [I] Character to search for.
230 *
231 * RETURNS
232 * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if
233 * not found.
234 * Failure: NULL, if any arguments are invalid.
235 */
237{
238 TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch);
239
240 if (lpszStr)
241 {
242 while (*lpszStr)
243 {
244 if (!SHLWAPI_ChrCmpA(*lpszStr, ch))
245 return (LPSTR)lpszStr;
246 lpszStr = CharNextA(lpszStr);
247 }
248 }
249 return NULL;
250}
251
252/*************************************************************************
253 * StrChrW [SHLWAPI.@]
254 *
255 * See StrChrA.
256 */
258{
259 LPWSTR lpszRet = NULL;
260
261 TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch);
262
263 if (lpszStr)
264 lpszRet = strchrW(lpszStr, ch);
265 return lpszRet;
266}
267
268/*************************************************************************
269 * StrChrIA [SHLWAPI.@]
270 *
271 * Find a given character in a string, ignoring case.
272 *
273 * PARAMS
274 * lpszStr [I] String to search in.
275 * ch [I] Character to search for.
276 *
277 * RETURNS
278 * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if
279 * not found.
280 * Failure: NULL, if any arguments are invalid.
281 */
283{
284 TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch);
285
286 if (lpszStr)
287 {
288 while (*lpszStr)
289 {
290 if (!ChrCmpIA(*lpszStr, ch))
291 return (LPSTR)lpszStr;
292 lpszStr = CharNextA(lpszStr);
293 }
294 }
295 return NULL;
296}
297
298/*************************************************************************
299 * StrChrIW [SHLWAPI.@]
300 *
301 * See StrChrA.
302 */
304{
305 TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch);
306
307 if (lpszStr)
308 {
309 ch = toupperW(ch);
310 while (*lpszStr)
311 {
312 if (toupperW(*lpszStr) == ch)
313 return (LPWSTR)lpszStr;
314 lpszStr++;
315 }
316 lpszStr = NULL;
317 }
318 return (LPWSTR)lpszStr;
319}
320
321/*************************************************************************
322 * StrChrNW [SHLWAPI.@]
323 */
325{
326 TRACE("(%s(%i),%i)\n", debugstr_wn(lpszStr,cchMax), cchMax, ch);
327
328 if (lpszStr)
329 {
330 while (*lpszStr && cchMax-- > 0)
331 {
332 if (*lpszStr == ch)
333 return (LPWSTR)lpszStr;
334 lpszStr++;
335 }
336 }
337 return NULL;
338}
339
340/*************************************************************************
341 * StrCmpIW [SHLWAPI.@]
342 *
343 * Compare two strings, ignoring case.
344 *
345 * PARAMS
346 * lpszStr [I] First string to compare
347 * lpszComp [I] Second string to compare
348 *
349 * RETURNS
350 * An integer less than, equal to or greater than 0, indicating that
351 * lpszStr is less than, the same, or greater than lpszComp.
352 */
353int WINAPI StrCmpIW(LPCWSTR lpszStr, LPCWSTR lpszComp)
354{
355 TRACE("(%s,%s)\n", debugstr_w(lpszStr),debugstr_w(lpszComp));
356 return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, -1, lpszComp, -1) - CSTR_EQUAL;
357}
358
359/*************************************************************************
360 * StrCmpNA [SHLWAPI.@]
361 *
362 * Compare two strings, up to a maximum length.
363 *
364 * PARAMS
365 * lpszStr [I] First string to compare
366 * lpszComp [I] Second string to compare
367 * iLen [I] Number of chars to compare
368 *
369 * RETURNS
370 * An integer less than, equal to or greater than 0, indicating that
371 * lpszStr is less than, the same, or greater than lpszComp.
372 */
373INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
374{
375 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
376 return CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
377}
378
379/*************************************************************************
380 * StrCmpNW [SHLWAPI.@]
381 *
382 * See StrCmpNA.
383 */
384INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
385{
386 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
387 return CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
388}
389
390/*************************************************************************
391 * StrCmpNIA [SHLWAPI.@]
392 *
393 * Compare two strings, up to a maximum length, ignoring case.
394 *
395 * PARAMS
396 * lpszStr [I] First string to compare
397 * lpszComp [I] Second string to compare
398 * iLen [I] Number of chars to compare
399 *
400 * RETURNS
401 * An integer less than, equal to or greater than 0, indicating that
402 * lpszStr is less than, the same, or greater than lpszComp.
403 */
404int WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, int iLen)
405{
406 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
407 return CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
408}
409
410/*************************************************************************
411 * StrCmpNIW [SHLWAPI.@]
412 *
413 * See StrCmpNIA.
414 */
415INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen)
416{
417 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
418 return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
419}
420
421/*************************************************************************
422 * StrCmpW [SHLWAPI.@]
423 *
424 * Compare two strings.
425 *
426 * PARAMS
427 * lpszStr [I] First string to compare
428 * lpszComp [I] Second string to compare
429 *
430 * RETURNS
431 * An integer less than, equal to or greater than 0, indicating that
432 * lpszStr is less than, the same, or greater than lpszComp.
433 */
434int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp)
435{
436 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
437 return CompareStringW(GetThreadLocale(), 0, lpszStr, -1, lpszComp, -1) - CSTR_EQUAL;
438}
439
440/*************************************************************************
441 * StrCatW [SHLWAPI.@]
442 *
443 * Concatenate two strings.
444 *
445 * PARAMS
446 * lpszStr [O] Initial string
447 * lpszSrc [I] String to concatenate
448 *
449 * RETURNS
450 * lpszStr.
451 */
453{
454 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSrc));
455
456 if (lpszStr && lpszSrc)
457 strcatW(lpszStr, lpszSrc);
458 return lpszStr;
459}
460
461/*************************************************************************
462 * StrCatChainW [SHLWAPI.@]
463 *
464 * Concatenates two unicode strings.
465 *
466 * PARAMS
467 * lpszStr [O] Initial string
468 * cchMax [I] Length of destination buffer
469 * ichAt [I] Offset from the destination buffer to begin concatenation
470 * lpszCat [I] String to concatenate
471 *
472 * RETURNS
473 * The offset from the beginning of pszDst to the terminating NULL.
474 */
476{
477 TRACE("(%s,%u,%d,%s)\n", debugstr_w(lpszStr), cchMax, ichAt, debugstr_w(lpszCat));
478
479 if (ichAt == -1)
480 ichAt = strlenW(lpszStr);
481
482 if (!cchMax)
483 return ichAt;
484
485 if (ichAt == cchMax)
486 ichAt--;
487
488 if (lpszCat && ichAt < cchMax)
489 {
490 lpszStr += ichAt;
491 while (ichAt < cchMax - 1 && *lpszCat)
492 {
493 *lpszStr++ = *lpszCat++;
494 ichAt++;
495 }
496 *lpszStr = 0;
497 }
498
499 return ichAt;
500}
501
502/*************************************************************************
503 * StrCpyW [SHLWAPI.@]
504 *
505 * Copy a string to another string.
506 *
507 * PARAMS
508 * lpszStr [O] Destination string
509 * lpszSrc [I] Source string
510 *
511 * RETURNS
512 * lpszStr.
513 */
515{
516 TRACE("(%p,%s)\n", lpszStr, debugstr_w(lpszSrc));
517
518 if (lpszStr && lpszSrc)
519 strcpyW(lpszStr, lpszSrc);
520 return lpszStr;
521}
522
523/*************************************************************************
524 * StrCpyNW [SHLWAPI.@]
525 *
526 * Copy a string to another string, up to a maximum number of characters.
527 *
528 * PARAMS
529 * dst [O] Destination string
530 * src [I] Source string
531 * count [I] Maximum number of chars to copy
532 *
533 * RETURNS
534 * dst.
535 */
537{
538 LPWSTR d = dst;
539 LPCWSTR s = src;
540
541 TRACE("(%p,%s,%i)\n", dst, debugstr_w(src), count);
542
543 if (s)
544 {
545 while ((count > 1) && *s)
546 {
547 count--;
548 *d++ = *s++;
549 }
550 }
551 if (count) *d = 0;
552
553 return dst;
554}
555
556/*************************************************************************
557 * SHLWAPI_StrStrHelperA
558 *
559 * Internal implementation of StrStrA/StrStrIA
560 */
561static LPSTR SHLWAPI_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch,
562 INT (WINAPI *pStrCmpFn)(LPCSTR,LPCSTR,INT))
563{
564 size_t iLen;
565 LPCSTR end;
566
567 if (!lpszStr || !lpszSearch || !*lpszSearch)
568 return NULL;
569
570 iLen = strlen(lpszSearch);
571 end = lpszStr + strlen(lpszStr);
572
573 while (lpszStr + iLen <= end)
574 {
575 if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
576 return (LPSTR)lpszStr;
577 lpszStr = CharNextA(lpszStr);
578 }
579 return NULL;
580}
581
582/*************************************************************************
583 * StrStrA [SHLWAPI.@]
584 *
585 * Find a substring within a string.
586 *
587 * PARAMS
588 * lpszStr [I] String to search in
589 * lpszSearch [I] String to look for
590 *
591 * RETURNS
592 * The start of lpszSearch within lpszStr, or NULL if not found.
593 */
594LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
595{
596 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
597
598 return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, StrCmpNA);
599}
600
601/*************************************************************************
602 * StrStrW [SHLWAPI.@]
603 *
604 * See StrStrA.
605 */
606LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
607{
608 TRACE("(%s, %s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
609
610 if (!lpszStr || !lpszSearch || !*lpszSearch) return NULL;
611 return strstrW( lpszStr, lpszSearch );
612}
613
614/*************************************************************************
615 * StrRStrIA [SHLWAPI.@]
616 *
617 * Find the last occurrence of a substring within a string.
618 *
619 * PARAMS
620 * lpszStr [I] String to search in
621 * lpszEnd [I] End of lpszStr
622 * lpszSearch [I] String to look for
623 *
624 * RETURNS
625 * The last occurrence lpszSearch within lpszStr, or NULL if not found.
626 */
627LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch)
628{
629 LPSTR lpszRet = NULL;
630 WORD ch1, ch2;
631 INT iLen;
632
633 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
634
635 if (!lpszStr || !lpszSearch || !*lpszSearch)
636 return NULL;
637
638 if (IsDBCSLeadByte(*lpszSearch))
639 ch1 = *lpszSearch << 8 | (UCHAR)lpszSearch[1];
640 else
641 ch1 = *lpszSearch;
642 iLen = lstrlenA(lpszSearch);
643
644 if (!lpszEnd)
645 lpszEnd = lpszStr + lstrlenA(lpszStr);
646 else /* reproduce the broken behaviour on Windows */
647 lpszEnd += min(iLen - 1, lstrlenA(lpszEnd));
648
649 while (lpszStr + iLen <= lpszEnd && *lpszStr)
650 {
651 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | (UCHAR)lpszStr[1] : *lpszStr;
652 if (!ChrCmpIA(ch1, ch2))
653 {
654 if (!StrCmpNIA(lpszStr, lpszSearch, iLen))
655 lpszRet = (LPSTR)lpszStr;
656 }
657 lpszStr = CharNextA(lpszStr);
658 }
659 return lpszRet;
660}
661
662/*************************************************************************
663 * StrRStrIW [SHLWAPI.@]
664 *
665 * See StrRStrIA.
666 */
667LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch)
668{
669 LPWSTR lpszRet = NULL;
670 INT iLen;
671
672 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
673
674 if (!lpszStr || !lpszSearch || !*lpszSearch)
675 return NULL;
676
677 iLen = strlenW(lpszSearch);
678
679 if (!lpszEnd)
680 lpszEnd = lpszStr + strlenW(lpszStr);
681 else /* reproduce the broken behaviour on Windows */
682 lpszEnd += min(iLen - 1, lstrlenW(lpszEnd));
683
684 while (lpszStr + iLen <= lpszEnd && *lpszStr)
685 {
686 if (!ChrCmpIW(*lpszSearch, *lpszStr))
687 {
688 if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
689 lpszRet = (LPWSTR)lpszStr;
690 }
691 lpszStr++;
692 }
693 return lpszRet;
694}
695
696/*************************************************************************
697 * StrStrIA [SHLWAPI.@]
698 *
699 * Find a substring within a string, ignoring case.
700 *
701 * PARAMS
702 * lpszStr [I] String to search in
703 * lpszSearch [I] String to look for
704 *
705 * RETURNS
706 * The start of lpszSearch within lpszStr, or NULL if not found.
707 */
708LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
709{
710 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
711
712 return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, StrCmpNIA);
713}
714
715/*************************************************************************
716 * StrStrIW [SHLWAPI.@]
717 *
718 * See StrStrIA.
719 */
721{
722 int iLen;
723 LPCWSTR end;
724
725 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
726
727 if (!lpszStr || !lpszSearch || !*lpszSearch)
728 return NULL;
729
730 iLen = strlenW(lpszSearch);
731 end = lpszStr + strlenW(lpszStr);
732
733 while (lpszStr + iLen <= end)
734 {
735 if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
736 return (LPWSTR)lpszStr;
737 lpszStr++;
738 }
739 return NULL;
740}
741
742/*************************************************************************
743 * StrStrNW [SHLWAPI.@]
744 *
745 * Find a substring within a string up to a given number of initial characters.
746 *
747 * PARAMS
748 * lpFirst [I] String to search in
749 * lpSrch [I] String to look for
750 * cchMax [I] Maximum number of initial search characters
751 *
752 * RETURNS
753 * The start of lpFirst within lpSrch, or NULL if not found.
754 */
756{
757 UINT i;
758 int len;
759
760 TRACE("(%s, %s, %u)\n", debugstr_w(lpFirst), debugstr_w(lpSrch), cchMax);
761
762 if (!lpFirst || !lpSrch || !*lpSrch || !cchMax)
763 return NULL;
764
765 len = strlenW(lpSrch);
766
767 for (i = cchMax; *lpFirst && (i > 0); i--, lpFirst++)
768 {
769 if (!strncmpW(lpFirst, lpSrch, len))
770 return (LPWSTR)lpFirst;
771 }
772
773 return NULL;
774}
775
776/*************************************************************************
777 * StrStrNIW [SHLWAPI.@]
778 *
779 * Find a substring within a string up to a given number of initial characters,
780 * ignoring case.
781 *
782 * PARAMS
783 * lpFirst [I] String to search in
784 * lpSrch [I] String to look for
785 * cchMax [I] Maximum number of initial search characters
786 *
787 * RETURNS
788 * The start of lpFirst within lpSrch, or NULL if not found.
789 */
791{
792 UINT i;
793 int len;
794
795 TRACE("(%s, %s, %u)\n", debugstr_w(lpFirst), debugstr_w(lpSrch), cchMax);
796
797 if (!lpFirst || !lpSrch || !*lpSrch || !cchMax)
798 return NULL;
799
800 len = strlenW(lpSrch);
801
802 for (i = cchMax; *lpFirst && (i > 0); i--, lpFirst++)
803 {
804 if (!strncmpiW(lpFirst, lpSrch, len))
805 return (LPWSTR)lpFirst;
806 }
807
808 return NULL;
809}
810
811/*************************************************************************
812 * StrToIntA [SHLWAPI.@]
813 *
814 * Read a signed integer from a string.
815 *
816 * PARAMS
817 * lpszStr [I] String to read integer from
818 *
819 * RETURNS
820 * The signed integer value represented by the string, or 0 if no integer is
821 * present.
822 *
823 * NOTES
824 * No leading space is allowed before the number, although a leading '-' is.
825 */
827{
828 int iRet = 0;
829
830 TRACE("(%s)\n", debugstr_a(lpszStr));
831
832 if (!lpszStr)
833 {
834 WARN("Invalid lpszStr would crash under Win32!\n");
835 return 0;
836 }
837
838 if (*lpszStr == '-' || isdigit(*lpszStr))
839 StrToIntExA(lpszStr, 0, &iRet);
840 return iRet;
841}
842
843/*************************************************************************
844 * StrToIntW [SHLWAPI.@]
845 *
846 * See StrToIntA.
847 */
849{
850 int iRet = 0;
851
852 TRACE("(%s)\n", debugstr_w(lpszStr));
853
854 if (!lpszStr)
855 {
856 WARN("Invalid lpszStr would crash under Win32!\n");
857 return 0;
858 }
859
860 if (*lpszStr == '-' || isdigitW(*lpszStr))
861 StrToIntExW(lpszStr, 0, &iRet);
862 return iRet;
863}
864
865/*************************************************************************
866 * StrToIntExA [SHLWAPI.@]
867 *
868 * Read an integer from a string.
869 *
870 * PARAMS
871 * lpszStr [I] String to read integer from
872 * dwFlags [I] Flags controlling the conversion
873 * lpiRet [O] Destination for read integer.
874 *
875 * RETURNS
876 * Success: TRUE. lpiRet contains the integer value represented by the string.
877 * Failure: FALSE, if the string is invalid, or no number is present.
878 *
879 * NOTES
880 * Leading whitespace, '-' and '+' are allowed before the number. If
881 * dwFlags includes STIF_SUPPORT_HEX, hexadecimal numbers are allowed, if
882 * preceded by '0x'. If this flag is not set, or there is no '0x' prefix,
883 * the string is treated as a decimal string. A leading '-' is ignored for
884 * hexadecimal numbers.
885 */
887{
888 LONGLONG li;
889 BOOL bRes;
890
891 TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet);
892
893 bRes = StrToInt64ExA(lpszStr, dwFlags, &li);
894 if (bRes) *lpiRet = li;
895 return bRes;
896}
897
898/*************************************************************************
899 * StrToInt64ExA [SHLWAPI.@]
900 *
901 * See StrToIntExA.
902 */
904{
905 BOOL bNegative = FALSE;
906 LONGLONG iRet = 0;
907
908 TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet);
909
910 if (!lpszStr || !lpiRet)
911 {
912 WARN("Invalid parameter would crash under Win32!\n");
913 return FALSE;
914 }
915 if (dwFlags > STIF_SUPPORT_HEX) WARN("Unknown flags %08x\n", dwFlags);
916
917 /* Skip leading space, '+', '-' */
918 while (isspace(*lpszStr))
919 lpszStr = CharNextA(lpszStr);
920
921 if (*lpszStr == '-')
922 {
923 bNegative = TRUE;
924 lpszStr++;
925 }
926 else if (*lpszStr == '+')
927 lpszStr++;
928
930 *lpszStr == '0' && tolower(lpszStr[1]) == 'x')
931 {
932 /* Read hex number */
933 lpszStr += 2;
934
935 if (!isxdigit(*lpszStr))
936 return FALSE;
937
938 while (isxdigit(*lpszStr))
939 {
940 iRet = iRet * 16;
941 if (isdigit(*lpszStr))
942 iRet += (*lpszStr - '0');
943 else
944 iRet += 10 + (tolower(*lpszStr) - 'a');
945 lpszStr++;
946 }
947 *lpiRet = iRet;
948 return TRUE;
949 }
950
951 /* Read decimal number */
952 if (!isdigit(*lpszStr))
953 return FALSE;
954
955 while (isdigit(*lpszStr))
956 {
957 iRet = iRet * 10;
958 iRet += (*lpszStr - '0');
959 lpszStr++;
960 }
961 *lpiRet = bNegative ? -iRet : iRet;
962 return TRUE;
963}
964
965/*************************************************************************
966 * StrToIntExW [SHLWAPI.@]
967 *
968 * See StrToIntExA.
969 */
971{
972 LONGLONG li;
973 BOOL bRes;
974
975 TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet);
976
977 bRes = StrToInt64ExW(lpszStr, dwFlags, &li);
978 if (bRes) *lpiRet = li;
979 return bRes;
980}
981
982/*************************************************************************
983 * StrToInt64ExW [SHLWAPI.@]
984 *
985 * See StrToIntExA.
986 */
988{
989 BOOL bNegative = FALSE;
990 LONGLONG iRet = 0;
991
992 TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet);
993
994 if (!lpszStr || !lpiRet)
995 {
996 WARN("Invalid parameter would crash under Win32!\n");
997 return FALSE;
998 }
999 if (dwFlags > STIF_SUPPORT_HEX) WARN("Unknown flags %08x\n", dwFlags);
1000
1001 /* Skip leading space, '+', '-' */
1002 while (isspaceW(*lpszStr)) lpszStr++;
1003
1004 if (*lpszStr == '-')
1005 {
1006 bNegative = TRUE;
1007 lpszStr++;
1008 }
1009 else if (*lpszStr == '+')
1010 lpszStr++;
1011
1012 if (dwFlags & STIF_SUPPORT_HEX &&
1013 *lpszStr == '0' && tolowerW(lpszStr[1]) == 'x')
1014 {
1015 /* Read hex number */
1016 lpszStr += 2;
1017
1018 if (!isxdigitW(*lpszStr))
1019 return FALSE;
1020
1021 while (isxdigitW(*lpszStr))
1022 {
1023 iRet = iRet * 16;
1024 if (isdigitW(*lpszStr))
1025 iRet += (*lpszStr - '0');
1026 else
1027 iRet += 10 + (tolowerW(*lpszStr) - 'a');
1028 lpszStr++;
1029 }
1030 *lpiRet = iRet;
1031 return TRUE;
1032 }
1033
1034 /* Read decimal number */
1035 if (!isdigitW(*lpszStr))
1036 return FALSE;
1037
1038 while (isdigitW(*lpszStr))
1039 {
1040 iRet = iRet * 10;
1041 iRet += (*lpszStr - '0');
1042 lpszStr++;
1043 }
1044 *lpiRet = bNegative ? -iRet : iRet;
1045 return TRUE;
1046}
1047
1048/*************************************************************************
1049 * StrDupA [SHLWAPI.@]
1050 *
1051 * Duplicate a string.
1052 *
1053 * PARAMS
1054 * lpszStr [I] String to duplicate.
1055 *
1056 * RETURNS
1057 * Success: A pointer to a new string containing the contents of lpszStr
1058 * Failure: NULL, if memory cannot be allocated
1059 *
1060 * NOTES
1061 * The string memory is allocated with LocalAlloc(), and so should be released
1062 * by calling LocalFree().
1063 */
1065{
1066 int iLen;
1067 LPSTR lpszRet;
1068
1069 TRACE("(%s)\n",debugstr_a(lpszStr));
1070
1071 iLen = lpszStr ? strlen(lpszStr) + 1 : 1;
1072 lpszRet = LocalAlloc(LMEM_FIXED, iLen);
1073
1074 if (lpszRet)
1075 {
1076 if (lpszStr)
1077 memcpy(lpszRet, lpszStr, iLen);
1078 else
1079 *lpszRet = '\0';
1080 }
1081 return lpszRet;
1082}
1083
1084/*************************************************************************
1085 * StrDupW [SHLWAPI.@]
1086 *
1087 * See StrDupA.
1088 */
1090{
1091 int iLen;
1092 LPWSTR lpszRet;
1093
1094 TRACE("(%s)\n",debugstr_w(lpszStr));
1095
1096 iLen = (lpszStr ? strlenW(lpszStr) + 1 : 1) * sizeof(WCHAR);
1097 lpszRet = LocalAlloc(LMEM_FIXED, iLen);
1098
1099 if (lpszRet)
1100 {
1101 if (lpszStr)
1102 memcpy(lpszRet, lpszStr, iLen);
1103 else
1104 *lpszRet = '\0';
1105 }
1106 return lpszRet;
1107}
1108
1109/*************************************************************************
1110 * SHLWAPI_StrSpnHelperA
1111 *
1112 * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA
1113 */
1114static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch,
1115 LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD),
1116 BOOL bInvert)
1117{
1118 LPCSTR lpszRead = lpszStr;
1119 if (lpszStr && *lpszStr && lpszMatch)
1120 {
1121 while (*lpszRead)
1122 {
1123 LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead);
1124
1125 if (!bInvert && !lpszTest)
1126 break;
1127 if (bInvert && lpszTest)
1128 break;
1129 lpszRead = CharNextA(lpszRead);
1130 };
1131 }
1132 return lpszRead - lpszStr;
1133}
1134
1135/*************************************************************************
1136 * StrSpnA [SHLWAPI.@]
1137 *
1138 * Find the length of the start of a string that contains only certain
1139 * characters.
1140 *
1141 * PARAMS
1142 * lpszStr [I] String to search
1143 * lpszMatch [I] Characters that can be in the substring
1144 *
1145 * RETURNS
1146 * The length of the part of lpszStr containing only chars from lpszMatch,
1147 * or 0 if any parameter is invalid.
1148 */
1149int WINAPI StrSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
1150{
1151 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1152
1153 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, FALSE);
1154}
1155
1156/*************************************************************************
1157 * StrSpnW [SHLWAPI.@]
1158 *
1159 * See StrSpnA.
1160 */
1161int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1162{
1163 if (!lpszStr || !lpszMatch) return 0;
1164 return strspnW( lpszStr, lpszMatch );
1165}
1166
1167/*************************************************************************
1168 * StrCSpnA [SHLWAPI.@]
1169 *
1170 * Find the length of the start of a string that does not contain certain
1171 * characters.
1172 *
1173 * PARAMS
1174 * lpszStr [I] String to search
1175 * lpszMatch [I] Characters that cannot be in the substring
1176 *
1177 * RETURNS
1178 * The length of the part of lpszStr containing only chars not in lpszMatch,
1179 * or 0 if any parameter is invalid.
1180 */
1181int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
1182{
1183 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1184
1185 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE);
1186}
1187
1188/*************************************************************************
1189 * StrCSpnW [SHLWAPI.@]
1190 *
1191 * See StrCSpnA.
1192 */
1193int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1194{
1195 if (!lpszStr || !lpszMatch) return 0;
1196 return strcspnW( lpszStr, lpszMatch );
1197}
1198
1199/*************************************************************************
1200 * StrCSpnIA [SHLWAPI.@]
1201 *
1202 * Find the length of the start of a string that does not contain certain
1203 * characters, ignoring case.
1204 *
1205 * PARAMS
1206 * lpszStr [I] String to search
1207 * lpszMatch [I] Characters that cannot be in the substring
1208 *
1209 * RETURNS
1210 * The length of the part of lpszStr containing only chars not in lpszMatch,
1211 * or 0 if any parameter is invalid.
1212 */
1213int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
1214{
1215 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1216
1217 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE);
1218}
1219
1220/*************************************************************************
1221 * StrCSpnIW [SHLWAPI.@]
1222 *
1223 * See StrCSpnIA.
1224 */
1225int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1226{
1227 LPCWSTR lpszRead = lpszStr;
1228
1229 TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch));
1230
1231 if (lpszStr && *lpszStr && lpszMatch)
1232 {
1233 while (*lpszRead)
1234 {
1235 if (StrChrIW(lpszMatch, *lpszRead)) break;
1236 lpszRead++;
1237 }
1238 }
1239 return lpszRead - lpszStr;
1240}
1241
1242/*************************************************************************
1243 * StrPBrkA [SHLWAPI.@]
1244 *
1245 * Search a string for any of a group of characters.
1246 *
1247 * PARAMS
1248 * lpszStr [I] String to search
1249 * lpszMatch [I] Characters to match
1250 *
1251 * RETURNS
1252 * A pointer to the first matching character in lpszStr, or NULL if no
1253 * match was found.
1254 */
1255LPSTR WINAPI StrPBrkA(LPCSTR lpszStr, LPCSTR lpszMatch)
1256{
1257 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1258
1259 if (lpszStr && lpszMatch && *lpszMatch)
1260 {
1261 while (*lpszStr)
1262 {
1263 if (StrChrA(lpszMatch, *lpszStr))
1264 return (LPSTR)lpszStr;
1265 lpszStr = CharNextA(lpszStr);
1266 }
1267 }
1268 return NULL;
1269}
1270
1271/*************************************************************************
1272 * StrPBrkW [SHLWAPI.@]
1273 *
1274 * See StrPBrkA.
1275 */
1277{
1278 if (!lpszStr || !lpszMatch) return NULL;
1279 return strpbrkW( lpszStr, lpszMatch );
1280}
1281
1282/*************************************************************************
1283 * SHLWAPI_StrRChrHelperA
1284 *
1285 * Internal implementation of StrRChrA/StrRChrIA.
1286 */
1288 LPCSTR lpszEnd, WORD ch,
1289 BOOL (WINAPI *pChrCmpFn)(WORD,WORD))
1290{
1291 LPCSTR lpszRet = NULL;
1292
1293 if (lpszStr)
1294 {
1295 WORD ch2;
1296
1297 if (!lpszEnd)
1298 lpszEnd = lpszStr + lstrlenA(lpszStr);
1299
1300 while (*lpszStr && lpszStr <= lpszEnd)
1301 {
1302 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
1303
1304 if (!pChrCmpFn(ch, ch2))
1305 lpszRet = lpszStr;
1306 lpszStr = CharNextA(lpszStr);
1307 }
1308 }
1309 return (LPSTR)lpszRet;
1310}
1311
1312/**************************************************************************
1313 * StrRChrA [SHLWAPI.@]
1314 *
1315 * Find the last occurrence of a character in string.
1316 *
1317 * PARAMS
1318 * lpszStr [I] String to search in
1319 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
1320 * ch [I] Character to search for.
1321 *
1322 * RETURNS
1323 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
1324 * or NULL if not found.
1325 * Failure: NULL, if any arguments are invalid.
1326 */
1327LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
1328{
1329 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
1330
1331 return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, SHLWAPI_ChrCmpA);
1332}
1333
1334/**************************************************************************
1335 * StrRChrW [SHLWAPI.@]
1336 *
1337 * See StrRChrA.
1338 */
1340{
1341 WCHAR *ret = NULL;
1342
1343 if (!str) return NULL;
1344 if (!end) end = str + strlenW(str);
1345 while (str < end)
1346 {
1347 if (*str == ch) ret = (WCHAR *)str;
1348 str++;
1349 }
1350 return ret;
1351}
1352
1353/**************************************************************************
1354 * StrRChrIA [SHLWAPI.@]
1355 *
1356 * Find the last occurrence of a character in string, ignoring case.
1357 *
1358 * PARAMS
1359 * lpszStr [I] String to search in
1360 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
1361 * ch [I] Character to search for.
1362 *
1363 * RETURNS
1364 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
1365 * or NULL if not found.
1366 * Failure: NULL, if any arguments are invalid.
1367 */
1369{
1370 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
1371
1372 return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, ChrCmpIA);
1373}
1374
1375/**************************************************************************
1376 * StrRChrIW [SHLWAPI.@]
1377 *
1378 * See StrRChrIA.
1379 */
1381{
1382 WCHAR *ret = NULL;
1383
1384 if (!str) return NULL;
1385 if (!end) end = str + strlenW(str);
1386 while (str < end)
1387 {
1388 if (!ChrCmpIW(*str, ch)) ret = (WCHAR *)str;
1389 str++;
1390 }
1391 return ret;
1392}
1393
1394/*************************************************************************
1395 * StrCatBuffA [SHLWAPI.@]
1396 *
1397 * Concatenate two strings together.
1398 *
1399 * PARAMS
1400 * lpszStr [O] String to concatenate to
1401 * lpszCat [I] String to add to lpszCat
1402 * cchMax [I] Maximum number of characters for the whole string
1403 *
1404 * RETURNS
1405 * lpszStr.
1406 *
1407 * NOTES
1408 * cchMax determines the number of characters in the final length of the
1409 * string, not the number appended to lpszStr from lpszCat.
1410 */
1412{
1413 INT iLen;
1414
1415 TRACE("(%p,%s,%d)\n", lpszStr, debugstr_a(lpszCat), cchMax);
1416
1417 if (!lpszStr)
1418 {
1419 WARN("Invalid lpszStr would crash under Win32!\n");
1420 return NULL;
1421 }
1422
1423 iLen = strlen(lpszStr);
1424 cchMax -= iLen;
1425
1426 if (cchMax > 0)
1427 StrCpyNA(lpszStr + iLen, lpszCat, cchMax);
1428 return lpszStr;
1429}
1430
1431/*************************************************************************
1432 * StrCatBuffW [SHLWAPI.@]
1433 *
1434 * See StrCatBuffA.
1435 */
1437{
1438 INT iLen;
1439
1440 TRACE("(%p,%s,%d)\n", lpszStr, debugstr_w(lpszCat), cchMax);
1441
1442 if (!lpszStr)
1443 {
1444 WARN("Invalid lpszStr would crash under Win32!\n");
1445 return NULL;
1446 }
1447
1448 iLen = strlenW(lpszStr);
1449 cchMax -= iLen;
1450
1451 if (cchMax > 0)
1452 StrCpyNW(lpszStr + iLen, lpszCat, cchMax);
1453 return lpszStr;
1454}
1455
1456/*************************************************************************
1457 * StrRetToBufA [SHLWAPI.@]
1458 *
1459 * Convert a STRRET to a normal string.
1460 *
1461 * PARAMS
1462 * lpStrRet [O] STRRET to convert
1463 * pIdl [I] ITEMIDLIST for lpStrRet->uType == STRRET_OFFSET
1464 * lpszDest [O] Destination for normal string
1465 * dwLen [I] Length of lpszDest
1466 *
1467 * RETURNS
1468 * Success: S_OK. lpszDest contains up to dwLen characters of the string.
1469 * If lpStrRet is of type STRRET_WSTR, its memory is freed with
1470 * CoTaskMemFree() and its type set to STRRET_CSTRA.
1471 * Failure: E_FAIL, if any parameters are invalid.
1472 */
1474{
1475 /* NOTE:
1476 * This routine is identical to that in dlls/shell32/shellstring.c.
1477 * It was duplicated because not every version of Shlwapi.dll exports
1478 * StrRetToBufA. If you change one routine, change them both.
1479 */
1480 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
1481
1482 if (!src)
1483 {
1484 WARN("Invalid lpStrRet would crash under Win32!\n");
1485 if (dest)
1486 *dest = '\0';
1487 return E_FAIL;
1488 }
1489
1490 if (!dest || !len)
1491 return E_FAIL;
1492
1493 *dest = '\0';
1494
1495 switch (src->uType)
1496 {
1497 case STRRET_WSTR:
1498 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, dest, len, NULL, NULL);
1499 CoTaskMemFree(src->u.pOleStr);
1500 break;
1501
1502 case STRRET_CSTR:
1503 lstrcpynA(dest, src->u.cStr, len);
1504 break;
1505
1506 case STRRET_OFFSET:
1507 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
1508 break;
1509
1510 default:
1511 FIXME("unknown type!\n");
1512 return E_NOTIMPL;
1513 }
1514 return S_OK;
1515}
1516
1517/*************************************************************************
1518 * StrRetToBufW [SHLWAPI.@]
1519 *
1520 * See StrRetToBufA.
1521 */
1523{
1524 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
1525
1526 if (!dest || !len)
1527 return E_FAIL;
1528
1529 if (!src)
1530 {
1531 WARN("Invalid lpStrRet would crash under Win32!\n");
1532 if (dest)
1533 *dest = '\0';
1534 return E_FAIL;
1535 }
1536
1537 *dest = '\0';
1538
1539 switch (src->uType) {
1540 case STRRET_WSTR: {
1541 size_t dst_len;
1542 if (!src->u.pOleStr)
1543 return E_FAIL;
1544 dst_len = strlenW(src->u.pOleStr);
1545 memcpy(dest, src->u.pOleStr, min(dst_len, len-1) * sizeof(WCHAR));
1546 dest[min(dst_len, len-1)] = 0;
1547 CoTaskMemFree(src->u.pOleStr);
1548 if (len <= dst_len)
1549 {
1550 dest[0] = 0;
1552 }
1553 break;
1554 }
1555
1556 case STRRET_CSTR:
1557 if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
1558 dest[len-1] = 0;
1559 break;
1560
1561 case STRRET_OFFSET:
1562 if (pidl)
1563 {
1564 if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
1565 dest, len ))
1566 dest[len-1] = 0;
1567 }
1568 break;
1569
1570 default:
1571 FIXME("unknown type!\n");
1572 return E_NOTIMPL;
1573 }
1574
1575 return S_OK;
1576}
1577
1578/*************************************************************************
1579 * StrRetToStrA [SHLWAPI.@]
1580 *
1581 * Converts a STRRET to a normal string.
1582 *
1583 * PARAMS
1584 * lpStrRet [O] STRRET to convert
1585 * pidl [I] ITEMIDLIST for lpStrRet->uType == STRRET_OFFSET
1586 * ppszName [O] Destination for converted string
1587 *
1588 * RETURNS
1589 * Success: S_OK. ppszName contains the new string, allocated with CoTaskMemAlloc().
1590 * Failure: E_FAIL, if any parameters are invalid.
1591 */
1593{
1594 HRESULT hRet = E_FAIL;
1595
1596 switch (lpStrRet->uType)
1597 {
1598 case STRRET_WSTR:
1599 hRet = _SHStrDupAW(lpStrRet->u.pOleStr, ppszName);
1600 CoTaskMemFree(lpStrRet->u.pOleStr);
1601 break;
1602
1603 case STRRET_CSTR:
1604 hRet = _SHStrDupAA(lpStrRet->u.cStr, ppszName);
1605 break;
1606
1607 case STRRET_OFFSET:
1608 hRet = _SHStrDupAA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1609 break;
1610
1611 default:
1612 *ppszName = NULL;
1613 }
1614
1615 return hRet;
1616}
1617
1618/*************************************************************************
1619 * StrRetToStrW [SHLWAPI.@]
1620 *
1621 * See StrRetToStrA.
1622 */
1624{
1625 HRESULT hRet = E_FAIL;
1626
1627 switch (lpStrRet->uType)
1628 {
1629 case STRRET_WSTR:
1630 hRet = SHStrDupW(lpStrRet->u.pOleStr, ppszName);
1631 CoTaskMemFree(lpStrRet->u.pOleStr);
1632 break;
1633
1634 case STRRET_CSTR:
1635 hRet = SHStrDupA(lpStrRet->u.cStr, ppszName);
1636 break;
1637
1638 case STRRET_OFFSET:
1639 hRet = SHStrDupA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1640 break;
1641
1642 default:
1643 *ppszName = NULL;
1644 }
1645
1646 return hRet;
1647}
1648
1649/* Create an ASCII string copy using SysAllocString() */
1651{
1652 *pBstrOut = NULL;
1653
1654 if (src)
1655 {
1656 INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
1657 WCHAR* szTemp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1658
1659 if (szTemp)
1660 {
1661 MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
1662 *pBstrOut = SysAllocString(szTemp);
1663 HeapFree(GetProcessHeap(), 0, szTemp);
1664
1665 if (*pBstrOut)
1666 return S_OK;
1667 }
1668 }
1669 return E_OUTOFMEMORY;
1670}
1671
1672/*************************************************************************
1673 * StrRetToBSTR [SHLWAPI.@]
1674 *
1675 * Converts a STRRET to a BSTR.
1676 *
1677 * PARAMS
1678 * lpStrRet [O] STRRET to convert
1679 * pidl [I] ITEMIDLIST for lpStrRet->uType = STRRET_OFFSET
1680 * pBstrOut [O] Destination for converted BSTR
1681 *
1682 * RETURNS
1683 * Success: S_OK. pBstrOut contains the new string.
1684 * Failure: E_FAIL, if any parameters are invalid.
1685 */
1687{
1688 HRESULT hRet = E_FAIL;
1689
1690 switch (lpStrRet->uType)
1691 {
1692 case STRRET_WSTR:
1693 *pBstrOut = SysAllocString(lpStrRet->u.pOleStr);
1694 if (*pBstrOut)
1695 hRet = S_OK;
1696 CoTaskMemFree(lpStrRet->u.pOleStr);
1697 break;
1698
1699 case STRRET_CSTR:
1700 hRet = _SHStrDupAToBSTR(lpStrRet->u.cStr, pBstrOut);
1701 break;
1702
1703 case STRRET_OFFSET:
1704 hRet = _SHStrDupAToBSTR(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, pBstrOut);
1705 break;
1706
1707 default:
1708 *pBstrOut = NULL;
1709 }
1710
1711 return hRet;
1712}
1713
1714/*************************************************************************
1715 * StrFormatKBSizeA [SHLWAPI.@]
1716 *
1717 * Create a formatted string containing a byte count in Kilobytes.
1718 *
1719 * PARAMS
1720 * llBytes [I] Byte size to format
1721 * lpszDest [I] Destination for formatted string
1722 * cchMax [I] Size of lpszDest
1723 *
1724 * RETURNS
1725 * lpszDest.
1726 */
1728{
1729 WCHAR wszBuf[256];
1730
1731 if (!StrFormatKBSizeW(llBytes, wszBuf, 256))
1732 return NULL;
1733 if (!WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, lpszDest, cchMax, NULL, NULL))
1734 return NULL;
1735 return lpszDest;
1736}
1737
1738/*************************************************************************
1739 * StrFormatKBSizeW [SHLWAPI.@]
1740 *
1741 * See StrFormatKBSizeA.
1742 */
1744{
1745 static const WCHAR kb[] = {' ','K','B',0};
1746 LONGLONG llKB = (llBytes + 1023) >> 10;
1747 int len;
1748
1749 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
1750
1751 if (!FormatInt(llKB, lpszDest, cchMax))
1752 return NULL;
1753
1755 if (cchMax - len < 4)
1756 return NULL;
1757 lstrcatW(lpszDest, kb);
1758 return lpszDest;
1759}
1760
1761/*************************************************************************
1762 * StrNCatA [SHLWAPI.@]
1763 *
1764 * Concatenate two strings together.
1765 *
1766 * PARAMS
1767 * lpszStr [O] String to concatenate to
1768 * lpszCat [I] String to add to lpszCat
1769 * cchMax [I] Maximum number of characters to concatenate
1770 *
1771 * RETURNS
1772 * lpszStr.
1773 *
1774 * NOTES
1775 * cchMax determines the number of characters that are appended to lpszStr,
1776 * not the total length of the string.
1777 */
1779{
1780 LPSTR lpszRet = lpszStr;
1781
1782 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszCat), cchMax);
1783
1784 if (!lpszStr)
1785 {
1786 WARN("Invalid lpszStr would crash under Win32!\n");
1787 return NULL;
1788 }
1789
1790 StrCpyNA(lpszStr + strlen(lpszStr), lpszCat, cchMax);
1791 return lpszRet;
1792}
1793
1794/*************************************************************************
1795 * StrNCatW [SHLWAPI.@]
1796 *
1797 * See StrNCatA.
1798 */
1800{
1801 LPWSTR lpszRet = lpszStr;
1802
1803 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszCat), cchMax);
1804
1805 if (!lpszStr)
1806 {
1807 WARN("Invalid lpszStr would crash under Win32\n");
1808 return NULL;
1809 }
1810
1811 StrCpyNW(lpszStr + strlenW(lpszStr), lpszCat, cchMax);
1812 return lpszRet;
1813}
1814
1815/*************************************************************************
1816 * StrTrimA [SHLWAPI.@]
1817 *
1818 * Remove characters from the start and end of a string.
1819 *
1820 * PARAMS
1821 * lpszStr [O] String to remove characters from
1822 * lpszTrim [I] Characters to remove from lpszStr
1823 *
1824 * RETURNS
1825 * TRUE If lpszStr was valid and modified
1826 * FALSE Otherwise
1827 */
1828BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim)
1829{
1830 DWORD dwLen;
1831 LPSTR lpszRead = lpszStr;
1832 BOOL bRet = FALSE;
1833
1834 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszTrim));
1835
1836 if (lpszRead && *lpszRead)
1837 {
1838 while (*lpszRead && StrChrA(lpszTrim, *lpszRead))
1839 lpszRead = CharNextA(lpszRead); /* Skip leading matches */
1840
1841 dwLen = strlen(lpszRead);
1842
1843 if (lpszRead != lpszStr)
1844 {
1845 memmove(lpszStr, lpszRead, dwLen + 1);
1846 bRet = TRUE;
1847 }
1848 if (dwLen > 0)
1849 {
1850 lpszRead = lpszStr + dwLen;
1851 while (StrChrA(lpszTrim, lpszRead[-1]))
1852 lpszRead = CharPrevA(lpszStr, lpszRead); /* Skip trailing matches */
1853
1854 if (lpszRead != lpszStr + dwLen)
1855 {
1856 *lpszRead = '\0';
1857 bRet = TRUE;
1858 }
1859 }
1860 }
1861 return bRet;
1862}
1863
1864/*************************************************************************
1865 * StrTrimW [SHLWAPI.@]
1866 *
1867 * See StrTrimA.
1868 */
1870{
1871 DWORD dwLen;
1872 LPWSTR lpszRead = lpszStr;
1873 BOOL bRet = FALSE;
1874
1875 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszTrim));
1876
1877 if (lpszRead && *lpszRead)
1878 {
1879 while (*lpszRead && StrChrW(lpszTrim, *lpszRead)) lpszRead++;
1880
1881 dwLen = strlenW(lpszRead);
1882
1883 if (lpszRead != lpszStr)
1884 {
1885 memmove(lpszStr, lpszRead, (dwLen + 1) * sizeof(WCHAR));
1886 bRet = TRUE;
1887 }
1888 if (dwLen > 0)
1889 {
1890 lpszRead = lpszStr + dwLen;
1891 while (StrChrW(lpszTrim, lpszRead[-1]))
1892 lpszRead--; /* Skip trailing matches */
1893
1894 if (lpszRead != lpszStr + dwLen)
1895 {
1896 *lpszRead = '\0';
1897 bRet = TRUE;
1898 }
1899 }
1900 }
1901 return bRet;
1902}
1903
1904/*************************************************************************
1905 * _SHStrDupAA [INTERNAL]
1906 *
1907 * Duplicates a ASCII string to ASCII. The destination buffer is allocated.
1908 */
1910{
1911 HRESULT hr;
1912 int len = 0;
1913
1914 if (src) {
1915 len = lstrlenA(src) + 1;
1917 } else {
1918 *dest = NULL;
1919 }
1920
1921 if (*dest) {
1922 lstrcpynA(*dest,src, len);
1923 hr = S_OK;
1924 } else {
1925 hr = E_OUTOFMEMORY;
1926 }
1927
1928 TRACE("%s->(%p)\n", debugstr_a(src), *dest);
1929 return hr;
1930}
1931
1932/*************************************************************************
1933 * SHStrDupA [SHLWAPI.@]
1934 *
1935 * Return a Unicode copy of a string, in memory allocated by CoTaskMemAlloc().
1936 *
1937 * PARAMS
1938 * lpszStr [I] String to copy
1939 * lppszDest [O] Destination for the new string copy
1940 *
1941 * RETURNS
1942 * Success: S_OK. lppszDest contains the new string in Unicode format.
1943 * Failure: E_OUTOFMEMORY, If any arguments are invalid or memory allocation
1944 * fails.
1945 */
1946HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR * lppszDest)
1947{
1948 HRESULT hRet;
1949 int len = 0;
1950
1951 if (lpszStr)
1952 {
1953 len = MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, NULL, 0) * sizeof(WCHAR);
1954 *lppszDest = CoTaskMemAlloc(len);
1955 }
1956 else
1957 *lppszDest = NULL;
1958
1959 if (*lppszDest)
1960 {
1961 MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, *lppszDest, len/sizeof(WCHAR));
1962 hRet = S_OK;
1963 }
1964 else
1965 hRet = E_OUTOFMEMORY;
1966
1967 TRACE("%s->(%p)\n", debugstr_a(lpszStr), *lppszDest);
1968 return hRet;
1969}
1970
1971/*************************************************************************
1972 * _SHStrDupAW [INTERNAL]
1973 *
1974 * Duplicates a UNICODE to a ASCII string. The destination buffer is allocated.
1975 */
1977{
1978 HRESULT hr;
1979 int len = 0;
1980
1981 if (src) {
1982 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
1984 } else {
1985 *dest = NULL;
1986 }
1987
1988 if (*dest) {
1990 hr = S_OK;
1991 } else {
1992 hr = E_OUTOFMEMORY;
1993 }
1994
1995 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
1996 return hr;
1997}
1998
1999/*************************************************************************
2000 * SHStrDupW [SHLWAPI.@]
2001 *
2002 * See SHStrDupA.
2003 */
2005{
2006 HRESULT hr;
2007 int len = 0;
2008
2009 if (src) {
2010 len = (lstrlenW(src) + 1) * sizeof(WCHAR);
2012 } else {
2013 *dest = NULL;
2014 }
2015
2016 if (*dest) {
2017 memcpy(*dest, src, len);
2018 hr = S_OK;
2019 } else {
2020 hr = E_OUTOFMEMORY;
2021 }
2022
2023 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2024 return hr;
2025}
2026
2027/*************************************************************************
2028 * SHLWAPI_WriteReverseNum
2029 *
2030 * Internal helper for SHLWAPI_WriteTimeClass.
2031 */
2032static inline LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
2033{
2034 *lpszOut-- = '\0';
2035
2036 /* Write a decimal number to a string, backwards */
2037 do
2038 {
2039 DWORD dwNextDigit = dwNum % 10;
2040 *lpszOut-- = '0' + dwNextDigit;
2041 dwNum = (dwNum - dwNextDigit) / 10;
2042 } while (dwNum > 0);
2043
2044 return lpszOut;
2045}
2046
2047/*************************************************************************
2048 * SHLWAPI_FormatSignificant
2049 *
2050 * Internal helper for SHLWAPI_WriteTimeClass.
2051 */
2052static inline int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
2053{
2054 /* Zero non significant digits, return remaining significant digits */
2055 while (*lpszNum)
2056 {
2057 lpszNum++;
2058 if (--dwDigits == 0)
2059 {
2060 while (*lpszNum)
2061 *lpszNum++ = '0';
2062 return 0;
2063 }
2064 }
2065 return dwDigits;
2066}
2067
2068/*************************************************************************
2069 * SHLWAPI_WriteTimeClass
2070 *
2071 * Internal helper for StrFromTimeIntervalW.
2072 */
2073static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue,
2074 UINT uClassStringId, int iDigits)
2075{
2076 WCHAR szBuff[64], *szOut = szBuff + 32;
2077
2078 szOut = SHLWAPI_WriteReverseNum(szOut, dwValue);
2079 iDigits = SHLWAPI_FormatSignificant(szOut + 1, iDigits);
2080 *szOut = ' ';
2081 LoadStringW(shlwapi_hInstance, uClassStringId, szBuff + 32, 32);
2082 strcatW(lpszOut, szOut);
2083 return iDigits;
2084}
2085
2086/*************************************************************************
2087 * StrFromTimeIntervalA [SHLWAPI.@]
2088 *
2089 * Format a millisecond time interval into a string
2090 *
2091 * PARAMS
2092 * lpszStr [O] Output buffer for formatted time interval
2093 * cchMax [I] Size of lpszStr
2094 * dwMS [I] Number of milliseconds
2095 * iDigits [I] Number of digits to print
2096 *
2097 * RETURNS
2098 * The length of the formatted string, or 0 if any parameter is invalid.
2099 *
2100 * NOTES
2101 * This implementation mimics the Win32 behaviour of always writing a leading
2102 * space before the time interval begins.
2103 *
2104 * iDigits is used to provide approximate times if accuracy is not important.
2105 * This number of digits will be written of the first non-zero time class
2106 * (hours/minutes/seconds). If this does not complete the time classification,
2107 * the remaining digits are changed to zeros (i.e. The time is _not_ rounded).
2108 * If there are digits remaining following the writing of a time class, the
2109 * next time class will be written.
2110 *
2111 * For example, given dwMS represents 138 hours,43 minutes and 15 seconds, the
2112 * following will result from the given values of iDigits:
2113 *
2114 *| iDigits 1 2 3 4 5 ...
2115 *| lpszStr "100 hr" "130 hr" "138 hr" "138 hr 40 min" "138 hr 43 min" ...
2116 */
2118 int iDigits)
2119{
2120 INT iRet = 0;
2121
2122 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2123
2124 if (lpszStr && cchMax)
2125 {
2126 WCHAR szBuff[128];
2127 StrFromTimeIntervalW(szBuff, sizeof(szBuff)/sizeof(WCHAR), dwMS, iDigits);
2128 WideCharToMultiByte(CP_ACP,0,szBuff,-1,lpszStr,cchMax,0,0);
2129 }
2130 return iRet;
2131}
2132
2133
2134/*************************************************************************
2135 * StrFromTimeIntervalW [SHLWAPI.@]
2136 *
2137 * See StrFromTimeIntervalA.
2138 */
2140 int iDigits)
2141{
2142 INT iRet = 0;
2143
2144 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2145
2146 if (lpszStr && cchMax)
2147 {
2148 WCHAR szCopy[128];
2149 DWORD dwHours, dwMinutes;
2150
2151 if (!iDigits || cchMax == 1)
2152 {
2153 *lpszStr = '\0';
2154 return 0;
2155 }
2156
2157 /* Calculate the time classes */
2158 dwMS = (dwMS + 500) / 1000;
2159 dwHours = dwMS / 3600;
2160 dwMS -= dwHours * 3600;
2161 dwMinutes = dwMS / 60;
2162 dwMS -= dwMinutes * 60;
2163
2164 szCopy[0] = '\0';
2165
2166 if (dwHours)
2167 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwHours, IDS_TIME_INTERVAL_HOURS, iDigits);
2168
2169 if (dwMinutes && iDigits)
2170 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwMinutes, IDS_TIME_INTERVAL_MINUTES, iDigits);
2171
2172 if (iDigits) /* Always write seconds if we have significant digits */
2173 SHLWAPI_WriteTimeClass(szCopy, dwMS, IDS_TIME_INTERVAL_SECONDS, iDigits);
2174
2175 lstrcpynW(lpszStr, szCopy, cchMax);
2176 iRet = strlenW(lpszStr);
2177 }
2178 return iRet;
2179}
2180
2181/*************************************************************************
2182 * StrIsIntlEqualA [SHLWAPI.@]
2183 *
2184 * Compare two strings.
2185 *
2186 * PARAMS
2187 * bCase [I] Whether to compare case sensitively
2188 * lpszStr [I] First string to compare
2189 * lpszComp [I] Second string to compare
2190 * iLen [I] Length to compare
2191 *
2192 * RETURNS
2193 * TRUE If the strings are equal.
2194 * FALSE Otherwise.
2195 */
2196BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
2197 int iLen)
2198{
2199 DWORD dwFlags;
2200
2201 TRACE("(%d,%s,%s,%d)\n", bCase,
2202 debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
2203
2204 /* FIXME: This flag is undocumented and unknown by our CompareString.
2205 * We need a define for it.
2206 */
2207 dwFlags = 0x10000000;
2208 if (!bCase) dwFlags |= NORM_IGNORECASE;
2209
2210 return (CompareStringA(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2211}
2212
2213/*************************************************************************
2214 * StrIsIntlEqualW [SHLWAPI.@]
2215 *
2216 * See StrIsIntlEqualA.
2217 */
2219 int iLen)
2220{
2221 DWORD dwFlags;
2222
2223 TRACE("(%d,%s,%s,%d)\n", bCase,
2224 debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
2225
2226 /* FIXME: This flag is undocumented and unknown by our CompareString.
2227 * We need a define for it.
2228 */
2229 dwFlags = 0x10000000;
2230 if (!bCase) dwFlags |= NORM_IGNORECASE;
2231
2232 return (CompareStringW(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2233}
2234
2235/*************************************************************************
2236 * @ [SHLWAPI.399]
2237 *
2238 * Copy a string to another string, up to a maximum number of characters.
2239 *
2240 * PARAMS
2241 * lpszDest [O] Destination string
2242 * lpszSrc [I] Source string
2243 * iLen [I] Maximum number of chars to copy
2244 *
2245 * RETURNS
2246 * Success: A pointer to the last character written to lpszDest.
2247 * Failure: lpszDest, if any arguments are invalid.
2248 */
2250{
2251 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_a(lpszSrc), iLen);
2252
2253 if (lpszDest && lpszSrc && iLen > 0)
2254 {
2255 while ((iLen-- > 1) && *lpszSrc)
2256 *lpszDest++ = *lpszSrc++;
2257 if (iLen >= 0)
2258 *lpszDest = '\0';
2259 }
2260 return lpszDest;
2261}
2262
2263/*************************************************************************
2264 * @ [SHLWAPI.400]
2265 *
2266 * Unicode version of StrCpyNXA.
2267 */
2269{
2270 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_w(lpszSrc), iLen);
2271
2272 if (lpszDest && lpszSrc && iLen > 0)
2273 {
2274 while ((iLen-- > 1) && *lpszSrc)
2275 *lpszDest++ = *lpszSrc++;
2276 if (iLen >= 0)
2277 *lpszDest = '\0';
2278 }
2279 return lpszDest;
2280}
2281
2282/*************************************************************************
2283 * StrCmpLogicalW [SHLWAPI.@]
2284 *
2285 * Compare two strings, ignoring case and comparing digits as numbers.
2286 *
2287 * PARAMS
2288 * lpszStr [I] First string to compare
2289 * lpszComp [I] Second string to compare
2290 * iLen [I] Length to compare
2291 *
2292 * RETURNS
2293 * TRUE If the strings are equal.
2294 * FALSE Otherwise.
2295 */
2297{
2298 INT iDiff;
2299
2300 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
2301
2302 if (lpszStr && lpszComp)
2303 {
2304 while (*lpszStr)
2305 {
2306 if (!*lpszComp)
2307 return 1;
2308 else if (isdigitW(*lpszStr))
2309 {
2310 int iStr, iComp;
2311
2312 if (!isdigitW(*lpszComp))
2313 return -1;
2314
2315 /* Compare the numbers */
2316 StrToIntExW(lpszStr, 0, &iStr);
2317 StrToIntExW(lpszComp, 0, &iComp);
2318
2319 if (iStr < iComp)
2320 return -1;
2321 else if (iStr > iComp)
2322 return 1;
2323
2324 /* Skip */
2325 while (isdigitW(*lpszStr))
2326 lpszStr++;
2327 while (isdigitW(*lpszComp))
2328 lpszComp++;
2329 }
2330 else if (isdigitW(*lpszComp))
2331 return 1;
2332 else
2333 {
2334 iDiff = ChrCmpIW(*lpszStr,*lpszComp);
2335 if (iDiff > 0)
2336 return 1;
2337 else if (iDiff < 0)
2338 return -1;
2339
2340 lpszStr++;
2341 lpszComp++;
2342 }
2343 }
2344 if (*lpszComp)
2345 return -1;
2346 }
2347 return 0;
2348}
2349
2350/* Structure for formatting byte strings */
2352{
2354 double dDivisor;
2357#ifdef __REACTOS__
2358 UINT nFormatID;
2359#else
2361#endif
2363
2364/*************************************************************************
2365 * StrFormatByteSizeW [SHLWAPI.@]
2366 *
2367 * Create a string containing an abbreviated byte count of up to 2^63-1.
2368 *
2369 * PARAMS
2370 * llBytes [I] Byte size to format
2371 * lpszDest [I] Destination for formatted string
2372 * cchMax [I] Size of lpszDest
2373 *
2374 * RETURNS
2375 * lpszDest.
2376 *
2377 * NOTES
2378 * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW().
2379 */
2381{
2382#define KB ((ULONGLONG)1024)
2383#define MB (KB*KB)
2384#define GB (KB*KB*KB)
2385#define TB (KB*KB*KB*KB)
2386#define PB (KB*KB*KB*KB*KB)
2387
2388 static const SHLWAPI_BYTEFORMATS bfFormats[] =
2389 {
2390#ifdef __REACTOS__
2391 { 10*KB, 10.24, 100.0, 2, IDS_KB_FORMAT }, /* 10 KB */
2392 { 100*KB, 102.4, 10.0, 1, IDS_KB_FORMAT }, /* 100 KB */
2393 { 1000*KB, 1024.0, 1.0, 0, IDS_KB_FORMAT }, /* 1000 KB */
2394 { 10*MB, 10485.76, 100.0, 2, IDS_MB_FORMAT }, /* 10 MB */
2395 { 100*MB, 104857.6, 10.0, 1, IDS_MB_FORMAT }, /* 100 MB */
2396 { 1000*MB, 1048576.0, 1.0, 0, IDS_MB_FORMAT }, /* 1000 MB */
2397 { 10*GB, 10737418.24, 100.0, 2, IDS_GB_FORMAT }, /* 10 GB */
2398 { 100*GB, 107374182.4, 10.0, 1, IDS_GB_FORMAT }, /* 100 GB */
2399 { 1000*GB, 1073741824.0, 1.0, 0, IDS_GB_FORMAT }, /* 1000 GB */
2400 { 10*TB, 10485.76, 100.0, 2, IDS_TB_FORMAT }, /* 10 TB */
2401 { 100*TB, 104857.6, 10.0, 1, IDS_TB_FORMAT }, /* 100 TB */
2402 { 1000*TB, 1048576.0, 1.0, 0, IDS_TB_FORMAT }, /* 1000 TB */
2403 { 10*PB, 10737418.24, 100.00, 2, IDS_PB_FORMAT }, /* 10 PB */
2404 { 100*PB, 107374182.4, 10.00, 1, IDS_PB_FORMAT }, /* 100 PB */
2405 { 1000*PB, 1073741824.0, 1.00, 0, IDS_PB_FORMAT }, /* 1000 PB */
2406 { 0, 10995116277.76, 100.00, 2, IDS_EB_FORMAT } /* EB's, catch all */
2407#else
2408 { 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
2409 { 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
2410 { 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
2411 { 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
2412 { 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
2413 { 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
2414 { 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
2415 { 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
2416 { 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
2417 { 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
2418 { 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
2419 { 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
2420 { 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
2421 { 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
2422 { 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
2423 { 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
2424#endif
2425 };
2426#ifdef __REACTOS__
2427 WCHAR szBuff[40], wszFormat[40];
2428#else
2429 WCHAR wszAdd[] = {' ','?','B',0};
2430#endif
2431 double dBytes;
2432 UINT i = 0;
2433
2434 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
2435
2436 if (!lpszDest || !cchMax)
2437 return lpszDest;
2438
2439 if (llBytes < 1024) /* 1K */
2440 {
2441 WCHAR wszBytesFormat[64];
2442 LoadStringW(shlwapi_hInstance, IDS_BYTES_FORMAT, wszBytesFormat, 64);
2443 snprintfW(lpszDest, cchMax, wszBytesFormat, (int)llBytes);
2444 return lpszDest;
2445 }
2446
2447 /* Note that if this loop completes without finding a match, i will be
2448 * pointing at the last entry, which is a catch all for > 1000 PB
2449 */
2450 while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
2451 {
2452 if (llBytes < bfFormats[i].dLimit)
2453 break;
2454 i++;
2455 }
2456 /* Above 1 TB we encounter problems with FP accuracy. So for amounts above
2457 * this number we integer shift down by 1 MB first. The table above has
2458 * the divisors scaled down from the '< 10 TB' entry onwards, to account
2459 * for this. We also add a small fudge factor to get the correct result for
2460 * counts that lie exactly on a 1024 byte boundary.
2461 */
2462 if (i > 8)
2463 dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by 1 MB */
2464 else
2465 dBytes = (double)llBytes + 0.00001;
2466
2467 dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
2468
2469#ifdef __REACTOS__
2470 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, szBuff, ARRAYSIZE(szBuff)))
2471 return NULL;
2472 LoadStringW(shlwapi_hInstance, bfFormats[i].nFormatID, wszFormat, ARRAYSIZE(wszFormat));
2473 snprintfW(lpszDest, cchMax, wszFormat, szBuff);
2474#else
2475 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
2476 return NULL;
2477 wszAdd[1] = bfFormats[i].wPrefix;
2478 StrCatBuffW(lpszDest, wszAdd, cchMax);
2479#endif
2480 return lpszDest;
2481}
2482
2483/*************************************************************************
2484 * StrFormatByteSize64A [SHLWAPI.@]
2485 *
2486 * See StrFormatByteSizeW.
2487 */
2489{
2490 WCHAR wszBuff[32];
2491
2492 StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
2493
2494 if (lpszDest)
2495 WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0);
2496 return lpszDest;
2497}
2498
2499/*************************************************************************
2500 * StrFormatByteSizeA [SHLWAPI.@]
2501 *
2502 * Create a string containing an abbreviated byte count of up to 2^31-1.
2503 *
2504 * PARAMS
2505 * dwBytes [I] Byte size to format
2506 * lpszDest [I] Destination for formatted string
2507 * cchMax [I] Size of lpszDest
2508 *
2509 * RETURNS
2510 * lpszDest.
2511 *
2512 * NOTES
2513 * The Ascii and Unicode versions of this function accept a different
2514 * integer type for dwBytes. See StrFormatByteSize64A().
2515 */
2517{
2518 TRACE("(%d,%p,%d)\n", dwBytes, lpszDest, cchMax);
2519
2520 return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
2521}
2522
2523/*************************************************************************
2524 * @ [SHLWAPI.162]
2525 *
2526 * Remove a hanging lead byte from the end of a string, if present.
2527 *
2528 * PARAMS
2529 * lpStr [I] String to check for a hanging lead byte
2530 * size [I] Length of lpStr
2531 *
2532 * RETURNS
2533 * Success: The new length of the string. Any hanging lead bytes are removed.
2534 * Failure: 0, if any parameters are invalid.
2535 */
2537{
2538 if (lpStr && size)
2539 {
2540 LPSTR lastByte = lpStr + size - 1;
2541
2542 while(lpStr < lastByte)
2543 lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
2544
2545 if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
2546 {
2547 *lpStr = '\0';
2548 size--;
2549 }
2550 return size;
2551 }
2552 return 0;
2553}
2554
2555/*************************************************************************
2556 * @ [SHLWAPI.203]
2557 *
2558 * Remove a single non-trailing ampersand ('&') from a string.
2559 *
2560 * PARAMS
2561 * lpszStr [I/O] String to remove ampersand from.
2562 *
2563 * RETURNS
2564 * The character after the first ampersand in lpszStr, or the first character
2565 * in lpszStr if there is no ampersand in the string.
2566 */
2568{
2569 LPSTR lpszIter, lpszTmp;
2570 char ch;
2571
2572 TRACE("(%s)\n", debugstr_a(lpszStr));
2573
2574 ch = *lpszStr;
2575
2576 if ((lpszIter = StrChrA(lpszStr, '&')))
2577 {
2578 lpszTmp = CharNextA(lpszIter);
2579 if (*lpszTmp)
2580 {
2581 if (*lpszTmp != '&')
2582 ch = *lpszTmp;
2583
2584 memmove( lpszIter, lpszTmp, strlen(lpszTmp) + 1 );
2585 }
2586 }
2587
2588 return ch;
2589}
2590
2591/*************************************************************************
2592 * @ [SHLWAPI.225]
2593 *
2594 * Unicode version of SHStripMneumonicA.
2595 */
2597{
2598 LPWSTR lpszIter, lpszTmp;
2599 WCHAR ch;
2600
2601 TRACE("(%s)\n", debugstr_w(lpszStr));
2602
2603 ch = *lpszStr;
2604
2605 if ((lpszIter = StrChrW(lpszStr, '&')))
2606 {
2607 lpszTmp = lpszIter + 1;
2608 if (*lpszTmp)
2609 {
2610 if (*lpszTmp != '&')
2611 ch = *lpszTmp;
2612
2613 memmove( lpszIter, lpszTmp, (strlenW(lpszTmp) + 1) * sizeof(WCHAR) );
2614 }
2615 }
2616
2617 return ch;
2618}
2619
2620/*************************************************************************
2621 * @ [SHLWAPI.216]
2622 *
2623 * Convert an Ascii string to Unicode.
2624 *
2625 * PARAMS
2626 * dwCp [I] Code page for the conversion
2627 * lpSrcStr [I] Source Ascii string to convert
2628 * lpDstStr [O] Destination for converted Unicode string
2629 * iLen [I] Length of lpDstStr
2630 *
2631 * RETURNS
2632 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2633 */
2634DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2635{
2636 DWORD dwRet;
2637
2638 dwRet = MultiByteToWideChar(dwCp, 0, lpSrcStr, -1, lpDstStr, iLen);
2639 TRACE("%s->%s,ret=%d\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
2640 return dwRet;
2641}
2642
2643/*************************************************************************
2644 * @ [SHLWAPI.215]
2645 *
2646 * Convert an Ascii string to Unicode.
2647 *
2648 * PARAMS
2649 * lpSrcStr [I] Source Ascii string to convert
2650 * lpDstStr [O] Destination for converted Unicode string
2651 * iLen [I] Length of lpDstStr
2652 *
2653 * RETURNS
2654 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2655 *
2656 * NOTES
2657 * This function simply calls SHAnsiToUnicodeCP with code page CP_ACP.
2658 */
2659DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2660{
2661 return SHAnsiToUnicodeCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2662}
2663
2664/*************************************************************************
2665 * @ [SHLWAPI.218]
2666 *
2667 * Convert a Unicode string to Ascii.
2668 *
2669 * PARAMS
2670 * CodePage [I] Code page to use for the conversion
2671 * lpSrcStr [I] Source Unicode string to convert
2672 * lpDstStr [O] Destination for converted Ascii string
2673 * dstlen [I] Length of buffer at lpDstStr
2674 *
2675 * RETURNS
2676 * Success: The length in bytes of the result at lpDstStr (including the terminator)
2677 * Failure: When using CP_UTF8, CP_UTF7 or 0xc350 as codePage, 0 is returned and
2678 * the result is not nul-terminated.
2679 * When using a different codepage, the length in bytes of the truncated
2680 * result at lpDstStr (including the terminator) is returned and
2681 * lpDstStr is always nul-terminated.
2682 *
2683 */
2684DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
2685{
2686 static const WCHAR emptyW[] = { '\0' };
2687 int len , reqLen;
2688 LPSTR mem;
2689
2690 if (!lpDstStr || !dstlen)
2691 return 0;
2692
2693 if (!lpSrcStr)
2694 lpSrcStr = emptyW;
2695
2696 *lpDstStr = '\0';
2697
2698 len = strlenW(lpSrcStr) + 1;
2699
2700 switch (CodePage)
2701 {
2702 case CP_WINUNICODE:
2703 CodePage = CP_UTF8; /* Fall through... */
2704 case 0x0000C350: /* FIXME: CP_ #define */
2705 case CP_UTF7:
2706 case CP_UTF8:
2707 {
2708 DWORD dwMode = 0;
2709 INT lenW = len - 1;
2710 INT needed = dstlen - 1;
2711 HRESULT hr;
2712
2713 /* try the user supplied buffer first */
2714 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, lpDstStr, &needed);
2715 if (hr == S_OK)
2716 {
2717 lpDstStr[needed] = '\0';
2718 return needed + 1;
2719 }
2720
2721 /* user buffer too small. exclude termination and copy as much as possible */
2722 lenW = len;
2723 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, NULL, &needed);
2724 needed++;
2725 mem = HeapAlloc(GetProcessHeap(), 0, needed);
2726 if (!mem)
2727 return 0;
2728
2729 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, &needed);
2730 if (hr == S_OK)
2731 {
2732 reqLen = SHTruncateString(mem, dstlen);
2733 if (reqLen > 0) memcpy(lpDstStr, mem, reqLen-1);
2734 }
2736 return 0;
2737 }
2738 default:
2739 break;
2740 }
2741
2742 /* try the user supplied buffer first */
2743 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, dstlen, NULL, NULL);
2744
2745 if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2746 {
2747 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
2748 if (reqLen)
2749 {
2750 mem = HeapAlloc(GetProcessHeap(), 0, reqLen);
2751 if (mem)
2752 {
2753 WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL);
2754
2755 reqLen = SHTruncateString(mem, dstlen -1);
2756 reqLen++;
2757
2758 lstrcpynA(lpDstStr, mem, reqLen);
2760 lpDstStr[reqLen-1] = '\0';
2761 }
2762 }
2763 }
2764 return reqLen;
2765}
2766
2767/*************************************************************************
2768 * @ [SHLWAPI.217]
2769 *
2770 * Convert a Unicode string to Ascii.
2771 *
2772 * PARAMS
2773 * lpSrcStr [I] Source Unicode string to convert
2774 * lpDstStr [O] Destination for converted Ascii string
2775 * iLen [O] Length of lpDstStr in characters
2776 *
2777 * RETURNS
2778 * See SHUnicodeToAnsiCP
2779
2780 * NOTES
2781 * This function simply calls SHUnicodeToAnsiCP() with CodePage = CP_ACP.
2782 */
2783INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
2784{
2785 return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2786}
2787
2788/*************************************************************************
2789 * @ [SHLWAPI.345]
2790 *
2791 * Copy one string to another.
2792 *
2793 * PARAMS
2794 * lpszSrc [I] Source string to copy
2795 * lpszDst [O] Destination for copy
2796 * iLen [I] Length of lpszDst in characters
2797 *
2798 * RETURNS
2799 * The length of the copied string, including the terminating NUL. lpszDst
2800 * contains iLen characters of lpszSrc.
2801 */
2802DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
2803{
2804 LPSTR lpszRet;
2805
2806 TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszSrc), lpszDst, iLen);
2807
2808 lpszRet = StrCpyNXA(lpszDst, lpszSrc, iLen);
2809 return lpszRet - lpszDst + 1;
2810}
2811
2812/*************************************************************************
2813 * @ [SHLWAPI.346]
2814 *
2815 * Unicode version of SSHAnsiToAnsi.
2816 */
2817DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
2818{
2819 LPWSTR lpszRet;
2820
2821 TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszSrc), lpszDst, iLen);
2822
2823 lpszRet = StrCpyNXW(lpszDst, lpszSrc, iLen);
2824 return lpszRet - lpszDst + 1;
2825}
2826
2827/*************************************************************************
2828 * @ [SHLWAPI.364]
2829 *
2830 * Determine if an Ascii string converts to Unicode and back identically.
2831 *
2832 * PARAMS
2833 * lpSrcStr [I] Source Unicode string to convert
2834 * lpDst [O] Destination for resulting Ascii string
2835 * iLen [I] Length of lpDst in characters
2836 *
2837 * RETURNS
2838 * TRUE, since Ascii strings always convert identically.
2839 */
2841{
2842 lstrcpynA(lpDst, lpSrcStr, iLen);
2843 return TRUE;
2844}
2845
2846/*************************************************************************
2847 * @ [SHLWAPI.365]
2848 *
2849 * Determine if a Unicode string converts to Ascii and back identically.
2850 *
2851 * PARAMS
2852 * lpSrcStr [I] Source Unicode string to convert
2853 * lpDst [O] Destination for resulting Ascii string
2854 * iLen [I] Length of lpDst in characters
2855 *
2856 * RETURNS
2857 * TRUE, if lpSrcStr converts to Ascii and back identically,
2858 * FALSE otherwise.
2859 */
2861{
2862 WCHAR szBuff[MAX_PATH];
2863
2864 SHUnicodeToAnsi(lpSrcStr, lpDst, iLen);
2865 SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
2866 return !strcmpW(lpSrcStr, szBuff);
2867}
2868
2869/*************************************************************************
2870 * SHLoadIndirectString [SHLWAPI.@]
2871 *
2872 * If passed a string that begins with '@', extract the string from the
2873 * appropriate resource, otherwise do a straight copy.
2874 *
2875 */
2877{
2878 WCHAR *dllname = NULL;
2879 HMODULE hmod = NULL;
2880 HRESULT hr = E_FAIL;
2881#ifdef __REACTOS__
2882 WCHAR szExpanded[512];
2883#endif
2884
2885 TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
2886
2887 if(src[0] == '@')
2888 {
2889 WCHAR *index_str;
2890 int index;
2891
2892#ifdef __REACTOS__
2893 if (wcschr(src, '%') != NULL)
2894 {
2895 ExpandEnvironmentStringsW(src, szExpanded, ARRAY_SIZE(szExpanded));
2896 src = szExpanded;
2897 }
2898#endif
2899 dst[0] = 0;
2900 dllname = StrDupW(src + 1);
2901 index_str = strchrW(dllname, ',');
2902
2903 if(!index_str) goto end;
2904
2905 *index_str = 0;
2906 index_str++;
2907 index = atoiW(index_str);
2908
2909#ifdef __REACTOS__
2911#else
2912 hmod = LoadLibraryW(dllname);
2913#endif
2914 if(!hmod) goto end;
2915
2916 if(index < 0)
2917 {
2918 if(LoadStringW(hmod, -index, dst, dst_len))
2919 hr = S_OK;
2920 }
2921 else
2922 FIXME("can't handle non-negative indices (%d)\n", index);
2923 }
2924 else
2925 {
2926 if(dst != src)
2927 lstrcpynW(dst, src, dst_len);
2928 hr = S_OK;
2929 }
2930
2931 TRACE("returning %s\n", debugstr_w(dst));
2932end:
2933 if(hmod) FreeLibrary(hmod);
2934 LocalFree(dllname);
2935 return hr;
2936}
2937
2939{
2940 WORD CharType;
2941 return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &CharType) && (CharType & C1_SPACE);
2942}
2943
2944/*************************************************************************
2945 * @ [SHLWAPI.29]
2946 *
2947 * Determine if a Unicode character is a space.
2948 *
2949 * PARAMS
2950 * wc [I] Character to check.
2951 *
2952 * RETURNS
2953 * TRUE, if wc is a space,
2954 * FALSE otherwise.
2955 */
2957{
2958 WORD CharType;
2959
2960 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
2961}
UINT cchMax
WCHAR lpszDest[260]
#define isspace(c)
Definition: acclib.h:69
#define isdigit(c)
Definition: acclib.h:68
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define isxdigit(c)
Definition: acclib.h:70
int tolower(int c)
Definition: utclib.c:902
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define IDS_BYTES_FORMAT
Definition: resource.h:120
#define index(s, c)
Definition: various.h:29
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define ARRAY_SIZE(A)
Definition: main.h:33
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define CP_WINUNICODE
Definition: ddeml.h:33
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:411
LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:635
LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch)
Definition: string.c:666
int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:750
int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:843
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:556
LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:355
LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
Definition: string.c:794
INT WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:300
LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch)
Definition: string.c:614
LPWSTR WINAPI StrRChrIW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:824
LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:594
LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
Definition: string.c:525
INT WINAPI StrToIntA(LPCSTR lpszStr)
Definition: string.c:374
int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:762
LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch)
Definition: string.c:270
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:311
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:384
int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:456
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:504
LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:582
LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch)
Definition: string.c:706
INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:493
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define lstrcpynA
Definition: compat.h:751
#define HeapAlloc
Definition: compat.h:733
#define FreeLibrary(x)
Definition: compat.h:748
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
OLECHAR * BSTR
Definition: compat.h:2293
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define LoadLibraryW(x)
Definition: compat.h:747
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
BOOL WINAPI IsDBCSLeadByte(BYTE TestByte)
Definition: nls.c:2359
#define IDS_TIME_INTERVAL_MINUTES
Definition: resource.h:28
#define IDS_TIME_INTERVAL_HOURS
Definition: resource.h:27
#define IDS_TIME_INTERVAL_SECONDS
Definition: resource.h:29
BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2)
Definition: string.c:217
LPWSTR WINAPI StrPBrkW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:1276
DWORD WINAPI SHTruncateString(LPSTR lpStr, DWORD size)
Definition: string.c:2536
static HRESULT _SHStrDupAToBSTR(LPCSTR src, BSTR *pBstrOut)
Definition: string.c:1650
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2004
INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2139
#define KB
BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2)
Definition: string.c:205
struct tagSHLWAPI_BYTEFORMATS SHLWAPI_BYTEFORMATS
WCHAR WINAPI SHStripMneumonicW(LPCWSTR lpszStr)
Definition: string.c:2596
LPSTR WINAPI StrNCatA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax)
Definition: string.c:1778
LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2488
LPSTR WINAPI StrCpyNXA(LPSTR lpszDest, LPCSTR lpszSrc, int iLen)
Definition: string.c:2249
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2659
static BOOL SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
Definition: string.c:157
#define PB
INT WINAPI StrCmpLogicalW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:2296
LPSTR WINAPI StrDupA(LPCSTR lpszStr)
Definition: string.c:1064
LPWSTR WINAPI StrCatBuffW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
Definition: string.c:1436
INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
Definition: string.c:2783
LPWSTR WINAPI StrFormatKBSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:1743
#define TB
BOOL WINAPI IsCharSpaceA(CHAR c)
Definition: string.c:2938
DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
Definition: string.c:2817
#define GB
LPWSTR WINAPI StrCatW(LPWSTR lpszStr, LPCWSTR lpszSrc)
Definition: string.c:452
DWORD WINAPI StrCatChainW(LPWSTR lpszStr, DWORD cchMax, DWORD ichAt, LPCWSTR lpszCat)
Definition: string.c:475
HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR *lppszDest)
Definition: string.c:1946
LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2516
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2117
DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
Definition: string.c:2802
BOOL WINAPI StrIsIntlEqualW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen)
Definition: string.c:2218
char WINAPI SHStripMneumonicA(LPCSTR lpszStr)
Definition: string.c:2567
LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:2380
HRESULT WINAPI StrRetToBSTR(STRRET *lpStrRet, LPCITEMIDLIST pidl, BSTR *pBstrOut)
Definition: string.c:1686
LPSTR WINAPI StrPBrkA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:1255
BOOL WINAPI StrToInt64ExW(LPCWSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet)
Definition: string.c:987
LPWSTR WINAPI StrCpyNXW(LPWSTR lpszDest, LPCWSTR lpszSrc, int iLen)
Definition: string.c:2268
int WINAPI StrCmpIW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:353
static int FormatInt(LONGLONG qdwValue, LPWSTR pszBuf, int cchBuf)
Definition: string.c:96
HRESULT WINAPI StrRetToBufW(LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
Definition: string.c:1522
BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:2860
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
static HRESULT _SHStrDupAA(LPCSTR, LPSTR *)
Definition: string.c:1909
LPWSTR WINAPI StrNCatW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
Definition: string.c:1799
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1869
HRESULT WINAPI StrRetToStrA(LPSTRRET lpStrRet, const ITEMIDLIST *pidl, LPSTR *ppszName)
Definition: string.c:1592
BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp, int iLen)
Definition: string.c:2196
static int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
Definition: string.c:2052
HRESULT WINAPI StrRetToStrW(LPSTRRET lpStrRet, const ITEMIDLIST *pidl, LPWSTR *ppszName)
Definition: string.c:1623
int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:1161
int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:434
LPWSTR WINAPI StrStrNW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax)
Definition: string.c:755
#define MB
static LPSTR SHLWAPI_StrRChrHelperA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch, BOOL(WINAPI *pChrCmpFn)(WORD, WORD))
Definition: string.c:1287
static LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
Definition: string.c:2032
LPWSTR WINAPI StrStrNIW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax)
Definition: string.c:790
HRESULT WINAPI SHLoadIndirectString(LPCWSTR src, LPWSTR dst, UINT dst_len, void **reserved)
Definition: string.c:2876
HINSTANCE shlwapi_hInstance
Definition: shlwapi_main.c:33
BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:970
static HRESULT _SHStrDupAW(LPCWSTR, LPSTR *)
Definition: string.c:1976
static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch, LPSTR(WINAPI *pStrChrFn)(LPCSTR, WORD), BOOL bInvert)
Definition: string.c:1114
BOOL WINAPI DoesStringRoundTripA(LPCSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:2840
LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc)
Definition: string.c:514
static BOOL WINAPI SHLWAPI_ChrCmpA(WORD ch1, WORD ch2)
Definition: string.c:187
BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:886
static void FillNumberFmt(NUMBERFMTW *fmt, LPWSTR decimal_buffer, int decimal_bufwlen, LPWSTR thousand_buffer, int thousand_bufwlen)
Definition: string.c:55
DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2634
LPSTR WINAPI StrFormatKBSizeA(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:1727
LPWSTR WINAPI StrDupW(LPCWSTR lpszStr)
Definition: string.c:1089
int WINAPI StrSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:1149
HRESULT WINAPI StrRetToBufA(LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, UINT len)
Definition: string.c:1473
static LPSTR SHLWAPI_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch, INT(WINAPI *pStrCmpFn)(LPCSTR, LPCSTR, INT))
Definition: string.c:561
BOOL WINAPI StrToInt64ExA(LPCSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet)
Definition: string.c:903
DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
Definition: string.c:2684
static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue, UINT uClassStringId, int iDigits)
Definition: string.c:2073
static int FormatDouble(double value, int decimals, LPWSTR pszBuf, int cchBuf)
Definition: string.c:129
LPSTR WINAPI StrCatBuffA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax)
Definition: string.c:1411
LPWSTR WINAPI StrChrNW(LPCWSTR lpszStr, WCHAR ch, UINT cchMax)
Definition: string.c:324
BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim)
Definition: string.c:1828
BOOL WINAPI IsCharSpaceW(WCHAR wc)
Definition: string.c:2956
r reserved
Definition: btrfs.c:3006
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
LARGE_INTEGER li
Definition: fxtimerapi.cpp:235
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define C1_SPACE
Definition: unicode.h:34
static const WCHAR emptyW[]
Definition: navigate.c:40
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
#define S_OK
Definition: intsafe.h:52
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
#define d
Definition: ke_i.h:81
#define c
Definition: ke_i.h:80
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
LCID WINAPI GetThreadLocale(void)
Definition: lang.c:1459
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: lang.c:1823
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: lang.c:2695
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: lang.c:2671
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: lang.c:1709
LCID WINAPI GetSystemDefaultLCID(void)
Definition: lang.c:797
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:1108
INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const NUMBERFMTW *lpFormat, LPWSTR lpNumberStr, int cchOut)
Definition: lcformat.c:1212
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:143
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
static DWORD dstlen
Definition: directory.c:51
static char * dest
Definition: rtl.c:135
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_USER_DEFAULT
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
#define atoiW(s)
Definition: unicode.h:54
#define strspnW(str, accept)
Definition: unicode.h:42
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
#define toupperW(n)
Definition: unicode.h:45
#define isdigitW(n)
Definition: unicode.h:50
#define strcmpW(s1, s2)
Definition: unicode.h:38
#define strstrW(d, s)
Definition: unicode.h:32
#define strchrW(s, c)
Definition: unicode.h:34
#define tolowerW(n)
Definition: unicode.h:44
#define strlenW(s)
Definition: unicode.h:28
#define strcatW(d, s)
Definition: unicode.h:30
#define strcspnW(d, s)
Definition: unicode.h:31
#define isxdigitW(n)
Definition: unicode.h:51
#define strncmpW(s1, s2, n)
Definition: unicode.h:36
#define isspaceW(n)
Definition: unicode.h:52
#define snprintfW
Definition: unicode.h:60
#define strcpyW(d, s)
Definition: unicode.h:29
#define strpbrkW(str, accept)
Definition: unicode.h:43
const WCHAR * str
#define CP_UTF8
Definition: nls.h:20
HRESULT hr
Definition: shlfolder.c:183
#define STIF_SUPPORT_HEX
Definition: shlwapi.h:1452
#define StrCpyNA
Definition: shlwapi.h:1514
SIGDN PWSTR * ppszName
Definition: shobjidl.idl:595
@ STRRET_CSTR
Definition: shtypes.idl:87
@ STRRET_OFFSET
Definition: shtypes.idl:86
@ STRRET_WSTR
Definition: shtypes.idl:85
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define TRACE(s)
Definition: solgame.cpp:4
SHITEMID mkid
Definition: shtypes.idl:34
char cStr[MAX_PATH]
Definition: shtypes.idl:98
UINT uType
Definition: shtypes.idl:93
LPWSTR pOleStr
Definition: shtypes.idl:96
UINT uOffset
Definition: shtypes.idl:97
Definition: dsound.c:943
Definition: mem.c:156
int64_t LONGLONG
Definition: typedefs.h:68
int32_t INT
Definition: typedefs.h:58
Definition: pdh_main.c:94
int ret
static BOOL bInvert
Definition: win.c:51
static CONVERTINETUNICODETOMULTIBYTE ConvertINetUnicodeToMultiByte
Definition: win_iconv.c:706
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:342
#define LMEM_FIXED
Definition: winbase.h:368
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
int * LPINT
Definition: windef.h:178
#define WINAPI
Definition: msvc.h:6
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
#define NORM_IGNORECASE
Definition: winnls.h:176
#define LOCALE_SGROUPING
Definition: winnls.h:44
#define LOCALE_SDECIMAL
Definition: winnls.h:42
#define CT_CTYPE1
Definition: winnls.h:237
#define CSTR_EQUAL
Definition: winnls.h:456
#define CP_UTF7
Definition: winnls.h:235
#define LOCALE_STHOUSAND
Definition: winnls.h:43
#define LOCALE_INEGNUMBER
Definition: winnls.h:47
#define LOCALE_ILZERO
Definition: winnls.h:46
LPSTR WINAPI CharPrevA(_In_ LPCSTR, _In_ LPCSTR)
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
LPSTR WINAPI CharNextA(_In_ LPCSTR)
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175