ReactOS  0.4.15-dev-1187-g119f102
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;
2357 #ifdef __REACTOS__
2358  UINT nFormatID;
2359 #else
2361 #endif
2363 
2364 /*************************************************************************
2365  * StrFormatByteSizeW [SHLWAPI.@]
2366  *
2367  * Create a string containing an abbreviated byte count of up to 2^63-1.
2368  *
2369  * PARAMS
2370  * llBytes [I] Byte size to format
2371  * lpszDest [I] Destination for formatted string
2372  * cchMax [I] Size of lpszDest
2373  *
2374  * RETURNS
2375  * lpszDest.
2376  *
2377  * NOTES
2378  * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW().
2379  */
2381 {
2382 #define KB ((ULONGLONG)1024)
2383 #define MB (KB*KB)
2384 #define GB (KB*KB*KB)
2385 #define TB (KB*KB*KB*KB)
2386 #define PB (KB*KB*KB*KB*KB)
2387 
2388  static const SHLWAPI_BYTEFORMATS bfFormats[] =
2389  {
2390 #ifdef __REACTOS__
2391  { 10*KB, 10.24, 100.0, 2, IDS_KB_FORMAT }, /* 10 KB */
2392  { 100*KB, 102.4, 10.0, 1, IDS_KB_FORMAT }, /* 100 KB */
2393  { 1000*KB, 1024.0, 1.0, 0, IDS_KB_FORMAT }, /* 1000 KB */
2394  { 10*MB, 10485.76, 100.0, 2, IDS_MB_FORMAT }, /* 10 MB */
2395  { 100*MB, 104857.6, 10.0, 1, IDS_MB_FORMAT }, /* 100 MB */
2396  { 1000*MB, 1048576.0, 1.0, 0, IDS_MB_FORMAT }, /* 1000 MB */
2397  { 10*GB, 10737418.24, 100.0, 2, IDS_GB_FORMAT }, /* 10 GB */
2398  { 100*GB, 107374182.4, 10.0, 1, IDS_GB_FORMAT }, /* 100 GB */
2399  { 1000*GB, 1073741824.0, 1.0, 0, IDS_GB_FORMAT }, /* 1000 GB */
2400  { 10*TB, 10485.76, 100.0, 2, IDS_TB_FORMAT }, /* 10 TB */
2401  { 100*TB, 104857.6, 10.0, 1, IDS_TB_FORMAT }, /* 100 TB */
2402  { 1000*TB, 1048576.0, 1.0, 0, IDS_TB_FORMAT }, /* 1000 TB */
2403  { 10*PB, 10737418.24, 100.00, 2, IDS_PB_FORMAT }, /* 10 PB */
2404  { 100*PB, 107374182.4, 10.00, 1, IDS_PB_FORMAT }, /* 100 PB */
2405  { 1000*PB, 1073741824.0, 1.00, 0, IDS_PB_FORMAT }, /* 1000 PB */
2406  { 0, 10995116277.76, 100.00, 2, IDS_EB_FORMAT } /* EB's, catch all */
2407 #else
2408  { 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
2409  { 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
2410  { 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
2411  { 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
2412  { 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
2413  { 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
2414  { 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
2415  { 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
2416  { 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
2417  { 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
2418  { 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
2419  { 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
2420  { 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
2421  { 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
2422  { 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
2423  { 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
2424 #endif
2425  };
2426 #ifdef __REACTOS__
2427  WCHAR szBuff[40], wszFormat[40];
2428 #else
2429  WCHAR wszAdd[] = {' ','?','B',0};
2430 #endif
2431  double dBytes;
2432  UINT i = 0;
2433 
2434  TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
2435 
2436  if (!lpszDest || !cchMax)
2437  return lpszDest;
2438 
2439  if (llBytes < 1024) /* 1K */
2440  {
2441  WCHAR wszBytesFormat[64];
2442  LoadStringW(shlwapi_hInstance, IDS_BYTES_FORMAT, wszBytesFormat, 64);
2443  snprintfW(lpszDest, cchMax, wszBytesFormat, (int)llBytes);
2444  return lpszDest;
2445  }
2446 
2447  /* Note that if this loop completes without finding a match, i will be
2448  * pointing at the last entry, which is a catch all for > 1000 PB
2449  */
2450  while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
2451  {
2452  if (llBytes < bfFormats[i].dLimit)
2453  break;
2454  i++;
2455  }
2456  /* Above 1 TB we encounter problems with FP accuracy. So for amounts above
2457  * this number we integer shift down by 1 MB first. The table above has
2458  * the divisors scaled down from the '< 10 TB' entry onwards, to account
2459  * for this. We also add a small fudge factor to get the correct result for
2460  * counts that lie exactly on a 1024 byte boundary.
2461  */
2462  if (i > 8)
2463  dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by 1 MB */
2464  else
2465  dBytes = (double)llBytes + 0.00001;
2466 
2467  dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
2468 
2469 #ifdef __REACTOS__
2470  if (!FormatDouble(dBytes, bfFormats[i].nDecimals, szBuff, ARRAYSIZE(szBuff)))
2471  return NULL;
2472  LoadStringW(shlwapi_hInstance, bfFormats[i].nFormatID, wszFormat, ARRAYSIZE(wszFormat));
2473  snprintfW(lpszDest, cchMax, wszFormat, szBuff);
2474 #else
2475  if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
2476  return NULL;
2477  wszAdd[1] = bfFormats[i].wPrefix;
2478  StrCatBuffW(lpszDest, wszAdd, cchMax);
2479 #endif
2480  return lpszDest;
2481 }
2482 
2483 /*************************************************************************
2484  * StrFormatByteSize64A [SHLWAPI.@]
2485  *
2486  * See StrFormatByteSizeW.
2487  */
2489 {
2490  WCHAR wszBuff[32];
2491 
2492  StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
2493 
2494  if (lpszDest)
2495  WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0);
2496  return lpszDest;
2497 }
2498 
2499 /*************************************************************************
2500  * StrFormatByteSizeA [SHLWAPI.@]
2501  *
2502  * Create a string containing an abbreviated byte count of up to 2^31-1.
2503  *
2504  * PARAMS
2505  * dwBytes [I] Byte size to format
2506  * lpszDest [I] Destination for formatted string
2507  * cchMax [I] Size of lpszDest
2508  *
2509  * RETURNS
2510  * lpszDest.
2511  *
2512  * NOTES
2513  * The Ascii and Unicode versions of this function accept a different
2514  * integer type for dwBytes. See StrFormatByteSize64A().
2515  */
2517 {
2518  TRACE("(%d,%p,%d)\n", dwBytes, lpszDest, cchMax);
2519 
2520  return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
2521 }
2522 
2523 /*************************************************************************
2524  * @ [SHLWAPI.162]
2525  *
2526  * Remove a hanging lead byte from the end of a string, if present.
2527  *
2528  * PARAMS
2529  * lpStr [I] String to check for a hanging lead byte
2530  * size [I] Length of lpStr
2531  *
2532  * RETURNS
2533  * Success: The new length of the string. Any hanging lead bytes are removed.
2534  * Failure: 0, if any parameters are invalid.
2535  */
2537 {
2538  if (lpStr && size)
2539  {
2540  LPSTR lastByte = lpStr + size - 1;
2541 
2542  while(lpStr < lastByte)
2543  lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
2544 
2545  if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
2546  {
2547  *lpStr = '\0';
2548  size--;
2549  }
2550  return size;
2551  }
2552  return 0;
2553 }
2554 
2555 /*************************************************************************
2556  * @ [SHLWAPI.203]
2557  *
2558  * Remove a single non-trailing ampersand ('&') from a string.
2559  *
2560  * PARAMS
2561  * lpszStr [I/O] String to remove ampersand from.
2562  *
2563  * RETURNS
2564  * The character after the first ampersand in lpszStr, or the first character
2565  * in lpszStr if there is no ampersand in the string.
2566  */
2568 {
2569  LPSTR lpszIter, lpszTmp;
2570  char ch;
2571 
2572  TRACE("(%s)\n", debugstr_a(lpszStr));
2573 
2574  ch = *lpszStr;
2575 
2576  if ((lpszIter = StrChrA(lpszStr, '&')))
2577  {
2578  lpszTmp = CharNextA(lpszIter);
2579  if (*lpszTmp)
2580  {
2581  if (*lpszTmp != '&')
2582  ch = *lpszTmp;
2583 
2584  memmove( lpszIter, lpszTmp, strlen(lpszTmp) + 1 );
2585  }
2586  }
2587 
2588  return ch;
2589 }
2590 
2591 /*************************************************************************
2592  * @ [SHLWAPI.225]
2593  *
2594  * Unicode version of SHStripMneumonicA.
2595  */
2597 {
2598  LPWSTR lpszIter, lpszTmp;
2599  WCHAR ch;
2600 
2601  TRACE("(%s)\n", debugstr_w(lpszStr));
2602 
2603  ch = *lpszStr;
2604 
2605  if ((lpszIter = StrChrW(lpszStr, '&')))
2606  {
2607  lpszTmp = lpszIter + 1;
2608  if (*lpszTmp)
2609  {
2610  if (*lpszTmp != '&')
2611  ch = *lpszTmp;
2612 
2613  memmove( lpszIter, lpszTmp, (strlenW(lpszTmp) + 1) * sizeof(WCHAR) );
2614  }
2615  }
2616 
2617  return ch;
2618 }
2619 
2620 /*************************************************************************
2621  * @ [SHLWAPI.216]
2622  *
2623  * Convert an Ascii string to Unicode.
2624  *
2625  * PARAMS
2626  * dwCp [I] Code page for the conversion
2627  * lpSrcStr [I] Source Ascii string to convert
2628  * lpDstStr [O] Destination for converted Unicode string
2629  * iLen [I] Length of lpDstStr
2630  *
2631  * RETURNS
2632  * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2633  */
2634 DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2635 {
2636  DWORD dwRet;
2637 
2638  dwRet = MultiByteToWideChar(dwCp, 0, lpSrcStr, -1, lpDstStr, iLen);
2639  TRACE("%s->%s,ret=%d\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
2640  return dwRet;
2641 }
2642 
2643 /*************************************************************************
2644  * @ [SHLWAPI.215]
2645  *
2646  * Convert an Ascii string to Unicode.
2647  *
2648  * PARAMS
2649  * lpSrcStr [I] Source Ascii string to convert
2650  * lpDstStr [O] Destination for converted Unicode string
2651  * iLen [I] Length of lpDstStr
2652  *
2653  * RETURNS
2654  * The return value of the MultiByteToWideChar() function called on lpSrcStr.
2655  *
2656  * NOTES
2657  * This function simply calls SHAnsiToUnicodeCP with code page CP_ACP.
2658  */
2659 DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
2660 {
2661  return SHAnsiToUnicodeCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2662 }
2663 
2664 /*************************************************************************
2665  * @ [SHLWAPI.218]
2666  *
2667  * Convert a Unicode string to Ascii.
2668  *
2669  * PARAMS
2670  * CodePage [I] Code page to use for the conversion
2671  * lpSrcStr [I] Source Unicode string to convert
2672  * lpDstStr [O] Destination for converted Ascii string
2673  * dstlen [I] Length of buffer at lpDstStr
2674  *
2675  * RETURNS
2676  * Success: The length in bytes of the result at lpDstStr (including the terminator)
2677  * Failure: When using CP_UTF8, CP_UTF7 or 0xc350 as codePage, 0 is returned and
2678  * the result is not nul-terminated.
2679  * When using a different codepage, the length in bytes of the truncated
2680  * result at lpDstStr (including the terminator) is returned and
2681  * lpDstStr is always nul-terminated.
2682  *
2683  */
2684 DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen)
2685 {
2686  static const WCHAR emptyW[] = { '\0' };
2687  int len , reqLen;
2688  LPSTR mem;
2689 
2690  if (!lpDstStr || !dstlen)
2691  return 0;
2692 
2693  if (!lpSrcStr)
2694  lpSrcStr = emptyW;
2695 
2696  *lpDstStr = '\0';
2697 
2698  len = strlenW(lpSrcStr) + 1;
2699 
2700  switch (CodePage)
2701  {
2702  case CP_WINUNICODE:
2703  CodePage = CP_UTF8; /* Fall through... */
2704  case 0x0000C350: /* FIXME: CP_ #define */
2705  case CP_UTF7:
2706  case CP_UTF8:
2707  {
2708  DWORD dwMode = 0;
2709  INT lenW = len - 1;
2710  INT needed = dstlen - 1;
2711  HRESULT hr;
2712 
2713  /* try the user supplied buffer first */
2714  hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, lpDstStr, &needed);
2715  if (hr == S_OK)
2716  {
2717  lpDstStr[needed] = '\0';
2718  return needed + 1;
2719  }
2720 
2721  /* user buffer too small. exclude termination and copy as much as possible */
2722  lenW = len;
2723  hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, NULL, &needed);
2724  needed++;
2725  mem = HeapAlloc(GetProcessHeap(), 0, needed);
2726  if (!mem)
2727  return 0;
2728 
2729  hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, &needed);
2730  if (hr == S_OK)
2731  {
2732  reqLen = SHTruncateString(mem, dstlen);
2733  if (reqLen > 0) memcpy(lpDstStr, mem, reqLen-1);
2734  }
2735  HeapFree(GetProcessHeap(), 0, mem);
2736  return 0;
2737  }
2738  default:
2739  break;
2740  }
2741 
2742  /* try the user supplied buffer first */
2743  reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, dstlen, NULL, NULL);
2744 
2745  if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2746  {
2747  reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
2748  if (reqLen)
2749  {
2750  mem = HeapAlloc(GetProcessHeap(), 0, reqLen);
2751  if (mem)
2752  {
2753  WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL);
2754 
2755  reqLen = SHTruncateString(mem, dstlen -1);
2756  reqLen++;
2757 
2758  lstrcpynA(lpDstStr, mem, reqLen);
2759  HeapFree(GetProcessHeap(), 0, mem);
2760  lpDstStr[reqLen-1] = '\0';
2761  }
2762  }
2763  }
2764  return reqLen;
2765 }
2766 
2767 /*************************************************************************
2768  * @ [SHLWAPI.217]
2769  *
2770  * Convert a Unicode string to Ascii.
2771  *
2772  * PARAMS
2773  * lpSrcStr [I] Source Unicode string to convert
2774  * lpDstStr [O] Destination for converted Ascii string
2775  * iLen [O] Length of lpDstStr in characters
2776  *
2777  * RETURNS
2778  * See SHUnicodeToAnsiCP
2779 
2780  * NOTES
2781  * This function simply calls SHUnicodeToAnsiCP() with CodePage = CP_ACP.
2782  */
2783 INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
2784 {
2785  return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
2786 }
2787 
2788 /*************************************************************************
2789  * @ [SHLWAPI.345]
2790  *
2791  * Copy one string to another.
2792  *
2793  * PARAMS
2794  * lpszSrc [I] Source string to copy
2795  * lpszDst [O] Destination for copy
2796  * iLen [I] Length of lpszDst in characters
2797  *
2798  * RETURNS
2799  * The length of the copied string, including the terminating NUL. lpszDst
2800  * contains iLen characters of lpszSrc.
2801  */
2802 DWORD WINAPI SHAnsiToAnsi(LPCSTR lpszSrc, LPSTR lpszDst, int iLen)
2803 {
2804  LPSTR lpszRet;
2805 
2806  TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszSrc), lpszDst, iLen);
2807 
2808  lpszRet = StrCpyNXA(lpszDst, lpszSrc, iLen);
2809  return lpszRet - lpszDst + 1;
2810 }
2811 
2812 /*************************************************************************
2813  * @ [SHLWAPI.346]
2814  *
2815  * Unicode version of SSHAnsiToAnsi.
2816  */
2817 DWORD WINAPI SHUnicodeToUnicode(LPCWSTR lpszSrc, LPWSTR lpszDst, int iLen)
2818 {
2819  LPWSTR lpszRet;
2820 
2821  TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszSrc), lpszDst, iLen);
2822 
2823  lpszRet = StrCpyNXW(lpszDst, lpszSrc, iLen);
2824  return lpszRet - lpszDst + 1;
2825 }
2826 
2827 /*************************************************************************
2828  * @ [SHLWAPI.364]
2829  *
2830  * Determine if an Ascii string converts to Unicode and back identically.
2831  *
2832  * PARAMS
2833  * lpSrcStr [I] Source Unicode string to convert
2834  * lpDst [O] Destination for resulting Ascii string
2835  * iLen [I] Length of lpDst in characters
2836  *
2837  * RETURNS
2838  * TRUE, since Ascii strings always convert identically.
2839  */
2841 {
2842  lstrcpynA(lpDst, lpSrcStr, iLen);
2843  return TRUE;
2844 }
2845 
2846 /*************************************************************************
2847  * @ [SHLWAPI.365]
2848  *
2849  * Determine if a Unicode string converts to Ascii and back identically.
2850  *
2851  * PARAMS
2852  * lpSrcStr [I] Source Unicode string to convert
2853  * lpDst [O] Destination for resulting Ascii string
2854  * iLen [I] Length of lpDst in characters
2855  *
2856  * RETURNS
2857  * TRUE, if lpSrcStr converts to Ascii and back identically,
2858  * FALSE otherwise.
2859  */
2861 {
2862  WCHAR szBuff[MAX_PATH];
2863 
2864  SHUnicodeToAnsi(lpSrcStr, lpDst, iLen);
2865  SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
2866  return !strcmpW(lpSrcStr, szBuff);
2867 }
2868 
2869 /*************************************************************************
2870  * SHLoadIndirectString [SHLWAPI.@]
2871  *
2872  * If passed a string that begins with '@', extract the string from the
2873  * appropriate resource, otherwise do a straight copy.
2874  *
2875  */
2877 {
2878  WCHAR *dllname = NULL;
2879  HMODULE hmod = NULL;
2880  HRESULT hr = E_FAIL;
2881 
2882  TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
2883 
2884  if(src[0] == '@')
2885  {
2886  WCHAR *index_str;
2887  int index;
2888 
2889  dst[0] = 0;
2890  dllname = StrDupW(src + 1);
2891  index_str = strchrW(dllname, ',');
2892 
2893  if(!index_str) goto end;
2894 
2895  *index_str = 0;
2896  index_str++;
2897  index = atoiW(index_str);
2898 
2899 #ifdef __REACTOS__
2901 #else
2902  hmod = LoadLibraryW(dllname);
2903 #endif
2904  if(!hmod) goto end;
2905 
2906  if(index < 0)
2907  {
2908  if(LoadStringW(hmod, -index, dst, dst_len))
2909  hr = S_OK;
2910  }
2911  else
2912  FIXME("can't handle non-negative indices (%d)\n", index);
2913  }
2914  else
2915  {
2916  if(dst != src)
2917  lstrcpynW(dst, src, dst_len);
2918  hr = S_OK;
2919  }
2920 
2921  TRACE("returning %s\n", debugstr_w(dst));
2922 end:
2923  if(hmod) FreeLibrary(hmod);
2924  LocalFree(dllname);
2925  return hr;
2926 }
2927 
2929 {
2930  WORD CharType;
2931  return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &CharType) && (CharType & C1_SPACE);
2932 }
2933 
2934 /*************************************************************************
2935  * @ [SHLWAPI.29]
2936  *
2937  * Determine if a Unicode character is a space.
2938  *
2939  * PARAMS
2940  * wc [I] Character to check.
2941  *
2942  * RETURNS
2943  * TRUE, if wc is a space,
2944  * FALSE otherwise.
2945  */
2947 {
2948  WORD CharType;
2949 
2950  return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
2951 }
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:2380
char WINAPI SHStripMneumonicA(LPCSTR lpszStr)
Definition: string.c:2567
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:2596
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:442
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:111
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:2488
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define TRUE
Definition: types.h:120
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:109
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
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
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:43
#define WARN(fmt,...)
Definition: debug.h:112
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:2817
#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
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
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:2041
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2004
BOOL WINAPI IsCharSpaceW(WCHAR wc)
Definition: string.c:2946
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:498
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:58
#define IDS_TIME_INTERVAL_SECONDS
Definition: resource.h:29
#define lstrcpynW
Definition: compat.h:486
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
#define FALSE
Definition: types.h:117
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:110
#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:111
r reserved
Definition: btrfs.c:2940
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:2536
const WCHAR * str
static WCHAR
Definition: string.c:57
#define LoadLibraryW(x)
Definition: compat.h:495
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:238
LPWSTR WINAPI StrStrNW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax)
Definition: string.c:755
BOOL WINAPI IsDBCSLeadByte(BYTE TestByte)
Definition: nls.c:2232
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:68
static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue, UINT uClassStringId, int iDigits)
Definition: string.c:2073
SIGDN PWSTR * ppszName
Definition: shobjidl.idl:593
#define StrCpyNA
Definition: shlwapi.h:1514
#define TRACE(s)
Definition: solgame.cpp:4
#define FreeLibrary(x)
Definition: compat.h:496
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:484
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:79
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:34
#define WINAPI
Definition: msvc.h:6
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:2659
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:2634
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:2783
#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:2684
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:59
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:2876
LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:594
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:338
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:51
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:40
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:2840
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:499
int snprintfW(WCHAR *str, size_t len, const WCHAR *format,...)
Definition: string.c:520
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:411
#define MultiByteToWideChar
Definition: compat.h:110
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:2928
#define isxdigit(c)
Definition: acclib.h:70
BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen)
Definition: string.c:2860
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:2802
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:49
#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:426
Definition: dsound.c:943
#define HeapFree(x, y, z)
Definition: compat.h:483
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:2516
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