Added an unknown VxD error code.
[wine] / dlls / shlwapi / string.c
1 #include <ctype.h>
2 #include <stdlib.h> 
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "winerror.h"
7 #include "windef.h"
8 #include "winbase.h"
9 #include "wingdi.h"
10 #include "winuser.h"
11 #include "shlwapi.h"
12 #include "shlobj.h"
13 #include "wine/unicode.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(shell);
17
18 /*************************************************************************
19  * StrChrA                                      [SHLWAPI]
20  */
21 LPSTR WINAPI StrChrA (LPCSTR str, WORD c)
22 {
23         TRACE("%s %i\n", str,c);
24         return strchr(str, c);
25 }
26
27 /*************************************************************************
28  * StrChrW                                      [SHLWAPI]
29  *
30  */
31 LPWSTR WINAPI StrChrW (LPCWSTR str, WCHAR x )
32 {
33         TRACE("%s 0x%04x\n",debugstr_w(str),x);
34         return strchrW(str, x);
35 }
36
37 /*************************************************************************
38  * StrCmpIW                                     [SHLWAPI]
39  */
40 int WINAPI StrCmpIW ( LPCWSTR wstr1, LPCWSTR wstr2 )
41 {
42     TRACE("%s %s\n", debugstr_w(wstr1),debugstr_w(wstr2));
43     return strcmpiW( wstr1, wstr2 );
44 }
45
46 /*************************************************************************
47  * StrCmpNA                                     [SHLWAPI]
48  */
49 INT WINAPI StrCmpNA ( LPCSTR str1, LPCSTR str2, INT len)
50 {
51         TRACE("%s %s %i stub\n", str1,str2,len);
52         return strncmp(str1, str2, len);
53 }
54
55 /*************************************************************************
56  * StrCmpNW                                     [SHLWAPI]
57  */
58 INT WINAPI StrCmpNW ( LPCWSTR wstr1, LPCWSTR wstr2, INT len)
59 {
60         TRACE("%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
61         return strncmpW(wstr1, wstr2, len);
62 }
63
64 /*************************************************************************
65  * StrCmpNIA                                    [SHLWAPI]
66  */
67 int WINAPI StrCmpNIA ( LPCSTR str1, LPCSTR str2, int len)
68 {
69         TRACE("%s %s %i stub\n", str1,str2,len);
70         return strncasecmp(str1, str2, len);
71 }
72
73 /*************************************************************************
74  * StrCmpNIW                                    [SHLWAPI]
75  */
76 int WINAPI StrCmpNIW ( LPCWSTR wstr1, LPCWSTR wstr2, int len)
77 {
78         TRACE("%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
79         return strncmpiW(wstr1, wstr2, len);
80 }
81
82 /*************************************************************************
83  * StrCmpW                                      [SHLWAPI]
84  */
85 int WINAPI StrCmpW ( LPCWSTR wstr1, LPCWSTR wstr2 )
86 {
87     TRACE("%s %s\n", debugstr_w(wstr1),debugstr_w(wstr2));
88     return strcmpW( wstr1, wstr2 );
89 }
90
91 /*************************************************************************
92  * StrCatW                                      [SHLWAPI]
93  */
94 LPWSTR WINAPI StrCatW( LPWSTR wstr1, LPCWSTR wstr2 )
95 {
96     return strcatW( wstr1, wstr2 );
97 }
98
99
100 /*************************************************************************
101  * StrCpyW                                      [SHLWAPI]
102  */
103 LPWSTR WINAPI StrCpyW( LPWSTR wstr1, LPCWSTR wstr2 )
104 {
105     return strcpyW( wstr1, wstr2 );
106 }
107
108
109 /*************************************************************************
110  * StrCpyNW                                     [SHLWAPI]
111  */
112 LPWSTR WINAPI StrCpyNW( LPWSTR wstr1, LPCWSTR wstr2, int n )
113 {
114     return lstrcpynW( wstr1, wstr2, n );
115 }
116
117
118 /*************************************************************************
119  * StrStrA                                      [SHLWAPI]
120  */
121 LPSTR WINAPI StrStrA(LPCSTR lpFirst, LPCSTR lpSrch)
122 {
123     while (*lpFirst)
124     {
125         LPCSTR p1 = lpFirst, p2 = lpSrch;
126         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
127         if (!*p2) return (LPSTR)lpFirst;
128         lpFirst++;
129     }
130     return NULL;
131 }
132
133 /*************************************************************************
134  * StrStrW                                      [SHLWAPI]
135  */
136 LPWSTR WINAPI StrStrW(LPCWSTR lpFirst, LPCWSTR lpSrch)
137 {
138     while (*lpFirst)
139     {
140         LPCWSTR p1 = lpFirst, p2 = lpSrch;
141         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
142         if (!*p2) return (LPWSTR)lpFirst;
143         lpFirst++;
144     }
145     return NULL;
146 }
147
148 /*************************************************************************
149  * StrStrIA                                     [SHLWAPI]
150  */
151 LPSTR WINAPI StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
152 {
153     while (*lpFirst)
154     {
155         LPCSTR p1 = lpFirst, p2 = lpSrch;
156         while (*p1 && *p2 && toupper(*p1) == toupper(*p2)) { p1++; p2++; }
157         if (!*p2) return (LPSTR)lpFirst;
158         lpFirst++;
159     }
160     return NULL;
161 }
162
163 /*************************************************************************
164  * StrStrIW                                     [SHLWAPI]
165  */
166 LPWSTR WINAPI StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
167 {
168     while (*lpFirst)
169     {
170         LPCWSTR p1 = lpFirst, p2 = lpSrch;
171         while (*p1 && *p2 && toupperW(*p1) == toupperW(*p2)) { p1++; p2++; }
172         if (!*p2) return (LPWSTR)lpFirst;
173         lpFirst++;
174     }
175     return NULL;
176 }
177
178 /*************************************************************************
179  *      StrToIntA                       [SHLWAPI]
180  */
181 int WINAPI StrToIntA(LPCSTR lpSrc)
182 {
183         TRACE("%s\n", lpSrc);
184         return atol(lpSrc);
185 }
186
187 /*************************************************************************
188  *      StrToIntW                       [SHLWAPI]
189  */
190 int WINAPI StrToIntW(LPCWSTR lpSrc)
191 {
192     char buffer[32];
193
194     TRACE("%s\n", debugstr_w(lpSrc));
195     WideCharToMultiByte( CP_ACP, 0, lpSrc, -1, buffer, sizeof(buffer), NULL, NULL );
196     buffer[sizeof(buffer)-1] = 0;
197     return atol(buffer);
198 }
199
200 /*************************************************************************
201  *      StrToIntExA                     [SHLWAPI]
202  */
203 BOOL WINAPI StrToIntExA( LPCSTR pszString, DWORD dwFlags, LPINT piRet)
204 {
205         TRACE("%s %ld stub !\n", debugstr_a(pszString), dwFlags);
206         piRet = (LPINT) StrToIntA(pszString);
207         return TRUE;
208 }
209
210 /*************************************************************************
211  *      StrToIntExW                     [SHLWAPI]
212  */
213 BOOL WINAPI StrToIntExW( LPCWSTR pszString, DWORD dwFlags, LPINT piRet)
214 {
215         TRACE("%s %ld stub !\n", debugstr_w(pszString), dwFlags);
216         piRet = (LPINT) StrToIntW(pszString);
217         return TRUE;
218 }
219
220 /*************************************************************************
221  *      StrDupA                 [SHLWAPI]
222  */
223 LPSTR WINAPI StrDupA (LPCSTR lpSrc)
224 {
225         int len = strlen(lpSrc);
226         LPSTR lpDest = (LPSTR) LocalAlloc(LMEM_FIXED, len+1);
227         
228         TRACE("%s\n", lpSrc);
229
230         if (lpDest) strcpy(lpDest, lpSrc);
231         return lpDest;
232 }
233
234 /*************************************************************************
235  *      StrDupW                 [SHLWAPI]
236  */
237 LPWSTR WINAPI StrDupW (LPCWSTR lpSrc)
238 {
239         int len = strlenW(lpSrc);
240         LPWSTR lpDest = (LPWSTR) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (len+1));
241         
242         TRACE("%s\n", debugstr_w(lpSrc));
243
244         if (lpDest) strcpyW(lpDest, lpSrc);
245         return lpDest;
246 }
247
248 /*************************************************************************
249  *      StrCSpnA                [SHLWAPI]
250  */
251 int WINAPI StrCSpnA (LPCSTR lpStr, LPCSTR lpSet)
252 {
253         int i,j, pos = strlen(lpStr);
254
255         TRACE("(%p %s  %p %s)\n",
256            lpStr, debugstr_a(lpStr), lpSet, debugstr_a(lpSet));
257
258         for (i=0; i < strlen(lpSet) ; i++ )
259         {
260           for (j = 0; j < pos;j++)
261           {
262             if (lpStr[j] == lpSet[i])
263             {
264               pos = j;
265             }
266           }
267         }      
268         TRACE("-- %u\n", pos);
269         return pos;     
270 }
271
272 /*************************************************************************
273  *      StrCSpnW                [SHLWAPI]
274  */
275 int WINAPI StrCSpnW (LPCWSTR lpStr, LPCWSTR lpSet)
276 {
277         int i,j, pos = strlenW(lpStr);
278
279         TRACE("(%p %s %p %s)\n",
280            lpStr, debugstr_w(lpStr), lpSet, debugstr_w(lpSet));
281
282         for (i=0; i < strlenW(lpSet) ; i++ )
283         {
284           for (j = 0; j < pos;j++)
285           {
286             if (lpStr[j] == lpSet[i])
287             {
288               pos = j;
289             }
290           }
291         }      
292         TRACE("-- %u\n", pos);
293         return pos;     
294 }
295
296 /**************************************************************************
297  * StrRChrA [SHLWAPI.@]
298  *
299  */
300 LPSTR WINAPI StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
301 {
302     LPCSTR lpGotIt = NULL;
303     BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
304
305     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
306
307     if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
308
309     for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
310     {
311         if (*lpStart != LOBYTE(wMatch)) continue;
312         if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
313         lpGotIt = lpStart;
314     }    
315     return (LPSTR)lpGotIt;
316 }
317
318
319 /**************************************************************************
320  * StrRChrW [SHLWAPI.@]
321  *
322  */
323 LPWSTR WINAPI StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
324 {
325     LPCWSTR lpGotIt = NULL;
326
327     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
328     if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
329
330     for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
331         if (*lpStart == wMatch) lpGotIt = lpStart;
332
333     return (LPWSTR)lpGotIt;
334 }
335
336
337 /*************************************************************************
338  *      StrCatBuffA             [SHLWAPI]
339  *
340  * Appends back onto front, stopping when front is size-1 characters long.
341  * Returns front.
342  *
343  */
344 LPSTR WINAPI StrCatBuffA(LPSTR front, LPCSTR back, INT size)
345 {
346     LPSTR dst = front + strlen(front);
347     LPCSTR src = back, end = front + size - 1;
348
349     while(dst < end && *src)
350         *dst++ = *src++;
351     *dst = '\0';
352     return front;
353 }
354
355 /*************************************************************************
356  *      StrCatBuffW             [SHLWAPI]
357  *
358  * Appends back onto front, stopping when front is size-1 characters long.
359  * Returns front.
360  *
361  */
362 LPWSTR WINAPI StrCatBuffW(LPWSTR front, LPCWSTR back, INT size)
363 {
364     LPWSTR dst = front + strlenW(front);
365     LPCWSTR src = back, end = front + size - 1;
366
367     while(dst < end && *src)
368         *dst++ = *src++;
369     *dst = '\0';
370     return front;
371 }
372
373 /*************************************************************************
374  * StrRetToBufA                                 [SHLWAPI.@]
375  * 
376  * converts a STRRET to a normal string
377  *
378  * NOTES
379  *  the pidl is for STRRET OFFSET
380  */
381 HRESULT WINAPI StrRetToBufA (LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, DWORD len)
382 {
383         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
384
385         switch (src->uType)
386         {
387           case STRRET_WSTR:
388             WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
389 /*          SHFree(src->u.pOleStr);  FIXME: is this right? */
390             break;
391
392           case STRRET_CSTRA:
393             lstrcpynA((LPSTR)dest, src->u.cStr, len);
394             break;
395
396           case STRRET_OFFSETA:
397             lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
398             break;
399
400           default:
401             FIXME("unknown type!\n");
402             if (len)
403             {
404               *(LPSTR)dest = '\0';
405             }
406             return(FALSE);
407         }
408         return S_OK;
409 }
410
411 /*************************************************************************
412  * StrRetToBufW                                 [SHLWAPI.@]
413  * 
414  * converts a STRRET to a normal string
415  *
416  * NOTES
417  *  the pidl is for STRRET OFFSET
418  */
419 HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, DWORD len)
420 {
421         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
422
423         switch (src->uType)
424         {
425           case STRRET_WSTR:
426             lstrcpynW((LPWSTR)dest, src->u.pOleStr, len);
427 /*          SHFree(src->u.pOleStr);  FIXME: is this right? */
428             break;
429
430           case STRRET_CSTRA:
431               if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len)
432                   dest[len-1] = 0;
433             break;
434
435           case STRRET_OFFSETA:
436             if (pidl)
437             {
438               if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
439                                         dest, len ) && len)
440                   dest[len-1] = 0;
441             }
442             break;
443
444           default:
445             FIXME("unknown type!\n");
446             if (len)
447             { *(LPSTR)dest = '\0';
448             }
449             return(FALSE);
450         }
451         return S_OK;
452 }
453
454 /*************************************************************************
455  * StrFormatByteSizeA                           [SHLWAPI]
456  */
457 LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
458 {       char buf[64];
459         TRACE("%lx %p %i\n", dw, pszBuf, cchBuf);
460         if ( dw<1024L )
461         { sprintf (buf,"%ld bytes", dw);
462         }
463         else if ( dw<1048576L)
464         { sprintf (buf,"%3.1f KB", (FLOAT)dw/1024);
465         }
466         else if ( dw < 1073741824L)
467         { sprintf (buf,"%3.1f MB", (FLOAT)dw/1048576L);
468         }
469         else
470         { sprintf (buf,"%3.1f GB", (FLOAT)dw/1073741824L);
471         }
472         lstrcpynA (pszBuf, buf, cchBuf);
473         return pszBuf;  
474 }
475
476 /*************************************************************************
477  * StrFormatByteSizeW                           [SHLWAPI]
478  */
479 LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
480 {
481         char buf[64];
482         StrFormatByteSizeA( dw, buf, sizeof(buf) );
483         if (!MultiByteToWideChar( CP_ACP, 0, buf, -1, pszBuf, cchBuf ) && cchBuf)
484             pszBuf[cchBuf-1] = 0;
485         return pszBuf;
486 }
487
488 /*************************************************************************
489  *      StrNCatA        [SHLWAPI]
490  */
491 LPSTR WINAPI StrNCatA(LPSTR front, LPCSTR back, INT cchMax)
492 {
493         TRACE("%s %s %i stub\n", debugstr_a(front),debugstr_a(back),cchMax);
494         return (front);
495 }
496
497 /*************************************************************************
498  *      StrNCatW        [SHLWAPI]
499  */
500 LPWSTR WINAPI StrNCatW(LPWSTR front, LPCWSTR back, INT cchMax)
501 {
502         TRACE("%s %s %i stub\n", debugstr_w(front),debugstr_w(back),cchMax);
503         return (front);
504 }
505
506 /*************************************************************************
507  *      StrTrimA        [SHLWAPI]
508  */
509 BOOL WINAPI StrTrimA(LPSTR pszSource, LPCSTR pszTrimChars)
510 {
511     BOOL trimmed = FALSE;
512     LPSTR pSrc;
513     LPCSTR pTrim;
514
515     TRACE("('%s', '%s');\n", pszSource, pszTrimChars);
516     for (pTrim = pszTrimChars; *pTrim; pTrim++)
517     {
518          for (pSrc = pszSource; *pSrc; pSrc++)
519              if (*pSrc == *pTrim)
520              {
521                  /* match -> remove this char.
522                   * strlen(pSrc) equiv. to the correct strlen(pSrc+1)+1 */
523                  memmove(pSrc, pSrc+1, strlen(pSrc));
524                  trimmed = TRUE;
525              }
526     }
527     TRACE("<- '%s'\n", pszSource);
528     return trimmed;
529 }
530
531 /*************************************************************************
532  *      wnsprintfA      [SHLWAPI]
533  */
534 int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
535 {
536     va_list valist;
537     INT res;
538
539     va_start( valist, lpFmt );
540     res = wvsnprintfA( lpOut, cchLimitIn, lpFmt, valist );
541     va_end( valist );
542     return res;
543 }
544
545 /*************************************************************************
546  *      wnsprintfW      [SHLWAPI]
547  */
548 int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
549 {
550     va_list valist;
551     INT res;
552
553     va_start( valist, lpFmt );
554     res = wvsnprintfW( lpOut, cchLimitIn, lpFmt, valist );
555     va_end( valist );
556     return res;
557 }