Implement StrRetToStr in shlwapi.
[wine/wine64.git] / dlls / shlwapi / string.c
blob415eaaa7df588effed66ed668d4f4dbee415603d
1 /*
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
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include "winerror.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winreg.h"
32 #define NO_SHLWAPI_STREAM
33 #include "shlwapi.h"
34 #include "shlobj.h"
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 /*************************************************************************
66 * StrChrA [SHLWAPI.@]
68 LPSTR WINAPI StrChrA (LPCSTR str, WORD c)
70 TRACE("%s %i\n", str,c);
71 return strchr(str, c);
74 /*************************************************************************
75 * StrChrW [SHLWAPI.@]
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)
170 while (*lpFirst)
172 LPCSTR p1 = lpFirst, p2 = lpSrch;
173 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
174 if (!*p2) return (LPSTR)lpFirst;
175 lpFirst++;
177 return NULL;
180 /*************************************************************************
181 * StrStrW [SHLWAPI.@]
183 LPWSTR WINAPI StrStrW(LPCWSTR lpFirst, LPCWSTR lpSrch)
185 while (*lpFirst)
187 LPCWSTR p1 = lpFirst, p2 = lpSrch;
188 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
189 if (!*p2) return (LPWSTR)lpFirst;
190 lpFirst++;
192 return NULL;
195 /*************************************************************************
196 * StrStrIA [SHLWAPI.@]
198 LPSTR WINAPI StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
200 while (*lpFirst)
202 LPCSTR p1 = lpFirst, p2 = lpSrch;
203 while (*p1 && *p2 && toupper(*p1) == toupper(*p2)) { p1++; p2++; }
204 if (!*p2) return (LPSTR)lpFirst;
205 lpFirst++;
207 return NULL;
210 /*************************************************************************
211 * StrStrIW [SHLWAPI.@]
213 LPWSTR WINAPI StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
215 while (*lpFirst)
217 LPCWSTR p1 = lpFirst, p2 = lpSrch;
218 while (*p1 && *p2 && toupperW(*p1) == toupperW(*p2)) { p1++; p2++; }
219 if (!*p2) return (LPWSTR)lpFirst;
220 lpFirst++;
222 return NULL;
225 /*************************************************************************
226 * StrToIntA [SHLWAPI.@]
228 int WINAPI StrToIntA(LPCSTR lpSrc)
230 TRACE("%s\n", lpSrc);
231 return atol(lpSrc);
234 /*************************************************************************
235 * StrToIntW [SHLWAPI.@]
237 int WINAPI StrToIntW(LPCWSTR lpSrc)
239 char buffer[32];
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;
244 return atol(buffer);
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);
254 return TRUE;
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);
264 return TRUE;
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);
278 return lpDest;
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);
292 return lpDest;
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])
311 pos = j;
315 TRACE("-- %u\n", pos);
316 return 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])
335 pos = j;
339 TRACE("-- %u\n", pos);
340 return 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;
360 lpGotIt = lpStart;
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))
400 if (dbcs) {
402 if (_mbctoupper(*lpStart) == _mbctoupper(wMatch))
403 lpGotIt = lpStart;
405 if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
406 } else {
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.
437 * Returns front.
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)
446 *dst++ = *src++;
447 *dst = '\0';
448 return front;
451 /*************************************************************************
452 * StrCatBuffW [SHLWAPI.@]
454 * Appends back onto front, stopping when front is size-1 characters long.
455 * Returns front.
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)
464 *dst++ = *src++;
465 *dst = '\0';
466 return front;
469 /*************************************************************************
470 * StrRetToBufA [SHLWAPI.@]
472 * converts a STRRET to a normal string
474 * NOTES
475 * the pidl is for STRRET OFFSET
477 * ***** NOTE *****
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
481 * WARNED.
482 * ***** NOTE *****
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);
488 switch (src->uType)
490 case STRRET_WSTR:
491 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
492 CoTaskMemFree(src->u.pOleStr);
493 break;
495 case STRRET_CSTR:
496 lstrcpynA((LPSTR)dest, src->u.cStr, len);
497 break;
499 case STRRET_OFFSET:
500 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
501 break;
503 default:
504 FIXME("unknown type!\n");
505 if (len)
507 *(LPSTR)dest = '\0';
509 return(FALSE);
511 return S_OK;
514 /*************************************************************************
515 * StrRetToBufW [SHLWAPI.@]
517 * converts a STRRET to a normal string
519 * NOTES
520 * the pidl is for STRRET OFFSET
522 * ***** NOTE *****
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
526 * WARNED.
527 * ***** NOTE *****
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);
533 switch (src->uType)
535 case STRRET_WSTR:
536 lstrcpynW((LPWSTR)dest, src->u.pOleStr, len);
537 CoTaskMemFree(src->u.pOleStr);
538 break;
540 case STRRET_CSTR:
541 if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len)
542 dest[len-1] = 0;
543 break;
545 case STRRET_OFFSET:
546 if (pidl)
548 if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
549 dest, len ) && len)
550 dest[len-1] = 0;
552 break;
554 default:
555 FIXME("unknown type!\n");
556 if (len)
557 { *(LPSTR)dest = '\0';
559 return(FALSE);
561 return S_OK;
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) {
574 case STRRET_WSTR:
575 ret = _SHStrDupAW(pstr->u.pOleStr, ppszName);
576 CoTaskMemFree(pstr->u.pOleStr);
577 break;
579 case STRRET_CSTR:
580 ret = _SHStrDupAA(pstr->u.cStr, ppszName);
581 break;
583 case STRRET_OFFSET:
584 ret = _SHStrDupAA(((LPCSTR)&pidl->mkid)+pstr->u.uOffset, ppszName);
585 break;
587 default:
588 *ppszName = NULL;
590 return ret;
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) {
603 case STRRET_WSTR:
604 ret = SHStrDupW(pstr->u.pOleStr, ppszName);
605 CoTaskMemFree(pstr->u.pOleStr);
606 break;
608 case STRRET_CSTR:
609 ret = SHStrDupA(pstr->u.cStr, ppszName);
610 break;
612 case STRRET_OFFSET:
613 ret = SHStrDupA(((LPCSTR)&pidl->mkid)+pstr->u.uOffset, ppszName);
614 break;
616 default:
617 *ppszName = NULL;
619 return ret;
622 /*************************************************************************
623 * StrFormatByteSizeA [SHLWAPI.@]
625 LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
626 { char buf[64];
627 TRACE("%lx %p %i\n", dw, pszBuf, cchBuf);
628 if ( dw<1024L )
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);
637 else
638 { sprintf (buf,"%3.1f GB", (FLOAT)dw/1073741824L);
640 lstrcpynA (pszBuf, buf, cchBuf);
641 return pszBuf;
644 /*************************************************************************
645 * StrFormatByteSizeW [SHLWAPI.@]
647 LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
649 char buf[64];
650 StrFormatByteSizeA( dw, buf, sizeof(buf) );
651 if (!MultiByteToWideChar( CP_ACP, 0, buf, -1, pszBuf, cchBuf ) && cchBuf)
652 pszBuf[cchBuf-1] = 0;
653 return pszBuf;
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);
662 return (front);
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);
671 return (front);
674 /*************************************************************************
675 * StrTrimA [SHLWAPI.@]
677 BOOL WINAPI StrTrimA(LPSTR pszSource, LPCSTR pszTrimChars)
679 BOOL trimmed = FALSE;
680 LPSTR pSrc;
681 LPCSTR pTrim;
683 TRACE("('%s', '%s');\n", pszSource, pszTrimChars);
684 for (pTrim = pszTrimChars; *pTrim; pTrim++)
686 for (pSrc = pszSource; *pSrc; pSrc++)
687 if (*pSrc == *pTrim)
689 /* match -> remove this char.
690 * strlen(pSrc) equiv. to the correct strlen(pSrc+1)+1 */
691 memmove(pSrc, pSrc+1, strlen(pSrc));
692 trimmed = TRUE;
695 TRACE("<- '%s'\n", pszSource);
696 return trimmed;
699 /*************************************************************************
700 * _SHStrDupA [INTERNAL]
702 * Duplicates a ASCII string to ASCII. The destination buffer is allocated.
704 HRESULT WINAPI _SHStrDupAA(LPCSTR src, LPSTR * dest)
706 HRESULT hr;
707 int len = 0;
709 if (src) {
710 len = lstrlenA(src);
711 *dest = CoTaskMemAlloc(len);
712 } else {
713 *dest = NULL;
716 if (*dest) {
717 lstrcpynA(*dest,src, len);
718 hr = S_OK;
719 } else {
720 hr = E_OUTOFMEMORY;
723 TRACE("%s->(%p)\n", debugstr_a(src), *dest);
724 return hr;
727 /*************************************************************************
728 * SHStrDupA [SHLWAPI.@]
730 * Duplicates a ASCII string to UNICODE. The destination buffer is allocated.
732 HRESULT WINAPI SHStrDupA(LPCSTR src, LPWSTR * dest)
734 HRESULT hr;
735 int len = 0;
737 if (src) {
738 len = (MultiByteToWideChar(0,0,src,-1,0,0) + 1)* sizeof(WCHAR);
739 *dest = CoTaskMemAlloc(len);
740 } else {
741 *dest = NULL;
744 if (*dest) {
745 MultiByteToWideChar(0,0,src,-1,*dest,len);
746 hr = S_OK;
747 } else {
748 hr = E_OUTOFMEMORY;
751 TRACE("%s->(%p)\n", debugstr_a(src), *dest);
752 return hr;
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)
762 HRESULT hr;
763 int len = 0;
765 if (src) {
766 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
767 *dest = CoTaskMemAlloc(len);
768 } else {
769 *dest = NULL;
772 if (*dest) {
773 WideCharToMultiByte(CP_ACP, 0, src, -1, *dest, len, NULL, NULL);
774 hr = S_OK;
775 } else {
776 hr = E_OUTOFMEMORY;
779 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
780 return hr;
783 /*************************************************************************
784 * SHStrDupW [SHLWAPI.@]
786 * Duplicates a UNICODE string. The destination buffer is allocated.
788 HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR * dest)
790 HRESULT hr;
791 int len = 0;
793 if (src) {
794 len = (lstrlenW(src) + 1) * sizeof(WCHAR);
795 *dest = CoTaskMemAlloc(len);
796 } else {
797 *dest = NULL;
800 if (*dest) {
801 memcpy(*dest, src, len);
802 hr = S_OK;
803 } else {
804 hr = E_OUTOFMEMORY;
807 TRACE("%s->(%p)\n", debugstr_w(src), *dest);
808 return hr;