ReactOS 0.4.16-dev-2207-geb15453
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
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#ifdef __REACTOS__
812#define IS_DIGIT(c) ((UINT)(c) - '0' <= 9)
813#endif
814/*************************************************************************
815 * StrToIntA [SHLWAPI.@]
816 *
817 * Read a signed integer from a string.
818 *
819 * PARAMS
820 * lpszStr [I] String to read integer from
821 *
822 * RETURNS
823 * The signed integer value represented by the string, or 0 if no integer is
824 * present.
825 *
826 * NOTES
827 * No leading space is allowed before the number, although a leading '-' is.
828 */
830{
831#ifdef __REACTOS__
832 if (!lpszStr)
833 return 0;
834
835 INT result = 0;
836 BOOL isNegative = FALSE;
837
838 if (*lpszStr == '-')
839 {
840 isNegative = TRUE;
841 ++lpszStr;
842 }
843
844 while (IS_DIGIT(*lpszStr))
845 {
846 result *= 10;
847 result += (*lpszStr - '0');
848 ++lpszStr;
849 }
850
851 return isNegative ? -result : result;
852#else
853 int iRet = 0;
854
855 TRACE("(%s)\n", debugstr_a(lpszStr));
856
857 if (!lpszStr)
858 {
859 WARN("Invalid lpszStr would crash under Win32!\n");
860 return 0;
861 }
862
863 if (*lpszStr == '-' || isdigit(*lpszStr))
864 StrToIntExA(lpszStr, 0, &iRet);
865 return iRet;
866#endif
867}
868
869/*************************************************************************
870 * StrToIntW [SHLWAPI.@]
871 *
872 * See StrToIntA.
873 */
875{
876#ifdef __REACTOS__
877 if (!lpszStr)
878 return 0;
879
880 INT result = 0;
881 BOOL isNegative = FALSE;
882
883 if (*lpszStr == L'-')
884 {
885 isNegative = TRUE;
886 ++lpszStr;
887 }
888
889 while (IS_DIGIT(*lpszStr))
890 {
891 result *= 10;
892 result += (*lpszStr - L'0');
893 ++lpszStr;
894 }
895
896 return isNegative ? -result : result;
897#else
898 int iRet = 0;
899
900 TRACE("(%s)\n", debugstr_w(lpszStr));
901
902 if (!lpszStr)
903 {
904 WARN("Invalid lpszStr would crash under Win32!\n");
905 return 0;
906 }
907
908 if (*lpszStr == '-' || isdigitW(*lpszStr))
909 StrToIntExW(lpszStr, 0, &iRet);
910 return iRet;
911#endif
912}
913
914/*************************************************************************
915 * StrToIntExA [SHLWAPI.@]
916 *
917 * Read an integer from a string.
918 *
919 * PARAMS
920 * lpszStr [I] String to read integer from
921 * dwFlags [I] Flags controlling the conversion
922 * lpiRet [O] Destination for read integer.
923 *
924 * RETURNS
925 * Success: TRUE. lpiRet contains the integer value represented by the string.
926 * Failure: FALSE, if the string is invalid, or no number is present.
927 *
928 * NOTES
929 * Leading whitespace, '-' and '+' are allowed before the number. If
930 * dwFlags includes STIF_SUPPORT_HEX, hexadecimal numbers are allowed, if
931 * preceded by '0x'. If this flag is not set, or there is no '0x' prefix,
932 * the string is treated as a decimal string. A leading '-' is ignored for
933 * hexadecimal numbers.
934 */
936{
937 LONGLONG li;
938 BOOL bRes;
939
940 TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet);
941
942 bRes = StrToInt64ExA(lpszStr, dwFlags, &li);
943#ifdef __REACTOS__
944 if (lpiRet) *lpiRet = bRes ? (INT)li : 0;
945#else
946 if (bRes) *lpiRet = li;
947#endif
948 return bRes;
949}
950
951/*************************************************************************
952 * StrToInt64ExA [SHLWAPI.@]
953 *
954 * See StrToIntExA.
955 */
957{
958#ifdef __REACTOS__
959 if (!lpszStr)
960 return FALSE;
961
962 WCHAR wideBuf[MAX_PATH];
963 if (MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, wideBuf, _countof(wideBuf)) <= 0)
964 return FALSE;
965
966 wideBuf[_countof(wideBuf) - 1] = UNICODE_NULL; // SECURITY: Avoid buffer overrun
967 return StrToInt64ExW(wideBuf, dwFlags, lpiRet);
968#else
969 BOOL bNegative = FALSE;
970 LONGLONG iRet = 0;
971
972 TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet);
973
974 if (!lpszStr || !lpiRet)
975 {
976 WARN("Invalid parameter would crash under Win32!\n");
977 return FALSE;
978 }
979 if (dwFlags > STIF_SUPPORT_HEX) WARN("Unknown flags %08x\n", dwFlags);
980
981 /* Skip leading space, '+', '-' */
982 while (isspace(*lpszStr))
983 lpszStr = CharNextA(lpszStr);
984
985 if (*lpszStr == '-')
986 {
987 bNegative = TRUE;
988 lpszStr++;
989 }
990 else if (*lpszStr == '+')
991 lpszStr++;
992
994 *lpszStr == '0' && tolower(lpszStr[1]) == 'x')
995 {
996 /* Read hex number */
997 lpszStr += 2;
998
999 if (!isxdigit(*lpszStr))
1000 return FALSE;
1001
1002 while (isxdigit(*lpszStr))
1003 {
1004 iRet = iRet * 16;
1005 if (isdigit(*lpszStr))
1006 iRet += (*lpszStr - '0');
1007 else
1008 iRet += 10 + (tolower(*lpszStr) - 'a');
1009 lpszStr++;
1010 }
1011 *lpiRet = iRet;
1012 return TRUE;
1013 }
1014
1015 /* Read decimal number */
1016 if (!isdigit(*lpszStr))
1017 return FALSE;
1018
1019 while (isdigit(*lpszStr))
1020 {
1021 iRet = iRet * 10;
1022 iRet += (*lpszStr - '0');
1023 lpszStr++;
1024 }
1025 *lpiRet = bNegative ? -iRet : iRet;
1026 return TRUE;
1027#endif
1028}
1029
1030/*************************************************************************
1031 * StrToIntExW [SHLWAPI.@]
1032 *
1033 * See StrToIntExA.
1034 */
1036{
1037 LONGLONG li;
1038 BOOL bRes;
1039
1040 TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet);
1041
1042 bRes = StrToInt64ExW(lpszStr, dwFlags, &li);
1043#ifdef __REACTOS__
1044 if (lpiRet) *lpiRet = bRes ? (INT)li : 0;
1045#else
1046 if (bRes) *lpiRet = li;
1047#endif
1048 return bRes;
1049}
1050
1051/*************************************************************************
1052 * StrToInt64ExW [SHLWAPI.@]
1053 *
1054 * See StrToIntExA.
1055 */
1057{
1058#ifdef __REACTOS__
1059 if (!lpszStr)
1060 return FALSE;
1061
1062 // Skip spaces
1063 LPCWSTR pch = lpszStr;
1064 while (*pch == L' ' || *pch == L'\n' || *pch == L'\t')
1065 pch++;
1066
1067 BOOL isNegative = FALSE;
1068 if (*pch == L'+' || *pch == L'-')
1069 {
1070 isNegative = (*pch == L'-');
1071 ++pch;
1072 }
1073
1074 ULONGLONG value = 0;
1075 LPCWSTR start = pch;
1076
1077 if ((dwFlags & STIF_SUPPORT_HEX) &&
1078 *pch == L'0' && (pch[1] == L'x' || pch[1] == L'X')) // "0x" or "0X"
1079 {
1080 pch += 2;
1081 start = pch;
1082 for (;;)
1083 {
1084 INT digit;
1085 if (IS_DIGIT(*pch)) digit = *pch - L'0';
1086 else if (L'a' <= *pch && *pch <= L'f') digit = *pch - L'a' + 10;
1087 else if (L'A' <= *pch && *pch <= L'F') digit = *pch - L'A' + 10;
1088 else break;
1089
1090 value *= 16;
1091 value += digit;
1092 ++pch;
1093 }
1094 isNegative = FALSE;
1095 }
1096 else
1097 {
1098 while (IS_DIGIT(*pch))
1099 {
1100 value *= 10;
1101 value += (*pch - L'0');
1102 ++pch;
1103 }
1104 }
1105
1106 if (pch == start)
1107 {
1108 if (lpiRet)
1109 *lpiRet = 0;
1110 return FALSE; // No data
1111 }
1112
1113 if (lpiRet)
1114 *lpiRet = isNegative ? -(LONGLONG)value : (LONGLONG)value;
1115
1116 return TRUE;
1117#else
1118 BOOL bNegative = FALSE;
1119 LONGLONG iRet = 0;
1120
1121 TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet);
1122
1123 if (!lpszStr || !lpiRet)
1124 {
1125 WARN("Invalid parameter would crash under Win32!\n");
1126 return FALSE;
1127 }
1128 if (dwFlags > STIF_SUPPORT_HEX) WARN("Unknown flags %08x\n", dwFlags);
1129
1130 /* Skip leading space, '+', '-' */
1131 while (isspaceW(*lpszStr)) lpszStr++;
1132
1133 if (*lpszStr == '-')
1134 {
1135 bNegative = TRUE;
1136 lpszStr++;
1137 }
1138 else if (*lpszStr == '+')
1139 lpszStr++;
1140
1141 if (dwFlags & STIF_SUPPORT_HEX &&
1142 *lpszStr == '0' && tolowerW(lpszStr[1]) == 'x')
1143 {
1144 /* Read hex number */
1145 lpszStr += 2;
1146
1147 if (!isxdigitW(*lpszStr))
1148 return FALSE;
1149
1150 while (isxdigitW(*lpszStr))
1151 {
1152 iRet = iRet * 16;
1153 if (isdigitW(*lpszStr))
1154 iRet += (*lpszStr - '0');
1155 else
1156 iRet += 10 + (tolowerW(*lpszStr) - 'a');
1157 lpszStr++;
1158 }
1159 *lpiRet = iRet;
1160 return TRUE;
1161 }
1162
1163 /* Read decimal number */
1164 if (!isdigitW(*lpszStr))
1165 return FALSE;
1166
1167 while (isdigitW(*lpszStr))
1168 {
1169 iRet = iRet * 10;
1170 iRet += (*lpszStr - '0');
1171 lpszStr++;
1172 }
1173 *lpiRet = bNegative ? -iRet : iRet;
1174 return TRUE;
1175#endif
1176}
1177
1178/*************************************************************************
1179 * StrDupA [SHLWAPI.@]
1180 *
1181 * Duplicate a string.
1182 *
1183 * PARAMS
1184 * lpszStr [I] String to duplicate.
1185 *
1186 * RETURNS
1187 * Success: A pointer to a new string containing the contents of lpszStr
1188 * Failure: NULL, if memory cannot be allocated
1189 *
1190 * NOTES
1191 * The string memory is allocated with LocalAlloc(), and so should be released
1192 * by calling LocalFree().
1193 */
1195{
1196 int iLen;
1197 LPSTR lpszRet;
1198
1199 TRACE("(%s)\n",debugstr_a(lpszStr));
1200
1201#ifdef __REACTOS__
1202 if (!lpszStr)
1203 return NULL;
1204#endif
1205 iLen = lpszStr ? strlen(lpszStr) + 1 : 1;
1206 lpszRet = LocalAlloc(LMEM_FIXED, iLen);
1207
1208 if (lpszRet)
1209 {
1210 if (lpszStr)
1211 memcpy(lpszRet, lpszStr, iLen);
1212 else
1213 *lpszRet = '\0';
1214 }
1215 return lpszRet;
1216}
1217
1218/*************************************************************************
1219 * StrDupW [SHLWAPI.@]
1220 *
1221 * See StrDupA.
1222 */
1224{
1225 int iLen;
1226 LPWSTR lpszRet;
1227
1228 TRACE("(%s)\n",debugstr_w(lpszStr));
1229
1230#ifdef __REACTOS__
1231 if (!lpszStr)
1232 return NULL;
1233#endif
1234 iLen = (lpszStr ? strlenW(lpszStr) + 1 : 1) * sizeof(WCHAR);
1235 lpszRet = LocalAlloc(LMEM_FIXED, iLen);
1236
1237 if (lpszRet)
1238 {
1239 if (lpszStr)
1240 memcpy(lpszRet, lpszStr, iLen);
1241 else
1242 *lpszRet = '\0';
1243 }
1244 return lpszRet;
1245}
1246
1247/*************************************************************************
1248 * SHLWAPI_StrSpnHelperA
1249 *
1250 * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA
1251 */
1252static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch,
1253 LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD),
1254 BOOL bInvert)
1255{
1256 LPCSTR lpszRead = lpszStr;
1257 if (lpszStr && *lpszStr && lpszMatch)
1258 {
1259 while (*lpszRead)
1260 {
1261 LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead);
1262
1263 if (!bInvert && !lpszTest)
1264 break;
1265 if (bInvert && lpszTest)
1266 break;
1267 lpszRead = CharNextA(lpszRead);
1268 };
1269 }
1270 return lpszRead - lpszStr;
1271}
1272
1273/*************************************************************************
1274 * StrSpnA [SHLWAPI.@]
1275 *
1276 * Find the length of the start of a string that contains only certain
1277 * characters.
1278 *
1279 * PARAMS
1280 * lpszStr [I] String to search
1281 * lpszMatch [I] Characters that can be in the substring
1282 *
1283 * RETURNS
1284 * The length of the part of lpszStr containing only chars from lpszMatch,
1285 * or 0 if any parameter is invalid.
1286 */
1287int WINAPI StrSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
1288{
1289 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1290
1291 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, FALSE);
1292}
1293
1294/*************************************************************************
1295 * StrSpnW [SHLWAPI.@]
1296 *
1297 * See StrSpnA.
1298 */
1299int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1300{
1301 if (!lpszStr || !lpszMatch) return 0;
1302 return strspnW( lpszStr, lpszMatch );
1303}
1304
1305/*************************************************************************
1306 * StrCSpnA [SHLWAPI.@]
1307 *
1308 * Find the length of the start of a string that does not contain certain
1309 * characters.
1310 *
1311 * PARAMS
1312 * lpszStr [I] String to search
1313 * lpszMatch [I] Characters that cannot be in the substring
1314 *
1315 * RETURNS
1316 * The length of the part of lpszStr containing only chars not in lpszMatch,
1317 * or 0 if any parameter is invalid.
1318 */
1319int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
1320{
1321 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1322
1323 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE);
1324}
1325
1326/*************************************************************************
1327 * StrCSpnW [SHLWAPI.@]
1328 *
1329 * See StrCSpnA.
1330 */
1331int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1332{
1333 if (!lpszStr || !lpszMatch) return 0;
1334 return strcspnW( lpszStr, lpszMatch );
1335}
1336
1337/*************************************************************************
1338 * StrCSpnIA [SHLWAPI.@]
1339 *
1340 * Find the length of the start of a string that does not contain certain
1341 * characters, ignoring case.
1342 *
1343 * PARAMS
1344 * lpszStr [I] String to search
1345 * lpszMatch [I] Characters that cannot be in the substring
1346 *
1347 * RETURNS
1348 * The length of the part of lpszStr containing only chars not in lpszMatch,
1349 * or 0 if any parameter is invalid.
1350 */
1351int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
1352{
1353 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1354
1355 return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE);
1356}
1357
1358/*************************************************************************
1359 * StrCSpnIW [SHLWAPI.@]
1360 *
1361 * See StrCSpnIA.
1362 */
1363int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
1364{
1365 LPCWSTR lpszRead = lpszStr;
1366
1367 TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch));
1368
1369 if (lpszStr && *lpszStr && lpszMatch)
1370 {
1371 while (*lpszRead)
1372 {
1373 if (StrChrIW(lpszMatch, *lpszRead)) break;
1374 lpszRead++;
1375 }
1376 }
1377 return lpszRead - lpszStr;
1378}
1379
1380/*************************************************************************
1381 * StrPBrkA [SHLWAPI.@]
1382 *
1383 * Search a string for any of a group of characters.
1384 *
1385 * PARAMS
1386 * lpszStr [I] String to search
1387 * lpszMatch [I] Characters to match
1388 *
1389 * RETURNS
1390 * A pointer to the first matching character in lpszStr, or NULL if no
1391 * match was found.
1392 */
1393LPSTR WINAPI StrPBrkA(LPCSTR lpszStr, LPCSTR lpszMatch)
1394{
1395 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
1396
1397 if (lpszStr && lpszMatch && *lpszMatch)
1398 {
1399 while (*lpszStr)
1400 {
1401 if (StrChrA(lpszMatch, *lpszStr))
1402 return (LPSTR)lpszStr;
1403 lpszStr = CharNextA(lpszStr);
1404 }
1405 }
1406 return NULL;
1407}
1408
1409/*************************************************************************
1410 * StrPBrkW [SHLWAPI.@]
1411 *
1412 * See StrPBrkA.
1413 */
1415{
1416 if (!lpszStr || !lpszMatch) return NULL;
1417 return strpbrkW( lpszStr, lpszMatch );
1418}
1419
1420/*************************************************************************
1421 * SHLWAPI_StrRChrHelperA
1422 *
1423 * Internal implementation of StrRChrA/StrRChrIA.
1424 */
1426 LPCSTR lpszEnd, WORD ch,
1427 BOOL (WINAPI *pChrCmpFn)(WORD,WORD))
1428{
1429 LPCSTR lpszRet = NULL;
1430
1431 if (lpszStr)
1432 {
1433 WORD ch2;
1434
1435 if (!lpszEnd)
1436 lpszEnd = lpszStr + lstrlenA(lpszStr);
1437
1438 while (*lpszStr && lpszStr <= lpszEnd)
1439 {
1440 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
1441
1442 if (!pChrCmpFn(ch, ch2))
1443 lpszRet = lpszStr;
1444 lpszStr = CharNextA(lpszStr);
1445 }
1446 }
1447 return (LPSTR)lpszRet;
1448}
1449
1450/**************************************************************************
1451 * StrRChrA [SHLWAPI.@]
1452 *
1453 * Find the last occurrence of a character in string.
1454 *
1455 * PARAMS
1456 * lpszStr [I] String to search in
1457 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
1458 * ch [I] Character to search for.
1459 *
1460 * RETURNS
1461 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
1462 * or NULL if not found.
1463 * Failure: NULL, if any arguments are invalid.
1464 */
1466{
1467 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
1468
1469 return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, SHLWAPI_ChrCmpA);
1470}
1471
1472/**************************************************************************
1473 * StrRChrW [SHLWAPI.@]
1474 *
1475 * See StrRChrA.
1476 */
1478{
1479 WCHAR *ret = NULL;
1480
1481 if (!str) return NULL;
1482 if (!end) end = str + strlenW(str);
1483 while (str < end)
1484 {
1485 if (*str == ch) ret = (WCHAR *)str;
1486 str++;
1487 }
1488 return ret;
1489}
1490
1491/**************************************************************************
1492 * StrRChrIA [SHLWAPI.@]
1493 *
1494 * Find the last occurrence of a character in string, ignoring case.
1495 *
1496 * PARAMS
1497 * lpszStr [I] String to search in
1498 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
1499 * ch [I] Character to search for.
1500 *
1501 * RETURNS
1502 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
1503 * or NULL if not found.
1504 * Failure: NULL, if any arguments are invalid.
1505 */
1507{
1508 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
1509
1510 return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, ChrCmpIA);
1511}
1512
1513/**************************************************************************
1514 * StrRChrIW [SHLWAPI.@]
1515 *
1516 * See StrRChrIA.
1517 */
1519{
1520 WCHAR *ret = NULL;
1521
1522 if (!str) return NULL;
1523 if (!end) end = str + strlenW(str);
1524 while (str < end)
1525 {
1526 if (!ChrCmpIW(*str, ch)) ret = (WCHAR *)str;
1527 str++;
1528 }
1529 return ret;
1530}
1531
1532/*************************************************************************
1533 * StrCatBuffA [SHLWAPI.@]
1534 *
1535 * Concatenate two strings together.
1536 *
1537 * PARAMS
1538 * lpszStr [O] String to concatenate to
1539 * lpszCat [I] String to add to lpszCat
1540 * cchMax [I] Maximum number of characters for the whole string
1541 *
1542 * RETURNS
1543 * lpszStr.
1544 *
1545 * NOTES
1546 * cchMax determines the number of characters in the final length of the
1547 * string, not the number appended to lpszStr from lpszCat.
1548 */
1550{
1551 INT iLen;
1552
1553 TRACE("(%p,%s,%d)\n", lpszStr, debugstr_a(lpszCat), cchMax);
1554
1555 if (!lpszStr)
1556 {
1557 WARN("Invalid lpszStr would crash under Win32!\n");
1558 return NULL;
1559 }
1560
1561 iLen = strlen(lpszStr);
1562 cchMax -= iLen;
1563
1564 if (cchMax > 0)
1565 StrCpyNA(lpszStr + iLen, lpszCat, cchMax);
1566 return lpszStr;
1567}
1568
1569/*************************************************************************
1570 * StrCatBuffW [SHLWAPI.@]
1571 *
1572 * See StrCatBuffA.
1573 */
1575{
1576 INT iLen;
1577
1578 TRACE("(%p,%s,%d)\n", lpszStr, debugstr_w(lpszCat), cchMax);
1579
1580 if (!lpszStr)
1581 {
1582 WARN("Invalid lpszStr would crash under Win32!\n");
1583 return NULL;
1584 }
1585
1586 iLen = strlenW(lpszStr);
1587 cchMax -= iLen;
1588
1589 if (cchMax > 0)
1590 StrCpyNW(lpszStr + iLen, lpszCat, cchMax);
1591 return lpszStr;
1592}
1593
1594/*************************************************************************
1595 * StrRetToBufA [SHLWAPI.@]
1596 *
1597 * Convert a STRRET to a normal string.
1598 *
1599 * PARAMS
1600 * lpStrRet [O] STRRET to convert
1601 * pIdl [I] ITEMIDLIST for lpStrRet->uType == STRRET_OFFSET
1602 * lpszDest [O] Destination for normal string
1603 * dwLen [I] Length of lpszDest
1604 *
1605 * RETURNS
1606 * Success: S_OK. lpszDest contains up to dwLen characters of the string.
1607 * If lpStrRet is of type STRRET_WSTR, its memory is freed with
1608 * CoTaskMemFree() and its type set to STRRET_CSTRA.
1609 * Failure: E_FAIL, if any parameters are invalid.
1610 */
1612{
1613 /* NOTE:
1614 * This routine is identical to that in dlls/shell32/shellstring.c.
1615 * It was duplicated because not every version of Shlwapi.dll exports
1616 * StrRetToBufA. If you change one routine, change them both.
1617 */
1618 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
1619
1620 if (!src)
1621 {
1622 WARN("Invalid lpStrRet would crash under Win32!\n");
1623 if (dest)
1624 *dest = '\0';
1625 return E_FAIL;
1626 }
1627
1628 if (!dest || !len)
1629 return E_FAIL;
1630
1631 *dest = '\0';
1632
1633 switch (src->uType)
1634 {
1635 case STRRET_WSTR:
1636 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, dest, len, NULL, NULL);
1637 CoTaskMemFree(src->u.pOleStr);
1638 break;
1639
1640 case STRRET_CSTR:
1641 lstrcpynA(dest, src->u.cStr, len);
1642 break;
1643
1644 case STRRET_OFFSET:
1645 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
1646 break;
1647
1648 default:
1649 FIXME("unknown type!\n");
1650 return E_NOTIMPL;
1651 }
1652 return S_OK;
1653}
1654
1655/*************************************************************************
1656 * StrRetToBufW [SHLWAPI.@]
1657 *
1658 * See StrRetToBufA.
1659 */
1661{
1662 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
1663
1664 if (!dest || !len)
1665 return E_FAIL;
1666
1667 if (!src)
1668 {
1669 WARN("Invalid lpStrRet would crash under Win32!\n");
1670 if (dest)
1671 *dest = '\0';
1672 return E_FAIL;
1673 }
1674
1675 *dest = '\0';
1676
1677 switch (src->uType) {
1678 case STRRET_WSTR: {
1679 size_t dst_len;
1680 if (!src->u.pOleStr)
1681 return E_FAIL;
1682 dst_len = strlenW(src->u.pOleStr);
1683 memcpy(dest, src->u.pOleStr, min(dst_len, len-1) * sizeof(WCHAR));
1684 dest[min(dst_len, len-1)] = 0;
1685 CoTaskMemFree(src->u.pOleStr);
1686 if (len <= dst_len)
1687 {
1688 dest[0] = 0;
1690 }
1691 break;
1692 }
1693
1694 case STRRET_CSTR:
1695 if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
1696 dest[len-1] = 0;
1697 break;
1698
1699 case STRRET_OFFSET:
1700 if (pidl)
1701 {
1702 if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
1703 dest, len ))
1704 dest[len-1] = 0;
1705 }
1706 break;
1707
1708 default:
1709 FIXME("unknown type!\n");
1710 return E_NOTIMPL;
1711 }
1712
1713 return S_OK;
1714}
1715
1716/*************************************************************************
1717 * StrRetToStrA [SHLWAPI.@]
1718 *
1719 * Converts a STRRET to a normal string.
1720 *
1721 * PARAMS
1722 * lpStrRet [O] STRRET to convert
1723 * pidl [I] ITEMIDLIST for lpStrRet->uType == STRRET_OFFSET
1724 * ppszName [O] Destination for converted string
1725 *
1726 * RETURNS
1727 * Success: S_OK. ppszName contains the new string, allocated with CoTaskMemAlloc().
1728 * Failure: E_FAIL, if any parameters are invalid.
1729 */
1731{
1732 HRESULT hRet = E_FAIL;
1733
1734 switch (lpStrRet->uType)
1735 {
1736 case STRRET_WSTR:
1737 hRet = _SHStrDupAW(lpStrRet->u.pOleStr, ppszName);
1738 CoTaskMemFree(lpStrRet->u.pOleStr);
1739 break;
1740
1741 case STRRET_CSTR:
1742 hRet = _SHStrDupAA(lpStrRet->u.cStr, ppszName);
1743 break;
1744
1745 case STRRET_OFFSET:
1746 hRet = _SHStrDupAA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1747 break;
1748
1749 default:
1750 *ppszName = NULL;
1751 }
1752
1753 return hRet;
1754}
1755
1756/*************************************************************************
1757 * StrRetToStrW [SHLWAPI.@]
1758 *
1759 * See StrRetToStrA.
1760 */
1762{
1763 HRESULT hRet = E_FAIL;
1764
1765 switch (lpStrRet->uType)
1766 {
1767 case STRRET_WSTR:
1768#ifdef __REACTOS__
1769 hRet = lpStrRet->u.pOleStr ? S_OK : E_FAIL;
1770 *ppszName = lpStrRet->u.pOleStr;
1771 lpStrRet->u.pOleStr = NULL; /* Windows does this, presumably in case someone calls SHFree */
1772#else
1773 hRet = SHStrDupW(lpStrRet->u.pOleStr, ppszName);
1774 CoTaskMemFree(lpStrRet->u.pOleStr);
1775#endif
1776 break;
1777
1778 case STRRET_CSTR:
1779 hRet = SHStrDupA(lpStrRet->u.cStr, ppszName);
1780 break;
1781
1782 case STRRET_OFFSET:
1783 hRet = SHStrDupA(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, ppszName);
1784 break;
1785
1786 default:
1787 *ppszName = NULL;
1788 }
1789
1790 return hRet;
1791}
1792
1793/* Create an ASCII string copy using SysAllocString() */
1795{
1796 *pBstrOut = NULL;
1797
1798 if (src)
1799 {
1800 INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
1801 WCHAR* szTemp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1802
1803 if (szTemp)
1804 {
1805 MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
1806 *pBstrOut = SysAllocString(szTemp);
1807 HeapFree(GetProcessHeap(), 0, szTemp);
1808
1809 if (*pBstrOut)
1810 return S_OK;
1811 }
1812 }
1813 return E_OUTOFMEMORY;
1814}
1815
1816/*************************************************************************
1817 * StrRetToBSTR [SHLWAPI.@]
1818 *
1819 * Converts a STRRET to a BSTR.
1820 *
1821 * PARAMS
1822 * lpStrRet [O] STRRET to convert
1823 * pidl [I] ITEMIDLIST for lpStrRet->uType = STRRET_OFFSET
1824 * pBstrOut [O] Destination for converted BSTR
1825 *
1826 * RETURNS
1827 * Success: S_OK. pBstrOut contains the new string.
1828 * Failure: E_FAIL, if any parameters are invalid.
1829 */
1831{
1832 HRESULT hRet = E_FAIL;
1833
1834 switch (lpStrRet->uType)
1835 {
1836 case STRRET_WSTR:
1837 *pBstrOut = SysAllocString(lpStrRet->u.pOleStr);
1838 if (*pBstrOut)
1839 hRet = S_OK;
1840 CoTaskMemFree(lpStrRet->u.pOleStr);
1841 break;
1842
1843 case STRRET_CSTR:
1844 hRet = _SHStrDupAToBSTR(lpStrRet->u.cStr, pBstrOut);
1845 break;
1846
1847 case STRRET_OFFSET:
1848 hRet = _SHStrDupAToBSTR(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, pBstrOut);
1849 break;
1850
1851 default:
1852 *pBstrOut = NULL;
1853 }
1854
1855 return hRet;
1856}
1857
1858/*************************************************************************
1859 * StrFormatKBSizeA [SHLWAPI.@]
1860 *
1861 * Create a formatted string containing a byte count in Kilobytes.
1862 *
1863 * PARAMS
1864 * llBytes [I] Byte size to format
1865 * lpszDest [I] Destination for formatted string
1866 * cchMax [I] Size of lpszDest
1867 *
1868 * RETURNS
1869 * lpszDest.
1870 */
1872{
1873 WCHAR wszBuf[256];
1874
1875 if (!StrFormatKBSizeW(llBytes, wszBuf, 256))
1876 return NULL;
1877 if (!WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, lpszDest, cchMax, NULL, NULL))
1878 return NULL;
1879 return lpszDest;
1880}
1881
1882/*************************************************************************
1883 * StrFormatKBSizeW [SHLWAPI.@]
1884 *
1885 * See StrFormatKBSizeA.
1886 */
1888{
1889 static const WCHAR kb[] = {' ','K','B',0};
1890 LONGLONG llKB = (llBytes + 1023) >> 10;
1891 int len;
1892
1893 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
1894
1895 if (!FormatInt(llKB, lpszDest, cchMax))
1896 return NULL;
1897
1899 if (cchMax - len < 4)
1900 return NULL;
1901 lstrcatW(lpszDest, kb);
1902 return lpszDest;
1903}
1904
1905/*************************************************************************
1906 * StrNCatA [SHLWAPI.@]
1907 *
1908 * Concatenate two strings together.
1909 *
1910 * PARAMS
1911 * lpszStr [O] String to concatenate to
1912 * lpszCat [I] String to add to lpszCat
1913 * cchMax [I] Maximum number of characters to concatenate
1914 *
1915 * RETURNS
1916 * lpszStr.
1917 *
1918 * NOTES
1919 * cchMax determines the number of characters that are appended to lpszStr,
1920 * not the total length of the string.
1921 */
1923{
1924 LPSTR lpszRet = lpszStr;
1925
1926 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszCat), cchMax);
1927
1928 if (!lpszStr)
1929 {
1930 WARN("Invalid lpszStr would crash under Win32!\n");
1931 return NULL;
1932 }
1933
1934 StrCpyNA(lpszStr + strlen(lpszStr), lpszCat, cchMax);
1935 return lpszRet;
1936}
1937
1938/*************************************************************************
1939 * StrNCatW [SHLWAPI.@]
1940 *
1941 * See StrNCatA.
1942 */
1944{
1945 LPWSTR lpszRet = lpszStr;
1946
1947 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszCat), cchMax);
1948
1949 if (!lpszStr)
1950 {
1951 WARN("Invalid lpszStr would crash under Win32\n");
1952 return NULL;
1953 }
1954
1955 StrCpyNW(lpszStr + strlenW(lpszStr), lpszCat, cchMax);
1956 return lpszRet;
1957}
1958
1959/*************************************************************************
1960 * StrTrimA [SHLWAPI.@]
1961 *
1962 * Remove characters from the start and end of a string.
1963 *
1964 * PARAMS
1965 * lpszStr [O] String to remove characters from
1966 * lpszTrim [I] Characters to remove from lpszStr
1967 *
1968 * RETURNS
1969 * TRUE If lpszStr was valid and modified
1970 * FALSE Otherwise
1971 */
1972BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim)
1973{
1974 DWORD dwLen;
1975 LPSTR lpszRead = lpszStr;
1976 BOOL bRet = FALSE;
1977
1978 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszTrim));
1979
1980 if (lpszRead && *lpszRead)
1981 {
1982 while (*lpszRead && StrChrA(lpszTrim, *lpszRead))
1983 lpszRead = CharNextA(lpszRead); /* Skip leading matches */
1984
1985 dwLen = strlen(lpszRead);
1986
1987 if (lpszRead != lpszStr)
1988 {
1989 memmove(lpszStr, lpszRead, dwLen + 1);
1990 bRet = TRUE;
1991 }
1992 if (dwLen > 0)
1993 {
1994 lpszRead = lpszStr + dwLen;
1995 while (StrChrA(lpszTrim, lpszRead[-1]))
1996 lpszRead = CharPrevA(lpszStr, lpszRead); /* Skip trailing matches */
1997
1998 if (lpszRead != lpszStr + dwLen)
1999 {
2000 *lpszRead = '\0';
2001 bRet = TRUE;
2002 }
2003 }
2004 }
2005 return bRet;
2006}
2007
2008/*************************************************************************
2009 * StrTrimW [SHLWAPI.@]
2010 *
2011 * See StrTrimA.
2012 */
2014{
2015 DWORD dwLen;
2016 LPWSTR lpszRead = lpszStr;
2017 BOOL bRet = FALSE;
2018
2019 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszTrim));
2020
2021 if (lpszRead && *lpszRead)
2022 {
2023 while (*lpszRead && StrChrW(lpszTrim, *lpszRead)) lpszRead++;
2024
2025 dwLen = strlenW(lpszRead);
2026
2027 if (lpszRead != lpszStr)
2028 {
2029 memmove(lpszStr, lpszRead, (dwLen + 1) * sizeof(WCHAR));
2030 bRet = TRUE;
2031 }
2032 if (dwLen > 0)
2033 {
2034 lpszRead = lpszStr + dwLen;
2035 while (StrChrW(lpszTrim, lpszRead[-1]))
2036 lpszRead--; /* Skip trailing matches */
2037
2038 if (lpszRead != lpszStr + dwLen)
2039 {
2040 *lpszRead = '\0';
2041 bRet = TRUE;
2042 }
2043 }
2044 }
2045 return bRet;
2046}
2047
2048/*************************************************************************
2049 * _SHStrDupAA [INTERNAL]
2050 *
2051 * Duplicates a ASCII string to ASCII. The destination buffer is allocated.
2052 */
2054{
2055 HRESULT hr;
2056 int len = 0;
2057
2058 if (src) {
2059 len = lstrlenA(src) + 1;
2061 } else {
2062 *dest = NULL;
2063 }
2064
2065 if (*dest) {
2066 lstrcpynA(*dest,src, len);
2067 hr = S_OK;
2068 } else {
2069 hr = E_OUTOFMEMORY;
2070 }
2071
2072 TRACE("%s->(%p)\n", debugstr_a(src), *dest);
2073 return hr;
2074}
2075
2076/*************************************************************************
2077 * SHStrDupA [SHLWAPI.@]
2078 *
2079 * Return a Unicode copy of a string, in memory allocated by CoTaskMemAlloc().
2080 *
2081 * PARAMS
2082 * lpszStr [I] String to copy
2083 * lppszDest [O] Destination for the new string copy
2084 *
2085 * RETURNS
2086 * Success: S_OK. lppszDest contains the new string in Unicode format.
2087 * Failure: E_OUTOFMEMORY, If any arguments are invalid or memory allocation
2088 * fails.
2089 */
2090HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR * lppszDest)
2091{
2092 HRESULT hRet;
2093 int len = 0;
2094
2095 if (lpszStr)
2096 {
2097 len = MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, NULL, 0) * sizeof(WCHAR);
2098 *lppszDest = CoTaskMemAlloc(len);
2099 }
2100 else
2101 *lppszDest = NULL;
2102
2103 if (*lppszDest)
2104 {
2105 MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, *lppszDest, len/sizeof(WCHAR));
2106 hRet = S_OK;
2107 }
2108 else
2109 hRet = E_OUTOFMEMORY;
2110
2111 TRACE("%s->(%p)\n", debugstr_a(lpszStr), *lppszDest);
2112 return hRet;
2113}
2114
2115/*************************************************************************
2116 * _SHStrDupAW [INTERNAL]
2117 *
2118 * Duplicates a UNICODE to a ASCII string. The destination buffer is allocated.
2119 */
2121{
2122 HRESULT hr;
2123 int len = 0;
2124
2125 if (src) {
2126 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
2128 } else {
2129 *dest = NULL;
2130 }
2131
2132 if (*dest) {
2134 hr = S_OK;
2135 } else {
2136 hr = E_OUTOFMEMORY;
2137 }
2138
2139 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2140 return hr;
2141}
2142
2143/*************************************************************************
2144 * SHStrDupW [SHLWAPI.@]
2145 *
2146 * See SHStrDupA.
2147 */
2149{
2150 HRESULT hr;
2151 int len = 0;
2152
2153 if (src) {
2154 len = (lstrlenW(src) + 1) * sizeof(WCHAR);
2156 } else {
2157 *dest = NULL;
2158 }
2159
2160 if (*dest) {
2161 memcpy(*dest, src, len);
2162 hr = S_OK;
2163 } else {
2164 hr = E_OUTOFMEMORY;
2165 }
2166
2167 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
2168 return hr;
2169}
2170
2171/*************************************************************************
2172 * SHLWAPI_WriteReverseNum
2173 *
2174 * Internal helper for SHLWAPI_WriteTimeClass.
2175 */
2176static inline LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
2177{
2178 *lpszOut-- = '\0';
2179
2180 /* Write a decimal number to a string, backwards */
2181 do
2182 {
2183 DWORD dwNextDigit = dwNum % 10;
2184 *lpszOut-- = '0' + dwNextDigit;
2185 dwNum = (dwNum - dwNextDigit) / 10;
2186 } while (dwNum > 0);
2187
2188 return lpszOut;
2189}
2190
2191/*************************************************************************
2192 * SHLWAPI_FormatSignificant
2193 *
2194 * Internal helper for SHLWAPI_WriteTimeClass.
2195 */
2196static inline int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
2197{
2198 /* Zero non significant digits, return remaining significant digits */
2199 while (*lpszNum)
2200 {
2201 lpszNum++;
2202 if (--dwDigits == 0)
2203 {
2204 while (*lpszNum)
2205 *lpszNum++ = '0';
2206 return 0;
2207 }
2208 }
2209 return dwDigits;
2210}
2211
2212/*************************************************************************
2213 * SHLWAPI_WriteTimeClass
2214 *
2215 * Internal helper for StrFromTimeIntervalW.
2216 */
2217static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue,
2218 UINT uClassStringId, int iDigits)
2219{
2220 WCHAR szBuff[64], *szOut = szBuff + 32;
2221
2222 szOut = SHLWAPI_WriteReverseNum(szOut, dwValue);
2223 iDigits = SHLWAPI_FormatSignificant(szOut + 1, iDigits);
2224 *szOut = ' ';
2225 LoadStringW(shlwapi_hInstance, uClassStringId, szBuff + 32, 32);
2226 strcatW(lpszOut, szOut);
2227 return iDigits;
2228}
2229
2230/*************************************************************************
2231 * StrFromTimeIntervalA [SHLWAPI.@]
2232 *
2233 * Format a millisecond time interval into a string
2234 *
2235 * PARAMS
2236 * lpszStr [O] Output buffer for formatted time interval
2237 * cchMax [I] Size of lpszStr
2238 * dwMS [I] Number of milliseconds
2239 * iDigits [I] Number of digits to print
2240 *
2241 * RETURNS
2242 * The length of the formatted string, or 0 if any parameter is invalid.
2243 *
2244 * NOTES
2245 * This implementation mimics the Win32 behaviour of always writing a leading
2246 * space before the time interval begins.
2247 *
2248 * iDigits is used to provide approximate times if accuracy is not important.
2249 * This number of digits will be written of the first non-zero time class
2250 * (hours/minutes/seconds). If this does not complete the time classification,
2251 * the remaining digits are changed to zeros (i.e. The time is _not_ rounded).
2252 * If there are digits remaining following the writing of a time class, the
2253 * next time class will be written.
2254 *
2255 * For example, given dwMS represents 138 hours,43 minutes and 15 seconds, the
2256 * following will result from the given values of iDigits:
2257 *
2258 *| iDigits 1 2 3 4 5 ...
2259 *| lpszStr "100 hr" "130 hr" "138 hr" "138 hr 40 min" "138 hr 43 min" ...
2260 */
2262 int iDigits)
2263{
2264 INT iRet = 0;
2265
2266 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2267
2268 if (lpszStr && cchMax)
2269 {
2270 WCHAR szBuff[128];
2271 StrFromTimeIntervalW(szBuff, sizeof(szBuff)/sizeof(WCHAR), dwMS, iDigits);
2272 WideCharToMultiByte(CP_ACP,0,szBuff,-1,lpszStr,cchMax,0,0);
2273 }
2274 return iRet;
2275}
2276
2277
2278/*************************************************************************
2279 * StrFromTimeIntervalW [SHLWAPI.@]
2280 *
2281 * See StrFromTimeIntervalA.
2282 */
2284 int iDigits)
2285{
2286 INT iRet = 0;
2287
2288 TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
2289
2290 if (lpszStr && cchMax)
2291 {
2292 WCHAR szCopy[128];
2293 DWORD dwHours, dwMinutes;
2294
2295 if (!iDigits || cchMax == 1)
2296 {
2297 *lpszStr = '\0';
2298 return 0;
2299 }
2300
2301 /* Calculate the time classes */
2302 dwMS = (dwMS + 500) / 1000;
2303 dwHours = dwMS / 3600;
2304 dwMS -= dwHours * 3600;
2305 dwMinutes = dwMS / 60;
2306 dwMS -= dwMinutes * 60;
2307
2308 szCopy[0] = '\0';
2309
2310 if (dwHours)
2311 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwHours, IDS_TIME_INTERVAL_HOURS, iDigits);
2312
2313 if (dwMinutes && iDigits)
2314 iDigits = SHLWAPI_WriteTimeClass(szCopy, dwMinutes, IDS_TIME_INTERVAL_MINUTES, iDigits);
2315
2316 if (iDigits) /* Always write seconds if we have significant digits */
2317 SHLWAPI_WriteTimeClass(szCopy, dwMS, IDS_TIME_INTERVAL_SECONDS, iDigits);
2318
2319 lstrcpynW(lpszStr, szCopy, cchMax);
2320 iRet = strlenW(lpszStr);
2321 }
2322 return iRet;
2323}
2324
2325/*************************************************************************
2326 * StrIsIntlEqualA [SHLWAPI.@]
2327 *
2328 * Compare two strings.
2329 *
2330 * PARAMS
2331 * bCase [I] Whether to compare case sensitively
2332 * lpszStr [I] First string to compare
2333 * lpszComp [I] Second string to compare
2334 * iLen [I] Length to compare
2335 *
2336 * RETURNS
2337 * TRUE If the strings are equal.
2338 * FALSE Otherwise.
2339 */
2340BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
2341 int iLen)
2342{
2343 DWORD dwFlags;
2344
2345 TRACE("(%d,%s,%s,%d)\n", bCase,
2346 debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
2347
2348 /* FIXME: This flag is undocumented and unknown by our CompareString.
2349 * We need a define for it.
2350 */
2351 dwFlags = 0x10000000;
2352 if (!bCase) dwFlags |= NORM_IGNORECASE;
2353
2354 return (CompareStringA(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2355}
2356
2357/*************************************************************************
2358 * StrIsIntlEqualW [SHLWAPI.@]
2359 *
2360 * See StrIsIntlEqualA.
2361 */
2363 int iLen)
2364{
2365 DWORD dwFlags;
2366
2367 TRACE("(%d,%s,%s,%d)\n", bCase,
2368 debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
2369
2370 /* FIXME: This flag is undocumented and unknown by our CompareString.
2371 * We need a define for it.
2372 */
2373 dwFlags = 0x10000000;
2374 if (!bCase) dwFlags |= NORM_IGNORECASE;
2375
2376 return (CompareStringW(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
2377}
2378
2379/*************************************************************************
2380 * @ [SHLWAPI.399]
2381 *
2382 * Copy a string to another string, up to a maximum number of characters.
2383 *
2384 * PARAMS
2385 * lpszDest [O] Destination string
2386 * lpszSrc [I] Source string
2387 * iLen [I] Maximum number of chars to copy
2388 *
2389 * RETURNS
2390 * Success: A pointer to the last character written to lpszDest.
2391 * Failure: lpszDest, if any arguments are invalid.
2392 */
2394{
2395 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_a(lpszSrc), iLen);
2396
2397 if (lpszDest && lpszSrc && iLen > 0)
2398 {
2399 while ((iLen-- > 1) && *lpszSrc)
2400 *lpszDest++ = *lpszSrc++;
2401 if (iLen >= 0)
2402 *lpszDest = '\0';
2403 }
2404 return lpszDest;
2405}
2406
2407/*************************************************************************
2408 * @ [SHLWAPI.400]
2409 *
2410 * Unicode version of StrCpyNXA.
2411 */
2413{
2414 TRACE("(%p,%s,%i)\n", lpszDest, debugstr_w(lpszSrc), iLen);
2415
2416 if (lpszDest && lpszSrc && iLen > 0)
2417 {
2418 while ((iLen-- > 1) && *lpszSrc)
2419 *lpszDest++ = *lpszSrc++;
2420 if (iLen >= 0)
2421 *lpszDest = '\0';
2422 }
2423 return lpszDest;
2424}
2425
2426/*************************************************************************
2427 * StrCmpLogicalW [SHLWAPI.@]
2428 *
2429 * Compare two strings, ignoring case and comparing digits as numbers.
2430 *
2431 * PARAMS
2432 * lpszStr [I] First string to compare
2433 * lpszComp [I] Second string to compare
2434 * iLen [I] Length to compare
2435 *
2436 * RETURNS
2437 * TRUE If the strings are equal.
2438 * FALSE Otherwise.
2439 */
2441{
2442 INT iDiff;
2443
2444 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
2445
2446 if (lpszStr && lpszComp)
2447 {
2448 while (*lpszStr)
2449 {
2450 if (!*lpszComp)
2451 return 1;
2452 else if (isdigitW(*lpszStr))
2453 {
2454 int iStr, iComp;
2455
2456 if (!isdigitW(*lpszComp))
2457 return -1;
2458
2459 /* Compare the numbers */
2460 StrToIntExW(lpszStr, 0, &iStr);
2461 StrToIntExW(lpszComp, 0, &iComp);
2462
2463 if (iStr < iComp)
2464 return -1;
2465 else if (iStr > iComp)
2466 return 1;
2467
2468 /* Skip */
2469 while (isdigitW(*lpszStr))
2470 lpszStr++;
2471 while (isdigitW(*lpszComp))
2472 lpszComp++;
2473 }
2474 else if (isdigitW(*lpszComp))
2475 return 1;
2476 else
2477 {
2478 iDiff = ChrCmpIW(*lpszStr,*lpszComp);
2479 if (iDiff > 0)
2480 return 1;
2481 else if (iDiff < 0)
2482 return -1;
2483
2484 lpszStr++;
2485 lpszComp++;
2486 }
2487 }
2488 if (*lpszComp)
2489 return -1;
2490 }
2491 return 0;
2492}
2493
2494/* Structure for formatting byte strings */
2496{
2498 double dDivisor;
2501#ifdef __REACTOS__
2502 UINT nFormatID;
2503#else
2505#endif
2507
2508/*************************************************************************
2509 * StrFormatByteSizeW [SHLWAPI.@]
2510 *
2511 * Create a string containing an abbreviated byte count of up to 2^63-1.
2512 *
2513 * PARAMS
2514 * llBytes [I] Byte size to format
2515 * lpszDest [I] Destination for formatted string
2516 * cchMax [I] Size of lpszDest
2517 *
2518 * RETURNS
2519 * lpszDest.
2520 *
2521 * NOTES
2522 * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW().
2523 */
2525{
2526#define KB ((ULONGLONG)1024)
2527#define MB (KB*KB)
2528#define GB (KB*KB*KB)
2529#define TB (KB*KB*KB*KB)
2530#define PB (KB*KB*KB*KB*KB)
2531
2532 static const SHLWAPI_BYTEFORMATS bfFormats[] =
2533 {
2534#ifdef __REACTOS__
2535 { 10*KB, 10.24, 100.0, 2, IDS_KB_FORMAT }, /* 10 KB */
2536 { 100*KB, 102.4, 10.0, 1, IDS_KB_FORMAT }, /* 100 KB */
2537 { 1000*KB, 1024.0, 1.0, 0, IDS_KB_FORMAT }, /* 1000 KB */
2538 { 10*MB, 10485.76, 100.0, 2, IDS_MB_FORMAT }, /* 10 MB */
2539 { 100*MB, 104857.6, 10.0, 1, IDS_MB_FORMAT }, /* 100 MB */
2540 { 1000*MB, 1048576.0, 1.0, 0, IDS_MB_FORMAT }, /* 1000 MB */
2541 { 10*GB, 10737418.24, 100.0, 2, IDS_GB_FORMAT }, /* 10 GB */
2542 { 100*GB, 107374182.4, 10.0, 1, IDS_GB_FORMAT }, /* 100 GB */
2543 { 1000*GB, 1073741824.0, 1.0, 0, IDS_GB_FORMAT }, /* 1000 GB */
2544 { 10*TB, 10485.76, 100.0, 2, IDS_TB_FORMAT }, /* 10 TB */
2545 { 100*TB, 104857.6, 10.0, 1, IDS_TB_FORMAT }, /* 100 TB */
2546 { 1000*TB, 1048576.0, 1.0, 0, IDS_TB_FORMAT }, /* 1000 TB */
2547 { 10*PB, 10737418.24, 100.00, 2, IDS_PB_FORMAT }, /* 10 PB */
2548 { 100*PB, 107374182.4, 10.00, 1, IDS_PB_FORMAT }, /* 100 PB */
2549 { 1000*PB, 1073741824.0, 1.00, 0, IDS_PB_FORMAT }, /* 1000 PB */
2550 { 0, 10995116277.76, 100.00, 2, IDS_EB_FORMAT } /* EB's, catch all */
2551#else
2552 { 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
2553 { 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
2554 { 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
2555 { 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
2556 { 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
2557 { 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
2558 { 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
2559 { 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
2560 { 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
2561 { 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
2562 { 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
2563 { 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
2564 { 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
2565 { 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
2566 { 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
2567 { 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
2568#endif
2569 };
2570#ifdef __REACTOS__
2571 WCHAR szBuff[40], wszFormat[40];
2572#else
2573 WCHAR wszAdd[] = {' ','?','B',0};
2574#endif
2575 double dBytes;
2576 UINT i = 0;
2577
2578 TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
2579
2580 if (!lpszDest || !cchMax)
2581 return lpszDest;
2582
2583 if (llBytes < 1024) /* 1K */
2584 {
2585 WCHAR wszBytesFormat[64];
2586 LoadStringW(shlwapi_hInstance, IDS_BYTES_FORMAT, wszBytesFormat, 64);
2587 snprintfW(lpszDest, cchMax, wszBytesFormat, (int)llBytes);
2588 return lpszDest;
2589 }
2590
2591 /* Note that if this loop completes without finding a match, i will be
2592 * pointing at the last entry, which is a catch all for > 1000 PB
2593 */
2594 while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
2595 {
2596 if (llBytes < bfFormats[i].dLimit)
2597 break;
2598 i++;
2599 }
2600 /* Above 1 TB we encounter problems with FP accuracy. So for amounts above
2601 * this number we integer shift down by 1 MB first. The table above has
2602 * the divisors scaled down from the '< 10 TB' entry onwards, to account
2603 * for this. We also add a small fudge factor to get the correct result for
2604 * counts that lie exactly on a 1024 byte boundary.
2605 */
2606 if (i > 8)
2607 dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by 1 MB */
2608 else
2609 dBytes = (double)llBytes + 0.00001;
2610
2611 dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
2612
2613#ifdef __REACTOS__
2614 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, szBuff, ARRAYSIZE(szBuff)))
2615 return NULL;
2616 LoadStringW(shlwapi_hInstance, bfFormats[i].nFormatID, wszFormat, ARRAYSIZE(wszFormat));
2617 snprintfW(lpszDest, cchMax, wszFormat, szBuff);
2618#else
2619 if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
2620 return NULL;
2621 wszAdd[1] = bfFormats[i].wPrefix;
2622 StrCatBuffW(lpszDest, wszAdd, cchMax);
2623#endif
2624 return lpszDest;
2625}
2626
2627/*************************************************************************
2628 * StrFormatByteSize64A [SHLWAPI.@]
2629 *
2630 * See StrFormatByteSizeW.
2631 */
2633{
2634 WCHAR wszBuff[32];
2635
2636 StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
2637
2638 if (lpszDest)
2639 WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0);
2640 return lpszDest;
2641}
2642
2643/*************************************************************************
2644 * StrFormatByteSizeA [SHLWAPI.@]
2645 *
2646 * Create a string containing an abbreviated byte count of up to 2^31-1.
2647 *
2648 * PARAMS
2649 * dwBytes [I] Byte size to format
2650 * lpszDest [I] Destination for formatted string
2651 * cchMax [I] Size of lpszDest
2652 *
2653 * RETURNS
2654 * lpszDest.
2655 *
2656 * NOTES
2657 * The Ascii and Unicode versions of this function accept a different
2658 * integer type for dwBytes. See StrFormatByteSize64A().
2659 */
2661{
2662 TRACE("(%d,%p,%d)\n", dwBytes, lpszDest, cchMax);
2663
2664 return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
2665}
2666
2667/*************************************************************************
2668 * @ [SHLWAPI.162]
2669 *
2670 * Remove a hanging lead byte from the end of a string, if present.
2671 *
2672 * PARAMS
2673 * lpStr [I] String to check for a hanging lead byte
2674 * size [I] Length of lpStr
2675 *
2676 * RETURNS
2677 * Success: The new length of the string. Any hanging lead bytes are removed.
2678 * Failure: 0, if any parameters are invalid.
2679 */
2681{
2682 if (lpStr && size)
2683 {
2684 LPSTR lastByte = lpStr + size - 1;
2685
2686 while(lpStr < lastByte)
2687 lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
2688
2689 if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
2690 {
2691 *lpStr = '\0';
2692 size--;
2693 }
2694 return size;
2695 }
2696 return 0;
2697}
2698
2699/*************************************************************************
2700 * @ [SHLWAPI.203]
2701 *
2702 * Remove a single non-trailing ampersand ('&') from a string.
2703 *
2704 * PARAMS
2705 * lpszStr [I/O] String to remove ampersand from.
2706 *
2707 * RETURNS
2708 * The character after the first ampersand in lpszStr, or the first character
2709 * in lpszStr if there is no ampersand in the string.
2710 */
2712{
2713 LPSTR lpszIter, lpszTmp;
2714 char ch;
2715
2716 TRACE("(%s)\n", debugstr_a(lpszStr));
2717
2718 ch = *lpszStr;
2719
2720 if ((lpszIter = StrChrA(lpszStr, '&')))
2721 {
2722 lpszTmp = CharNextA(lpszIter);
2723 if (*lpszTmp)
2724 {
2725 if (*lpszTmp != '&')
2726 ch = *lpszTmp;
2727
2728 memmove( lpszIter, lpszTmp, strlen(lpszTmp) + 1 );
2729 }
2730 }
2731
2732 return ch;
2733}
2734
2735/*************************************************************************
2736 * @ [SHLWAPI.225]
2737 *
2738 * Unicode version of SHStripMneumonicA.
2739 */
2741{
2742 LPWSTR lpszIter, lpszTmp;
2743 WCHAR ch;
2744
2745 TRACE("(%s)\n", debugstr_w(lpszStr));
2746
2747 ch = *lpszStr;
2748
2749 if ((lpszIter = StrChrW(lpszStr, '&')))
2750 {
2751 lpszTmp = lpszIter + 1;
2752 if (*lpszTmp)
2753 {
2754 if (*lpszTmp != '&')
2755 ch = *lpszTmp;
2756
2757 memmove( lpszIter, lpszTmp, (strlenW(lpszTmp) + 1) * sizeof(WCHAR) );
2758 }
2759 }
2760
2761 return ch;
2762}
2763
2764/*************************************************************************
2765 * @ [SHLWAPI.216]
2766 *
2767 * Convert an Ascii string to Unicode.
2768 *
2769 * PARAMS
2770 * dwCp [I] Code page for the conversion
2771 * lpSrcStr [I] Source Ascii string to convert
2772 * lpDstStr [O] Destination for converted Unicode string
2773 * iLen [I] Length of lpDstStr
2774 *
2775 * RETURNS
2776 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2777 */
2778DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2779{
2780 DWORD dwRet;
2781
2782 dwRet = MultiByteToWideChar(dwCp, 0, lpSrcStr, -1, lpDstStr, iLen);
2783 TRACE("%s->%s,ret=%d\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
2784 return dwRet;
2785}
2786
2787/*************************************************************************
2788 * @ [SHLWAPI.215]
2789 *
2790 * Convert an Ascii string to Unicode.
2791 *
2792 * PARAMS
2793 * lpSrcStr [I] Source Ascii string to convert
2794 * lpDstStr [O] Destination for converted Unicode string
2795 * iLen [I] Length of lpDstStr
2796 *
2797 * RETURNS
2798 * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2799 *
2800 * NOTES
2801 * This function simply calls SHAnsiToUnicodeCP with code page CP_ACP.
2802 */
2803DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2804{
2805 return SHAnsiToUnicodeCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2806}
2807
2808/*************************************************************************
2809 * @ [SHLWAPI.218]
2810 *
2811 * Convert a Unicode string to Ascii.
2812 *
2813 * PARAMS
2814 * CodePage [I] Code page to use for the conversion
2815 * lpSrcStr [I] Source Unicode string to convert
2816 * lpDstStr [O] Destination for converted Ascii string
2817 * dstlen [I] Length of buffer at lpDstStr
2818 *
2819 * RETURNS
2820 * Success: The length in bytes of the result at lpDstStr (including the terminator)
2821 * Failure: When using CP_UTF8, CP_UTF7 or 0xc350 as codePage, 0 is returned and
2822 * the result is not nul-terminated.
2823 * When using a different codepage, the length in bytes of the truncated
2824 * result at lpDstStr (including the terminator) is returned and
2825 * lpDstStr is always nul-terminated.
2826 *
2827 */
2828DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
2829{
2830 static const WCHAR emptyW[] = { '\0' };
2831 int len , reqLen;
2832 LPSTR mem;
2833
2834 if (!lpDstStr || !dstlen)
2835 return 0;
2836
2837 if (!lpSrcStr)
2838 lpSrcStr = emptyW;
2839
2840 *lpDstStr = '\0';
2841
2842 len = strlenW(lpSrcStr) + 1;
2843
2844 switch (CodePage)
2845 {
2846 case CP_WINUNICODE:
2847 CodePage = CP_UTF8; /* Fall through... */
2848 case 0x0000C350: /* FIXME: CP_ #define */
2849 case CP_UTF7:
2850 case CP_UTF8:
2851 {
2852 DWORD dwMode = 0;
2853 INT lenW = len - 1;
2854 INT needed = dstlen - 1;
2855 HRESULT hr;
2856
2857 /* try the user supplied buffer first */
2858 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, lpDstStr, &needed);
2859 if (hr == S_OK)
2860 {
2861 lpDstStr[needed] = '\0';
2862 return needed + 1;
2863 }
2864
2865 /* user buffer too small. exclude termination and copy as much as possible */
2866 lenW = len;
2867 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, NULL, &needed);
2868 needed++;
2869 mem = HeapAlloc(GetProcessHeap(), 0, needed);
2870 if (!mem)
2871 return 0;
2872
2873 hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, &needed);
2874 if (hr == S_OK)
2875 {
2876 reqLen = SHTruncateString(mem, dstlen);
2877 if (reqLen > 0) memcpy(lpDstStr, mem, reqLen-1);
2878 }
2880 return 0;
2881 }
2882 default:
2883 break;
2884 }
2885
2886 /* try the user supplied buffer first */
2887 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, dstlen, NULL, NULL);
2888
2889 if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2890 {
2891 reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
2892 if (reqLen)
2893 {
2894 mem = HeapAlloc(GetProcessHeap(), 0, reqLen);
2895 if (mem)
2896 {
2897 WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL);
2898
2899 reqLen = SHTruncateString(mem, dstlen -1);
2900 reqLen++;
2901
2902 lstrcpynA(lpDstStr, mem, reqLen);
2904 lpDstStr[reqLen-1] = '\0';
2905 }
2906 }
2907 }
2908 return reqLen;
2909}
2910
2911/*************************************************************************
2912 * @ [SHLWAPI.217]
2913 *
2914 * Convert a Unicode string to Ascii.
2915 *
2916 * PARAMS
2917 * lpSrcStr [I] Source Unicode string to convert
2918 * lpDstStr [O] Destination for converted Ascii string
2919 * iLen [O] Length of lpDstStr in characters
2920 *
2921 * RETURNS
2922 * See SHUnicodeToAnsiCP
2923
2924 * NOTES
2925 * This function simply calls SHUnicodeToAnsiCP() with CodePage = CP_ACP.
2926 */
2927INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
2928{
2929 return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2930}
2931
2932/*************************************************************************
2933 * @ [SHLWAPI.345]
2934 *
2935 * Copy one string to another.
2936 *
2937 * PARAMS
2938 * lpszSrc [I] Source string to copy
2939 * lpszDst [O] Destination for copy
2940 * iLen [I] Length of lpszDst in characters
2941 *
2942 * RETURNS
2943 * The length of the copied string, including the terminating NUL. lpszDst
2944 * contains iLen characters of lpszSrc.
2945 */
2946DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
2947{
2948 LPSTR lpszRet;
2949
2950 TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszSrc), lpszDst, iLen);
2951
2952 lpszRet = StrCpyNXA(lpszDst, lpszSrc, iLen);
2953 return lpszRet - lpszDst + 1;
2954}
2955
2956/*************************************************************************
2957 * @ [SHLWAPI.346]
2958 *
2959 * Unicode version of SSHAnsiToAnsi.
2960 */
2961DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
2962{
2963 LPWSTR lpszRet;
2964
2965 TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszSrc), lpszDst, iLen);
2966
2967 lpszRet = StrCpyNXW(lpszDst, lpszSrc, iLen);
2968 return lpszRet - lpszDst + 1;
2969}
2970
2971/*************************************************************************
2972 * @ [SHLWAPI.364]
2973 *
2974 * Determine if an Ascii string converts to Unicode and back identically.
2975 *
2976 * PARAMS
2977 * lpSrcStr [I] Source Unicode string to convert
2978 * lpDst [O] Destination for resulting Ascii string
2979 * iLen [I] Length of lpDst in characters
2980 *
2981 * RETURNS
2982 * TRUE, since Ascii strings always convert identically.
2983 */
2985{
2986 lstrcpynA(lpDst, lpSrcStr, iLen);
2987 return TRUE;
2988}
2989
2990/*************************************************************************
2991 * @ [SHLWAPI.365]
2992 *
2993 * Determine if a Unicode string converts to Ascii and back identically.
2994 *
2995 * PARAMS
2996 * lpSrcStr [I] Source Unicode string to convert
2997 * lpDst [O] Destination for resulting Ascii string
2998 * iLen [I] Length of lpDst in characters
2999 *
3000 * RETURNS
3001 * TRUE, if lpSrcStr converts to Ascii and back identically,
3002 * FALSE otherwise.
3003 */
3005{
3006 WCHAR szBuff[MAX_PATH];
3007
3008 SHUnicodeToAnsi(lpSrcStr, lpDst, iLen);
3009 SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
3010 return !strcmpW(lpSrcStr, szBuff);
3011}
3012
3013/*************************************************************************
3014 * SHLoadIndirectString [SHLWAPI.@]
3015 *
3016 * If passed a string that begins with '@', extract the string from the
3017 * appropriate resource, otherwise do a straight copy.
3018 *
3019 */
3021{
3022 WCHAR *dllname = NULL;
3023 HMODULE hmod = NULL;
3024 HRESULT hr = E_FAIL;
3025#ifdef __REACTOS__
3026 WCHAR szExpanded[512];
3027#endif
3028
3029 TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
3030
3031 if(src[0] == '@')
3032 {
3033 WCHAR *index_str;
3034 int index;
3035
3036#ifdef __REACTOS__
3037 if (wcschr(src, '%') != NULL)
3038 {
3039 ExpandEnvironmentStringsW(src, szExpanded, ARRAY_SIZE(szExpanded));
3040 src = szExpanded;
3041 }
3042#endif
3043 dst[0] = 0;
3044 dllname = StrDupW(src + 1);
3045 index_str = strchrW(dllname, ',');
3046
3047 if(!index_str) goto end;
3048
3049 *index_str = 0;
3050 index_str++;
3051 index = atoiW(index_str);
3052
3053#ifdef __REACTOS__
3055#else
3056 hmod = LoadLibraryW(dllname);
3057#endif
3058 if(!hmod) goto end;
3059
3060 if(index < 0)
3061 {
3062 if(LoadStringW(hmod, -index, dst, dst_len))
3063 hr = S_OK;
3064 }
3065 else
3066 FIXME("can't handle non-negative indices (%d)\n", index);
3067 }
3068 else
3069 {
3070 if(dst != src)
3071 lstrcpynW(dst, src, dst_len);
3072 hr = S_OK;
3073 }
3074
3075 TRACE("returning %s\n", debugstr_w(dst));
3076end:
3077 if(hmod) FreeLibrary(hmod);
3078 LocalFree(dllname);
3079 return hr;
3080}
3081
3083{
3084 WORD CharType;
3085 return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &CharType) && (CharType & C1_SPACE);
3086}
3087
3088/*************************************************************************
3089 * @ [SHLWAPI.29]
3090 *
3091 * Determine if a Unicode character is a space.
3092 *
3093 * PARAMS
3094 * wc [I] Character to check.
3095 *
3096 * RETURNS
3097 * TRUE, if wc is a space,
3098 * FALSE otherwise.
3099 */
3101{
3102 WORD CharType;
3103
3104 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
3105}
UINT cchMax
WCHAR lpszDest[260]
#define isspace(c)
Definition: acclib.h:69
#define isdigit(c)
Definition: acclib.h:68
#define isxdigit(c)
Definition: acclib.h:70
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define IDS_BYTES_FORMAT
Definition: resource.h:122
#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:520
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2803
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2126
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: locale.c:3212
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: locale.c:4086
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4017
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3098
LCID WINAPI GetSystemDefaultLCID(void)
Definition: locale.c:1235
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1675
BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2)
Definition: string.c:341
BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret)
Definition: string.c:972
LPSTR WINAPI CharNextA(const char *ptr)
Definition: string.c:1107
BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2)
Definition: string.c:334
WCHAR *WINAPI StrCatBuffW(WCHAR *str, const WCHAR *cat, INT max_len)
Definition: string.c:1390
WCHAR *WINAPI StrChrNW(const WCHAR *str, WCHAR ch, UINT max_len)
Definition: string.c:275
INT WINAPI DECLSPEC_HOTPATCH LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen)
Definition: string.c:1220
WCHAR *WINAPI StrStrNW(const WCHAR *str, const WCHAR *search, UINT max_len)
Definition: string.c:376
BOOL WINAPI StrIsIntlEqualA(BOOL case_sensitive, const char *str, const char *cmp, int len)
Definition: string.c:1341
WCHAR *WINAPI StrStrNIW(const WCHAR *str, const WCHAR *search, UINT max_len)
Definition: string.c:402
int WINAPI StrCmpW(const WCHAR *str, const WCHAR *comp)
Definition: string.c:450
BOOL WINAPI StrTrimA(char *str, const char *trim)
Definition: string.c:758
DWORD WINAPI SHTruncateString(char *str, DWORD size)
Definition: string.c:1434
BOOL WINAPI StrIsIntlEqualW(BOOL case_sensitive, const WCHAR *str, const WCHAR *cmp, int len)
Definition: string.c:1357
BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim)
Definition: string.c:796
BOOL WINAPI StrToIntExA(const char *str, DWORD flags, INT *ret)
Definition: string.c:960
char *WINAPI StrCatBuffA(char *str, const char *cat, INT max_len)
Definition: string.c:1373
int WINAPI StrCmpLogicalW(const WCHAR *str, const WCHAR *comp)
Definition: string.c:1289
char *WINAPI StrCpyNXA(char *dst, const char *src, int len)
Definition: string.c:1013
char *WINAPI StrPBrkA(const char *str, const char *match)
Definition: string.c:735
WCHAR *WINAPI StrDupW(const WCHAR *str)
Definition: string.c:313
HRESULT WINAPI SHLoadIndirectString(const WCHAR *src, WCHAR *dst, UINT dst_len, void **reserved)
Definition: string.c:1455
int WINAPI StrSpnW(const WCHAR *str, const WCHAR *match)
Definition: string.c:541
LPSTR WINAPI CharPrevA(const char *start, const char *ptr)
Definition: string.c:1128
int WINAPI StrCmpIW(const WCHAR *str, const WCHAR *comp)
Definition: string.c:456
DWORD WINAPI StrCatChainW(WCHAR *str, DWORD max_len, DWORD at, const WCHAR *cat)
Definition: string.c:1407
char *WINAPI StrDupA(const char *str)
Definition: string.c:292
WCHAR *WINAPI StrCpyNXW(WCHAR *dst, const WCHAR *src, int len)
Definition: string.c:1028
BOOL WINAPI StrToInt64ExA(const char *str, DWORD flags, LONGLONG *ret)
Definition: string.c:834
int WINAPI StrSpnA(const char *str, const char *match)
Definition: string.c:525
BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret)
Definition: string.c:897
WCHAR *WINAPI StrPBrkW(const WCHAR *str, const WCHAR *match)
Definition: string.c:752
WCHAR *WINAPI StrCpyNW(WCHAR *dst, const WCHAR *src, int count)
Definition: string.c:462
unsigned char ch[4][2]
Definition: console.c:118
int CDECL tolower(int c)
Definition: ctype.c:572
_ACRTIMP double __cdecl floor(double)
Definition: floor.c:18
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
#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
static HRESULT _SHStrDupAToBSTR(LPCSTR src, BSTR *pBstrOut)
Definition: string.c:1794
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2148
INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2283
#define KB
struct tagSHLWAPI_BYTEFORMATS SHLWAPI_BYTEFORMATS
WCHAR WINAPI SHStripMneumonicW(LPCWSTR lpszStr)
Definition: string.c:2740
LPSTR WINAPI StrNCatA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax)
Definition: string.c:1922
LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2632
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2803
static BOOL SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
Definition: string.c:157
#define PB
INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
Definition: string.c:2927
LPWSTR WINAPI StrFormatKBSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:1887
#define TB
BOOL WINAPI IsCharSpaceA(CHAR c)
Definition: string.c:3082
DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
Definition: string.c:2961
#define GB
LPWSTR WINAPI StrCatW(LPWSTR lpszStr, LPCWSTR lpszSrc)
Definition: string.c:452
HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR *lppszDest)
Definition: string.c:2090
LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:2660
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2261
DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
Definition: string.c:2946
char WINAPI SHStripMneumonicA(LPCSTR lpszStr)
Definition: string.c:2711
LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
Definition: string.c:2524
HRESULT WINAPI StrRetToBSTR(STRRET *lpStrRet, LPCITEMIDLIST pidl, BSTR *pBstrOut)
Definition: string.c:1830
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:1660
BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:3004
static HRESULT _SHStrDupAA(LPCSTR, LPSTR *)
Definition: string.c:2053
LPWSTR WINAPI StrNCatW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
Definition: string.c:1943
HRESULT WINAPI StrRetToStrA(LPSTRRET lpStrRet, const ITEMIDLIST *pidl, LPSTR *ppszName)
Definition: string.c:1730
static int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
Definition: string.c:2196
HRESULT WINAPI StrRetToStrW(LPSTRRET lpStrRet, const ITEMIDLIST *pidl, LPWSTR *ppszName)
Definition: string.c:1761
#define MB
static LPSTR SHLWAPI_StrRChrHelperA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch, BOOL(WINAPI *pChrCmpFn)(WORD, WORD))
Definition: string.c:1425
static LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
Definition: string.c:2176
HINSTANCE shlwapi_hInstance
Definition: shlwapi_main.c:33
static HRESULT _SHStrDupAW(LPCWSTR, LPSTR *)
Definition: string.c:2120
static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch, LPSTR(WINAPI *pStrChrFn)(LPCSTR, WORD), BOOL bInvert)
Definition: string.c:1252
BOOL WINAPI DoesStringRoundTripA(LPCSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:2984
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:2778
LPSTR WINAPI StrFormatKBSizeA(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
Definition: string.c:1871
HRESULT WINAPI StrRetToBufA(LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, UINT len)
Definition: string.c:1611
static LPSTR SHLWAPI_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch, INT(WINAPI *pStrCmpFn)(LPCSTR, LPCSTR, INT))
Definition: string.c:561
DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
Definition: string.c:2828
static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue, UINT uClassStringId, int iDigits)
Definition: string.c:2217
static int FormatDouble(double value, int decimals, LPWSTR pszBuf, int cchBuf)
Definition: string.c:129
BOOL WINAPI IsCharSpaceW(WCHAR wc)
Definition: string.c:3100
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r reserved
Definition: btrfs.c:3006
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
LARGE_INTEGER li
Definition: fxtimerapi.cpp:235
GLuint start
Definition: gl.h:1545
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
GLuint64EXT * result
Definition: glext.h:11304
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
#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:1208
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define LMEM_FIXED
Definition: minwinbase.h:81
#define pch(ap)
Definition: match.c:418
#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:91
static DWORD dstlen
Definition: directory.c:51
static char * dest
Definition: rtl.c:135
static BOOL bInvert
Definition: win.c:51
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define LOCALE_USER_DEFAULT
#define UNICODE_NULL
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
#define IS_DIGIT(c)
#define INT
Definition: polytest.cpp:20
#define STIF_SUPPORT_HEX
Definition: shlwapi.h:1059
#define StrCpyNA
Definition: shlwapi.h:1104
_In_ UINT cchBuf
Definition: shlwapi.h:378
const WCHAR * str
#define CP_UTF8
Definition: nls.h:20
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
XML_HIDDEN void xmlParserErrors const char const xmlChar * str1
Definition: parser.h:35
HRESULT hr
Definition: shlfolder.c:183
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 _countof(array)
Definition: sndvol32.h:70
#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
uint64_t ULONGLONG
Definition: typedefs.h:67
Definition: pdh_main.c:96
static CONVERTINETUNICODETOMULTIBYTE ConvertINetUnicodeToMultiByte
Definition: win_iconv.c:706
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:338
#define WINAPI
Definition: msvc.h:6
#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
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:3437
#define NORM_IGNORECASE
Definition: winnls.h:187
#define LOCALE_SGROUPING
Definition: winnls.h:51
#define LOCALE_SDECIMAL
Definition: winnls.h:49
#define CT_CTYPE1
Definition: winnls.h:255
#define CSTR_EQUAL
Definition: winnls.h:500
#define CP_UTF7
Definition: winnls.h:253
#define LOCALE_STHOUSAND
Definition: winnls.h:50
#define LOCALE_INEGNUMBER
Definition: winnls.h:54
#define LOCALE_ILZERO
Definition: winnls.h:53
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175