ReactOS 0.4.15-dev-8093-g3285f69
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#ifdef __REACTOS__
1072 if (!lpszStr)
1073 return NULL;
1074#endif
1075 iLen = lpszStr ? strlen(lpszStr) + 1 : 1;
1076 lpszRet = LocalAlloc(LMEM_FIXED, iLen);
1077
1078 if (lpszRet)
1079 {
1080 if (lpszStr)
1081 memcpy(lpszRet, lpszStr, iLen);
1082 else
1083 *lpszRet = '\0';
1084 }
1085 return lpszRet;
1086}
1087
1088/*************************************************************************
1089 * StrDupW [SHLWAPI.@]
1090 *
1091 * See StrDupA.
1092 */
1094{
1095 int iLen;
1096 LPWSTR lpszRet;
1097
1098 TRACE("(%s)\n",debugstr_w(lpszStr));
1099
1100#ifdef __REACTOS__
1101 if (!lpszStr)
1102 return NULL;
1103#endif
1104 iLen = (lpszStr ? strlenW(lpszStr) + 1 : 1) * sizeof(WCHAR);
1105 lpszRet = LocalAlloc(LMEM_FIXED, iLen);
1106
1107 if (lpszRet)
1108 {
1109 if (lpszStr)
1110 memcpy(lpszRet, lpszStr, iLen);
1111 else
1112 *lpszRet = '\0';
1113 }
1114 return lpszRet;
1115}
1116
1117/*************************************************************************
1118 * SHLWAPI_StrSpnHelperA
1119 *
1120 * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA
1121 */
1122static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch,
1123 LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD),
1124 BOOL bInvert)
1125{
1126 LPCSTR lpszRead = lpszStr;
1127 if (lpszStr && *lpszStr && lpszMatch)
1128 {
1129 while (*lpszRead)
1130 {
1131 LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead);
1132
1133 if (!bInvert && !lpszTest)
1134 break;
1135 if (bInvert && lpszTest)
1136 break;
1137 lpszRead = CharNextA(lpszRead);
1138 };
1139 }
1140 return lpszRead - lpszStr;
1141}
1142
1143/*************************************************************************
1144 * StrSpnA [SHLWAPI.@]
1145 *
1146 * Find the length of the start of a string that contains only certain
1147 * characters.
1148 *
1149 * PARAMS
1150 * lpszStr [I] String to search
1151 * lpszMatch [I] Characters that can be in the substring
1152 *
1153 * RETURNS
1154 * The length of the part of lpszStr containing only chars from lpszMatch,
1155 * or 0 if any parameter is invalid.
1156 */
1157int WINAPI StrSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
1158{
1159 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1160
1161 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, FALSE);
1162}
1163
1164/*************************************************************************
1165 * StrSpnW [SHLWAPI.@]
1166 *
1167 * See StrSpnA.
1168 */
1169int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1170{
1171 if (!lpszStr || !lpszMatch) return 0;
1172 return strspnW( lpszStr, lpszMatch );
1173}
1174
1175/*************************************************************************
1176 * StrCSpnA [SHLWAPI.@]
1177 *
1178 * Find the length of the start of a string that does not contain certain
1179 * characters.
1180 *
1181 * PARAMS
1182 * lpszStr [I] String to search
1183 * lpszMatch [I] Characters that cannot be in the substring
1184 *
1185 * RETURNS
1186 * The length of the part of lpszStr containing only chars not in lpszMatch,
1187 * or 0 if any parameter is invalid.
1188 */
1189int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
1190{
1191 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1192
1193 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE);
1194}
1195
1196/*************************************************************************
1197 * StrCSpnW [SHLWAPI.@]
1198 *
1199 * See StrCSpnA.
1200 */
1201int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1202{
1203 if (!lpszStr || !lpszMatch) return 0;
1204 return strcspnW( lpszStr, lpszMatch );
1205}
1206
1207/*************************************************************************
1208 * StrCSpnIA [SHLWAPI.@]
1209 *
1210 * Find the length of the start of a string that does not contain certain
1211 * characters, ignoring case.
1212 *
1213 * PARAMS
1214 * lpszStr [I] String to search
1215 * lpszMatch [I] Characters that cannot be in the substring
1216 *
1217 * RETURNS
1218 * The length of the part of lpszStr containing only chars not in lpszMatch,
1219 * or 0 if any parameter is invalid.
1220 */
1221int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
1222{
1223 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1224
1225 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE);
1226}
1227
1228/*************************************************************************
1229 * StrCSpnIW [SHLWAPI.@]
1230 *
1231 * See StrCSpnIA.
1232 */
1233int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1234{
1235 LPCWSTR lpszRead = lpszStr;
1236
1237 TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch));
1238
1239 if (lpszStr && *lpszStr && lpszMatch)
1240 {
1241 while (*lpszRead)
1242 {
1243 if (StrChrIW(lpszMatch, *lpszRead)) break;
1244 lpszRead++;
1245 }
1246 }
1247 return lpszRead - lpszStr;
1248}
1249
1250/*************************************************************************
1251 * StrPBrkA [SHLWAPI.@]
1252 *
1253 * Search a string for any of a group of characters.
1254 *
1255 * PARAMS
1256 * lpszStr [I] String to search
1257 * lpszMatch [I] Characters to match
1258 *
1259 * RETURNS
1260 * A pointer to the first matching character in lpszStr, or NULL if no
1261 * match was found.
1262 */
1263LPSTR WINAPI StrPBrkA(LPCSTR lpszStr, LPCSTR lpszMatch)
1264{
1265 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1266
1267 if (lpszStr && lpszMatch && *lpszMatch)
1268 {
1269 while (*lpszStr)
1270 {
1271 if (StrChrA(lpszMatch, *lpszStr))
1272 return (LPSTR)lpszStr;
1273 lpszStr = CharNextA(lpszStr);
1274 }
1275 }
1276 return NULL;
1277}
1278
1279/*************************************************************************
1280 * StrPBrkW [SHLWAPI.@]
1281 *
1282 * See StrPBrkA.
1283 */
1285{
1286 if (!lpszStr || !lpszMatch) return NULL;
1287 return strpbrkW( lpszStr, lpszMatch );
1288}
1289
1290/*************************************************************************
1291 * SHLWAPI_StrRChrHelperA
1292 *
1293 * Internal implementation of StrRChrA/StrRChrIA.
1294 */
1296 LPCSTR lpszEnd, WORD ch,
1297 BOOL (WINAPI *pChrCmpFn)(WORD,WORD))
1298{
1299 LPCSTR lpszRet = NULL;
1300
1301 if (lpszStr)
1302 {
1303 WORD ch2;
1304
1305 if (!lpszEnd)
1306 lpszEnd = lpszStr + lstrlenA(lpszStr);
1307
1308 while (*lpszStr && lpszStr <= lpszEnd)
1309 {
1310 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
1311
1312 if (!pChrCmpFn(ch, ch2))
1313 lpszRet = lpszStr;
1314 lpszStr = CharNextA(lpszStr);
1315 }
1316 }
1317 return (LPSTR)lpszRet;
1318}
1319
1320/**************************************************************************
1321 * StrRChrA [SHLWAPI.@]
1322 *
1323 * Find the last occurrence of a character in string.
1324 *
1325 * PARAMS
1326 * lpszStr [I] String to search in
1327 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
1328 * ch [I] Character to search for.
1329 *
1330 * RETURNS
1331 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
1332 * or NULL if not found.
1333 * Failure: NULL, if any arguments are invalid.
1334 */
1335LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
1336{
1337 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
1338
1339 return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, SHLWAPI_ChrCmpA);
1340}
1341
1342/**************************************************************************
1343 * StrRChrW [SHLWAPI.@]
1344 *
1345 * See StrRChrA.
1346 */
1348{
1349 WCHAR *ret = NULL;
1350
1351 if (!str) return NULL;
1352 if (!end) end = str + strlenW(str);
1353 while (str < end)
1354 {
1355 if (*str == ch) ret = (WCHAR *)str;
1356 str++;
1357 }
1358 return ret;
1359}
1360
1361/**************************************************************************
1362 * StrRChrIA [SHLWAPI.@]
1363 *
1364 * Find the last occurrence of a character in string, ignoring case.
1365 *
1366 * PARAMS
1367 * lpszStr [I] String to search in
1368 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
1369 * ch [I] Character to search for.
1370 *
1371 * RETURNS
1372 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
1373 * or NULL if not found.
1374 * Failure: NULL, if any arguments are invalid.
1375 */
1377{
1378 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
1379
1380 return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, ChrCmpIA);
1381}
1382
1383/**************************************************************************
1384 * StrRChrIW [SHLWAPI.@]
1385 *
1386 * See StrRChrIA.
1387 */
1389{
1390 WCHAR *ret = NULL;
1391
1392 if (!str) return NULL;
1393 if (!end) end = str + strlenW(str);
1394 while (str < end)
1395 {
1396 if (!ChrCmpIW(*str, ch)) ret = (WCHAR *)str;
1397 str++;
1398 }
1399 return ret;
1400}
1401
1402/*************************************************************************
1403 * StrCatBuffA [SHLWAPI.@]
1404 *
1405 * Concatenate two strings together.
1406 *
1407 * PARAMS
1408 * lpszStr [O] String to concatenate to
1409 * lpszCat [I] String to add to lpszCat
1410 * cchMax [I] Maximum number of characters for the whole string
1411 *
1412 * RETURNS
1413 * lpszStr.
1414 *
1415 * NOTES
1416 * cchMax determines the number of characters in the final length of the
1417 * string, not the number appended to lpszStr from lpszCat.
1418 */
1420{
1421 INT iLen;
1422
1423 TRACE("(%p,%s,%d)\n", lpszStr, debugstr_a(lpszCat), cchMax);
1424
1425 if (!lpszStr)
1426 {
1427 WARN("Invalid lpszStr would crash under Win32!\n");
1428 return NULL;
1429 }
1430
1431 iLen = strlen(lpszStr);
1432 cchMax -= iLen;
1433
1434 if (cchMax > 0)
1435 StrCpyNA(lpszStr + iLen, lpszCat, cchMax);
1436 return lpszStr;
1437}
1438
1439/*************************************************************************
1440 * StrCatBuffW [SHLWAPI.@]
1441 *
1442 * See StrCatBuffA.
1443 */
1445{
1446 INT iLen;
1447
1448 TRACE("(%p,%s,%d)\n", lpszStr, debugstr_w(lpszCat), cchMax);
1449
1450 if (!lpszStr)
1451 {
1452 WARN("Invalid lpszStr would crash under Win32!\n");
1453 return NULL;
1454 }
1455
1456 iLen = strlenW(lpszStr);
1457 cchMax -= iLen;
1458
1459 if (cchMax > 0)
1460 StrCpyNW(lpszStr + iLen, lpszCat, cchMax);
1461 return lpszStr;
1462}
1463
1464/*************************************************************************
1465 * StrRetToBufA [SHLWAPI.@]
1466 *
1467 * Convert a STRRET to a normal string.
1468 *
1469 * PARAMS
1470 * lpStrRet [O] STRRET to convert
1471 * pIdl [I] ITEMIDLIST for lpStrRet->uType == STRRET_OFFSET
1472 * lpszDest [O] Destination for normal string
1473 * dwLen [I] Length of lpszDest
1474 *
1475 * RETURNS
1476 * Success: S_OK. lpszDest contains up to dwLen characters of the string.
1477 * If lpStrRet is of type STRRET_WSTR, its memory is freed with
1478 * CoTaskMemFree() and its type set to STRRET_CSTRA.
1479 * Failure: E_FAIL, if any parameters are invalid.
1480 */
1482{
1483 /* NOTE:
1484 * This routine is identical to that in dlls/shell32/shellstring.c.
1485 * It was duplicated because not every version of Shlwapi.dll exports
1486 * StrRetToBufA. If you change one routine, change them both.
1487 */
1488 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
1489
1490 if (!src)
1491 {
1492 WARN("Invalid lpStrRet would crash under Win32!\n");
1493 if (dest)
1494 *dest = '\0';
1495 return E_FAIL;
1496 }
1497
1498 if (!dest || !len)
1499 return E_FAIL;
1500
1501 *dest = '\0';
1502
1503 switch (src->uType)
1504 {
1505 case STRRET_WSTR:
1506 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, dest, len, NULL, NULL);
1507 CoTaskMemFree(src->u.pOleStr);
1508 break;
1509
1510 case STRRET_CSTR:
1511 lstrcpynA(dest, src->u.cStr, len);
1512 break;
1513
1514 case STRRET_OFFSET:
1515 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
1516 break;
1517
1518 default:
1519 FIXME("unknown type!\n");
1520 return E_NOTIMPL;
1521 }
1522 return S_OK;
1523}
1524
1525/*************************************************************************
1526 * StrRetToBufW [SHLWAPI.@]
1527 *
1528 * See StrRetToBufA.
1529 */
1531{
1532 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
1533
1534 if (!dest || !len)
1535 return E_FAIL;
1536
1537 if (!src)
1538 {
1539 WARN("Invalid lpStrRet would crash under Win32!\n");
1540 if (dest)
1541 *dest = '\0';
1542 return E_FAIL;
1543 }
1544
1545 *dest = '\0';
1546
1547 switch (src->uType) {
1548 case STRRET_WSTR: {
1549 size_t dst_len;
1550 if (!src->u.pOleStr)
1551 return E_FAIL;
1552 dst_len = strlenW(src->u.pOleStr);
1553 memcpy(dest, src->u.pOleStr, min(dst_len, len-1) * sizeof(WCHAR));
1554 dest[min(dst_len, len-1)] = 0;
1555 CoTaskMemFree(src->u.pOleStr);
1556 if (len <= dst_len)
1557 {
1558 dest[0] = 0;
1560 }
1561 break;
1562 }
1563
1564 case STRRET_CSTR:
1565 if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
1566 dest[len-1] = 0;
1567 break;
1568
1569 case STRRET_OFFSET:
1570 if (pidl)
1571 {
1572 if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
1573 dest, len ))
1574 dest[len-1] = 0;
1575 }
1576 break;
1577
1578 default:
1579 FIXME("unknown type!\n");
1580 return E_NOTIMPL;
1581 }
1582
1583 return S_OK;
1584}
1585
1586/*************************************************************************
1587 * StrRetToStrA [SHLWAPI.@]
1588 *
1589 * Converts a STRRET to a normal string.
1590 *
1591 * PARAMS
1592 * lpStrRet [O] STRRET to convert
1593 * pidl [I] ITEMIDLIST for lpStrRet->uType == STRRET_OFFSET
1594 * ppszName [O] Destination for converted string
1595 *
1596 * RETURNS
1597 * Success: S_OK. ppszName contains the new string, allocated with CoTaskMemAlloc().
1598 * Failure: E_FAIL, if any parameters are invalid.
1599 */
1601{
1602 HRESULT hRet = E_FAIL;
1603
1604 switch (lpStrRet->uType)
1605 {
1606 case STRRET_WSTR:
1607 hRet = _SHStrDupAW(lpStrRet->u.pOleStr, ppszName);
1608 CoTaskMemFree(lpStrRet->u.pOleStr);
1609 break;
1610
1611 case STRRET_CSTR:
1612 hRet = _SHStrDupAA(lpStrRet->u.cStr, ppszName);
1613 break;
1614
1615 case STRRET_OFFSET:
1616 hRet = _SHStrDupAA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1617 break;
1618
1619 default:
1620 *ppszName = NULL;
1621 }
1622
1623 return hRet;
1624}
1625
1626/*************************************************************************
1627 * StrRetToStrW [SHLWAPI.@]
1628 *
1629 * See StrRetToStrA.
1630 */
1632{
1633 HRESULT hRet = E_FAIL;
1634
1635 switch (lpStrRet->uType)
1636 {
1637 case STRRET_WSTR:
1638 hRet = SHStrDupW(lpStrRet->u.pOleStr, ppszName);
1639 CoTaskMemFree(lpStrRet->u.pOleStr);
1640 break;
1641
1642 case STRRET_CSTR:
1643 hRet = SHStrDupA(lpStrRet->u.cStr, ppszName);
1644 break;
1645
1646 case STRRET_OFFSET:
1647 hRet = SHStrDupA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1648 break;
1649
1650 default:
1651 *ppszName = NULL;
1652 }
1653
1654 return hRet;
1655}
1656
1657/* Create an ASCII string copy using SysAllocString() */
1659{
1660 *pBstrOut = NULL;
1661
1662 if (src)
1663 {
1664 INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
1665 WCHAR* szTemp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1666
1667 if (szTemp)
1668 {
1669 MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
1670 *pBstrOut = SysAllocString(szTemp);
1671 HeapFree(GetProcessHeap(), 0, szTemp);
1672
1673 if (*pBstrOut)
1674 return S_OK;
1675 }
1676 }
1677 return E_OUTOFMEMORY;
1678}
1679
1680/*************************************************************************
1681 * StrRetToBSTR [SHLWAPI.@]
1682 *
1683 * Converts a STRRET to a BSTR.
1684 *
1685 * PARAMS
1686 * lpStrRet [O] STRRET to convert
1687 * pidl [I] ITEMIDLIST for lpStrRet->uType = STRRET_OFFSET
1688 * pBstrOut [O] Destination for converted BSTR
1689 *
1690 * RETURNS
1691 * Success: S_OK. pBstrOut contains the new string.
1692 * Failure: E_FAIL, if any parameters are invalid.
1693 */
1695{
1696 HRESULT hRet = E_FAIL;
1697
1698 switch (lpStrRet->uType)
1699 {
1700 case STRRET_WSTR:
1701 *pBstrOut = SysAllocString(lpStrRet->u.pOleStr);
1702 if (*pBstrOut)
1703 hRet = S_OK;
1704 CoTaskMemFree(lpStrRet->u.pOleStr);
1705 break;
1706
1707 case STRRET_CSTR:
1708 hRet = _SHStrDupAToBSTR(lpStrRet->u.cStr, pBstrOut);
1709 break;
1710
1711 case STRRET_OFFSET:
1712 hRet = _SHStrDupAToBSTR(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, pBstrOut);
1713 break;
1714
1715 default:
1716 *pBstrOut = NULL;
1717 }
1718
1719 return hRet;
1720}
1721
1722/*************************************************************************
1723 * StrFormatKBSizeA [SHLWAPI.@]
1724 *
1725 * Create a formatted string containing a byte count in Kilobytes.
1726 *
1727 * PARAMS
1728 * llBytes [I] Byte size to format
1729 * lpszDest [I] Destination for formatted string
1730 * cchMax [I] Size of lpszDest
1731 *
1732 * RETURNS
1733 * lpszDest.
1734 */
1736{
1737 WCHAR wszBuf[256];
1738
1739 if (!StrFormatKBSizeW(llBytes, wszBuf, 256))
1740 return NULL;
1741 if (!WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, lpszDest, cchMax, NULL, NULL))
1742 return NULL;
1743 return lpszDest;
1744}
1745
1746/*************************************************************************
1747 * StrFormatKBSizeW [SHLWAPI.@]
1748 *
1749 * See StrFormatKBSizeA.
1750 */
1752{
1753 static const WCHAR kb[] = {' ','K','B',0};
1754 LONGLONG llKB = (llBytes + 1023) >> 10;
1755 int len;
1756
1757 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
1758
1759 if (!FormatInt(llKB, lpszDest, cchMax))
1760 return NULL;
1761
1763 if (cchMax - len < 4)
1764 return NULL;
1765 lstrcatW(lpszDest, kb);
1766 return lpszDest;
1767}
1768
1769/*************************************************************************
1770 * StrNCatA [SHLWAPI.@]
1771 *
1772 * Concatenate two strings together.
1773 *
1774 * PARAMS
1775 * lpszStr [O] String to concatenate to
1776 * lpszCat [I] String to add to lpszCat
1777 * cchMax [I] Maximum number of characters to concatenate
1778 *
1779 * RETURNS
1780 * lpszStr.
1781 *
1782 * NOTES
1783 * cchMax determines the number of characters that are appended to lpszStr,
1784 * not the total length of the string.
1785 */
1787{
1788 LPSTR lpszRet = lpszStr;
1789
1790 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszCat), cchMax);
1791
1792 if (!lpszStr)
1793 {
1794 WARN("Invalid lpszStr would crash under Win32!\n");
1795 return NULL;
1796 }
1797
1798 StrCpyNA(lpszStr + strlen(lpszStr), lpszCat, cchMax);
1799 return lpszRet;
1800}
1801
1802/*************************************************************************
1803 * StrNCatW [SHLWAPI.@]
1804 *
1805 * See StrNCatA.
1806 */
1808{
1809 LPWSTR lpszRet = lpszStr;
1810
1811 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszCat), cchMax);
1812
1813 if (!lpszStr)
1814 {
1815 WARN("Invalid lpszStr would crash under Win32\n");
1816 return NULL;
1817 }
1818
1819 StrCpyNW(lpszStr + strlenW(lpszStr), lpszCat, cchMax);
1820 return lpszRet;
1821}
1822
1823/*************************************************************************
1824 * StrTrimA [SHLWAPI.@]
1825 *
1826 * Remove characters from the start and end of a string.
1827 *
1828 * PARAMS
1829 * lpszStr [O] String to remove characters from
1830 * lpszTrim [I] Characters to remove from lpszStr
1831 *
1832 * RETURNS
1833 * TRUE If lpszStr was valid and modified
1834 * FALSE Otherwise
1835 */
1836BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim)
1837{
1838 DWORD dwLen;
1839 LPSTR lpszRead = lpszStr;
1840 BOOL bRet = FALSE;
1841
1842 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszTrim));
1843
1844 if (lpszRead && *lpszRead)
1845 {
1846 while (*lpszRead && StrChrA(lpszTrim, *lpszRead))
1847 lpszRead = CharNextA(lpszRead); /* Skip leading matches */
1848
1849 dwLen = strlen(lpszRead);
1850
1851 if (lpszRead != lpszStr)
1852 {
1853 memmove(lpszStr, lpszRead, dwLen + 1);
1854 bRet = TRUE;
1855 }
1856 if (dwLen > 0)
1857 {
1858 lpszRead = lpszStr + dwLen;
1859 while (StrChrA(lpszTrim, lpszRead[-1]))
1860 lpszRead = CharPrevA(lpszStr, lpszRead); /* Skip trailing matches */
1861
1862 if (lpszRead != lpszStr + dwLen)
1863 {
1864 *lpszRead = '\0';
1865 bRet = TRUE;
1866 }
1867 }
1868 }
1869 return bRet;
1870}
1871
1872/*************************************************************************
1873 * StrTrimW [SHLWAPI.@]
1874 *
1875 * See StrTrimA.
1876 */
1878{
1879 DWORD dwLen;
1880 LPWSTR lpszRead = lpszStr;
1881 BOOL bRet = FALSE;
1882
1883 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszTrim));
1884
1885 if (lpszRead && *lpszRead)
1886 {
1887 while (*lpszRead && StrChrW(lpszTrim, *lpszRead)) lpszRead++;
1888
1889 dwLen = strlenW(lpszRead);
1890
1891 if (lpszRead != lpszStr)
1892 {
1893 memmove(lpszStr, lpszRead, (dwLen + 1) * sizeof(WCHAR));
1894 bRet = TRUE;
1895 }
1896 if (dwLen > 0)
1897 {
1898 lpszRead = lpszStr + dwLen;
1899 while (StrChrW(lpszTrim, lpszRead[-1]))
1900 lpszRead--; /* Skip trailing matches */
1901
1902 if (lpszRead != lpszStr + dwLen)
1903 {
1904 *lpszRead = '\0';
1905 bRet = TRUE;
1906 }
1907 }
1908 }
1909 return bRet;
1910}
1911
1912/*************************************************************************
1913 * _SHStrDupAA [INTERNAL]
1914 *
1915 * Duplicates a ASCII string to ASCII. The destination buffer is allocated.
1916 */
1918{
1919 HRESULT hr;
1920 int len = 0;
1921
1922 if (src) {
1923 len = lstrlenA(src) + 1;
1925 } else {
1926 *dest = NULL;
1927 }
1928
1929 if (*dest) {
1930 lstrcpynA(*dest,src, len);
1931 hr = S_OK;
1932 } else {
1933 hr = E_OUTOFMEMORY;
1934 }
1935
1936 TRACE("%s->(%p)\n", debugstr_a(src), *dest);
1937 return hr;
1938}
1939
1940/*************************************************************************
1941 * SHStrDupA [SHLWAPI.@]
1942 *
1943 * Return a Unicode copy of a string, in memory allocated by CoTaskMemAlloc().
1944 *
1945 * PARAMS
1946 * lpszStr [I] String to copy
1947 * lppszDest [O] Destination for the new string copy
1948 *
1949 * RETURNS
1950 * Success: S_OK. lppszDest contains the new string in Unicode format.
1951 * Failure: E_OUTOFMEMORY, If any arguments are invalid or memory allocation
1952 * fails.
1953 */
1954HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR * lppszDest)
1955{
1956 HRESULT hRet;
1957 int len = 0;
1958
1959 if (lpszStr)
1960 {
1961 len = MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, NULL, 0) * sizeof(WCHAR);
1962 *lppszDest = CoTaskMemAlloc(len);
1963 }
1964 else
1965 *lppszDest = NULL;
1966
1967 if (*lppszDest)
1968 {
1969 MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, *lppszDest, len/sizeof(WCHAR));
1970 hRet = S_OK;
1971 }
1972 else
1973 hRet = E_OUTOFMEMORY;
1974
1975 TRACE("%s->(%p)\n", debugstr_a(lpszStr), *lppszDest);
1976 return hRet;
1977}
1978
1979/*************************************************************************
1980 * _SHStrDupAW [INTERNAL]
1981 *
1982 * Duplicates a UNICODE to a ASCII string. The destination buffer is allocated.
1983 */
1985{
1986 HRESULT hr;
1987 int len = 0;
1988
1989 if (src) {
1990 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
1992 } else {
1993 *dest = NULL;
1994 }
1995
1996 if (*dest) {
1998 hr = S_OK;
1999 } else {
2000 hr = E_OUTOFMEMORY;
2001 }
2002
2003 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2004 return hr;
2005}
2006
2007/*************************************************************************
2008 * SHStrDupW [SHLWAPI.@]
2009 *
2010 * See SHStrDupA.
2011 */
2013{
2014 HRESULT hr;
2015 int len = 0;
2016
2017 if (src) {
2018 len = (lstrlenW(src) + 1) * sizeof(WCHAR);
2020 } else {
2021 *dest = NULL;
2022 }
2023
2024 if (*dest) {
2025 memcpy(*dest, src, len);
2026 hr = S_OK;
2027 } else {
2028 hr = E_OUTOFMEMORY;
2029 }
2030
2031 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2032 return hr;
2033}
2034
2035/*************************************************************************
2036 * SHLWAPI_WriteReverseNum
2037 *
2038 * Internal helper for SHLWAPI_WriteTimeClass.
2039 */
2040static inline LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
2041{
2042 *lpszOut-- = '\0';
2043
2044 /* Write a decimal number to a string, backwards */
2045 do
2046 {
2047 DWORD dwNextDigit = dwNum % 10;
2048 *lpszOut-- = '0' + dwNextDigit;
2049 dwNum = (dwNum - dwNextDigit) / 10;
2050 } while (dwNum > 0);
2051
2052 return lpszOut;
2053}
2054
2055/*************************************************************************
2056 * SHLWAPI_FormatSignificant
2057 *
2058 * Internal helper for SHLWAPI_WriteTimeClass.
2059 */
2060static inline int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
2061{
2062 /* Zero non significant digits, return remaining significant digits */
2063 while (*lpszNum)
2064 {
2065 lpszNum++;
2066 if (--dwDigits == 0)
2067 {
2068 while (*lpszNum)
2069 *lpszNum++ = '0';
2070 return 0;
2071 }
2072 }
2073 return dwDigits;
2074}
2075
2076/*************************************************************************
2077 * SHLWAPI_WriteTimeClass
2078 *
2079 * Internal helper for StrFromTimeIntervalW.
2080 */
2081static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue,
2082 UINT uClassStringId, int iDigits)
2083{
2084 WCHAR szBuff[64], *szOut = szBuff + 32;
2085
2086 szOut = SHLWAPI_WriteReverseNum(szOut, dwValue);
2087 iDigits = SHLWAPI_FormatSignificant(szOut + 1, iDigits);
2088 *szOut = ' ';
2089 LoadStringW(shlwapi_hInstance, uClassStringId, szBuff + 32, 32);
2090 strcatW(lpszOut, szOut);
2091 return iDigits;
2092}
2093
2094/*************************************************************************
2095 * StrFromTimeIntervalA [SHLWAPI.@]
2096 *
2097 * Format a millisecond time interval into a string
2098 *
2099 * PARAMS
2100 * lpszStr [O] Output buffer for formatted time interval
2101 * cchMax [I] Size of lpszStr
2102 * dwMS [I] Number of milliseconds
2103 * iDigits [I] Number of digits to print
2104 *
2105 * RETURNS
2106 * The length of the formatted string, or 0 if any parameter is invalid.
2107 *
2108 * NOTES
2109 * This implementation mimics the Win32 behaviour of always writing a leading
2110 * space before the time interval begins.
2111 *
2112 * iDigits is used to provide approximate times if accuracy is not important.
2113 * This number of digits will be written of the first non-zero time class
2114 * (hours/minutes/seconds). If this does not complete the time classification,
2115 * the remaining digits are changed to zeros (i.e. The time is _not_ rounded).
2116 * If there are digits remaining following the writing of a time class, the
2117 * next time class will be written.
2118 *
2119 * For example, given dwMS represents 138 hours,43 minutes and 15 seconds, the
2120 * following will result from the given values of iDigits:
2121 *
2122 *| iDigits 1 2 3 4 5 ...
2123 *| lpszStr "100 hr" "130 hr" "138 hr" "138 hr 40 min" "138 hr 43 min" ...
2124 */
2126 int iDigits)
2127{
2128 INT iRet = 0;
2129
2130 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2131
2132 if (lpszStr && cchMax)
2133 {
2134 WCHAR szBuff[128];
2135 StrFromTimeIntervalW(szBuff, sizeof(szBuff)/sizeof(WCHAR), dwMS, iDigits);
2136 WideCharToMultiByte(CP_ACP,0,szBuff,-1,lpszStr,cchMax,0,0);
2137 }
2138 return iRet;
2139}
2140
2141
2142/*************************************************************************
2143 * StrFromTimeIntervalW [SHLWAPI.@]
2144 *
2145 * See StrFromTimeIntervalA.
2146 */
2148 int iDigits)
2149{
2150 INT iRet = 0;
2151
2152 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2153
2154 if (lpszStr && cchMax)
2155 {
2156 WCHAR szCopy[128];
2157 DWORD dwHours, dwMinutes;
2158
2159 if (!iDigits || cchMax == 1)
2160 {
2161 *lpszStr = '\0';
2162 return 0;
2163 }
2164
2165 /* Calculate the time classes */
2166 dwMS = (dwMS + 500) / 1000;
2167 dwHours = dwMS / 3600;
2168 dwMS -= dwHours * 3600;
2169 dwMinutes = dwMS / 60;
2170 dwMS -= dwMinutes * 60;
2171
2172 szCopy[0] = '\0';
2173
2174 if (dwHours)
2175 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwHours, IDS_TIME_INTERVAL_HOURS, iDigits);
2176
2177 if (dwMinutes && iDigits)
2178 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwMinutes, IDS_TIME_INTERVAL_MINUTES, iDigits);
2179
2180 if (iDigits) /* Always write seconds if we have significant digits */
2181 SHLWAPI_WriteTimeClass(szCopy, dwMS, IDS_TIME_INTERVAL_SECONDS, iDigits);
2182
2183 lstrcpynW(lpszStr, szCopy, cchMax);
2184 iRet = strlenW(lpszStr);
2185 }
2186 return iRet;
2187}
2188
2189/*************************************************************************
2190 * StrIsIntlEqualA [SHLWAPI.@]
2191 *
2192 * Compare two strings.
2193 *
2194 * PARAMS
2195 * bCase [I] Whether to compare case sensitively
2196 * lpszStr [I] First string to compare
2197 * lpszComp [I] Second string to compare
2198 * iLen [I] Length to compare
2199 *
2200 * RETURNS
2201 * TRUE If the strings are equal.
2202 * FALSE Otherwise.
2203 */
2204BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
2205 int iLen)
2206{
2207 DWORD dwFlags;
2208
2209 TRACE("(%d,%s,%s,%d)\n", bCase,
2210 debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
2211
2212 /* FIXME: This flag is undocumented and unknown by our CompareString.
2213 * We need a define for it.
2214 */
2215 dwFlags = 0x10000000;
2216 if (!bCase) dwFlags |= NORM_IGNORECASE;
2217
2218 return (CompareStringA(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2219}
2220
2221/*************************************************************************
2222 * StrIsIntlEqualW [SHLWAPI.@]
2223 *
2224 * See StrIsIntlEqualA.
2225 */
2227 int iLen)
2228{
2229 DWORD dwFlags;
2230
2231 TRACE("(%d,%s,%s,%d)\n", bCase,
2232 debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
2233
2234 /* FIXME: This flag is undocumented and unknown by our CompareString.
2235 * We need a define for it.
2236 */
2237 dwFlags = 0x10000000;
2238 if (!bCase) dwFlags |= NORM_IGNORECASE;
2239
2240 return (CompareStringW(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2241}
2242
2243/*************************************************************************
2244 * @ [SHLWAPI.399]
2245 *
2246 * Copy a string to another string, up to a maximum number of characters.
2247 *
2248 * PARAMS
2249 * lpszDest [O] Destination string
2250 * lpszSrc [I] Source string
2251 * iLen [I] Maximum number of chars to copy
2252 *
2253 * RETURNS
2254 * Success: A pointer to the last character written to lpszDest.
2255 * Failure: lpszDest, if any arguments are invalid.
2256 */
2258{
2259 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_a(lpszSrc), iLen);
2260
2261 if (lpszDest && lpszSrc && iLen > 0)
2262 {
2263 while ((iLen-- > 1) && *lpszSrc)
2264 *lpszDest++ = *lpszSrc++;
2265 if (iLen >= 0)
2266 *lpszDest = '\0';
2267 }
2268 return lpszDest;
2269}
2270
2271/*************************************************************************
2272 * @ [SHLWAPI.400]
2273 *
2274 * Unicode version of StrCpyNXA.
2275 */
2277{
2278 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_w(lpszSrc), iLen);
2279
2280 if (lpszDest && lpszSrc && iLen > 0)
2281 {
2282 while ((iLen-- > 1) && *lpszSrc)
2283 *lpszDest++ = *lpszSrc++;
2284 if (iLen >= 0)
2285 *lpszDest = '\0';
2286 }
2287 return lpszDest;
2288}
2289
2290/*************************************************************************
2291 * StrCmpLogicalW [SHLWAPI.@]
2292 *
2293 * Compare two strings, ignoring case and comparing digits as numbers.
2294 *
2295 * PARAMS
2296 * lpszStr [I] First string to compare
2297 * lpszComp [I] Second string to compare
2298 * iLen [I] Length to compare
2299 *
2300 * RETURNS
2301 * TRUE If the strings are equal.
2302 * FALSE Otherwise.
2303 */
2305{
2306 INT iDiff;
2307
2308 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
2309
2310 if (lpszStr && lpszComp)
2311 {
2312 while (*lpszStr)
2313 {
2314 if (!*lpszComp)
2315 return 1;
2316 else if (isdigitW(*lpszStr))
2317 {
2318 int iStr, iComp;
2319
2320 if (!isdigitW(*lpszComp))
2321 return -1;
2322
2323 /* Compare the numbers */
2324 StrToIntExW(lpszStr, 0, &iStr);
2325 StrToIntExW(lpszComp, 0, &iComp);
2326
2327 if (iStr < iComp)
2328 return -1;
2329 else if (iStr > iComp)
2330 return 1;
2331
2332 /* Skip */
2333 while (isdigitW(*lpszStr))
2334 lpszStr++;
2335 while (isdigitW(*lpszComp))
2336 lpszComp++;
2337 }
2338 else if (isdigitW(*lpszComp))
2339 return 1;
2340 else
2341 {
2342 iDiff = ChrCmpIW(*lpszStr,*lpszComp);
2343 if (iDiff > 0)
2344 return 1;
2345 else if (iDiff < 0)
2346 return -1;
2347
2348 lpszStr++;
2349 lpszComp++;
2350 }
2351 }
2352 if (*lpszComp)
2353 return -1;
2354 }
2355 return 0;
2356}
2357
2358/* Structure for formatting byte strings */
2360{
2362 double dDivisor;
2365#ifdef __REACTOS__
2366 UINT nFormatID;
2367#else
2369#endif
2371
2372/*************************************************************************
2373 * StrFormatByteSizeW [SHLWAPI.@]
2374 *
2375 * Create a string containing an abbreviated byte count of up to 2^63-1.
2376 *
2377 * PARAMS
2378 * llBytes [I] Byte size to format
2379 * lpszDest [I] Destination for formatted string
2380 * cchMax [I] Size of lpszDest
2381 *
2382 * RETURNS
2383 * lpszDest.
2384 *
2385 * NOTES
2386 * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW().
2387 */
2389{
2390#define KB ((ULONGLONG)1024)
2391#define MB (KB*KB)
2392#define GB (KB*KB*KB)
2393#define TB (KB*KB*KB*KB)
2394#define PB (KB*KB*KB*KB*KB)
2395
2396 static const SHLWAPI_BYTEFORMATS bfFormats[] =
2397 {
2398#ifdef __REACTOS__
2399 { 10*KB, 10.24, 100.0, 2, IDS_KB_FORMAT }, /* 10 KB */
2400 { 100*KB, 102.4, 10.0, 1, IDS_KB_FORMAT }, /* 100 KB */
2401 { 1000*KB, 1024.0, 1.0, 0, IDS_KB_FORMAT }, /* 1000 KB */
2402 { 10*MB, 10485.76, 100.0, 2, IDS_MB_FORMAT }, /* 10 MB */
2403 { 100*MB, 104857.6, 10.0, 1, IDS_MB_FORMAT }, /* 100 MB */
2404 { 1000*MB, 1048576.0, 1.0, 0, IDS_MB_FORMAT }, /* 1000 MB */
2405 { 10*GB, 10737418.24, 100.0, 2, IDS_GB_FORMAT }, /* 10 GB */
2406 { 100*GB, 107374182.4, 10.0, 1, IDS_GB_FORMAT }, /* 100 GB */
2407 { 1000*GB, 1073741824.0, 1.0, 0, IDS_GB_FORMAT }, /* 1000 GB */
2408 { 10*TB, 10485.76, 100.0, 2, IDS_TB_FORMAT }, /* 10 TB */
2409 { 100*TB, 104857.6, 10.0, 1, IDS_TB_FORMAT }, /* 100 TB */
2410 { 1000*TB, 1048576.0, 1.0, 0, IDS_TB_FORMAT }, /* 1000 TB */
2411 { 10*PB, 10737418.24, 100.00, 2, IDS_PB_FORMAT }, /* 10 PB */
2412 { 100*PB, 107374182.4, 10.00, 1, IDS_PB_FORMAT }, /* 100 PB */
2413 { 1000*PB, 1073741824.0, 1.00, 0, IDS_PB_FORMAT }, /* 1000 PB */
2414 { 0, 10995116277.76, 100.00, 2, IDS_EB_FORMAT } /* EB's, catch all */
2415#else
2416 { 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
2417 { 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
2418 { 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
2419 { 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
2420 { 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
2421 { 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
2422 { 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
2423 { 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
2424 { 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
2425 { 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
2426 { 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
2427 { 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
2428 { 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
2429 { 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
2430 { 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
2431 { 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
2432#endif
2433 };
2434#ifdef __REACTOS__
2435 WCHAR szBuff[40], wszFormat[40];
2436#else
2437 WCHAR wszAdd[] = {' ','?','B',0};
2438#endif
2439 double dBytes;
2440 UINT i = 0;
2441
2442 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
2443
2444 if (!lpszDest || !cchMax)
2445 return lpszDest;
2446
2447 if (llBytes < 1024) /* 1K */
2448 {
2449 WCHAR wszBytesFormat[64];
2450 LoadStringW(shlwapi_hInstance, IDS_BYTES_FORMAT, wszBytesFormat, 64);
2451 snprintfW(lpszDest, cchMax, wszBytesFormat, (int)llBytes);
2452 return lpszDest;
2453 }
2454
2455 /* Note that if this loop completes without finding a match, i will be
2456 * pointing at the last entry, which is a catch all for > 1000 PB
2457 */
2458 while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
2459 {
2460 if (llBytes < bfFormats[i].dLimit)
2461 break;
2462 i++;
2463 }
2464 /* Above 1 TB we encounter problems with FP accuracy. So for amounts above
2465 * this number we integer shift down by 1 MB first. The table above has
2466 * the divisors scaled down from the '< 10 TB' entry onwards, to account
2467 * for this. We also add a small fudge factor to get the correct result for
2468 * counts that lie exactly on a 1024 byte boundary.
2469 */
2470 if (i > 8)
2471 dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by 1 MB */
2472 else
2473 dBytes = (double)llBytes + 0.00001;
2474
2475 dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
2476
2477#ifdef __REACTOS__
2478 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, szBuff, ARRAYSIZE(szBuff)))
2479 return NULL;
2480 LoadStringW(shlwapi_hInstance, bfFormats[i].nFormatID, wszFormat, ARRAYSIZE(wszFormat));
2481 snprintfW(lpszDest, cchMax, wszFormat, szBuff);
2482#else
2483 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
2484 return NULL;
2485 wszAdd[1] = bfFormats[i].wPrefix;
2486 StrCatBuffW(lpszDest, wszAdd, cchMax);
2487#endif
2488 return lpszDest;
2489}
2490
2491/*************************************************************************
2492 * StrFormatByteSize64A [SHLWAPI.@]
2493 *
2494 * See StrFormatByteSizeW.
2495 */
2497{
2498 WCHAR wszBuff[32];
2499
2500 StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
2501
2502 if (lpszDest)
2503 WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0);
2504 return lpszDest;
2505}
2506
2507/*************************************************************************
2508 * StrFormatByteSizeA [SHLWAPI.@]
2509 *
2510 * Create a string containing an abbreviated byte count of up to 2^31-1.
2511 *
2512 * PARAMS
2513 * dwBytes [I] Byte size to format
2514 * lpszDest [I] Destination for formatted string
2515 * cchMax [I] Size of lpszDest
2516 *
2517 * RETURNS
2518 * lpszDest.
2519 *
2520 * NOTES
2521 * The Ascii and Unicode versions of this function accept a different
2522 * integer type for dwBytes. See StrFormatByteSize64A().
2523 */
2525{
2526 TRACE("(%d,%p,%d)\n", dwBytes, lpszDest, cchMax);
2527
2528 return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
2529}
2530
2531/*************************************************************************
2532 * @ [SHLWAPI.162]
2533 *
2534 * Remove a hanging lead byte from the end of a string, if present.
2535 *
2536 * PARAMS
2537 * lpStr [I] String to check for a hanging lead byte
2538 * size [I] Length of lpStr
2539 *
2540 * RETURNS
2541 * Success: The new length of the string. Any hanging lead bytes are removed.
2542 * Failure: 0, if any parameters are invalid.
2543 */
2545{
2546 if (lpStr && size)
2547 {
2548 LPSTR lastByte = lpStr + size - 1;
2549
2550 while(lpStr < lastByte)
2551 lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
2552
2553 if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
2554 {
2555 *lpStr = '\0';
2556 size--;
2557 }
2558 return size;
2559 }
2560 return 0;
2561}
2562
2563/*************************************************************************
2564 * @ [SHLWAPI.203]
2565 *
2566 * Remove a single non-trailing ampersand ('&') from a string.
2567 *
2568 * PARAMS
2569 * lpszStr [I/O] String to remove ampersand from.
2570 *
2571 * RETURNS
2572 * The character after the first ampersand in lpszStr, or the first character
2573 * in lpszStr if there is no ampersand in the string.
2574 */
2576{
2577 LPSTR lpszIter, lpszTmp;
2578 char ch;
2579
2580 TRACE("(%s)\n", debugstr_a(lpszStr));
2581
2582 ch = *lpszStr;
2583
2584 if ((lpszIter = StrChrA(lpszStr, '&')))
2585 {
2586 lpszTmp = CharNextA(lpszIter);
2587 if (*lpszTmp)
2588 {
2589 if (*lpszTmp != '&')
2590 ch = *lpszTmp;
2591
2592 memmove( lpszIter, lpszTmp, strlen(lpszTmp) + 1 );
2593 }
2594 }
2595
2596 return ch;
2597}
2598
2599/*************************************************************************
2600 * @ [SHLWAPI.225]
2601 *
2602 * Unicode version of SHStripMneumonicA.
2603 */
2605{
2606 LPWSTR lpszIter, lpszTmp;
2607 WCHAR ch;
2608
2609 TRACE("(%s)\n", debugstr_w(lpszStr));
2610
2611 ch = *lpszStr;
2612
2613 if ((lpszIter = StrChrW(lpszStr, '&')))
2614 {
2615 lpszTmp = lpszIter + 1;
2616 if (*lpszTmp)
2617 {
2618 if (*lpszTmp != '&')
2619 ch = *lpszTmp;
2620
2621 memmove( lpszIter, lpszTmp, (strlenW(lpszTmp) + 1) * sizeof(WCHAR) );
2622 }
2623 }
2624
2625 return ch;
2626}
2627
2628/*************************************************************************
2629 * @ [SHLWAPI.216]
2630 *
2631 * Convert an Ascii string to Unicode.
2632 *
2633 * PARAMS
2634 * dwCp [I] Code page for the conversion
2635 * lpSrcStr [I] Source Ascii string to convert
2636 * lpDstStr [O] Destination for converted Unicode string
2637 * iLen [I] Length of lpDstStr
2638 *
2639 * RETURNS
2640 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2641 */
2642DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2643{
2644 DWORD dwRet;
2645
2646 dwRet = MultiByteToWideChar(dwCp, 0, lpSrcStr, -1, lpDstStr, iLen);
2647 TRACE("%s->%s,ret=%d\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
2648 return dwRet;
2649}
2650
2651/*************************************************************************
2652 * @ [SHLWAPI.215]
2653 *
2654 * Convert an Ascii string to Unicode.
2655 *
2656 * PARAMS
2657 * lpSrcStr [I] Source Ascii string to convert
2658 * lpDstStr [O] Destination for converted Unicode string
2659 * iLen [I] Length of lpDstStr
2660 *
2661 * RETURNS
2662 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2663 *
2664 * NOTES
2665 * This function simply calls SHAnsiToUnicodeCP with code page CP_ACP.
2666 */
2667DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2668{
2669 return SHAnsiToUnicodeCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2670}
2671
2672/*************************************************************************
2673 * @ [SHLWAPI.218]
2674 *
2675 * Convert a Unicode string to Ascii.
2676 *
2677 * PARAMS
2678 * CodePage [I] Code page to use for the conversion
2679 * lpSrcStr [I] Source Unicode string to convert
2680 * lpDstStr [O] Destination for converted Ascii string
2681 * dstlen [I] Length of buffer at lpDstStr
2682 *
2683 * RETURNS
2684 * Success: The length in bytes of the result at lpDstStr (including the terminator)
2685 * Failure: When using CP_UTF8, CP_UTF7 or 0xc350 as codePage, 0 is returned and
2686 * the result is not nul-terminated.
2687 * When using a different codepage, the length in bytes of the truncated
2688 * result at lpDstStr (including the terminator) is returned and
2689 * lpDstStr is always nul-terminated.
2690 *
2691 */
2692DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
2693{
2694 static const WCHAR emptyW[] = { '\0' };
2695 int len , reqLen;
2696 LPSTR mem;
2697
2698 if (!lpDstStr || !dstlen)
2699 return 0;
2700
2701 if (!lpSrcStr)
2702 lpSrcStr = emptyW;
2703
2704 *lpDstStr = '\0';
2705
2706 len = strlenW(lpSrcStr) + 1;
2707
2708 switch (CodePage)
2709 {
2710 case CP_WINUNICODE:
2711 CodePage = CP_UTF8; /* Fall through... */
2712 case 0x0000C350: /* FIXME: CP_ #define */
2713 case CP_UTF7:
2714 case CP_UTF8:
2715 {
2716 DWORD dwMode = 0;
2717 INT lenW = len - 1;
2718 INT needed = dstlen - 1;
2719 HRESULT hr;
2720
2721 /* try the user supplied buffer first */
2722 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, lpDstStr, &needed);
2723 if (hr == S_OK)
2724 {
2725 lpDstStr[needed] = '\0';
2726 return needed + 1;
2727 }
2728
2729 /* user buffer too small. exclude termination and copy as much as possible */
2730 lenW = len;
2731 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, NULL, &needed);
2732 needed++;
2733 mem = HeapAlloc(GetProcessHeap(), 0, needed);
2734 if (!mem)
2735 return 0;
2736
2737 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, &needed);
2738 if (hr == S_OK)
2739 {
2740 reqLen = SHTruncateString(mem, dstlen);
2741 if (reqLen > 0) memcpy(lpDstStr, mem, reqLen-1);
2742 }
2744 return 0;
2745 }
2746 default:
2747 break;
2748 }
2749
2750 /* try the user supplied buffer first */
2751 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, dstlen, NULL, NULL);
2752
2753 if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2754 {
2755 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
2756 if (reqLen)
2757 {
2758 mem = HeapAlloc(GetProcessHeap(), 0, reqLen);
2759 if (mem)
2760 {
2761 WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL);
2762
2763 reqLen = SHTruncateString(mem, dstlen -1);
2764 reqLen++;
2765
2766 lstrcpynA(lpDstStr, mem, reqLen);
2768 lpDstStr[reqLen-1] = '\0';
2769 }
2770 }
2771 }
2772 return reqLen;
2773}
2774
2775/*************************************************************************
2776 * @ [SHLWAPI.217]
2777 *
2778 * Convert a Unicode string to Ascii.
2779 *
2780 * PARAMS
2781 * lpSrcStr [I] Source Unicode string to convert
2782 * lpDstStr [O] Destination for converted Ascii string
2783 * iLen [O] Length of lpDstStr in characters
2784 *
2785 * RETURNS
2786 * See SHUnicodeToAnsiCP
2787
2788 * NOTES
2789 * This function simply calls SHUnicodeToAnsiCP() with CodePage = CP_ACP.
2790 */
2791INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
2792{
2793 return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2794}
2795
2796/*************************************************************************
2797 * @ [SHLWAPI.345]
2798 *
2799 * Copy one string to another.
2800 *
2801 * PARAMS
2802 * lpszSrc [I] Source string to copy
2803 * lpszDst [O] Destination for copy
2804 * iLen [I] Length of lpszDst in characters
2805 *
2806 * RETURNS
2807 * The length of the copied string, including the terminating NUL. lpszDst
2808 * contains iLen characters of lpszSrc.
2809 */
2810DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
2811{
2812 LPSTR lpszRet;
2813
2814 TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszSrc), lpszDst, iLen);
2815
2816 lpszRet = StrCpyNXA(lpszDst, lpszSrc, iLen);
2817 return lpszRet - lpszDst + 1;
2818}
2819
2820/*************************************************************************
2821 * @ [SHLWAPI.346]
2822 *
2823 * Unicode version of SSHAnsiToAnsi.
2824 */
2825DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
2826{
2827 LPWSTR lpszRet;
2828
2829 TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszSrc), lpszDst, iLen);
2830
2831 lpszRet = StrCpyNXW(lpszDst, lpszSrc, iLen);
2832 return lpszRet - lpszDst + 1;
2833}
2834
2835/*************************************************************************
2836 * @ [SHLWAPI.364]
2837 *
2838 * Determine if an Ascii string converts to Unicode and back identically.
2839 *
2840 * PARAMS
2841 * lpSrcStr [I] Source Unicode string to convert
2842 * lpDst [O] Destination for resulting Ascii string
2843 * iLen [I] Length of lpDst in characters
2844 *
2845 * RETURNS
2846 * TRUE, since Ascii strings always convert identically.
2847 */
2849{
2850 lstrcpynA(lpDst, lpSrcStr, iLen);
2851 return TRUE;
2852}
2853
2854/*************************************************************************
2855 * @ [SHLWAPI.365]
2856 *
2857 * Determine if a Unicode string converts to Ascii and back identically.
2858 *
2859 * PARAMS
2860 * lpSrcStr [I] Source Unicode string to convert
2861 * lpDst [O] Destination for resulting Ascii string
2862 * iLen [I] Length of lpDst in characters
2863 *
2864 * RETURNS
2865 * TRUE, if lpSrcStr converts to Ascii and back identically,
2866 * FALSE otherwise.
2867 */
2869{
2870 WCHAR szBuff[MAX_PATH];
2871
2872 SHUnicodeToAnsi(lpSrcStr, lpDst, iLen);
2873 SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
2874 return !strcmpW(lpSrcStr, szBuff);
2875}
2876
2877/*************************************************************************
2878 * SHLoadIndirectString [SHLWAPI.@]
2879 *
2880 * If passed a string that begins with '@', extract the string from the
2881 * appropriate resource, otherwise do a straight copy.
2882 *
2883 */
2885{
2886 WCHAR *dllname = NULL;
2887 HMODULE hmod = NULL;
2888 HRESULT hr = E_FAIL;
2889#ifdef __REACTOS__
2890 WCHAR szExpanded[512];
2891#endif
2892
2893 TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
2894
2895 if(src[0] == '@')
2896 {
2897 WCHAR *index_str;
2898 int index;
2899
2900#ifdef __REACTOS__
2901 if (wcschr(src, '%') != NULL)
2902 {
2903 ExpandEnvironmentStringsW(src, szExpanded, ARRAY_SIZE(szExpanded));
2904 src = szExpanded;
2905 }
2906#endif
2907 dst[0] = 0;
2908 dllname = StrDupW(src + 1);
2909 index_str = strchrW(dllname, ',');
2910
2911 if(!index_str) goto end;
2912
2913 *index_str = 0;
2914 index_str++;
2915 index = atoiW(index_str);
2916
2917#ifdef __REACTOS__
2919#else
2920 hmod = LoadLibraryW(dllname);
2921#endif
2922 if(!hmod) goto end;
2923
2924 if(index < 0)
2925 {
2926 if(LoadStringW(hmod, -index, dst, dst_len))
2927 hr = S_OK;
2928 }
2929 else
2930 FIXME("can't handle non-negative indices (%d)\n", index);
2931 }
2932 else
2933 {
2934 if(dst != src)
2935 lstrcpynW(dst, src, dst_len);
2936 hr = S_OK;
2937 }
2938
2939 TRACE("returning %s\n", debugstr_w(dst));
2940end:
2941 if(hmod) FreeLibrary(hmod);
2942 LocalFree(dllname);
2943 return hr;
2944}
2945
2947{
2948 WORD CharType;
2949 return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &CharType) && (CharType & C1_SPACE);
2950}
2951
2952/*************************************************************************
2953 * @ [SHLWAPI.29]
2954 *
2955 * Determine if a Unicode character is a space.
2956 *
2957 * PARAMS
2958 * wc [I] Character to check.
2959 *
2960 * RETURNS
2961 * TRUE, if wc is a space,
2962 * FALSE otherwise.
2963 */
2965{
2966 WORD CharType;
2967
2968 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
2969}
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:114
#define WARN(fmt,...)
Definition: debug.h:115
#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
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2800
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2123
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: locale.c:3208
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: locale.c:4082
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4013
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3094
LCID WINAPI GetSystemDefaultLCID(void)
Definition: locale.c:1229
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1665
#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:1284
DWORD WINAPI SHTruncateString(LPSTR lpStr, DWORD size)
Definition: string.c:2544
static HRESULT _SHStrDupAToBSTR(LPCSTR src, BSTR *pBstrOut)
Definition: string.c:1658
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2012
INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2147
#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:2604
LPSTR WINAPI StrNCatA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax)
Definition: string.c:1786
LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2496
LPSTR WINAPI StrCpyNXA(LPSTR lpszDest, LPCSTR lpszSrc, int iLen)
Definition: string.c:2257
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2667
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:2304
LPSTR WINAPI StrDupA(LPCSTR lpszStr)
Definition: string.c:1064
LPWSTR WINAPI StrCatBuffW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
Definition: string.c:1444
INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
Definition: string.c:2791
LPWSTR WINAPI StrFormatKBSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:1751
#define TB
BOOL WINAPI IsCharSpaceA(CHAR c)
Definition: string.c:2946
DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
Definition: string.c:2825
#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:1954
LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2524
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2125
DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
Definition: string.c:2810
BOOL WINAPI StrIsIntlEqualW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen)
Definition: string.c:2226
char WINAPI SHStripMneumonicA(LPCSTR lpszStr)
Definition: string.c:2575
LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:2388
HRESULT WINAPI StrRetToBSTR(STRRET *lpStrRet, LPCITEMIDLIST pidl, BSTR *pBstrOut)
Definition: string.c:1694
LPSTR WINAPI StrPBrkA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:1263
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:2276
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:1530
BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:2868
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
static HRESULT _SHStrDupAA(LPCSTR, LPSTR *)
Definition: string.c:1917
LPWSTR WINAPI StrNCatW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
Definition: string.c:1807
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1877
HRESULT WINAPI StrRetToStrA(LPSTRRET lpStrRet, const ITEMIDLIST *pidl, LPSTR *ppszName)
Definition: string.c:1600
BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp, int iLen)
Definition: string.c:2204
static int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
Definition: string.c:2060
HRESULT WINAPI StrRetToStrW(LPSTRRET lpStrRet, const ITEMIDLIST *pidl, LPWSTR *ppszName)
Definition: string.c:1631
int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:1169
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:1295
static LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
Definition: string.c:2040
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:2884
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:1984
static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch, LPSTR(WINAPI *pStrChrFn)(LPCSTR, WORD), BOOL bInvert)
Definition: string.c:1122
BOOL WINAPI DoesStringRoundTripA(LPCSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:2848
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:2642
LPSTR WINAPI StrFormatKBSizeA(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:1735
LPWSTR WINAPI StrDupW(LPCWSTR lpszStr)
Definition: string.c:1093
int WINAPI StrSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:1157
HRESULT WINAPI StrRetToBufA(LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, UINT len)
Definition: string.c:1481
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:2692
static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue, UINT uClassStringId, int iDigits)
Definition: string.c:2081
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:1419
LPWSTR WINAPI StrChrNW(LPCWSTR lpszStr, WCHAR ch, UINT cchMax)
Definition: string.c:324
BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim)
Definition: string.c:1836
BOOL WINAPI IsCharSpaceW(WCHAR wc)
Definition: string.c:2964
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
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:60
#define strspnW(str, accept)
Definition: unicode.h:48
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define toupperW(n)
Definition: unicode.h:51
#define isdigitW(n)
Definition: unicode.h:56
#define strcmpW(s1, s2)
Definition: unicode.h:44
#define strstrW(d, s)
Definition: unicode.h:38
#define strchrW(s, c)
Definition: unicode.h:40
#define tolowerW(n)
Definition: unicode.h:50
#define strlenW(s)
Definition: unicode.h:34
#define strcatW(d, s)
Definition: unicode.h:36
#define strcspnW(d, s)
Definition: unicode.h:37
#define isxdigitW(n)
Definition: unicode.h:57
#define strncmpW(s1, s2, n)
Definition: unicode.h:42
#define isspaceW(n)
Definition: unicode.h:58
#define snprintfW
Definition: unicode.h:66
#define strcpyW(d, s)
Definition: unicode.h:35
#define strpbrkW(str, accept)
Definition: unicode.h:49
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:601
@ 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