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