ReactOS 0.4.16-dev-570-g1868985
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#ifdef __REACTOS__
1639 hRet = lpStrRet->u.pOleStr ? S_OK : E_FAIL;
1640 *ppszName = lpStrRet->u.pOleStr;
1641 lpStrRet->u.pOleStr = NULL; /* Windows does this, presumably in case someone calls SHFree */
1642#else
1643 hRet = SHStrDupW(lpStrRet->u.pOleStr, ppszName);
1644 CoTaskMemFree(lpStrRet->u.pOleStr);
1645#endif
1646 break;
1647
1648 case STRRET_CSTR:
1649 hRet = SHStrDupA(lpStrRet->u.cStr, ppszName);
1650 break;
1651
1652 case STRRET_OFFSET:
1653 hRet = SHStrDupA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1654 break;
1655
1656 default:
1657 *ppszName = NULL;
1658 }
1659
1660 return hRet;
1661}
1662
1663/* Create an ASCII string copy using SysAllocString() */
1665{
1666 *pBstrOut = NULL;
1667
1668 if (src)
1669 {
1670 INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
1671 WCHAR* szTemp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1672
1673 if (szTemp)
1674 {
1675 MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
1676 *pBstrOut = SysAllocString(szTemp);
1677 HeapFree(GetProcessHeap(), 0, szTemp);
1678
1679 if (*pBstrOut)
1680 return S_OK;
1681 }
1682 }
1683 return E_OUTOFMEMORY;
1684}
1685
1686/*************************************************************************
1687 * StrRetToBSTR [SHLWAPI.@]
1688 *
1689 * Converts a STRRET to a BSTR.
1690 *
1691 * PARAMS
1692 * lpStrRet [O] STRRET to convert
1693 * pidl [I] ITEMIDLIST for lpStrRet->uType = STRRET_OFFSET
1694 * pBstrOut [O] Destination for converted BSTR
1695 *
1696 * RETURNS
1697 * Success: S_OK. pBstrOut contains the new string.
1698 * Failure: E_FAIL, if any parameters are invalid.
1699 */
1701{
1702 HRESULT hRet = E_FAIL;
1703
1704 switch (lpStrRet->uType)
1705 {
1706 case STRRET_WSTR:
1707 *pBstrOut = SysAllocString(lpStrRet->u.pOleStr);
1708 if (*pBstrOut)
1709 hRet = S_OK;
1710 CoTaskMemFree(lpStrRet->u.pOleStr);
1711 break;
1712
1713 case STRRET_CSTR:
1714 hRet = _SHStrDupAToBSTR(lpStrRet->u.cStr, pBstrOut);
1715 break;
1716
1717 case STRRET_OFFSET:
1718 hRet = _SHStrDupAToBSTR(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, pBstrOut);
1719 break;
1720
1721 default:
1722 *pBstrOut = NULL;
1723 }
1724
1725 return hRet;
1726}
1727
1728/*************************************************************************
1729 * StrFormatKBSizeA [SHLWAPI.@]
1730 *
1731 * Create a formatted string containing a byte count in Kilobytes.
1732 *
1733 * PARAMS
1734 * llBytes [I] Byte size to format
1735 * lpszDest [I] Destination for formatted string
1736 * cchMax [I] Size of lpszDest
1737 *
1738 * RETURNS
1739 * lpszDest.
1740 */
1742{
1743 WCHAR wszBuf[256];
1744
1745 if (!StrFormatKBSizeW(llBytes, wszBuf, 256))
1746 return NULL;
1747 if (!WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, lpszDest, cchMax, NULL, NULL))
1748 return NULL;
1749 return lpszDest;
1750}
1751
1752/*************************************************************************
1753 * StrFormatKBSizeW [SHLWAPI.@]
1754 *
1755 * See StrFormatKBSizeA.
1756 */
1758{
1759 static const WCHAR kb[] = {' ','K','B',0};
1760 LONGLONG llKB = (llBytes + 1023) >> 10;
1761 int len;
1762
1763 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
1764
1765 if (!FormatInt(llKB, lpszDest, cchMax))
1766 return NULL;
1767
1769 if (cchMax - len < 4)
1770 return NULL;
1771 lstrcatW(lpszDest, kb);
1772 return lpszDest;
1773}
1774
1775/*************************************************************************
1776 * StrNCatA [SHLWAPI.@]
1777 *
1778 * Concatenate two strings together.
1779 *
1780 * PARAMS
1781 * lpszStr [O] String to concatenate to
1782 * lpszCat [I] String to add to lpszCat
1783 * cchMax [I] Maximum number of characters to concatenate
1784 *
1785 * RETURNS
1786 * lpszStr.
1787 *
1788 * NOTES
1789 * cchMax determines the number of characters that are appended to lpszStr,
1790 * not the total length of the string.
1791 */
1793{
1794 LPSTR lpszRet = lpszStr;
1795
1796 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszCat), cchMax);
1797
1798 if (!lpszStr)
1799 {
1800 WARN("Invalid lpszStr would crash under Win32!\n");
1801 return NULL;
1802 }
1803
1804 StrCpyNA(lpszStr + strlen(lpszStr), lpszCat, cchMax);
1805 return lpszRet;
1806}
1807
1808/*************************************************************************
1809 * StrNCatW [SHLWAPI.@]
1810 *
1811 * See StrNCatA.
1812 */
1814{
1815 LPWSTR lpszRet = lpszStr;
1816
1817 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszCat), cchMax);
1818
1819 if (!lpszStr)
1820 {
1821 WARN("Invalid lpszStr would crash under Win32\n");
1822 return NULL;
1823 }
1824
1825 StrCpyNW(lpszStr + strlenW(lpszStr), lpszCat, cchMax);
1826 return lpszRet;
1827}
1828
1829/*************************************************************************
1830 * StrTrimA [SHLWAPI.@]
1831 *
1832 * Remove characters from the start and end of a string.
1833 *
1834 * PARAMS
1835 * lpszStr [O] String to remove characters from
1836 * lpszTrim [I] Characters to remove from lpszStr
1837 *
1838 * RETURNS
1839 * TRUE If lpszStr was valid and modified
1840 * FALSE Otherwise
1841 */
1842BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim)
1843{
1844 DWORD dwLen;
1845 LPSTR lpszRead = lpszStr;
1846 BOOL bRet = FALSE;
1847
1848 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszTrim));
1849
1850 if (lpszRead && *lpszRead)
1851 {
1852 while (*lpszRead && StrChrA(lpszTrim, *lpszRead))
1853 lpszRead = CharNextA(lpszRead); /* Skip leading matches */
1854
1855 dwLen = strlen(lpszRead);
1856
1857 if (lpszRead != lpszStr)
1858 {
1859 memmove(lpszStr, lpszRead, dwLen + 1);
1860 bRet = TRUE;
1861 }
1862 if (dwLen > 0)
1863 {
1864 lpszRead = lpszStr + dwLen;
1865 while (StrChrA(lpszTrim, lpszRead[-1]))
1866 lpszRead = CharPrevA(lpszStr, lpszRead); /* Skip trailing matches */
1867
1868 if (lpszRead != lpszStr + dwLen)
1869 {
1870 *lpszRead = '\0';
1871 bRet = TRUE;
1872 }
1873 }
1874 }
1875 return bRet;
1876}
1877
1878/*************************************************************************
1879 * StrTrimW [SHLWAPI.@]
1880 *
1881 * See StrTrimA.
1882 */
1884{
1885 DWORD dwLen;
1886 LPWSTR lpszRead = lpszStr;
1887 BOOL bRet = FALSE;
1888
1889 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszTrim));
1890
1891 if (lpszRead && *lpszRead)
1892 {
1893 while (*lpszRead && StrChrW(lpszTrim, *lpszRead)) lpszRead++;
1894
1895 dwLen = strlenW(lpszRead);
1896
1897 if (lpszRead != lpszStr)
1898 {
1899 memmove(lpszStr, lpszRead, (dwLen + 1) * sizeof(WCHAR));
1900 bRet = TRUE;
1901 }
1902 if (dwLen > 0)
1903 {
1904 lpszRead = lpszStr + dwLen;
1905 while (StrChrW(lpszTrim, lpszRead[-1]))
1906 lpszRead--; /* Skip trailing matches */
1907
1908 if (lpszRead != lpszStr + dwLen)
1909 {
1910 *lpszRead = '\0';
1911 bRet = TRUE;
1912 }
1913 }
1914 }
1915 return bRet;
1916}
1917
1918/*************************************************************************
1919 * _SHStrDupAA [INTERNAL]
1920 *
1921 * Duplicates a ASCII string to ASCII. The destination buffer is allocated.
1922 */
1924{
1925 HRESULT hr;
1926 int len = 0;
1927
1928 if (src) {
1929 len = lstrlenA(src) + 1;
1931 } else {
1932 *dest = NULL;
1933 }
1934
1935 if (*dest) {
1936 lstrcpynA(*dest,src, len);
1937 hr = S_OK;
1938 } else {
1939 hr = E_OUTOFMEMORY;
1940 }
1941
1942 TRACE("%s->(%p)\n", debugstr_a(src), *dest);
1943 return hr;
1944}
1945
1946/*************************************************************************
1947 * SHStrDupA [SHLWAPI.@]
1948 *
1949 * Return a Unicode copy of a string, in memory allocated by CoTaskMemAlloc().
1950 *
1951 * PARAMS
1952 * lpszStr [I] String to copy
1953 * lppszDest [O] Destination for the new string copy
1954 *
1955 * RETURNS
1956 * Success: S_OK. lppszDest contains the new string in Unicode format.
1957 * Failure: E_OUTOFMEMORY, If any arguments are invalid or memory allocation
1958 * fails.
1959 */
1960HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR * lppszDest)
1961{
1962 HRESULT hRet;
1963 int len = 0;
1964
1965 if (lpszStr)
1966 {
1967 len = MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, NULL, 0) * sizeof(WCHAR);
1968 *lppszDest = CoTaskMemAlloc(len);
1969 }
1970 else
1971 *lppszDest = NULL;
1972
1973 if (*lppszDest)
1974 {
1975 MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, *lppszDest, len/sizeof(WCHAR));
1976 hRet = S_OK;
1977 }
1978 else
1979 hRet = E_OUTOFMEMORY;
1980
1981 TRACE("%s->(%p)\n", debugstr_a(lpszStr), *lppszDest);
1982 return hRet;
1983}
1984
1985/*************************************************************************
1986 * _SHStrDupAW [INTERNAL]
1987 *
1988 * Duplicates a UNICODE to a ASCII string. The destination buffer is allocated.
1989 */
1991{
1992 HRESULT hr;
1993 int len = 0;
1994
1995 if (src) {
1996 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
1998 } else {
1999 *dest = NULL;
2000 }
2001
2002 if (*dest) {
2004 hr = S_OK;
2005 } else {
2006 hr = E_OUTOFMEMORY;
2007 }
2008
2009 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2010 return hr;
2011}
2012
2013/*************************************************************************
2014 * SHStrDupW [SHLWAPI.@]
2015 *
2016 * See SHStrDupA.
2017 */
2019{
2020 HRESULT hr;
2021 int len = 0;
2022
2023 if (src) {
2024 len = (lstrlenW(src) + 1) * sizeof(WCHAR);
2026 } else {
2027 *dest = NULL;
2028 }
2029
2030 if (*dest) {
2031 memcpy(*dest, src, len);
2032 hr = S_OK;
2033 } else {
2034 hr = E_OUTOFMEMORY;
2035 }
2036
2037 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2038 return hr;
2039}
2040
2041/*************************************************************************
2042 * SHLWAPI_WriteReverseNum
2043 *
2044 * Internal helper for SHLWAPI_WriteTimeClass.
2045 */
2046static inline LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
2047{
2048 *lpszOut-- = '\0';
2049
2050 /* Write a decimal number to a string, backwards */
2051 do
2052 {
2053 DWORD dwNextDigit = dwNum % 10;
2054 *lpszOut-- = '0' + dwNextDigit;
2055 dwNum = (dwNum - dwNextDigit) / 10;
2056 } while (dwNum > 0);
2057
2058 return lpszOut;
2059}
2060
2061/*************************************************************************
2062 * SHLWAPI_FormatSignificant
2063 *
2064 * Internal helper for SHLWAPI_WriteTimeClass.
2065 */
2066static inline int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
2067{
2068 /* Zero non significant digits, return remaining significant digits */
2069 while (*lpszNum)
2070 {
2071 lpszNum++;
2072 if (--dwDigits == 0)
2073 {
2074 while (*lpszNum)
2075 *lpszNum++ = '0';
2076 return 0;
2077 }
2078 }
2079 return dwDigits;
2080}
2081
2082/*************************************************************************
2083 * SHLWAPI_WriteTimeClass
2084 *
2085 * Internal helper for StrFromTimeIntervalW.
2086 */
2087static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue,
2088 UINT uClassStringId, int iDigits)
2089{
2090 WCHAR szBuff[64], *szOut = szBuff + 32;
2091
2092 szOut = SHLWAPI_WriteReverseNum(szOut, dwValue);
2093 iDigits = SHLWAPI_FormatSignificant(szOut + 1, iDigits);
2094 *szOut = ' ';
2095 LoadStringW(shlwapi_hInstance, uClassStringId, szBuff + 32, 32);
2096 strcatW(lpszOut, szOut);
2097 return iDigits;
2098}
2099
2100/*************************************************************************
2101 * StrFromTimeIntervalA [SHLWAPI.@]
2102 *
2103 * Format a millisecond time interval into a string
2104 *
2105 * PARAMS
2106 * lpszStr [O] Output buffer for formatted time interval
2107 * cchMax [I] Size of lpszStr
2108 * dwMS [I] Number of milliseconds
2109 * iDigits [I] Number of digits to print
2110 *
2111 * RETURNS
2112 * The length of the formatted string, or 0 if any parameter is invalid.
2113 *
2114 * NOTES
2115 * This implementation mimics the Win32 behaviour of always writing a leading
2116 * space before the time interval begins.
2117 *
2118 * iDigits is used to provide approximate times if accuracy is not important.
2119 * This number of digits will be written of the first non-zero time class
2120 * (hours/minutes/seconds). If this does not complete the time classification,
2121 * the remaining digits are changed to zeros (i.e. The time is _not_ rounded).
2122 * If there are digits remaining following the writing of a time class, the
2123 * next time class will be written.
2124 *
2125 * For example, given dwMS represents 138 hours,43 minutes and 15 seconds, the
2126 * following will result from the given values of iDigits:
2127 *
2128 *| iDigits 1 2 3 4 5 ...
2129 *| lpszStr "100 hr" "130 hr" "138 hr" "138 hr 40 min" "138 hr 43 min" ...
2130 */
2132 int iDigits)
2133{
2134 INT iRet = 0;
2135
2136 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2137
2138 if (lpszStr && cchMax)
2139 {
2140 WCHAR szBuff[128];
2141 StrFromTimeIntervalW(szBuff, sizeof(szBuff)/sizeof(WCHAR), dwMS, iDigits);
2142 WideCharToMultiByte(CP_ACP,0,szBuff,-1,lpszStr,cchMax,0,0);
2143 }
2144 return iRet;
2145}
2146
2147
2148/*************************************************************************
2149 * StrFromTimeIntervalW [SHLWAPI.@]
2150 *
2151 * See StrFromTimeIntervalA.
2152 */
2154 int iDigits)
2155{
2156 INT iRet = 0;
2157
2158 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2159
2160 if (lpszStr && cchMax)
2161 {
2162 WCHAR szCopy[128];
2163 DWORD dwHours, dwMinutes;
2164
2165 if (!iDigits || cchMax == 1)
2166 {
2167 *lpszStr = '\0';
2168 return 0;
2169 }
2170
2171 /* Calculate the time classes */
2172 dwMS = (dwMS + 500) / 1000;
2173 dwHours = dwMS / 3600;
2174 dwMS -= dwHours * 3600;
2175 dwMinutes = dwMS / 60;
2176 dwMS -= dwMinutes * 60;
2177
2178 szCopy[0] = '\0';
2179
2180 if (dwHours)
2181 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwHours, IDS_TIME_INTERVAL_HOURS, iDigits);
2182
2183 if (dwMinutes && iDigits)
2184 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwMinutes, IDS_TIME_INTERVAL_MINUTES, iDigits);
2185
2186 if (iDigits) /* Always write seconds if we have significant digits */
2187 SHLWAPI_WriteTimeClass(szCopy, dwMS, IDS_TIME_INTERVAL_SECONDS, iDigits);
2188
2189 lstrcpynW(lpszStr, szCopy, cchMax);
2190 iRet = strlenW(lpszStr);
2191 }
2192 return iRet;
2193}
2194
2195/*************************************************************************
2196 * StrIsIntlEqualA [SHLWAPI.@]
2197 *
2198 * Compare two strings.
2199 *
2200 * PARAMS
2201 * bCase [I] Whether to compare case sensitively
2202 * lpszStr [I] First string to compare
2203 * lpszComp [I] Second string to compare
2204 * iLen [I] Length to compare
2205 *
2206 * RETURNS
2207 * TRUE If the strings are equal.
2208 * FALSE Otherwise.
2209 */
2210BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
2211 int iLen)
2212{
2213 DWORD dwFlags;
2214
2215 TRACE("(%d,%s,%s,%d)\n", bCase,
2216 debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
2217
2218 /* FIXME: This flag is undocumented and unknown by our CompareString.
2219 * We need a define for it.
2220 */
2221 dwFlags = 0x10000000;
2222 if (!bCase) dwFlags |= NORM_IGNORECASE;
2223
2224 return (CompareStringA(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2225}
2226
2227/*************************************************************************
2228 * StrIsIntlEqualW [SHLWAPI.@]
2229 *
2230 * See StrIsIntlEqualA.
2231 */
2233 int iLen)
2234{
2235 DWORD dwFlags;
2236
2237 TRACE("(%d,%s,%s,%d)\n", bCase,
2238 debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
2239
2240 /* FIXME: This flag is undocumented and unknown by our CompareString.
2241 * We need a define for it.
2242 */
2243 dwFlags = 0x10000000;
2244 if (!bCase) dwFlags |= NORM_IGNORECASE;
2245
2246 return (CompareStringW(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2247}
2248
2249/*************************************************************************
2250 * @ [SHLWAPI.399]
2251 *
2252 * Copy a string to another string, up to a maximum number of characters.
2253 *
2254 * PARAMS
2255 * lpszDest [O] Destination string
2256 * lpszSrc [I] Source string
2257 * iLen [I] Maximum number of chars to copy
2258 *
2259 * RETURNS
2260 * Success: A pointer to the last character written to lpszDest.
2261 * Failure: lpszDest, if any arguments are invalid.
2262 */
2264{
2265 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_a(lpszSrc), iLen);
2266
2267 if (lpszDest && lpszSrc && iLen > 0)
2268 {
2269 while ((iLen-- > 1) && *lpszSrc)
2270 *lpszDest++ = *lpszSrc++;
2271 if (iLen >= 0)
2272 *lpszDest = '\0';
2273 }
2274 return lpszDest;
2275}
2276
2277/*************************************************************************
2278 * @ [SHLWAPI.400]
2279 *
2280 * Unicode version of StrCpyNXA.
2281 */
2283{
2284 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_w(lpszSrc), iLen);
2285
2286 if (lpszDest && lpszSrc && iLen > 0)
2287 {
2288 while ((iLen-- > 1) && *lpszSrc)
2289 *lpszDest++ = *lpszSrc++;
2290 if (iLen >= 0)
2291 *lpszDest = '\0';
2292 }
2293 return lpszDest;
2294}
2295
2296/*************************************************************************
2297 * StrCmpLogicalW [SHLWAPI.@]
2298 *
2299 * Compare two strings, ignoring case and comparing digits as numbers.
2300 *
2301 * PARAMS
2302 * lpszStr [I] First string to compare
2303 * lpszComp [I] Second string to compare
2304 * iLen [I] Length to compare
2305 *
2306 * RETURNS
2307 * TRUE If the strings are equal.
2308 * FALSE Otherwise.
2309 */
2311{
2312 INT iDiff;
2313
2314 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
2315
2316 if (lpszStr && lpszComp)
2317 {
2318 while (*lpszStr)
2319 {
2320 if (!*lpszComp)
2321 return 1;
2322 else if (isdigitW(*lpszStr))
2323 {
2324 int iStr, iComp;
2325
2326 if (!isdigitW(*lpszComp))
2327 return -1;
2328
2329 /* Compare the numbers */
2330 StrToIntExW(lpszStr, 0, &iStr);
2331 StrToIntExW(lpszComp, 0, &iComp);
2332
2333 if (iStr < iComp)
2334 return -1;
2335 else if (iStr > iComp)
2336 return 1;
2337
2338 /* Skip */
2339 while (isdigitW(*lpszStr))
2340 lpszStr++;
2341 while (isdigitW(*lpszComp))
2342 lpszComp++;
2343 }
2344 else if (isdigitW(*lpszComp))
2345 return 1;
2346 else
2347 {
2348 iDiff = ChrCmpIW(*lpszStr,*lpszComp);
2349 if (iDiff > 0)
2350 return 1;
2351 else if (iDiff < 0)
2352 return -1;
2353
2354 lpszStr++;
2355 lpszComp++;
2356 }
2357 }
2358 if (*lpszComp)
2359 return -1;
2360 }
2361 return 0;
2362}
2363
2364/* Structure for formatting byte strings */
2366{
2368 double dDivisor;
2371#ifdef __REACTOS__
2372 UINT nFormatID;
2373#else
2375#endif
2377
2378/*************************************************************************
2379 * StrFormatByteSizeW [SHLWAPI.@]
2380 *
2381 * Create a string containing an abbreviated byte count of up to 2^63-1.
2382 *
2383 * PARAMS
2384 * llBytes [I] Byte size to format
2385 * lpszDest [I] Destination for formatted string
2386 * cchMax [I] Size of lpszDest
2387 *
2388 * RETURNS
2389 * lpszDest.
2390 *
2391 * NOTES
2392 * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW().
2393 */
2395{
2396#define KB ((ULONGLONG)1024)
2397#define MB (KB*KB)
2398#define GB (KB*KB*KB)
2399#define TB (KB*KB*KB*KB)
2400#define PB (KB*KB*KB*KB*KB)
2401
2402 static const SHLWAPI_BYTEFORMATS bfFormats[] =
2403 {
2404#ifdef __REACTOS__
2405 { 10*KB, 10.24, 100.0, 2, IDS_KB_FORMAT }, /* 10 KB */
2406 { 100*KB, 102.4, 10.0, 1, IDS_KB_FORMAT }, /* 100 KB */
2407 { 1000*KB, 1024.0, 1.0, 0, IDS_KB_FORMAT }, /* 1000 KB */
2408 { 10*MB, 10485.76, 100.0, 2, IDS_MB_FORMAT }, /* 10 MB */
2409 { 100*MB, 104857.6, 10.0, 1, IDS_MB_FORMAT }, /* 100 MB */
2410 { 1000*MB, 1048576.0, 1.0, 0, IDS_MB_FORMAT }, /* 1000 MB */
2411 { 10*GB, 10737418.24, 100.0, 2, IDS_GB_FORMAT }, /* 10 GB */
2412 { 100*GB, 107374182.4, 10.0, 1, IDS_GB_FORMAT }, /* 100 GB */
2413 { 1000*GB, 1073741824.0, 1.0, 0, IDS_GB_FORMAT }, /* 1000 GB */
2414 { 10*TB, 10485.76, 100.0, 2, IDS_TB_FORMAT }, /* 10 TB */
2415 { 100*TB, 104857.6, 10.0, 1, IDS_TB_FORMAT }, /* 100 TB */
2416 { 1000*TB, 1048576.0, 1.0, 0, IDS_TB_FORMAT }, /* 1000 TB */
2417 { 10*PB, 10737418.24, 100.00, 2, IDS_PB_FORMAT }, /* 10 PB */
2418 { 100*PB, 107374182.4, 10.00, 1, IDS_PB_FORMAT }, /* 100 PB */
2419 { 1000*PB, 1073741824.0, 1.00, 0, IDS_PB_FORMAT }, /* 1000 PB */
2420 { 0, 10995116277.76, 100.00, 2, IDS_EB_FORMAT } /* EB's, catch all */
2421#else
2422 { 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
2423 { 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
2424 { 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
2425 { 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
2426 { 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
2427 { 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
2428 { 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
2429 { 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
2430 { 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
2431 { 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
2432 { 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
2433 { 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
2434 { 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
2435 { 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
2436 { 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
2437 { 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
2438#endif
2439 };
2440#ifdef __REACTOS__
2441 WCHAR szBuff[40], wszFormat[40];
2442#else
2443 WCHAR wszAdd[] = {' ','?','B',0};
2444#endif
2445 double dBytes;
2446 UINT i = 0;
2447
2448 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
2449
2450 if (!lpszDest || !cchMax)
2451 return lpszDest;
2452
2453 if (llBytes < 1024) /* 1K */
2454 {
2455 WCHAR wszBytesFormat[64];
2456 LoadStringW(shlwapi_hInstance, IDS_BYTES_FORMAT, wszBytesFormat, 64);
2457 snprintfW(lpszDest, cchMax, wszBytesFormat, (int)llBytes);
2458 return lpszDest;
2459 }
2460
2461 /* Note that if this loop completes without finding a match, i will be
2462 * pointing at the last entry, which is a catch all for > 1000 PB
2463 */
2464 while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
2465 {
2466 if (llBytes < bfFormats[i].dLimit)
2467 break;
2468 i++;
2469 }
2470 /* Above 1 TB we encounter problems with FP accuracy. So for amounts above
2471 * this number we integer shift down by 1 MB first. The table above has
2472 * the divisors scaled down from the '< 10 TB' entry onwards, to account
2473 * for this. We also add a small fudge factor to get the correct result for
2474 * counts that lie exactly on a 1024 byte boundary.
2475 */
2476 if (i > 8)
2477 dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by 1 MB */
2478 else
2479 dBytes = (double)llBytes + 0.00001;
2480
2481 dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
2482
2483#ifdef __REACTOS__
2484 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, szBuff, ARRAYSIZE(szBuff)))
2485 return NULL;
2486 LoadStringW(shlwapi_hInstance, bfFormats[i].nFormatID, wszFormat, ARRAYSIZE(wszFormat));
2487 snprintfW(lpszDest, cchMax, wszFormat, szBuff);
2488#else
2489 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
2490 return NULL;
2491 wszAdd[1] = bfFormats[i].wPrefix;
2492 StrCatBuffW(lpszDest, wszAdd, cchMax);
2493#endif
2494 return lpszDest;
2495}
2496
2497/*************************************************************************
2498 * StrFormatByteSize64A [SHLWAPI.@]
2499 *
2500 * See StrFormatByteSizeW.
2501 */
2503{
2504 WCHAR wszBuff[32];
2505
2506 StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
2507
2508 if (lpszDest)
2509 WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0);
2510 return lpszDest;
2511}
2512
2513/*************************************************************************
2514 * StrFormatByteSizeA [SHLWAPI.@]
2515 *
2516 * Create a string containing an abbreviated byte count of up to 2^31-1.
2517 *
2518 * PARAMS
2519 * dwBytes [I] Byte size to format
2520 * lpszDest [I] Destination for formatted string
2521 * cchMax [I] Size of lpszDest
2522 *
2523 * RETURNS
2524 * lpszDest.
2525 *
2526 * NOTES
2527 * The Ascii and Unicode versions of this function accept a different
2528 * integer type for dwBytes. See StrFormatByteSize64A().
2529 */
2531{
2532 TRACE("(%d,%p,%d)\n", dwBytes, lpszDest, cchMax);
2533
2534 return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
2535}
2536
2537/*************************************************************************
2538 * @ [SHLWAPI.162]
2539 *
2540 * Remove a hanging lead byte from the end of a string, if present.
2541 *
2542 * PARAMS
2543 * lpStr [I] String to check for a hanging lead byte
2544 * size [I] Length of lpStr
2545 *
2546 * RETURNS
2547 * Success: The new length of the string. Any hanging lead bytes are removed.
2548 * Failure: 0, if any parameters are invalid.
2549 */
2551{
2552 if (lpStr && size)
2553 {
2554 LPSTR lastByte = lpStr + size - 1;
2555
2556 while(lpStr < lastByte)
2557 lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
2558
2559 if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
2560 {
2561 *lpStr = '\0';
2562 size--;
2563 }
2564 return size;
2565 }
2566 return 0;
2567}
2568
2569/*************************************************************************
2570 * @ [SHLWAPI.203]
2571 *
2572 * Remove a single non-trailing ampersand ('&') from a string.
2573 *
2574 * PARAMS
2575 * lpszStr [I/O] String to remove ampersand from.
2576 *
2577 * RETURNS
2578 * The character after the first ampersand in lpszStr, or the first character
2579 * in lpszStr if there is no ampersand in the string.
2580 */
2582{
2583 LPSTR lpszIter, lpszTmp;
2584 char ch;
2585
2586 TRACE("(%s)\n", debugstr_a(lpszStr));
2587
2588 ch = *lpszStr;
2589
2590 if ((lpszIter = StrChrA(lpszStr, '&')))
2591 {
2592 lpszTmp = CharNextA(lpszIter);
2593 if (*lpszTmp)
2594 {
2595 if (*lpszTmp != '&')
2596 ch = *lpszTmp;
2597
2598 memmove( lpszIter, lpszTmp, strlen(lpszTmp) + 1 );
2599 }
2600 }
2601
2602 return ch;
2603}
2604
2605/*************************************************************************
2606 * @ [SHLWAPI.225]
2607 *
2608 * Unicode version of SHStripMneumonicA.
2609 */
2611{
2612 LPWSTR lpszIter, lpszTmp;
2613 WCHAR ch;
2614
2615 TRACE("(%s)\n", debugstr_w(lpszStr));
2616
2617 ch = *lpszStr;
2618
2619 if ((lpszIter = StrChrW(lpszStr, '&')))
2620 {
2621 lpszTmp = lpszIter + 1;
2622 if (*lpszTmp)
2623 {
2624 if (*lpszTmp != '&')
2625 ch = *lpszTmp;
2626
2627 memmove( lpszIter, lpszTmp, (strlenW(lpszTmp) + 1) * sizeof(WCHAR) );
2628 }
2629 }
2630
2631 return ch;
2632}
2633
2634/*************************************************************************
2635 * @ [SHLWAPI.216]
2636 *
2637 * Convert an Ascii string to Unicode.
2638 *
2639 * PARAMS
2640 * dwCp [I] Code page for the conversion
2641 * lpSrcStr [I] Source Ascii string to convert
2642 * lpDstStr [O] Destination for converted Unicode string
2643 * iLen [I] Length of lpDstStr
2644 *
2645 * RETURNS
2646 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2647 */
2648DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2649{
2650 DWORD dwRet;
2651
2652 dwRet = MultiByteToWideChar(dwCp, 0, lpSrcStr, -1, lpDstStr, iLen);
2653 TRACE("%s->%s,ret=%d\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
2654 return dwRet;
2655}
2656
2657/*************************************************************************
2658 * @ [SHLWAPI.215]
2659 *
2660 * Convert an Ascii string to Unicode.
2661 *
2662 * PARAMS
2663 * lpSrcStr [I] Source Ascii string to convert
2664 * lpDstStr [O] Destination for converted Unicode string
2665 * iLen [I] Length of lpDstStr
2666 *
2667 * RETURNS
2668 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2669 *
2670 * NOTES
2671 * This function simply calls SHAnsiToUnicodeCP with code page CP_ACP.
2672 */
2673DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2674{
2675 return SHAnsiToUnicodeCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2676}
2677
2678/*************************************************************************
2679 * @ [SHLWAPI.218]
2680 *
2681 * Convert a Unicode string to Ascii.
2682 *
2683 * PARAMS
2684 * CodePage [I] Code page to use for the conversion
2685 * lpSrcStr [I] Source Unicode string to convert
2686 * lpDstStr [O] Destination for converted Ascii string
2687 * dstlen [I] Length of buffer at lpDstStr
2688 *
2689 * RETURNS
2690 * Success: The length in bytes of the result at lpDstStr (including the terminator)
2691 * Failure: When using CP_UTF8, CP_UTF7 or 0xc350 as codePage, 0 is returned and
2692 * the result is not nul-terminated.
2693 * When using a different codepage, the length in bytes of the truncated
2694 * result at lpDstStr (including the terminator) is returned and
2695 * lpDstStr is always nul-terminated.
2696 *
2697 */
2698DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
2699{
2700 static const WCHAR emptyW[] = { '\0' };
2701 int len , reqLen;
2702 LPSTR mem;
2703
2704 if (!lpDstStr || !dstlen)
2705 return 0;
2706
2707 if (!lpSrcStr)
2708 lpSrcStr = emptyW;
2709
2710 *lpDstStr = '\0';
2711
2712 len = strlenW(lpSrcStr) + 1;
2713
2714 switch (CodePage)
2715 {
2716 case CP_WINUNICODE:
2717 CodePage = CP_UTF8; /* Fall through... */
2718 case 0x0000C350: /* FIXME: CP_ #define */
2719 case CP_UTF7:
2720 case CP_UTF8:
2721 {
2722 DWORD dwMode = 0;
2723 INT lenW = len - 1;
2724 INT needed = dstlen - 1;
2725 HRESULT hr;
2726
2727 /* try the user supplied buffer first */
2728 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, lpDstStr, &needed);
2729 if (hr == S_OK)
2730 {
2731 lpDstStr[needed] = '\0';
2732 return needed + 1;
2733 }
2734
2735 /* user buffer too small. exclude termination and copy as much as possible */
2736 lenW = len;
2737 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, NULL, &needed);
2738 needed++;
2739 mem = HeapAlloc(GetProcessHeap(), 0, needed);
2740 if (!mem)
2741 return 0;
2742
2743 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, &needed);
2744 if (hr == S_OK)
2745 {
2746 reqLen = SHTruncateString(mem, dstlen);
2747 if (reqLen > 0) memcpy(lpDstStr, mem, reqLen-1);
2748 }
2750 return 0;
2751 }
2752 default:
2753 break;
2754 }
2755
2756 /* try the user supplied buffer first */
2757 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, dstlen, NULL, NULL);
2758
2759 if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2760 {
2761 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
2762 if (reqLen)
2763 {
2764 mem = HeapAlloc(GetProcessHeap(), 0, reqLen);
2765 if (mem)
2766 {
2767 WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL);
2768
2769 reqLen = SHTruncateString(mem, dstlen -1);
2770 reqLen++;
2771
2772 lstrcpynA(lpDstStr, mem, reqLen);
2774 lpDstStr[reqLen-1] = '\0';
2775 }
2776 }
2777 }
2778 return reqLen;
2779}
2780
2781/*************************************************************************
2782 * @ [SHLWAPI.217]
2783 *
2784 * Convert a Unicode string to Ascii.
2785 *
2786 * PARAMS
2787 * lpSrcStr [I] Source Unicode string to convert
2788 * lpDstStr [O] Destination for converted Ascii string
2789 * iLen [O] Length of lpDstStr in characters
2790 *
2791 * RETURNS
2792 * See SHUnicodeToAnsiCP
2793
2794 * NOTES
2795 * This function simply calls SHUnicodeToAnsiCP() with CodePage = CP_ACP.
2796 */
2797INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
2798{
2799 return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2800}
2801
2802/*************************************************************************
2803 * @ [SHLWAPI.345]
2804 *
2805 * Copy one string to another.
2806 *
2807 * PARAMS
2808 * lpszSrc [I] Source string to copy
2809 * lpszDst [O] Destination for copy
2810 * iLen [I] Length of lpszDst in characters
2811 *
2812 * RETURNS
2813 * The length of the copied string, including the terminating NUL. lpszDst
2814 * contains iLen characters of lpszSrc.
2815 */
2816DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
2817{
2818 LPSTR lpszRet;
2819
2820 TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszSrc), lpszDst, iLen);
2821
2822 lpszRet = StrCpyNXA(lpszDst, lpszSrc, iLen);
2823 return lpszRet - lpszDst + 1;
2824}
2825
2826/*************************************************************************
2827 * @ [SHLWAPI.346]
2828 *
2829 * Unicode version of SSHAnsiToAnsi.
2830 */
2831DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
2832{
2833 LPWSTR lpszRet;
2834
2835 TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszSrc), lpszDst, iLen);
2836
2837 lpszRet = StrCpyNXW(lpszDst, lpszSrc, iLen);
2838 return lpszRet - lpszDst + 1;
2839}
2840
2841/*************************************************************************
2842 * @ [SHLWAPI.364]
2843 *
2844 * Determine if an Ascii string converts to Unicode and back identically.
2845 *
2846 * PARAMS
2847 * lpSrcStr [I] Source Unicode string to convert
2848 * lpDst [O] Destination for resulting Ascii string
2849 * iLen [I] Length of lpDst in characters
2850 *
2851 * RETURNS
2852 * TRUE, since Ascii strings always convert identically.
2853 */
2855{
2856 lstrcpynA(lpDst, lpSrcStr, iLen);
2857 return TRUE;
2858}
2859
2860/*************************************************************************
2861 * @ [SHLWAPI.365]
2862 *
2863 * Determine if a Unicode string converts to Ascii and back identically.
2864 *
2865 * PARAMS
2866 * lpSrcStr [I] Source Unicode string to convert
2867 * lpDst [O] Destination for resulting Ascii string
2868 * iLen [I] Length of lpDst in characters
2869 *
2870 * RETURNS
2871 * TRUE, if lpSrcStr converts to Ascii and back identically,
2872 * FALSE otherwise.
2873 */
2875{
2876 WCHAR szBuff[MAX_PATH];
2877
2878 SHUnicodeToAnsi(lpSrcStr, lpDst, iLen);
2879 SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
2880 return !strcmpW(lpSrcStr, szBuff);
2881}
2882
2883/*************************************************************************
2884 * SHLoadIndirectString [SHLWAPI.@]
2885 *
2886 * If passed a string that begins with '@', extract the string from the
2887 * appropriate resource, otherwise do a straight copy.
2888 *
2889 */
2891{
2892 WCHAR *dllname = NULL;
2893 HMODULE hmod = NULL;
2894 HRESULT hr = E_FAIL;
2895#ifdef __REACTOS__
2896 WCHAR szExpanded[512];
2897#endif
2898
2899 TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
2900
2901 if(src[0] == '@')
2902 {
2903 WCHAR *index_str;
2904 int index;
2905
2906#ifdef __REACTOS__
2907 if (wcschr(src, '%') != NULL)
2908 {
2909 ExpandEnvironmentStringsW(src, szExpanded, ARRAY_SIZE(szExpanded));
2910 src = szExpanded;
2911 }
2912#endif
2913 dst[0] = 0;
2914 dllname = StrDupW(src + 1);
2915 index_str = strchrW(dllname, ',');
2916
2917 if(!index_str) goto end;
2918
2919 *index_str = 0;
2920 index_str++;
2921 index = atoiW(index_str);
2922
2923#ifdef __REACTOS__
2925#else
2926 hmod = LoadLibraryW(dllname);
2927#endif
2928 if(!hmod) goto end;
2929
2930 if(index < 0)
2931 {
2932 if(LoadStringW(hmod, -index, dst, dst_len))
2933 hr = S_OK;
2934 }
2935 else
2936 FIXME("can't handle non-negative indices (%d)\n", index);
2937 }
2938 else
2939 {
2940 if(dst != src)
2941 lstrcpynW(dst, src, dst_len);
2942 hr = S_OK;
2943 }
2944
2945 TRACE("returning %s\n", debugstr_w(dst));
2946end:
2947 if(hmod) FreeLibrary(hmod);
2948 LocalFree(dllname);
2949 return hr;
2950}
2951
2953{
2954 WORD CharType;
2955 return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &CharType) && (CharType & C1_SPACE);
2956}
2957
2958/*************************************************************************
2959 * @ [SHLWAPI.29]
2960 *
2961 * Determine if a Unicode character is a space.
2962 *
2963 * PARAMS
2964 * wc [I] Character to check.
2965 *
2966 * RETURNS
2967 * TRUE, if wc is a space,
2968 * FALSE otherwise.
2969 */
2971{
2972 WORD CharType;
2973
2974 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
2975}
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:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#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:407
LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:631
LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch)
Definition: string.c:662
int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:746
int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:839
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:464
LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:552
LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:351
LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
Definition: string.c:790
INT WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:296
LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch)
Definition: string.c:610
LPWSTR WINAPI StrRChrIW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:820
LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:590
LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
Definition: string.c:521
INT WINAPI StrToIntA(LPCSTR lpszStr)
Definition: string.c:370
int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:758
LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch)
Definition: string.c:266
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:307
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:380
int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
Definition: string.c:452
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:500
LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:578
LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch)
Definition: string.c:702
INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:489
#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:2801
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2124
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: locale.c:3209
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: locale.c:4083
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4014
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3095
LCID WINAPI GetSystemDefaultLCID(void)
Definition: locale.c:1230
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1666
#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:2550
static HRESULT _SHStrDupAToBSTR(LPCSTR src, BSTR *pBstrOut)
Definition: string.c:1664
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2018
INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2153
#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:2610
LPSTR WINAPI StrNCatA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax)
Definition: string.c:1792
LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2502
LPSTR WINAPI StrCpyNXA(LPSTR lpszDest, LPCSTR lpszSrc, int iLen)
Definition: string.c:2263
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2673
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:2310
LPSTR WINAPI StrDupA(LPCSTR lpszStr)
Definition: string.c:1064
BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, int *lpiRet)
Definition: string.c:970
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:2797
LPWSTR WINAPI StrFormatKBSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:1757
#define TB
BOOL WINAPI IsCharSpaceA(CHAR c)
Definition: string.c:2952
DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
Definition: string.c:2831
#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:1960
LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2530
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2131
DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
Definition: string.c:2816
BOOL WINAPI StrIsIntlEqualW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen)
Definition: string.c:2232
char WINAPI SHStripMneumonicA(LPCSTR lpszStr)
Definition: string.c:2581
LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:2394
HRESULT WINAPI StrRetToBSTR(STRRET *lpStrRet, LPCITEMIDLIST pidl, BSTR *pBstrOut)
Definition: string.c:1700
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:2282
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:2874
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
static HRESULT _SHStrDupAA(LPCSTR, LPSTR *)
Definition: string.c:1923
LPWSTR WINAPI StrNCatW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
Definition: string.c:1813
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1883
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:2210
static int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
Definition: string.c:2066
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
BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, int *lpiRet)
Definition: string.c:886
#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:2046
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:2890
HINSTANCE shlwapi_hInstance
Definition: shlwapi_main.c:33
static HRESULT _SHStrDupAW(LPCWSTR, LPSTR *)
Definition: string.c:1990
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:2854
LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc)
Definition: string.c:514
static BOOL WINAPI SHLWAPI_ChrCmpA(WORD ch1, WORD ch2)
Definition: string.c:187
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:2648
LPSTR WINAPI StrFormatKBSizeA(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:1741
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:2698
static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue, UINT uClassStringId, int iDigits)
Definition: string.c:2087
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:1842
BOOL WINAPI IsCharSpaceW(WCHAR wc)
Definition: string.c:2970
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
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLenum src
Definition: glext.h:6340
GLsizeiptr size
Definition: glext.h:5919
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:1478
#define StrCpyNA
Definition: shlwapi.h:1540
SIGDN PWSTR * ppszName
Definition: shobjidl.idl:606
@ 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:349
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:368
#define LMEM_FIXED
Definition: winbase.h:394
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define WINAPI
Definition: msvc.h:6
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
#define NORM_IGNORECASE
Definition: winnls.h:178
#define LOCALE_SGROUPING
Definition: winnls.h:46
#define LOCALE_SDECIMAL
Definition: winnls.h:44
#define CT_CTYPE1
Definition: winnls.h:239
#define CSTR_EQUAL
Definition: winnls.h:458
#define CP_UTF7
Definition: winnls.h:237
#define LOCALE_STHOUSAND
Definition: winnls.h:45
#define LOCALE_INEGNUMBER
Definition: winnls.h:49
#define LOCALE_ILZERO
Definition: winnls.h:48
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