2 * Shlwapi string functions
4 * Copyright 1998 Juergen Schmied
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #define NO_SHLWAPI_STREAM
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
40 HRESULT WINAPI
_SHStrDupAA(LPCSTR src
, LPSTR
* dest
);
41 HRESULT WINAPI
_SHStrDupAW(LPCWSTR src
, LPSTR
* dest
);
43 /*************************************************************************
44 * ChrCmpIA [SHLWAPI.385]
46 * Note: Returns 0 (FALSE) if characters are equal (insensitive).
48 BOOL WINAPI
ChrCmpIA (WORD w1
, WORD w2
)
50 TRACE("%c ? %c\n", w1
, w2
);
51 return (toupper(w1
) != toupper(w2
));
54 /*************************************************************************
55 * ChrCmpIW [SHLWAPI.386]
57 * Note: Returns 0 (FALSE) if characters are equal (insensitive).
59 BOOL WINAPI
ChrCmpIW (WCHAR w1
, WCHAR w2
)
61 TRACE("%c ? %c\n", w1
, w2
);
62 return (toupperW(w1
) != toupperW(w2
));
65 /*************************************************************************
68 LPSTR WINAPI
StrChrA (LPCSTR str
, WORD c
)
70 TRACE("%s %i\n", str
,c
);
71 return strchr(str
, c
);
74 /*************************************************************************
78 LPWSTR WINAPI
StrChrW (LPCWSTR str
, WCHAR x
)
80 TRACE("%s 0x%04x\n",debugstr_w(str
),x
);
81 return strchrW(str
, x
);
84 /*************************************************************************
85 * StrCmpIW [SHLWAPI.@]
87 int WINAPI
StrCmpIW ( LPCWSTR wstr1
, LPCWSTR wstr2
)
89 TRACE("%s %s\n", debugstr_w(wstr1
),debugstr_w(wstr2
));
90 return strcmpiW( wstr1
, wstr2
);
93 /*************************************************************************
94 * StrCmpNA [SHLWAPI.@]
96 INT WINAPI
StrCmpNA ( LPCSTR str1
, LPCSTR str2
, INT len
)
98 TRACE("%s %s %i stub\n", str1
,str2
,len
);
99 return strncmp(str1
, str2
, len
);
102 /*************************************************************************
103 * StrCmpNW [SHLWAPI.@]
105 INT WINAPI
StrCmpNW ( LPCWSTR wstr1
, LPCWSTR wstr2
, INT len
)
107 TRACE("%s %s %i stub\n", debugstr_w(wstr1
),debugstr_w(wstr2
),len
);
108 return strncmpW(wstr1
, wstr2
, len
);
111 /*************************************************************************
112 * StrCmpNIA [SHLWAPI.@]
114 int WINAPI
StrCmpNIA ( LPCSTR str1
, LPCSTR str2
, int len
)
116 TRACE("%s %s %i stub\n", str1
,str2
,len
);
117 return strncasecmp(str1
, str2
, len
);
120 /*************************************************************************
121 * StrCmpNIW [SHLWAPI.@]
123 int WINAPI
StrCmpNIW ( LPCWSTR wstr1
, LPCWSTR wstr2
, int len
)
125 TRACE("%s %s %i stub\n", debugstr_w(wstr1
),debugstr_w(wstr2
),len
);
126 return strncmpiW(wstr1
, wstr2
, len
);
129 /*************************************************************************
130 * StrCmpW [SHLWAPI.@]
132 int WINAPI
StrCmpW ( LPCWSTR wstr1
, LPCWSTR wstr2
)
134 TRACE("%s %s\n", debugstr_w(wstr1
),debugstr_w(wstr2
));
135 return strcmpW( wstr1
, wstr2
);
138 /*************************************************************************
139 * StrCatW [SHLWAPI.@]
141 LPWSTR WINAPI
StrCatW( LPWSTR wstr1
, LPCWSTR wstr2
)
143 return strcatW( wstr1
, wstr2
);
147 /*************************************************************************
148 * StrCpyW [SHLWAPI.@]
150 LPWSTR WINAPI
StrCpyW( LPWSTR wstr1
, LPCWSTR wstr2
)
152 return strcpyW( wstr1
, wstr2
);
156 /*************************************************************************
157 * StrCpyNW [SHLWAPI.@]
159 LPWSTR WINAPI
StrCpyNW( LPWSTR wstr1
, LPCWSTR wstr2
, int n
)
161 return lstrcpynW( wstr1
, wstr2
, n
);
165 /*************************************************************************
166 * StrStrA [SHLWAPI.@]
168 LPSTR WINAPI
StrStrA(LPCSTR lpFirst
, LPCSTR lpSrch
)
172 LPCSTR p1
= lpFirst
, p2
= lpSrch
;
173 while (*p1
&& *p2
&& *p1
== *p2
) { p1
++; p2
++; }
174 if (!*p2
) return (LPSTR
)lpFirst
;
180 /*************************************************************************
181 * StrStrW [SHLWAPI.@]
183 LPWSTR WINAPI
StrStrW(LPCWSTR lpFirst
, LPCWSTR lpSrch
)
187 LPCWSTR p1
= lpFirst
, p2
= lpSrch
;
188 while (*p1
&& *p2
&& *p1
== *p2
) { p1
++; p2
++; }
189 if (!*p2
) return (LPWSTR
)lpFirst
;
195 /*************************************************************************
196 * StrStrIA [SHLWAPI.@]
198 LPSTR WINAPI
StrStrIA(LPCSTR lpFirst
, LPCSTR lpSrch
)
202 LPCSTR p1
= lpFirst
, p2
= lpSrch
;
203 while (*p1
&& *p2
&& toupper(*p1
) == toupper(*p2
)) { p1
++; p2
++; }
204 if (!*p2
) return (LPSTR
)lpFirst
;
210 /*************************************************************************
211 * StrStrIW [SHLWAPI.@]
213 LPWSTR WINAPI
StrStrIW(LPCWSTR lpFirst
, LPCWSTR lpSrch
)
217 LPCWSTR p1
= lpFirst
, p2
= lpSrch
;
218 while (*p1
&& *p2
&& toupperW(*p1
) == toupperW(*p2
)) { p1
++; p2
++; }
219 if (!*p2
) return (LPWSTR
)lpFirst
;
225 /*************************************************************************
226 * StrToIntA [SHLWAPI.@]
228 int WINAPI
StrToIntA(LPCSTR lpSrc
)
230 TRACE("%s\n", lpSrc
);
234 /*************************************************************************
235 * StrToIntW [SHLWAPI.@]
237 int WINAPI
StrToIntW(LPCWSTR lpSrc
)
241 TRACE("%s\n", debugstr_w(lpSrc
));
242 WideCharToMultiByte( CP_ACP
, 0, lpSrc
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
243 buffer
[sizeof(buffer
)-1] = 0;
247 /*************************************************************************
248 * StrToIntExA [SHLWAPI.@]
250 BOOL WINAPI
StrToIntExA( LPCSTR pszString
, DWORD dwFlags
, LPINT piRet
)
252 TRACE("%s %ld stub !\n", debugstr_a(pszString
), dwFlags
);
253 piRet
= (LPINT
) StrToIntA(pszString
);
257 /*************************************************************************
258 * StrToIntExW [SHLWAPI.@]
260 BOOL WINAPI
StrToIntExW( LPCWSTR pszString
, DWORD dwFlags
, LPINT piRet
)
262 TRACE("%s %ld stub !\n", debugstr_w(pszString
), dwFlags
);
263 piRet
= (LPINT
) StrToIntW(pszString
);
267 /*************************************************************************
268 * StrDupA [SHLWAPI.@]
270 LPSTR WINAPI
StrDupA (LPCSTR lpSrc
)
272 int len
= strlen(lpSrc
);
273 LPSTR lpDest
= (LPSTR
) LocalAlloc(LMEM_FIXED
, len
+1);
275 TRACE("%s\n", lpSrc
);
277 if (lpDest
) strcpy(lpDest
, lpSrc
);
281 /*************************************************************************
282 * StrDupW [SHLWAPI.@]
284 LPWSTR WINAPI
StrDupW (LPCWSTR lpSrc
)
286 int len
= strlenW(lpSrc
);
287 LPWSTR lpDest
= (LPWSTR
) LocalAlloc(LMEM_FIXED
, sizeof(WCHAR
) * (len
+1));
289 TRACE("%s\n", debugstr_w(lpSrc
));
291 if (lpDest
) strcpyW(lpDest
, lpSrc
);
295 /*************************************************************************
296 * StrCSpnA [SHLWAPI.@]
298 int WINAPI
StrCSpnA (LPCSTR lpStr
, LPCSTR lpSet
)
300 int i
,j
, pos
= strlen(lpStr
);
302 TRACE("(%p %s %p %s)\n",
303 lpStr
, debugstr_a(lpStr
), lpSet
, debugstr_a(lpSet
));
305 for (i
=0; i
< strlen(lpSet
) ; i
++ )
307 for (j
= 0; j
< pos
;j
++)
309 if (lpStr
[j
] == lpSet
[i
])
315 TRACE("-- %u\n", pos
);
319 /*************************************************************************
320 * StrCSpnW [SHLWAPI.@]
322 int WINAPI
StrCSpnW (LPCWSTR lpStr
, LPCWSTR lpSet
)
324 int i
,j
, pos
= strlenW(lpStr
);
326 TRACE("(%p %s %p %s)\n",
327 lpStr
, debugstr_w(lpStr
), lpSet
, debugstr_w(lpSet
));
329 for (i
=0; i
< strlenW(lpSet
) ; i
++ )
331 for (j
= 0; j
< pos
;j
++)
333 if (lpStr
[j
] == lpSet
[i
])
339 TRACE("-- %u\n", pos
);
343 /**************************************************************************
344 * StrRChrA [SHLWAPI.@]
347 LPSTR WINAPI
StrRChrA( LPCSTR lpStart
, LPCSTR lpEnd
, WORD wMatch
)
349 LPCSTR lpGotIt
= NULL
;
350 BOOL dbcs
= IsDBCSLeadByte( LOBYTE(wMatch
) );
352 TRACE("(%p, %p, %x)\n", lpStart
, lpEnd
, wMatch
);
353 if (!lpStart
&& !lpEnd
) return NULL
;
354 if (!lpEnd
) lpEnd
= lpStart
+ strlen(lpStart
);
356 for(; lpStart
< lpEnd
; lpStart
= CharNextA(lpStart
))
358 if (*lpStart
!= LOBYTE(wMatch
)) continue;
359 if (dbcs
&& lpStart
[1] != HIBYTE(wMatch
)) continue;
362 return (LPSTR
)lpGotIt
;
366 /**************************************************************************
367 * StrRChrW [SHLWAPI.@]
370 LPWSTR WINAPI
StrRChrW( LPCWSTR lpStart
, LPCWSTR lpEnd
, WORD wMatch
)
372 LPCWSTR lpGotIt
= NULL
;
374 TRACE("(%p, %p, %x)\n", lpStart
, lpEnd
, wMatch
);
375 if (!lpStart
&& !lpEnd
) return NULL
;
376 if (!lpEnd
) lpEnd
= lpStart
+ strlenW(lpStart
);
378 for(; lpStart
< lpEnd
; lpStart
= CharNextW(lpStart
))
379 if (*lpStart
== wMatch
) lpGotIt
= lpStart
;
381 return (LPWSTR
)lpGotIt
;
385 /**************************************************************************
386 * StrRChrIA [SHLWAPI.@]
389 LPSTR WINAPI
StrRChrIA( LPCSTR lpStart
, LPCSTR lpEnd
, WORD wMatch
)
391 LPCSTR lpGotIt
= NULL
;
392 BOOL dbcs
= IsDBCSLeadByte( LOBYTE(wMatch
) );
394 TRACE("(%p, %p, %x)\n", lpStart
, lpEnd
, wMatch
);
395 if (!lpStart
&& !lpEnd
) return NULL
;
396 if (!lpEnd
) lpEnd
= lpStart
+ strlen(lpStart
);
398 for(; lpStart
< lpEnd
; lpStart
= CharNextA(lpStart
))
402 if (_mbctoupper(*lpStart) == _mbctoupper(wMatch))
405 if (toupper(*lpStart
) == toupper(wMatch
)) lpGotIt
= lpStart
;
407 if (toupper(*lpStart
) == toupper(wMatch
)) lpGotIt
= lpStart
;
410 return (LPSTR
)lpGotIt
;
414 /**************************************************************************
415 * StrRChrIW [SHLWAPI.@]
418 LPWSTR WINAPI
StrRChrIW( LPCWSTR lpStart
, LPCWSTR lpEnd
, WORD wMatch
)
420 LPCWSTR lpGotIt
= NULL
;
422 TRACE("(%p, %p, %x)\n", lpStart
, lpEnd
, wMatch
);
423 if (!lpStart
&& !lpEnd
) return NULL
;
424 if (!lpEnd
) lpEnd
= lpStart
+ strlenW(lpStart
);
426 for(; lpStart
< lpEnd
; lpStart
= CharNextW(lpStart
))
427 if (toupperW(*lpStart
) == toupperW(wMatch
)) lpGotIt
= lpStart
;
429 return (LPWSTR
)lpGotIt
;
433 /*************************************************************************
434 * StrCatBuffA [SHLWAPI.@]
436 * Appends back onto front, stopping when front is size-1 characters long.
440 LPSTR WINAPI
StrCatBuffA(LPSTR front
, LPCSTR back
, INT size
)
442 LPSTR dst
= front
+ strlen(front
);
443 LPCSTR src
= back
, end
= front
+ size
- 1;
445 while(dst
< end
&& *src
)
451 /*************************************************************************
452 * StrCatBuffW [SHLWAPI.@]
454 * Appends back onto front, stopping when front is size-1 characters long.
458 LPWSTR WINAPI
StrCatBuffW(LPWSTR front
, LPCWSTR back
, INT size
)
460 LPWSTR dst
= front
+ strlenW(front
);
461 LPCWSTR src
= back
, end
= front
+ size
- 1;
463 while(dst
< end
&& *src
)
469 /*************************************************************************
470 * StrRetToBufA [SHLWAPI.@]
472 * converts a STRRET to a normal string
475 * the pidl is for STRRET OFFSET
478 * This routine is identical to StrRetToStrNA in dlls/shell32/shellstring.c.
479 * It was duplicated there because not every version of Shlwapi.dll exports
480 * StrRetToBufA. If you change one routine, change them both. YOU HAVE BEEN
484 HRESULT WINAPI
StrRetToBufA (LPSTRRET src
, const ITEMIDLIST
*pidl
, LPSTR dest
, DWORD len
)
486 TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest
,len
,src
,pidl
);
491 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
492 CoTaskMemFree(src
->u
.pOleStr
);
496 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
500 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
504 FIXME("unknown type!\n");
514 /*************************************************************************
515 * StrRetToBufW [SHLWAPI.@]
517 * converts a STRRET to a normal string
520 * the pidl is for STRRET OFFSET
523 * This routine is identical to StrRetToStrNW in dlls/shell32/shellstring.c.
524 * It was duplicated there because not every version of Shlwapi.dll exports
525 * StrRetToBufW. If you change one routine, change them both. YOU HAVE BEEN
529 HRESULT WINAPI
StrRetToBufW (LPSTRRET src
, const ITEMIDLIST
*pidl
, LPWSTR dest
, DWORD len
)
531 TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest
,len
,src
,pidl
);
536 lstrcpynW((LPWSTR
)dest
, src
->u
.pOleStr
, len
);
537 CoTaskMemFree(src
->u
.pOleStr
);
541 if (!MultiByteToWideChar( CP_ACP
, 0, src
->u
.cStr
, -1, dest
, len
) && len
)
548 if (!MultiByteToWideChar( CP_ACP
, 0, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, -1,
555 FIXME("unknown type!\n");
557 { *(LPSTR
)dest
= '\0';
564 /*************************************************************************
565 * StrRetToStrA [SHLWAPI.@]
567 * converts a STRRET to a normal string
569 HRESULT WINAPI
StrRetToStrA(LPSTRRET pstr
, const ITEMIDLIST
* pidl
, LPSTR
* ppszName
)
571 HRESULT ret
= E_FAIL
;
573 switch (pstr
->uType
) {
575 ret
= _SHStrDupAW(pstr
->u
.pOleStr
, ppszName
);
576 CoTaskMemFree(pstr
->u
.pOleStr
);
580 ret
= _SHStrDupAA(pstr
->u
.cStr
, ppszName
);
584 ret
= _SHStrDupAA(((LPCSTR
)&pidl
->mkid
)+pstr
->u
.uOffset
, ppszName
);
593 /*************************************************************************
594 * StrRetToStrW [SHLWAPI.@]
596 * converts a STRRET to a normal string
598 HRESULT WINAPI
StrRetToStrW(LPSTRRET pstr
, const ITEMIDLIST
* pidl
, LPWSTR
* ppszName
)
600 HRESULT ret
= E_FAIL
;
602 switch (pstr
->uType
) {
604 ret
= SHStrDupW(pstr
->u
.pOleStr
, ppszName
);
605 CoTaskMemFree(pstr
->u
.pOleStr
);
609 ret
= SHStrDupA(pstr
->u
.cStr
, ppszName
);
613 ret
= SHStrDupA(((LPCSTR
)&pidl
->mkid
)+pstr
->u
.uOffset
, ppszName
);
622 /*************************************************************************
623 * StrFormatByteSizeA [SHLWAPI.@]
625 LPSTR WINAPI
StrFormatByteSizeA ( DWORD dw
, LPSTR pszBuf
, UINT cchBuf
)
627 TRACE("%lx %p %i\n", dw
, pszBuf
, cchBuf
);
629 { sprintf (buf
,"%ld bytes", dw
);
631 else if ( dw
<1048576L)
632 { sprintf (buf
,"%3.1f KB", (FLOAT
)dw
/1024);
634 else if ( dw
< 1073741824L)
635 { sprintf (buf
,"%3.1f MB", (FLOAT
)dw
/1048576L);
638 { sprintf (buf
,"%3.1f GB", (FLOAT
)dw
/1073741824L);
640 lstrcpynA (pszBuf
, buf
, cchBuf
);
644 /*************************************************************************
645 * StrFormatByteSizeW [SHLWAPI.@]
647 LPWSTR WINAPI
StrFormatByteSizeW ( DWORD dw
, LPWSTR pszBuf
, UINT cchBuf
)
650 StrFormatByteSizeA( dw
, buf
, sizeof(buf
) );
651 if (!MultiByteToWideChar( CP_ACP
, 0, buf
, -1, pszBuf
, cchBuf
) && cchBuf
)
652 pszBuf
[cchBuf
-1] = 0;
656 /*************************************************************************
657 * StrNCatA [SHLWAPI.@]
659 LPSTR WINAPI
StrNCatA(LPSTR front
, LPCSTR back
, INT cchMax
)
661 TRACE("%s %s %i stub\n", debugstr_a(front
),debugstr_a(back
),cchMax
);
665 /*************************************************************************
666 * StrNCatW [SHLWAPI.@]
668 LPWSTR WINAPI
StrNCatW(LPWSTR front
, LPCWSTR back
, INT cchMax
)
670 TRACE("%s %s %i stub\n", debugstr_w(front
),debugstr_w(back
),cchMax
);
674 /*************************************************************************
675 * StrTrimA [SHLWAPI.@]
677 BOOL WINAPI
StrTrimA(LPSTR pszSource
, LPCSTR pszTrimChars
)
679 BOOL trimmed
= FALSE
;
683 TRACE("('%s', '%s');\n", pszSource
, pszTrimChars
);
684 for (pTrim
= pszTrimChars
; *pTrim
; pTrim
++)
686 for (pSrc
= pszSource
; *pSrc
; pSrc
++)
689 /* match -> remove this char.
690 * strlen(pSrc) equiv. to the correct strlen(pSrc+1)+1 */
691 memmove(pSrc
, pSrc
+1, strlen(pSrc
));
695 TRACE("<- '%s'\n", pszSource
);
699 /*************************************************************************
700 * _SHStrDupA [INTERNAL]
702 * Duplicates a ASCII string to ASCII. The destination buffer is allocated.
704 HRESULT WINAPI
_SHStrDupAA(LPCSTR src
, LPSTR
* dest
)
711 *dest
= CoTaskMemAlloc(len
);
717 lstrcpynA(*dest
,src
, len
);
723 TRACE("%s->(%p)\n", debugstr_a(src
), *dest
);
727 /*************************************************************************
728 * SHStrDupA [SHLWAPI.@]
730 * Duplicates a ASCII string to UNICODE. The destination buffer is allocated.
732 HRESULT WINAPI
SHStrDupA(LPCSTR src
, LPWSTR
* dest
)
738 len
= (MultiByteToWideChar(0,0,src
,-1,0,0) + 1)* sizeof(WCHAR
);
739 *dest
= CoTaskMemAlloc(len
);
745 MultiByteToWideChar(0,0,src
,-1,*dest
,len
);
751 TRACE("%s->(%p)\n", debugstr_a(src
), *dest
);
755 /*************************************************************************
756 * _SHStrDupAW [INTERNAL]
758 * Duplicates a UNICODE to a ASCII string. The destination buffer is allocated.
760 HRESULT WINAPI
_SHStrDupAW(LPCWSTR src
, LPSTR
* dest
)
766 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
767 *dest
= CoTaskMemAlloc(len
);
773 WideCharToMultiByte(CP_ACP
, 0, src
, -1, *dest
, len
, NULL
, NULL
);
779 TRACE("%s->(%p)\n", debugstr_w(src
), *dest
);
783 /*************************************************************************
784 * SHStrDupW [SHLWAPI.@]
786 * Duplicates a UNICODE string. The destination buffer is allocated.
788 HRESULT WINAPI
SHStrDupW(LPCWSTR src
, LPWSTR
* dest
)
794 len
= (lstrlenW(src
) + 1) * sizeof(WCHAR
);
795 *dest
= CoTaskMemAlloc(len
);
801 memcpy(*dest
, src
, len
);
807 TRACE("%s->(%p)\n", debugstr_w(src
), *dest
);