Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / shlwapi / ordinal.c
1 /*
2  * SHLWAPI ordinal functions
3  *
4  * Copyright 1997 Marcus Meissner
5  *           1998 Jürgen Schmied
6  *           2001 Jon Griffiths
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winnls.h"
28 #include "winbase.h"
29 #include "ddeml.h"
30 #include "shlobj.h"
31 #include "shellapi.h"
32 #include "commdlg.h"
33 #include "wine/unicode.h"
34 #include "wine/obj_base.h"
35 #include "wine/obj_inplace.h"
36 #include "wine/obj_serviceprovider.h"
37 #include "wingdi.h"
38 #include "winreg.h"
39 #include "winuser.h"
40 #include "wine/debug.h"
41 #include "ordinal.h"
42 #include "shlwapi.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(shell);
45
46 extern HINSTANCE shlwapi_hInstance;
47 extern HMODULE SHLWAPI_hshell32;
48 extern HMODULE SHLWAPI_hwinmm;
49 extern HMODULE SHLWAPI_hcomdlg32;
50 extern HMODULE SHLWAPI_hmpr;
51 extern HMODULE SHLWAPI_hmlang;
52 extern HMODULE SHLWAPI_hversion;
53
54 extern DWORD SHLWAPI_ThreadRef_index;
55
56 typedef HANDLE HSHARED; /* Shared memory */
57
58 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
59 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
60 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
61 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
62
63 /* The following schemes were identified in the native version of
64  * SHLWAPI.DLL version 5.50
65  */
66 typedef enum {
67     URL_SCHEME_INVALID     = -1,
68     URL_SCHEME_UNKNOWN     =  0,
69     URL_SCHEME_FTP,
70     URL_SCHEME_HTTP,
71     URL_SCHEME_GOPHER,
72     URL_SCHEME_MAILTO,
73     URL_SCHEME_NEWS,
74     URL_SCHEME_NNTP,
75     URL_SCHEME_TELNET,
76     URL_SCHEME_WAIS,
77     URL_SCHEME_FILE,
78     URL_SCHEME_MK,
79     URL_SCHEME_HTTPS,
80     URL_SCHEME_SHELL,
81     URL_SCHEME_SNEWS,
82     URL_SCHEME_LOCAL,
83     URL_SCHEME_JAVASCRIPT,
84     URL_SCHEME_VBSCRIPT,
85     URL_SCHEME_ABOUT,
86     URL_SCHEME_RES,
87     URL_SCHEME_MAXVALUE
88 } URL_SCHEME;
89
90 typedef struct {
91     URL_SCHEME  scheme_number;
92     LPCSTR scheme_name;
93 } SHL_2_inet_scheme;
94
95 static const SHL_2_inet_scheme shlwapi_schemes[] = {
96   {URL_SCHEME_FTP,        "ftp"},
97   {URL_SCHEME_HTTP,       "http"},
98   {URL_SCHEME_GOPHER,     "gopher"},
99   {URL_SCHEME_MAILTO,     "mailto"},
100   {URL_SCHEME_NEWS,       "news"},
101   {URL_SCHEME_NNTP,       "nntp"},
102   {URL_SCHEME_TELNET,     "telnet"},
103   {URL_SCHEME_WAIS,       "wais"},
104   {URL_SCHEME_FILE,       "file"},
105   {URL_SCHEME_MK,         "mk"},
106   {URL_SCHEME_HTTPS,      "https"},
107   {URL_SCHEME_SHELL,      "shell"},
108   {URL_SCHEME_SNEWS,      "snews"},
109   {URL_SCHEME_LOCAL,      "local"},
110   {URL_SCHEME_JAVASCRIPT, "javascript"},
111   {URL_SCHEME_VBSCRIPT,   "vbscript"},
112   {URL_SCHEME_ABOUT,      "about"},
113   {URL_SCHEME_RES,        "res"},
114   {0, 0}
115 };
116
117 /* function pointers for GET_FUNC macro; these need to be global because of gcc bug */
118 static LPITEMIDLIST (WINAPI *pSHBrowseForFolderW)(LPBROWSEINFOW);
119 static HRESULT (WINAPI *pConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
120 static BOOL    (WINAPI *pPlaySoundW)(LPCWSTR, HMODULE, DWORD);
121 static DWORD   (WINAPI *pSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
122 static UINT    (WINAPI *pDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
123 static BOOL    (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
124 static BOOL    (WINAPI *pShellExecuteExW)(LPSHELLEXECUTEINFOW);
125 static HICON   (WINAPI *pSHFileOperationW)(LPSHFILEOPSTRUCTW);
126 static HICON   (WINAPI *pExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
127 static BOOL    (WINAPI *pSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
128 static DWORD   (WINAPI *pSHDefExtractIconW)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID, LPVOID); /* FIXME: Correct args */
129 static HICON   (WINAPI *pExtractIconW)(HINSTANCE, LPCWSTR, UINT);
130 static BOOL    (WINAPI *pGetSaveFileNameW)(LPOPENFILENAMEW);
131 static DWORD   (WINAPI *pWNetRestoreConnectionW)(LPVOID, LPVOID); /* FIXME: Correct args */
132 static DWORD   (WINAPI *pWNetGetLastErrorW)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID); /* FIXME: Correct args */
133 static BOOL    (WINAPI *pPageSetupDlgW)(LPPAGESETUPDLGW);
134 static BOOL    (WINAPI *pPrintDlgW)(LPPRINTDLGW);
135 static BOOL    (WINAPI *pGetOpenFileNameW)(LPOPENFILENAMEW);
136 static HRESULT (WINAPI *pSHGetInstanceExplorer)(LPUNKNOWN *);
137 static DWORD   (WINAPI *pGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
138 static BOOL    (WINAPI *pGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
139 static WORD    (WINAPI *pVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
140
141 /*
142  NOTES: Most functions exported by ordinal seem to be superflous.
143  The reason for these functions to be there is to provide a wraper
144  for unicode functions to provide these functions on systems without
145  unicode functions eg. win95/win98. Since we have such functions we just
146  call these. If running Wine with native DLL's, some late bound calls may
147  fail. However, its better to implement the functions in the forward DLL
148  and recommend the builtin rather than reimplementing the calls here!
149 */
150
151 /*************************************************************************
152  *      @       [SHLWAPI.1]
153  *
154  * Identifies the Internet "scheme" in the passed string. ASCII based.
155  * Also determines start and length of item after the ':'
156  */
157 DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
158 {
159     DWORD cnt;
160     const SHL_2_inet_scheme *inet_pro;
161
162     if (y->size != 0x18) return E_INVALIDARG;
163     /* FIXME: leading white space generates error of 0x80041001 which
164      *        is undefined
165      */
166     if (*x <= ' ') return 0x80041001;
167     cnt = 0;
168     y->sizep1 = 0;
169     y->ap1 = x;
170     while (*x) {
171         if (*x == ':') {
172             y->sizep1 = cnt;
173             cnt = -1;
174             y->ap2 = x+1;
175             break;
176         }
177         x++;
178         cnt++;
179     }
180
181     /* check for no scheme in string start */
182     /* (apparently schemes *must* be larger than a single character)  */
183     if ((*x == '\0') || (y->sizep1 <= 1)) {
184         y->ap1 = 0;
185         return 0x80041001;
186     }
187
188     /* found scheme, set length of remainder */
189     y->sizep2 = lstrlenA(y->ap2);
190
191     /* see if known scheme and return indicator number */
192     y->fcncde = URL_SCHEME_UNKNOWN;
193     inet_pro = shlwapi_schemes;
194     while (inet_pro->scheme_name) {
195         if (!strncasecmp(inet_pro->scheme_name, y->ap1,
196                     min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
197             y->fcncde = inet_pro->scheme_number;
198             break;
199         }
200         inet_pro++;
201     }
202     return S_OK;
203 }
204
205 /*************************************************************************
206  *      @       [SHLWAPI.2]
207  *
208  * Identifies the Internet "scheme" in the passed string. UNICODE based.
209  * Also determines start and length of item after the ':'
210  */
211 DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
212 {
213     DWORD cnt;
214     const SHL_2_inet_scheme *inet_pro;
215     LPSTR cmpstr;
216     INT len;
217
218     if (y->size != 0x18) return E_INVALIDARG;
219     /* FIXME: leading white space generates error of 0x80041001 which
220      *        is undefined
221      */
222     if (*x <= L' ') return 0x80041001;
223     cnt = 0;
224     y->sizep1 = 0;
225     y->ap1 = x;
226     while (*x) {
227         if (*x == L':') {
228             y->sizep1 = cnt;
229             cnt = -1;
230             y->ap2 = x+1;
231             break;
232         }
233         x++;
234         cnt++;
235     }
236
237     /* check for no scheme in string start */
238     /* (apparently schemes *must* be larger than a single character)  */
239     if ((*x == L'\0') || (y->sizep1 <= 1)) {
240         y->ap1 = 0;
241         return 0x80041001;
242     }
243
244     /* found scheme, set length of remainder */
245     y->sizep2 = lstrlenW(y->ap2);
246
247     /* see if known scheme and return indicator number */
248     len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
249     cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
250     WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
251     y->fcncde = URL_SCHEME_UNKNOWN;
252     inet_pro = shlwapi_schemes;
253     while (inet_pro->scheme_name) {
254         if (!strncasecmp(inet_pro->scheme_name, cmpstr,
255                     min(len, lstrlenA(inet_pro->scheme_name)))) {
256             y->fcncde = inet_pro->scheme_number;
257             break;
258         }
259         inet_pro++;
260     }
261     HeapFree(GetProcessHeap(), 0, cmpstr);
262     return S_OK;
263 }
264
265 /*************************************************************************
266  * @    [SHLWAPI.3]
267  *
268  * Determine if a file exists locally and is of an executable type.
269  *
270  * PARAMS
271  *  lpszFile       [O] File to search for
272  *  dwWhich        [I] Type of executable to search for
273  *
274  * RETURNS
275  *  TRUE  If the file was found. lpszFile contains the file name.
276  *  FALSE Otherwise.
277  *
278  * NOTES
279  *  lpszPath is modified in place and must be at least MAX_PATH in length.
280  *  If the function returns FALSE, the path is modified to its orginal state.
281  *  If the given path contains an extension or dwWhich is 0, executable
282  *  extensions are not checked.
283  *
284  *  Ordinals 3-6 are a classic case of MS exposing limited functionality to
285  *  users (here through PathFindOnPath) and keeping advanced functionality for
286  *  their own developers exclusive use. Monopoly, anyone?
287  */
288 BOOL WINAPI SHLWAPI_3(LPSTR lpszFile,DWORD dwWhich)
289 {
290   return SHLWAPI_PathFindLocalExeA(lpszFile,dwWhich);
291 }
292
293 /*************************************************************************
294  * @    [SHLWAPI.4]
295  *
296  * Unicode version of SHLWAPI_3.
297  */
298 BOOL WINAPI SHLWAPI_4(LPWSTR lpszFile,DWORD dwWhich)
299 {
300   return SHLWAPI_PathFindLocalExeW(lpszFile,dwWhich);
301 }
302
303 /*************************************************************************
304  * @    [SHLWAPI.5]
305  *
306  * Search a range of paths for a specific type of executable.
307  *
308  * PARAMS
309  *  lpszFile       [O] File to search for
310  *  lppszOtherDirs [I] Other directories to look in
311  *  dwWhich        [I] Type of executable to search for
312  *
313  * RETURNS
314  *  Success: TRUE. The path to the executable is stored in sFile.
315  *  Failure: FALSE. The path to the executable is unchanged.
316  */
317 BOOL WINAPI SHLWAPI_5(LPSTR lpszFile,LPCSTR *lppszOtherDirs,DWORD dwWhich)
318 {
319   return SHLWAPI_PathFindOnPathExA(lpszFile,lppszOtherDirs,dwWhich);
320 }
321
322 /*************************************************************************
323  * @    [SHLWAPI.6]
324  *
325  * Unicode version of SHLWAPI_5.
326  */
327 BOOL WINAPI SHLWAPI_6(LPWSTR lpszFile,LPCWSTR *lppszOtherDirs,DWORD dwWhich)
328 {
329   return SHLWAPI_PathFindOnPathExW(lpszFile,lppszOtherDirs,dwWhich);
330 }
331
332 /*************************************************************************
333  * SHLWAPI_DupSharedHandle
334  *
335  * Internal implemetation of SHLWAPI_11.
336  */
337 static
338 HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
339                                        DWORD dwSrcProcId, DWORD dwAccess,
340                                        DWORD dwOptions)
341 {
342   HANDLE hDst, hSrc;
343   DWORD dwMyProcId = GetCurrentProcessId();
344   HSHARED hRet = (HSHARED)NULL;
345
346   TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
347         dwAccess, dwOptions);
348
349   /* Get dest process handle */
350   if (dwDstProcId == dwMyProcId)
351     hDst = GetCurrentProcess();
352   else
353     hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
354
355   if (hDst)
356   {
357     /* Get src process handle */
358     if (dwSrcProcId == dwMyProcId)
359       hSrc = GetCurrentProcess();
360     else
361       hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
362
363     if (hSrc)
364     {
365       /* Make handle available to dest process */
366       if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
367                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
368         hRet = (HSHARED)NULL;
369
370       if (dwSrcProcId != dwMyProcId)
371         CloseHandle(hSrc);
372     }
373
374     if (dwDstProcId != dwMyProcId)
375       CloseHandle(hDst);
376   }
377
378   TRACE("Returning handle %p\n", (PVOID)hRet);
379   return hRet;
380 }
381
382 /*************************************************************************
383  * @  [SHLWAPI.7]
384  *
385  * Create a block of sharable memory and initialise it with data.
386  *
387  * PARAMS
388  * dwProcId [I] ID of process owning data
389  * lpvData  [I] Pointer to data to write
390  * dwSize   [I] Size of data
391  *
392  * RETURNS
393  * Success: A shared memory handle
394  * Failure: NULL
395  *
396  * NOTES
397  * Ordinals 7-11 provide a set of calls to create shared memory between a
398  * group of processes. The shared memory is treated opaquely in that its size
399  * is not exposed to clients who map it. This is accomplished by storing
400  * the size of the map as the first DWORD of mapped data, and then offsetting
401  * the view pointer returned by this size.
402  *
403  * SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
404  * SHLWAPI_8/SHLWAPI_9  - Get/Release a pointer to the shared data
405  * SHLWAPI_11           - Helper function; Duplicate cross-process handles
406    */
407 HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
408 {
409   HANDLE hMap;
410   LPVOID pMapped;
411   HSHARED hRet = (HSHARED)NULL;
412
413   TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
414
415   /* Create file mapping of the correct length */
416   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
417                             dwSize + sizeof(dwSize), NULL);
418   if (!hMap)
419     return hRet;
420
421   /* Get a view in our process address space */
422   pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
423
424   if (pMapped)
425   {
426     /* Write size of data, followed by the data, to the view */
427     *((DWORD*)pMapped) = dwSize;
428     if (dwSize)
429       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
430
431     /* Release view. All further views mapped will be opaque */
432     UnmapViewOfFile(pMapped);
433     hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
434                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
435                                    DUPLICATE_SAME_ACCESS);
436   }
437
438   CloseHandle(hMap);
439   return hRet;
440 }
441
442 /*************************************************************************
443  * @ [SHLWAPI.8]
444  *
445  * Get a pointer to a block of shared memory from a shared memory handle.
446  *
447  * PARAMS
448  * hShared  [I] Shared memory handle
449  * dwProcId [I] ID of process owning hShared
450  *
451  * RETURNS
452  * Success: A pointer to the shared memory
453  * Failure: NULL
454  *
455  * NOTES
456  * See SHLWAPI_7.
457    */
458 PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
459   {
460   HSHARED hDup;
461   LPVOID pMapped;
462
463   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
464
465   /* Get handle to shared memory for current process */
466   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
467                                  FILE_MAP_ALL_ACCESS, 0);
468   /* Get View */
469   pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
470   CloseHandle(hDup);
471
472   if (pMapped)
473     return (char *) pMapped + sizeof(DWORD); /* Hide size */
474   return NULL;
475 }
476
477 /*************************************************************************
478  * @ [SHLWAPI.9]
479  *
480  * Release a pointer to a block of shared memory.
481  *
482  * PARAMS
483  * lpView [I] Shared memory pointer
484  *
485  * RETURNS
486  * Success: TRUE
487  * Failure: FALSE
488  *
489  * NOTES
490  * See SHLWAPI_7.
491  */
492 BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
493 {
494   TRACE("(%p)\n", lpView);
495   return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
496 }
497
498 /*************************************************************************
499  * @ [SHLWAPI.10]
500  *
501  * Destroy a block of sharable memory.
502  *
503  * PARAMS
504  * hShared  [I] Shared memory handle
505  * dwProcId [I] ID of process owning hShared
506  *
507  * RETURNS
508  * Success: TRUE
509  * Failure: FALSE
510  *
511  * NOTES
512  * See SHLWAPI_7.
513  */
514 BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
515 {
516   HSHARED hClose;
517
518   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
519
520   /* Get a copy of the handle for our process, closing the source handle */
521   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
522                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
523   /* Close local copy */
524   return CloseHandle((HANDLE)hClose);
525 }
526
527 /*************************************************************************
528  * @   [SHLWAPI.11]
529  *
530  * Copy a sharable memory handle from one process to another.
531  *
532  * PARAMS
533  * hShared     [I] Shared memory handle to duplicate
534  * dwDstProcId [I] ID of the process wanting the duplicated handle
535  * dwSrcProcId [I] ID of the process owning hShared
536  * dwAccess    [I] Desired DuplicateHandle access
537  * dwOptions   [I] Desired DuplicateHandle options
538  *
539  * RETURNS
540  * Success: A handle suitable for use by the dwDstProcId process.
541  * Failure: A NULL handle.
542  *
543  * NOTES
544  * See SHLWAPI_7.
545  */
546 HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
547                           DWORD dwAccess, DWORD dwOptions)
548 {
549   HSHARED hRet;
550
551   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
552                                  dwAccess, dwOptions);
553   return hRet;
554 }
555
556 /*************************************************************************
557  *      @       [SHLWAPI.13]
558  * (Used by IE4 during startup)
559  */
560 HRESULT WINAPI SHLWAPI_13 (
561         LPVOID w,
562         LPVOID x)
563 {
564         FIXME("(%p %p)stub\n",w,x);
565         return 1;
566 #if 0
567         /* pseudo code extracted from relay trace */
568         RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Aceepted Documents", &newkey);
569         ret = 0;
570         i = 0;
571         size = 0;
572         while(!ret) {
573             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
574             size += ???;
575             i++;
576         }
577         b1 = LocalAlloc(0x40, size);
578         ret = 0;
579         i = 0;
580         while(!ret) {
581             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
582             RegisterClipBoardFormatA(a4);
583             i++;
584         }
585         hwnd1 = GetModuleHandleA("URLMON.DLL");
586         proc = GetProcAddress(hwnd1, "CreateFormatEnumerator");
587         HeapAlloc(??, 0, 0x14);
588         HeapAlloc(??, 0, 0x50);
589         LocalAlloc(0x40, 0x78);
590         /* FIXME: bad string below */
591         lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
592         StrCpyW(a6,  L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
593
594         GetTickCount();
595         IsBadReadPtr(c1 = 0x403fd210,4);
596         InterlockedIncrement(c1+4);
597         LocalFree(b1);
598         RegCloseKey(newkey);
599         IsBadReadPtr(c1 = 0x403fd210,4);
600         InterlockedIncrement(c1+4);
601
602         HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
603         HeapAlloc(40350000,00000000,00000050) retval=403feb44;
604         hwnd1 = GetModuleHandleA("URLMON.DLL");
605         proc = GetProcAddress(hwnd1, "RegisterFormatEnumerator");
606         /* 0x1a40c88c is in URLMON.DLL just before above proc
607          * content is L"_EnumFORMATETC_"
608          * label is d1
609          */
610         IsBadReadPtr(d1 = 0x1a40c88c,00000002);
611         lstrlenW(d1);
612         lstrlenW(d1);
613         HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
614         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
615         InterlockedIncrement(d2+4);
616         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
617         InterlockedDecrement(d2+4);
618         IsBadReadPtr(c1,00000004);
619         InterlockedDecrement(c1+4);
620         IsBadReadPtr(c1,00000004);
621         InterlockedDecrement(c1+4);
622
623 #endif
624 }
625
626 /*************************************************************************
627  *      @       [SHLWAPI.14]
628  *
629  * Function:
630  *    Retrieves IE "AcceptLanguage" value from registry. ASCII mode.
631  *
632  */
633 HRESULT WINAPI SHLWAPI_14 (
634         LPSTR langbuf,
635         LPDWORD buflen)
636 {
637         CHAR *mystr;
638         DWORD mystrlen, mytype;
639         HKEY mykey;
640         LCID mylcid;
641
642         mystrlen = (*buflen > 6) ? *buflen : 6;
643         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
644                                  HEAP_ZERO_MEMORY, mystrlen);
645         RegOpenKeyA(HKEY_CURRENT_USER,
646                     "Software\\Microsoft\\Internet Explorer\\International",
647                     &mykey);
648         if (RegQueryValueExA(mykey, "AcceptLanguage",
649                               0, &mytype, mystr, &mystrlen)) {
650             /* Did not find value */
651             mylcid = GetUserDefaultLCID();
652             /* somehow the mylcid translates into "en-us"
653              *  this is similar to "LOCALE_SABBREVLANGNAME"
654              *  which could be gotten via GetLocaleInfo.
655              *  The only problem is LOCALE_SABBREVLANGUAGE" is
656              *  a 3 char string (first 2 are country code and third is
657              *  letter for "sublanguage", which does not come close to
658              *  "en-us"
659              */
660             lstrcpyA(mystr, "en-us");
661             mystrlen = lstrlenA(mystr);
662         }
663         else {
664             /* handle returned string */
665             FIXME("missing code\n");
666         }
667         if (mystrlen > *buflen)
668             lstrcpynA(langbuf, mystr, *buflen);
669         else {
670             lstrcpyA(langbuf, mystr);
671             *buflen = lstrlenA(langbuf);
672         }
673         RegCloseKey(mykey);
674         HeapFree(GetProcessHeap(), 0, mystr);
675         TRACE("language is %s\n", debugstr_a(langbuf));
676         return 0;
677 }
678
679 /*************************************************************************
680  *      @       [SHLWAPI.15]
681  *
682  * Function:
683  *    Retrieves IE "AcceptLanguage" value from registry. UNICODE mode.
684  *
685  */
686 HRESULT WINAPI SHLWAPI_15 (
687         LPWSTR langbuf,
688         LPDWORD buflen)
689 {
690         CHAR *mystr;
691         DWORD mystrlen, mytype;
692         HKEY mykey;
693         LCID mylcid;
694
695         mystrlen = (*buflen > 6) ? *buflen : 6;
696         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
697                                  HEAP_ZERO_MEMORY, mystrlen);
698         RegOpenKeyA(HKEY_CURRENT_USER,
699                     "Software\\Microsoft\\Internet Explorer\\International",
700                     &mykey);
701         if (RegQueryValueExA(mykey, "AcceptLanguage",
702                               0, &mytype, mystr, &mystrlen)) {
703             /* Did not find value */
704             mylcid = GetUserDefaultLCID();
705             /* somehow the mylcid translates into "en-us"
706              *  this is similar to "LOCALE_SABBREVLANGNAME"
707              *  which could be gotten via GetLocaleInfo.
708              *  The only problem is LOCALE_SABBREVLANGUAGE" is
709              *  a 3 char string (first 2 are country code and third is
710              *  letter for "sublanguage", which does not come close to
711              *  "en-us"
712              */
713             lstrcpyA(mystr, "en-us");
714             mystrlen = lstrlenA(mystr);
715         }
716         else {
717             /* handle returned string */
718             FIXME("missing code\n");
719         }
720         RegCloseKey(mykey);
721         *buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
722         HeapFree(GetProcessHeap(), 0, mystr);
723         TRACE("language is %s\n", debugstr_w(langbuf));
724         return 0;
725 }
726
727 /*************************************************************************
728  *      @       [SHLWAPI.16]
729  */
730 HRESULT WINAPI SHLWAPI_16 (
731         LPVOID w,
732         LPVOID x,
733         LPVOID y,
734         LPWSTR z)
735 {
736         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
737         return 0xabba1252;
738 }
739
740 /*************************************************************************
741  *      @       [SHLWAPI.18]
742  *
743  *  w is pointer to address of callback routine
744  *  x is pointer to LPVOID to receive address of locally allocated
745  *         space size 0x14
746  *  return is 0 (unless out of memory???)
747  *
748  * related to _19, _21 and _22 below
749  *  only seen invoked by SHDOCVW
750  */
751 LONG WINAPI SHLWAPI_18 (
752         LPVOID *w,
753         LPVOID x)
754 {
755         FIXME("(%p %p)stub\n",w,x);
756         *((LPDWORD)x) = 0;
757         return 0;
758 }
759
760 /*************************************************************************
761  *      @       [SHLWAPI.19]
762  *
763  *  w is address of allocated memory from _21
764  *  return is 0 (unless out of memory???)
765  *
766  * related to _18, _21 and _22 below
767  *  only seen invoked by SHDOCVW
768  */
769 LONG WINAPI SHLWAPI_19 (
770         LPVOID w)
771 {
772         FIXME("(%p) stub\n",w);
773         return 0;
774 }
775
776 /*************************************************************************
777  *      @       [SHLWAPI.21]
778  *
779  *  w points to space allocated via .18 above
780  *      LocalSize is done on it (retrieves 18)
781  *      LocalReAlloc is done on it to size 8 with LMEM_MOVEABLE & LMEM_ZEROINIT
782  *  x values seen 0xa0000005
783  *  returns 1
784  *
785  *  relates to _18, _19 and _22 above and below
786  *   only seen invoked by SHDOCVW
787  */
788 LONG WINAPI SHLWAPI_21 (
789         LPVOID w,
790         DWORD  x)
791 {
792         FIXME("(%p %lx)stub\n",w,x);
793         return 1;
794 }
795
796 /*************************************************************************
797  *      @       [SHLWAPI.22]
798  *
799  *  return is 'w' value seen in x is 0xa0000005
800  *
801  *  relates to _18, _19 and _21 above
802  *   only seen invoked by SHDOCVW
803  */
804 LPVOID WINAPI SHLWAPI_22 (
805         LPVOID w,
806         DWORD  x)
807 {
808         FIXME("(%p %lx)stub\n",w,x);
809         return w;
810 }
811
812 /*************************************************************************
813  *      @       [SHLWAPI.23]
814  *
815  * NOTES
816  *      converts a guid to a string
817  *      returns strlen(str)
818  */
819 DWORD WINAPI SHLWAPI_23 (
820         REFGUID guid,   /* [in]  clsid */
821         LPSTR str,      /* [out] buffer */
822         INT cmax)       /* [in]  size of buffer */
823 {
824         char xguid[40];
825
826         sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
827                  guid->Data1, guid->Data2, guid->Data3,
828                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
829                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
830         TRACE("(%s %p 0x%08x)stub\n", xguid, str, cmax);
831         if (strlen(xguid)>=cmax) return 0;
832         strcpy(str,xguid);
833         return strlen(xguid) + 1;
834 }
835
836 /*************************************************************************
837  *      @       [SHLWAPI.24]
838  *
839  * NOTES
840  *      converts a guid to a string
841  *      returns strlen(str)
842  */
843 DWORD WINAPI SHLWAPI_24 (
844         REFGUID guid,   /* [in]  clsid */
845         LPWSTR str,     /* [out] buffer */
846         INT cmax)       /* [in]  size of buffer */
847 {
848     char xguid[40];
849
850     sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
851              guid->Data1, guid->Data2, guid->Data3,
852              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
853              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
854     return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
855 }
856
857 /*************************************************************************
858  *      @       [SHLWAPI.25]
859  *
860  * Seems to be iswalpha
861  */
862 BOOL WINAPI SHLWAPI_25(WCHAR wc)
863 {
864     return (get_char_typeW(wc) & C1_ALPHA) != 0;
865 }
866
867 /*************************************************************************
868  *      @       [SHLWAPI.26]
869  *
870  * Seems to be iswupper
871  */
872 BOOL WINAPI SHLWAPI_26(WCHAR wc)
873 {
874     return (get_char_typeW(wc) & C1_UPPER) != 0;
875 }
876
877 /*************************************************************************
878  *      @       [SHLWAPI.27]
879  *
880  * Seems to be iswlower
881  */
882 BOOL WINAPI SHLWAPI_27(WCHAR wc)
883 {
884     return (get_char_typeW(wc) & C1_LOWER) != 0;
885 }
886
887 /*************************************************************************
888  *      @       [SHLWAPI.28]
889  *
890  * Seems to be iswalnum
891  */
892 BOOL WINAPI SHLWAPI_28(WCHAR wc)
893 {
894     return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
895 }
896
897 /*************************************************************************
898  *      @       [SHLWAPI.29]
899  *
900  * Seems to be iswspace
901  */
902 BOOL WINAPI SHLWAPI_29(WCHAR wc)
903 {
904     return (get_char_typeW(wc) & C1_SPACE) != 0;
905 }
906
907 /*************************************************************************
908  *      @       [SHLWAPI.30]
909  *
910  * Seems to be iswblank
911  */
912 BOOL WINAPI SHLWAPI_30(WCHAR wc)
913 {
914     return (get_char_typeW(wc) & C1_BLANK) != 0;
915 }
916
917 /*************************************************************************
918  *      @       [SHLWAPI.31]
919  *
920  * Seems to be iswpunct
921  */
922 BOOL WINAPI SHLWAPI_31(WCHAR wc)
923 {
924     return (get_char_typeW(wc) & C1_PUNCT) != 0;
925 }
926
927 /*************************************************************************
928  *      @       [SHLWAPI.32]
929  *
930  * Seems to be iswcntrl
931  */
932 BOOL WINAPI SHLWAPI_32(WCHAR wc)
933 {
934     return (get_char_typeW(wc) & C1_CNTRL) != 0;
935 }
936
937 /*************************************************************************
938  *      @       [SHLWAPI.33]
939  *
940  * Seems to be iswdigit
941  */
942 BOOL WINAPI SHLWAPI_33(WCHAR wc)
943 {
944     return (get_char_typeW(wc) & C1_DIGIT) != 0;
945 }
946
947 /*************************************************************************
948  *      @       [SHLWAPI.34]
949  *
950  * Seems to be iswxdigit
951  */
952 BOOL WINAPI SHLWAPI_34(WCHAR wc)
953 {
954     return (get_char_typeW(wc) & C1_XDIGIT) != 0;
955 }
956
957 /*************************************************************************
958  *      @       [SHLWAPI.35]
959  *
960  */
961 BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
962 {
963     FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
964     return TRUE;
965 }
966
967 /*************************************************************************
968  *      @       [SHLWAPI.36]
969  *
970  */
971 BOOL WINAPI SHLWAPI_36(HMENU h1, UINT ui2, UINT h3, LPCWSTR p4)
972 {
973     TRACE("(0x%08x, 0x%08x, 0x%08x, %s): stub\n",
974           h1, ui2, h3, debugstr_w(p4));
975     return AppendMenuW(h1, ui2, h3, p4);
976 }
977
978 /*************************************************************************
979  *      @       [SHLWAPI.74]
980  *
981  * Get the text from a given dialog item.
982  */
983 INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
984 {
985   HWND hItem = GetDlgItem(hWnd, nItem);
986
987   if (hItem)
988     return GetWindowTextW(hItem, lpsDest, nDestLen);
989   if (nDestLen)
990     *lpsDest = (WCHAR)'\0';
991   return 0;
992 }
993
994 /*************************************************************************
995  *      @       [SHLWAPI.151]
996  * Function:  Compare two ASCII strings for "len" bytes.
997  * Returns:   *str1-*str2  (case sensitive)
998  */
999 DWORD WINAPI SHLWAPI_151(LPSTR str1, LPSTR str2, INT len)
1000 {
1001     return strncmp( str1, str2, len );
1002 }
1003
1004 /*************************************************************************
1005  *      @       [SHLWAPI.152]
1006  *
1007  * Function:  Compare two WIDE strings for "len" bytes.
1008  * Returns:   *str1-*str2  (case sensitive)
1009  */
1010 DWORD WINAPI SHLWAPI_152(LPWSTR str1, LPWSTR str2, INT len)
1011 {
1012     return strncmpW( str1, str2, len );
1013 }
1014
1015 /*************************************************************************
1016  *      @       [SHLWAPI.153]
1017  * Function:  Compare two ASCII strings for "len" bytes via caseless compare.
1018  * Returns:   *str1-*str2  (case insensitive)
1019  */
1020 DWORD WINAPI SHLWAPI_153(LPSTR str1, LPSTR str2, DWORD len)
1021 {
1022     return strncasecmp( str1, str2, len );
1023 }
1024
1025 /*************************************************************************
1026  *      @       [SHLWAPI.154]
1027  *
1028  * Function:  Compare two WIDE strings for "len" bytes via caseless compare.
1029  * Returns:   *str1-*str2  (case insensitive)
1030  */
1031 DWORD WINAPI SHLWAPI_154(LPWSTR str1, LPWSTR str2, DWORD len)
1032 {
1033     return strncmpiW( str1, str2, len );
1034 }
1035
1036 /*************************************************************************
1037  *      @       [SHLWAPI.155]
1038  *
1039  *      Case sensitive string compare (ASCII). Does not SetLastError().
1040  */
1041 DWORD WINAPI SHLWAPI_155 ( LPSTR str1, LPSTR str2)
1042 {
1043     return strcmp(str1, str2);
1044 }
1045
1046 /*************************************************************************
1047  *      @       [SHLWAPI.156]
1048  *
1049  *      Case sensitive string compare. Does not SetLastError().
1050  */
1051 DWORD WINAPI SHLWAPI_156 ( LPWSTR str1, LPWSTR str2)
1052 {
1053     return strcmpW( str1, str2 );
1054 }
1055
1056 /*************************************************************************
1057  *      @       [SHLWAPI.158]
1058  *
1059  *      Case insensitive string compare. Does not SetLastError(). ??
1060  */
1061 DWORD WINAPI SHLWAPI_158 ( LPWSTR str1, LPWSTR str2)
1062 {
1063     return strcmpiW( str1, str2 );
1064 }
1065
1066 /*************************************************************************
1067  *      @       [SHLWAPI.162]
1068  *
1069  * Ensure a multibyte character string doesn't end in a hanging lead byte.
1070  */
1071 DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
1072 {
1073   if (lpStr && size)
1074   {
1075     LPSTR lastByte = lpStr + size - 1;
1076
1077     while(lpStr < lastByte)
1078       lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
1079
1080     if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
1081     {
1082       *lpStr = '\0';
1083       size--;
1084     }
1085     return size;
1086   }
1087   return 0;
1088 }
1089
1090 /*************************************************************************
1091  *      @       [SHLWAPI.164]
1092  */
1093 DWORD WINAPI SHLWAPI_164 (
1094         LPVOID u,
1095         LPVOID v,
1096         LPVOID w,
1097         LPVOID x,
1098         LPVOID y,
1099         LPVOID z)
1100 {
1101         TRACE("(%p %p %p %p %p %p) stub\n",u,v,w,x,y,z);
1102         return 0x80004002;    /* E_NOINTERFACE */
1103 }
1104
1105 /*************************************************************************
1106  *      @       [SHLWAPI.165]
1107  *
1108  * SetWindowLongA with mask.
1109  */
1110 LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wFlags, UINT wMask)
1111 {
1112   LONG ret = GetWindowLongA(hwnd, offset);
1113   UINT newFlags = (wFlags & wMask) | (ret & ~wFlags);
1114
1115   if (newFlags != ret)
1116     ret = SetWindowLongA(hwnd, offset, newFlags);
1117   return ret;
1118 }
1119
1120 /*************************************************************************
1121  *      @       [SHLWAPI.169]
1122  *
1123  *  Do IUnknown::Release on passed object.
1124  */
1125 DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
1126 {
1127         IUnknown *temp;
1128
1129         TRACE("(%p)\n",lpUnknown);
1130         if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1131         temp = *lpUnknown;
1132         *lpUnknown = NULL;
1133         TRACE("doing Release\n");
1134         return IUnknown_Release(temp);
1135 }
1136
1137 /*************************************************************************
1138  *      @       [SHLWAPI.170]
1139  *
1140  * Skip URL '//' sequence.
1141  */
1142 LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
1143 {
1144   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1145     lpszSrc += 2;
1146   return lpszSrc;
1147 }
1148
1149 /*************************************************************************
1150  *      @       [SHLWAPI.172]
1151  * Get window handle of OLE object
1152  */
1153 DWORD WINAPI SHLWAPI_172 (
1154         IUnknown *y,       /* [in]   OLE object interface */
1155         LPHWND z)          /* [out]  location to put window handle */
1156 {
1157         DWORD ret;
1158         IUnknown *pv;
1159
1160         TRACE("(%p %p)\n",y,z);
1161         if (!y) return E_FAIL;
1162
1163         if ((ret = IUnknown_QueryInterface(y, &IID_IOleWindow,(LPVOID *)&pv)) < 0) {
1164             /* error */
1165             return ret;
1166         }
1167         ret = IOleWindow_GetWindow((IOleWindow *)pv, z);
1168         IUnknown_Release(pv);
1169         TRACE("result hwnd=%08x\n", *z);
1170         return ret;
1171 }
1172
1173 /*************************************************************************
1174  *      @       [SHLWAPI.174]
1175  *
1176  * Seems to do call either IObjectWithSite::SetSite or
1177  *   IPersistMoniker::GetClassID.  But since we do not implement either
1178  *   of those classes in our headers, we will fake it out.
1179  */
1180 DWORD WINAPI SHLWAPI_174(
1181         IUnknown *p1,     /* [in]   OLE object                          */
1182         LPVOID *p2)       /* [out]  ptr to result of either GetClassID
1183                                     or SetSite call.                    */
1184 {
1185     DWORD ret, aa;
1186
1187     if (!p1) return E_FAIL;
1188
1189     /* see if SetSite interface exists for IObjectWithSite object */
1190     ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1191     TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1192     if (ret) {
1193
1194         /* see if GetClassId interface exists for IPersistMoniker object */
1195         ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1196         TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1197         if (ret) return ret;
1198
1199         /* fake a GetClassId call */
1200         ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1201         TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1202               *(LPDWORD)p2);
1203         IUnknown_Release((IUnknown *)aa);
1204     }
1205     else {
1206         /* fake a SetSite call */
1207         ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1208         TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1209               *(LPDWORD)p2);
1210         IUnknown_Release((IUnknown *)p1);
1211     }
1212     return ret;
1213 }
1214
1215 /*************************************************************************
1216  *      @       [SHLWAPI.175]
1217  *
1218  *      NOTE:
1219  *        Param1 can be an IShellFolder Object
1220  */
1221 HRESULT WINAPI SHLWAPI_175 (LPVOID x, LPVOID y)
1222 {
1223         FIXME("(%p %p) stub\n", x,y);
1224         return E_FAIL;
1225 }
1226 /*************************************************************************
1227  *      @       [SHLWAPI.176]
1228  *
1229  * Function appears to be interface to IServiceProvider::QueryService
1230  *
1231  * NOTE:
1232  *   returns E_NOINTERFACE
1233  *           E_FAIL  if w == 0
1234  *           S_OK    if _219 called successfully
1235  */
1236 DWORD WINAPI SHLWAPI_176 (
1237         IUnknown* unk,    /* [in]    object to give Service Provider */
1238         REFGUID   sid,    /* [in]    Service ID                      */
1239         REFIID    riid,   /* [in]    Function requested              */
1240         LPVOID    *z)     /* [out]   place to save interface pointer */
1241 {
1242     DWORD ret;
1243     LPVOID aa;
1244     *z = 0;
1245     if (!unk) return E_FAIL;
1246     ret = IUnknown_QueryInterface(unk, &IID_IServiceProvider, &aa);
1247     TRACE("did IU_QI retval=%08lx, aa=%p\n", ret, aa);
1248     if (ret) return ret;
1249     ret = IServiceProvider_QueryService((IServiceProvider *)aa, sid, riid,
1250                                         (void **)z);
1251     TRACE("did ISP_QS retval=%08lx, *z=%p\n", ret, (LPVOID)*z);
1252     IUnknown_Release((IUnknown*)aa);
1253     return ret;
1254 }
1255
1256 /*************************************************************************
1257  *      @       [SHLWAPI.181]
1258  *
1259  *      Enable or disable a menu item.
1260  */
1261 UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
1262 {
1263   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1264 }
1265
1266 /*************************************************************************
1267  *      @       [SHLWAPI.183]
1268  *
1269  * Register a window class if it isn't already.
1270  */
1271 DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
1272 {
1273   WNDCLASSA wca;
1274   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1275     return TRUE;
1276   return (DWORD)RegisterClassA(wndclass);
1277 }
1278
1279 /*************************************************************************
1280  *      @       [SHLWAPI.193]
1281  */
1282 DWORD WINAPI SHLWAPI_193 ()
1283 {
1284         HDC hdc;
1285         DWORD ret;
1286
1287         TRACE("()\n");
1288
1289         hdc = GetDC(0);
1290         ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1291         ReleaseDC(0, hdc);
1292         return ret;
1293 }
1294
1295 /*************************************************************************
1296  *      @       [SHLWAPI.199]
1297  *
1298  * Copy interface pointer
1299  */
1300 DWORD WINAPI SHLWAPI_199 (
1301         IUnknown **dest,   /* [out] pointer to copy of interface ptr */
1302         IUnknown *src)     /* [in]  interface pointer */
1303 {
1304         TRACE("(%p %p)\n",dest,src);
1305         if (*dest != src) {
1306             if (*dest)
1307                 IUnknown_Release(*dest);
1308             if (src) {
1309                 IUnknown_AddRef(src);
1310                 *dest = src;
1311             }
1312         }
1313         return 4;
1314 }
1315
1316 /*************************************************************************
1317  *      @       [SHLWAPI.208]
1318  *
1319  * Some sort of memory management process - associated with _210
1320  */
1321 DWORD WINAPI SHLWAPI_208 (
1322         DWORD    a,
1323         DWORD    b,
1324         LPVOID   c,
1325         LPVOID   d,
1326         DWORD    e)
1327 {
1328     FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
1329           a, b, c, d, e);
1330     return 1;
1331 }
1332
1333 /*************************************************************************
1334  *      @       [SHLWAPI.209]
1335  *
1336  * Some sort of memory management process - associated with _208
1337  */
1338 DWORD WINAPI SHLWAPI_209 (
1339         LPVOID   a)
1340 {
1341     FIXME("(%p) stub\n",
1342           a);
1343     return 1;
1344 }
1345
1346 /*************************************************************************
1347  *      @       [SHLWAPI.210]
1348  *
1349  * Some sort of memory management process - associated with _208
1350  */
1351 DWORD WINAPI SHLWAPI_210 (
1352         LPVOID   a,
1353         DWORD    b,
1354         LPVOID   c)
1355 {
1356     FIXME("(%p 0x%08lx %p) stub\n",
1357           a, b, c);
1358     return 0;
1359 }
1360
1361 /*************************************************************************
1362  *      @       [SHLWAPI.211]
1363  */
1364 DWORD WINAPI SHLWAPI_211 (
1365         LPVOID   a,
1366         DWORD    b)
1367 {
1368     FIXME("(%p 0x%08lx) stub\n",
1369           a, b);
1370     return 1;
1371 }
1372
1373 /*************************************************************************
1374  *      @       [SHLWAPI.215]
1375  *
1376  * NOTES
1377  *  check me!
1378  */
1379 DWORD WINAPI SHLWAPI_215 (
1380         LPCSTR lpStrSrc,
1381         LPWSTR lpwStrDest,
1382         int len)
1383 {
1384         INT len_a, ret;
1385
1386         len_a = lstrlenA(lpStrSrc);
1387         ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
1388         TRACE("%s %s %d, ret=%d\n",
1389               debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
1390         return ret;
1391 }
1392
1393 /*************************************************************************
1394  *      @       [SHLWAPI.218]
1395  *
1396  * WideCharToMultiByte with multi language support.
1397  */
1398 INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
1399                        LPINT lpnMultiCharCount)
1400 {
1401   WCHAR emptyW[] = { '\0' };
1402   int len , reqLen;
1403   LPSTR mem;
1404
1405   if (!lpDstStr || !lpnMultiCharCount)
1406     return 0;
1407
1408   if (!lpSrcStr)
1409     lpSrcStr = emptyW;
1410
1411   *lpDstStr = '\0';
1412
1413   len = strlenW(lpSrcStr) + 1;
1414
1415   switch (CodePage)
1416   {
1417   case CP_WINUNICODE:
1418     CodePage = CP_UTF8; /* Fall through... */
1419   case 0x0000C350: /* FIXME: CP_ #define */
1420   case CP_UTF7:
1421   case CP_UTF8:
1422     {
1423       DWORD dwMode = 0;
1424       INT nWideCharCount = len - 1;
1425
1426       GET_FUNC(pConvertINetUnicodeToMultiByte, mlang, "ConvertINetUnicodeToMultiByte", 0);
1427       if (!pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
1428                                           lpnMultiCharCount))
1429         return 0;
1430
1431       if (nWideCharCount < len - 1)
1432       {
1433         mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
1434         if (!mem)
1435           return 0;
1436
1437         *lpnMultiCharCount = 0;
1438
1439         if (pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
1440         {
1441           SHLWAPI_162 (mem, *lpnMultiCharCount);
1442           lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
1443           return *lpnMultiCharCount + 1;
1444         }
1445         HeapFree(GetProcessHeap(), 0, mem);
1446         return *lpnMultiCharCount;
1447       }
1448       lpDstStr[*lpnMultiCharCount] = '\0';
1449       return *lpnMultiCharCount;
1450     }
1451     break;
1452   default:
1453     break;
1454   }
1455
1456   reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
1457                                *lpnMultiCharCount, NULL, NULL);
1458
1459   if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1460   {
1461     reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
1462     if (reqLen)
1463     {
1464       mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
1465       if (mem)
1466       {
1467         reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
1468                                      reqLen, NULL, NULL);
1469
1470         reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
1471         reqLen++;
1472
1473         lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
1474
1475         HeapFree(GetProcessHeap(), 0, mem);
1476       }
1477     }
1478   }
1479   return reqLen;
1480 }
1481
1482 /*************************************************************************
1483  *      @       [SHLWAPI.217]
1484  *
1485  * Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
1486  * --> Crash. Something wrong here.
1487  *
1488  * It seems from OE v5 that the third param is the count. (GA 11/2001)
1489  */
1490 INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
1491 {
1492     INT myint = MultiCharCount;
1493
1494     return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
1495 }
1496
1497 /*************************************************************************
1498  *      @       [SHLWAPI.219]
1499  *
1500  * Seems to be "super" QueryInterface. Supplied with at table of interfaces
1501  * and an array of IIDs and offsets into the table.
1502  *
1503  * NOTES
1504  *  error codes: E_POINTER, E_NOINTERFACE
1505  */
1506 typedef struct {
1507     REFIID   refid;
1508     DWORD    indx;
1509 } IFACE_INDEX_TBL;
1510
1511 HRESULT WINAPI SHLWAPI_219 (
1512         LPVOID w,           /* [in]   table of interfaces                   */
1513         IFACE_INDEX_TBL *x, /* [in]   array of REFIIDs and indexes to above */
1514         REFIID riid,        /* [in]   REFIID to get interface for           */
1515         LPVOID *z)          /* [out]  location to get interface pointer     */
1516 {
1517         HRESULT ret;
1518         IUnknown *a_vtbl;
1519         IFACE_INDEX_TBL *xmove;
1520
1521         TRACE("(%p %p %s %p)\n",
1522               w,x,debugstr_guid(riid),z);
1523         if (z) {
1524             xmove = x;
1525             while (xmove->refid) {
1526                 TRACE("trying (indx %ld) %s\n", xmove->indx,
1527                       debugstr_guid(xmove->refid));
1528                 if (IsEqualIID(riid, xmove->refid)) {
1529                     a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
1530                     TRACE("matched, returning (%p)\n", a_vtbl);
1531                     *z = (LPVOID)a_vtbl;
1532                     IUnknown_AddRef(a_vtbl);
1533                     return S_OK;
1534                 }
1535                 xmove++;
1536             }
1537
1538             if (IsEqualIID(riid, &IID_IUnknown)) {
1539                 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
1540                 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
1541                 *z = (LPVOID)a_vtbl;
1542                 IUnknown_AddRef(a_vtbl);
1543                 return S_OK;
1544             }
1545             *z = 0;
1546             ret = E_NOINTERFACE;
1547         } else
1548             ret = E_POINTER;
1549         return ret;
1550 }
1551
1552 /*************************************************************************
1553  *      @       [SHLWAPI.222]
1554  *
1555  * NOTES
1556  *  securityattributes missing
1557  */
1558 HANDLE WINAPI SHLWAPI_222 (LPCLSID guid)
1559 {
1560         char lpstrName[80];
1561
1562         sprintf( lpstrName, "shell.{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1563                  guid->Data1, guid->Data2, guid->Data3,
1564                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
1565                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
1566         FIXME("(%s) stub\n", lpstrName);
1567         return CreateSemaphoreA(NULL,0, 0x7fffffff, lpstrName);
1568 }
1569
1570 /*************************************************************************
1571  *      @       [SHLWAPI.223]
1572  *
1573  * NOTES
1574  *  get the count of the semaphore
1575  */
1576 DWORD WINAPI SHLWAPI_223 (HANDLE handle)
1577 {
1578         DWORD oldCount;
1579
1580         FIXME("(0x%08x) stub\n",handle);
1581
1582         ReleaseSemaphore( handle, 1, &oldCount);        /* +1 */
1583         WaitForSingleObject( handle, 0 );               /* -1 */
1584         return oldCount;
1585 }
1586
1587 /*************************************************************************
1588  *      @       [SHLWAPI.236]
1589  */
1590 HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
1591 {
1592     HKEY newkey;
1593     DWORD type, count;
1594     CHAR value[MAX_PATH], string[MAX_PATH];
1595
1596     strcpy(string, "CLSID\\");
1597     strcat(string, debugstr_guid(lpUnknown));
1598     strcat(string, "\\InProcServer32");
1599
1600     count = MAX_PATH;
1601     RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
1602     RegQueryValueExA(newkey, 0, 0, &type, value, &count);
1603     RegCloseKey(newkey);
1604     return LoadLibraryExA(value, 0, 0);
1605 }
1606
1607 /*************************************************************************
1608  *      @       [SHLWAPI.237]
1609  *
1610  * Unicode version of SHLWAPI_183.
1611  */
1612 DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
1613 {
1614         WNDCLASSW WndClass;
1615
1616         TRACE("(0x%08x %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
1617
1618         if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
1619                 return TRUE;
1620         return RegisterClassW(lpWndClass);
1621 }
1622
1623 /*************************************************************************
1624  *      @       [SHLWAPI.239]
1625  */
1626 DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
1627 {
1628     FIXME("(0x%08x %p 0x%08lx) stub\n",
1629           hInstance, p2, dw3);
1630     return 0;
1631 #if 0
1632     /* pseudo code from relay trace */
1633     WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
1634     GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
1635     /* above pair repeated for:
1636            TridentThicketUrlDlClass
1637            Shell Embedding
1638            CIESplashScreen
1639            Inet Notify_Hidden
1640            OCHost
1641     */
1642 #endif
1643 }
1644
1645 /*************************************************************************
1646  *      @       [SHLWAPI.240]
1647  *
1648  *      Calls ASCII or Unicode WindowProc for the given window.
1649  */
1650 LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1651 {
1652         if (IsWindowUnicode(hWnd))
1653                 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1654         return DefWindowProcA(hWnd, uMessage, wParam, lParam);
1655 }
1656
1657 /*************************************************************************
1658  *      @       [SHLWAPI.241]
1659  *
1660  */
1661 DWORD WINAPI SHLWAPI_241 ()
1662 {
1663         FIXME("()stub\n");
1664         return /* 0xabba1243 */ 0;
1665 }
1666
1667 /*************************************************************************
1668  *      @       [SHLWAPI.266]
1669  *
1670  * native does at least approximately:
1671  *     strcpyW(newstr, x);
1672  *     strcatW(newstr, "\\Restrictions");
1673  *     if (RegOpenKeyExA(80000001, newstr, 00000000,00000001,40520b78))
1674  *        return 0;
1675  *    *unknown*
1676  */
1677 DWORD WINAPI SHLWAPI_266 (
1678         LPVOID w,
1679         LPVOID x,   /* [in] partial registry key */
1680         LPVOID y,
1681         LPVOID z)
1682 {
1683         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1684         return /* 0xabba1248 */ 0;
1685 }
1686
1687 /*************************************************************************
1688  *      @       [SHLWAPI.267]
1689  */
1690 HRESULT WINAPI SHLWAPI_267 (
1691         LPVOID w,
1692         LPVOID x,
1693         LPVOID y, /* [???] NOTE: same as 3rd parameter of SHLWAPI_219 */
1694         LPVOID z) /* [???] NOTE: same as 4th parameter of SHLWAPI_219 */
1695 {
1696         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1697
1698         /* native seems to do:
1699          *  SHLWAPI_219 ((LPVOID)(((LPSTR)x)-4), ???, (REFIID) y, (LPVOID*) z);
1700          */
1701
1702         *((LPDWORD)z) = 0xabba1200;
1703         return /* 0xabba1254 */ 0;
1704 }
1705
1706 /*************************************************************************
1707  *      @       [SHLWAPI.268]
1708  */
1709 DWORD WINAPI SHLWAPI_268 (
1710         LPVOID w,
1711         LPVOID x)
1712 {
1713         FIXME("(%p %p)\n",w,x);
1714         return 0xabba1251; /* 0 = failure */
1715 }
1716
1717 /*************************************************************************
1718  *      @       [SHLWAPI.276]
1719  *
1720  * on first call process does following:  other calls just returns 2
1721  *  instance = LoadLibraryA("SHELL32.DLL");
1722  *  func = GetProcAddress(instance, "DllGetVersion");
1723  *  ret = RegOpenKeyExA(80000002, "Software\\Microsoft\\Internet Explorer",00000000,0002001f, newkey);
1724  *  ret = RegQueryValueExA(newkey, "IntegratedBrowser",00000000,00000000,4052588c,40525890);
1725  *  RegCloseKey(newkey);
1726  *  FreeLibrary(instance);
1727  *  return 2;
1728  */
1729 DWORD WINAPI SHLWAPI_276 ()
1730 {
1731         FIXME("()stub\n");
1732         return /* 0xabba1244 */ 2;
1733 }
1734
1735 /*************************************************************************
1736  *      @       [SHLWAPI.278]
1737  *
1738  */
1739 HWND WINAPI SHLWAPI_278 (
1740         LONG wndProc,
1741         HWND hWndParent,
1742         DWORD dwExStyle,
1743         DWORD dwStyle,
1744         HMENU hMenu,
1745         LONG z)
1746 {
1747         WNDCLASSA wndclass;
1748         HWND hwnd;
1749         HCURSOR hCursor;
1750         char * clsname = "WorkerA";
1751
1752         FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
1753           wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
1754
1755         hCursor = LoadCursorA(0x00000000,IDC_ARROWA);
1756
1757         if(!GetClassInfoA(shlwapi_hInstance, clsname, &wndclass))
1758         {
1759           RtlZeroMemory(&wndclass, sizeof(WNDCLASSA));
1760           wndclass.lpfnWndProc = DefWindowProcW;
1761           wndclass.cbWndExtra = 4;
1762           wndclass.hInstance = shlwapi_hInstance;
1763           wndclass.hCursor = hCursor;
1764           wndclass.hbrBackground = COLOR_BTNSHADOW;
1765           wndclass.lpszMenuName = NULL;
1766           wndclass.lpszClassName = clsname;
1767           RegisterClassA (&wndclass);
1768         }
1769         hwnd = CreateWindowExA(dwExStyle, clsname, 0,dwStyle,0,0,0,0,hWndParent,
1770                 hMenu,shlwapi_hInstance,0);
1771         SetWindowLongA(hwnd, 0, z);
1772         SetWindowLongA(hwnd, GWL_WNDPROC, wndProc);
1773         return hwnd;
1774 }
1775
1776 /*************************************************************************
1777  *      @       [SHLWAPI.289]
1778  *
1779  * Late bound call to winmm.PlaySoundW
1780  */
1781 BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
1782 {
1783   GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
1784   return pPlaySoundW(pszSound, hmod, fdwSound);
1785 }
1786
1787 /*************************************************************************
1788  *      @       [SHLWAPI.294]
1789  */
1790 BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
1791 {
1792     /*
1793      * str1:            "I"     "I"     pushl esp+0x20
1794      * str2:            "U"     "I"     pushl 0x77c93810
1795      * (is "I" and "U" "integer" and "unsigned" ??)
1796      *
1797      * pStr:            ""      ""      pushl eax
1798      * some_len:        0x824   0x104   pushl 0x824
1799      * lpStr2:          "%l"    "%l"    pushl esp+0xc
1800      *
1801      * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
1802      * LocalAlloc(0x00, some_len) -> irrelevant_var
1803      * LocalAlloc(0x40, irrelevant_len) -> pStr
1804      * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
1805      * shlwapi.PathRemoveBlanksW(pStr);
1806      */
1807     ERR("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
1808     return TRUE;
1809 }
1810
1811 /*************************************************************************
1812  *      @       [SHLWAPI.313]
1813  *
1814  * Late bound call to shell32.SHGetFileInfoW
1815  */
1816 DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
1817                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
1818 {
1819   GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
1820   return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
1821 }
1822
1823 /*************************************************************************
1824  *      @       [SHLWAPI.318]
1825  *
1826  * Late bound call to shell32.DragQueryFileW
1827  */
1828 UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
1829 {
1830   GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
1831   return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
1832 }
1833
1834 /*************************************************************************
1835  *      @       [SHLWAPI.333]
1836  *
1837  * Late bound call to shell32.SHBrowseForFolderW
1838  */
1839 LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
1840 {
1841   GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
1842   return pSHBrowseForFolderW(lpBi);
1843 }
1844
1845 /*************************************************************************
1846  *      @       [SHLWAPI.334]
1847  *
1848  * Late bound call to shell32.SHGetPathFromIDListW
1849  */
1850 BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
1851 {
1852   GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
1853   return pSHGetPathFromIDListW(pidl, pszPath);
1854 }
1855
1856 /*************************************************************************
1857  *      @       [SHLWAPI.335]
1858  *
1859  * Late bound call to shell32.ShellExecuteExW
1860  */
1861 BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
1862 {
1863   GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
1864   return pShellExecuteExW(lpExecInfo);
1865 }
1866
1867 /*************************************************************************
1868  *      @       [SHLWAPI.336]
1869  *
1870  * Late bound call to shell32.SHFileOperationW.
1871  */
1872 DWORD WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
1873 {
1874   GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
1875   return pSHFileOperationW(lpFileOp);
1876 }
1877
1878 /*************************************************************************
1879  *      @       [SHLWAPI.337]
1880  *
1881  * Late bound call to shell32.ExtractIconExW.
1882  */
1883 HICON WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
1884                          HICON *phiconSmall, UINT nIcons)
1885 {
1886   GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", (HICON)0);
1887   return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
1888 }
1889
1890 /*************************************************************************
1891  *      @       [SHLWAPI.342]
1892  *
1893  */
1894 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
1895 {
1896         return InterlockedCompareExchange(dest, xchg, compare);
1897 }
1898
1899 /*************************************************************************
1900  *      @       [SHLWAPI.346]
1901  */
1902 DWORD WINAPI SHLWAPI_346 (
1903         LPCWSTR src,
1904         LPWSTR dest,
1905         int len)
1906 {
1907         FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
1908         lstrcpynW(dest, src, len);
1909         return lstrlenW(dest)+1;
1910 }
1911
1912 /*************************************************************************
1913  *      @       [SHLWAPI.350]
1914  *
1915  * seems to be late bound call to GetFileVersionInfoSizeW
1916  */
1917 DWORD WINAPI SHLWAPI_350 (
1918         LPWSTR x,
1919         LPVOID y)
1920 {
1921         DWORD ret;
1922
1923         GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
1924         ret = pGetFileVersionInfoSizeW(x, y);
1925         return 0x208 + ret;
1926 }
1927
1928 /*************************************************************************
1929  *      @       [SHLWAPI.351]
1930  *
1931  * seems to be late bound call to GetFileVersionInfoW
1932  */
1933 BOOL  WINAPI SHLWAPI_351 (
1934         LPWSTR w,   /* [in] path to dll */
1935         DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */
1936         DWORD  y,   /* [in] return value from .350 - assume length */
1937         LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA) */
1938 {
1939     GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
1940     return pGetFileVersionInfoW(w, x, y-0x208, z+0x208);
1941 }
1942
1943 /*************************************************************************
1944  *      @       [SHLWAPI.352]
1945  *
1946  * seems to be late bound call to VerQueryValueW
1947  */
1948 WORD WINAPI SHLWAPI_352 (
1949         LPVOID w,   /* [in] buffer from _351 */
1950         LPWSTR x,   /* [in]   value to retrieve -
1951                               converted and passed to VerQueryValueA as #2 */
1952         LPVOID y,   /* [out]  ver buffer - passed to VerQueryValueA as #3 */
1953         UINT*  z)   /* [in]   ver length - passed to VerQueryValueA as #4 */
1954 {
1955     GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
1956     return pVerQueryValueW(w+0x208, x, y, z);
1957 }
1958
1959 /**************************************************************************
1960  *      @       [SHLWAPI.356]
1961  *
1962  *      mbc - this function is undocumented, The parameters are correct and
1963  *            the calls to InitializeSecurityDescriptor and
1964  *            SetSecurityDescriptorDacl are correct, but apparently some
1965  *            apps call this function with all zero parameters.
1966  */
1967
1968 DWORD WINAPI SHLWAPI_356(PACL pDacl, PSECURITY_DESCRIPTOR pSD, LPCSTR *str)
1969 {
1970   if(str != 0){
1971     *str = 0;
1972   }
1973
1974   if(!pDacl){
1975     return 0;
1976   }
1977
1978   if (!InitializeSecurityDescriptor(pSD, 1)) return 0;
1979   return SetSecurityDescriptorDacl(pSD, 1, pDacl, 0);
1980 }
1981
1982
1983 /*************************************************************************
1984  *      @       [SHLWAPI.357]
1985  *
1986  * Late bound call to shell32.SHGetNewLinkInfoW
1987  */
1988 BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
1989                         BOOL *pfMustCopy, UINT uFlags)
1990 {
1991   GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
1992   return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
1993 }
1994
1995 /*************************************************************************
1996  *      @       [SHLWAPI.358]
1997  *
1998  * Late bound call to shell32.SHDefExtractIconW
1999  */
2000 DWORD WINAPI SHLWAPI_358(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2001                          LPVOID arg5, LPVOID arg6)
2002 {
2003   GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
2004   return pSHDefExtractIconW(arg1, arg2, arg3, arg4, arg5, arg6);
2005 }
2006
2007 /*************************************************************************
2008  *      @       [SHLWAPI.364]
2009  *
2010  * Wrapper for lstrcpynA with src and dst swapped.
2011  */
2012 DWORD WINAPI SHLWAPI_364(LPCSTR src, LPSTR dst, INT n)
2013 {
2014   lstrcpynA(dst, src, n);
2015   return TRUE;
2016 }
2017
2018 /*************************************************************************
2019  *      @       [SHLWAPI.370]
2020  *
2021  * Late bound call to shell32.ExtractIconW
2022  */
2023 HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
2024                          UINT nIconIndex)
2025 {
2026   GET_FUNC(pExtractIconW, shell32, "ExtractIconW", (HICON)0);
2027   return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
2028 }
2029
2030 /*************************************************************************
2031  *      @       [SHLWAPI.376]
2032  */
2033 LANGID WINAPI SHLWAPI_376 ()
2034 {
2035     FIXME("() stub\n");
2036     /* FIXME: This should be a forward in the .spec file to the win2k function
2037      * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
2038      */
2039     return GetUserDefaultLangID();
2040 }
2041
2042 /*************************************************************************
2043  *      @       [SHLWAPI.377]
2044  *
2045  * FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
2046  *        each call here.
2047  * FIXME: Native shows calls to:
2048  *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
2049  *                      CheckVersion
2050  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
2051  *  RegQueryValueExA for "LPKInstalled"
2052  *  RegCloseKey
2053  *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
2054  *  RegQueryValueExA for "ResourceLocale"
2055  *  RegCloseKey
2056  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
2057  *  RegQueryValueExA for "Locale"
2058  *  RegCloseKey
2059  *  and then tests the Locale ("en" for me).
2060  *     code below
2061  *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
2062  */
2063 DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
2064 {
2065     CHAR mod_path[2*MAX_PATH];
2066     LPSTR ptr;
2067
2068     GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
2069     ptr = strrchr(mod_path, '\\');
2070     if (ptr) {
2071         strcpy(ptr+1, new_mod);
2072         TRACE("loading %s\n", debugstr_a(mod_path));
2073         return (DWORD)LoadLibraryA(mod_path);
2074     }
2075     return 0;
2076 }
2077
2078 /*************************************************************************
2079  *      @       [SHLWAPI.378]
2080  *
2081  *  This is Unicode version of .377
2082  */
2083 DWORD WINAPI SHLWAPI_378 (
2084         LPCWSTR   new_mod,          /* [in] new module name        */
2085         HMODULE   inst_hwnd,        /* [in] calling module handle  */
2086         LPVOID z)                   /* [???] 4 */
2087 {
2088     WCHAR mod_path[2*MAX_PATH];
2089     LPWSTR ptr;
2090
2091     GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
2092     ptr = strrchrW(mod_path, '\\');
2093     if (ptr) {
2094         strcpyW(ptr+1, new_mod);
2095         TRACE("loading %s\n", debugstr_w(mod_path));
2096         return (DWORD)LoadLibraryW(mod_path);
2097     }
2098     return 0;
2099 }
2100
2101 /*************************************************************************
2102  *      @       [SHLWAPI.389]
2103  *
2104  * Late bound call to comdlg32.GetSaveFileNameW
2105  */
2106 BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
2107 {
2108   GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
2109   return pGetSaveFileNameW(ofn);
2110 }
2111
2112 /*************************************************************************
2113  *      @       [SHLWAPI.390]
2114  *
2115  * Late bound call to mpr.WNetRestoreConnectionW
2116  */
2117 DWORD WINAPI SHLWAPI_390(LPVOID arg1, LPVOID arg2)
2118 {
2119   GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
2120   return pWNetRestoreConnectionW(arg1, arg2);
2121 }
2122
2123 /*************************************************************************
2124  *      @       [SHLWAPI.391]
2125  *
2126  * Late bound call to mpr.WNetGetLastErrorW
2127  */
2128 DWORD WINAPI SHLWAPI_391(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2129                          LPVOID arg5)
2130 {
2131   GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
2132   return pWNetGetLastErrorW(arg1, arg2, arg3, arg4, arg5);
2133 }
2134
2135 /*************************************************************************
2136  *      @       [SHLWAPI.401]
2137  *
2138  * Late bound call to comdlg32.PageSetupDlgW
2139  */
2140 BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
2141 {
2142   GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
2143   return pPageSetupDlgW(pagedlg);
2144 }
2145
2146 /*************************************************************************
2147  *      @       [SHLWAPI.402]
2148  *
2149  * Late bound call to comdlg32.PrintDlgW
2150  */
2151 BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
2152 {
2153   GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
2154   return pPrintDlgW(printdlg);
2155 }
2156
2157 /*************************************************************************
2158  *      @       [SHLWAPI.403]
2159  *
2160  * Late bound call to comdlg32.GetOpenFileNameW
2161  */
2162 BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
2163 {
2164   GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
2165   return pGetOpenFileNameW(ofn);
2166 }
2167
2168 /* INTERNAL: Map from HLS color space to RGB */
2169 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
2170 {
2171   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
2172
2173   if (wHue > 160)
2174     return wMid1;
2175   else if (wHue > 120)
2176     wHue = 160 - wHue;
2177   else if (wHue > 40)
2178     return wMid2;
2179
2180   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
2181 }
2182
2183 /* Convert to RGB and scale into RGB range (0..255) */
2184 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
2185
2186 /*************************************************************************
2187  *      ColorHLSToRGB   [SHLWAPI.404]
2188  *
2189  * Convert from HLS color space into an RGB COLORREF.
2190  *
2191  * NOTES
2192  * Input HLS values are constrained to the range (0..240).
2193  */
2194 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
2195 {
2196   WORD wRed;
2197
2198   if (wSaturation)
2199   {
2200     WORD wGreen, wBlue, wMid1, wMid2;
2201
2202     if (wLuminosity > 120)
2203       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
2204     else
2205       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
2206
2207     wMid1 = wLuminosity * 2 - wMid2;
2208
2209     wRed   = GET_RGB(wHue + 80);
2210     wGreen = GET_RGB(wHue);
2211     wBlue  = GET_RGB(wHue - 80);
2212
2213     return RGB(wRed, wGreen, wBlue);
2214   }
2215
2216   wRed = wLuminosity * 255 / 240;
2217   return RGB(wRed, wRed, wRed);
2218 }
2219
2220 /*************************************************************************
2221  *      @       [SHLWAPI.413]
2222  *
2223  * Function unknown seems to always to return 0
2224  */
2225 DWORD WINAPI SHLWAPI_413 (DWORD x)
2226 {
2227         FIXME("(0x%08lx)stub\n", x);
2228         return 0;
2229 }
2230
2231 /*************************************************************************
2232  *      @       [SHLWAPI.418]
2233  *
2234  * Function seems to do FreeLibrary plus other things.
2235  *
2236  * FIXME native shows the following calls:
2237  *   RtlEnterCriticalSection
2238  *   LocalFree
2239  *   GetProcAddress(Comctl32??, 150L)
2240  *   DPA_DeletePtr
2241  *   RtlLeaveCriticalSection
2242  *  followed by the FreeLibrary.
2243  *  The above code may be related to .377 above.
2244  */
2245 BOOL  WINAPI SHLWAPI_418 (HMODULE x)
2246 {
2247         FIXME("(0x%08lx) partial stub\n", (LONG)x);
2248         return FreeLibrary(x);
2249 }
2250
2251 /*************************************************************************
2252  *      @       [SHLWAPI.431]
2253  */
2254 DWORD WINAPI SHLWAPI_431 (DWORD x)
2255 {
2256         FIXME("(0x%08lx)stub\n", x);
2257         return 0xabba1247;
2258 }
2259
2260 /*************************************************************************
2261  *      @       [SHLWAPI.436]
2262  *
2263  *  This is really CLSIDFromString which is exported by ole32.dll,
2264  *  however the native shlwapi.dll does *not* import ole32. Nor does
2265  *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude
2266  *  that MS duplicated the code for CLSIDFromString.
2267  *
2268  *  This is a duplicate (with changes for UNICODE) of CLSIDFromString16
2269  *  in dlls/ole32/compobj.c
2270  */
2271 DWORD WINAPI SHLWAPI_436 (LPWSTR idstr, CLSID *id)
2272 {
2273     LPWSTR s = idstr;
2274     BYTE *p;
2275     INT i;
2276     WCHAR table[256];
2277
2278     if (!s) {
2279         memset(s, 0, sizeof(CLSID));
2280         return S_OK;
2281     }
2282     else {  /* validate the CLSID string */
2283
2284         if (strlenW(s) != 38)
2285             return CO_E_CLASSSTRING;
2286
2287         if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
2288             return CO_E_CLASSSTRING;
2289
2290         for (i=1; i<37; i++)
2291             {
2292                 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
2293                 if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||
2294                       ((s[i] >= L'a') && (s[i] <= L'f'))  ||
2295                       ((s[i] >= L'A') && (s[i] <= L'F')))
2296                     )
2297                     return CO_E_CLASSSTRING;
2298             }
2299     }
2300
2301     TRACE("%s -> %p\n", debugstr_w(s), id);
2302
2303   /* quick lookup table */
2304     memset(table, 0, 256*sizeof(WCHAR));
2305
2306     for (i = 0; i < 10; i++) {
2307         table['0' + i] = i;
2308     }
2309     for (i = 0; i < 6; i++) {
2310         table['A' + i] = i+10;
2311         table['a' + i] = i+10;
2312     }
2313
2314     /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
2315
2316     p = (BYTE *) id;
2317
2318     s++;        /* skip leading brace  */
2319     for (i = 0; i < 4; i++) {
2320         p[3 - i] = table[*s]<<4 | table[*(s+1)];
2321         s += 2;
2322     }
2323     p += 4;
2324     s++;        /* skip - */
2325
2326     for (i = 0; i < 2; i++) {
2327         p[1-i] = table[*s]<<4 | table[*(s+1)];
2328         s += 2;
2329     }
2330     p += 2;
2331     s++;        /* skip - */
2332
2333     for (i = 0; i < 2; i++) {
2334         p[1-i] = table[*s]<<4 | table[*(s+1)];
2335         s += 2;
2336     }
2337     p += 2;
2338     s++;        /* skip - */
2339
2340     /* these are just sequential bytes */
2341     for (i = 0; i < 2; i++) {
2342         *p++ = table[*s]<<4 | table[*(s+1)];
2343         s += 2;
2344     }
2345     s++;        /* skip - */
2346
2347     for (i = 0; i < 6; i++) {
2348         *p++ = table[*s]<<4 | table[*(s+1)];
2349         s += 2;
2350     }
2351
2352     return S_OK;
2353 }
2354
2355 /*************************************************************************
2356  *      @       [SHLWAPI.437]
2357  *
2358  * NOTES
2359  *  In the real shlwapi, One time initialisation calls GetVersionEx and reads
2360  *  the registry to determine what O/S & Service Pack level is running, and
2361  *  therefore which functions are available. Currently we always run as NT,
2362  *  since this means that we don't need extra code to emulate Unicode calls,
2363  *  they are forwarded directly to the appropriate API call instead.
2364  *  Since the flags for whether to call or emulate Unicode are internal to
2365  *  the dll, this function does not need a full implementation.
2366  */
2367 DWORD WINAPI SHLWAPI_437 (DWORD functionToCall)
2368 {
2369         FIXME("(0x%08lx)stub\n", functionToCall);
2370         return /* 0xabba1247 */ 0;
2371 }
2372
2373 /*************************************************************************
2374  *      ColorRGBToHLS   [SHLWAPI.445]
2375  *
2376  * Convert from RGB COLORREF into the HLS color space.
2377  *
2378  * NOTES
2379  * Input HLS values are constrained to the range (0..240).
2380  */
2381 VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue,
2382                           LPWORD wLuminance, LPWORD pwSaturation)
2383 {
2384     FIXME("stub\n");
2385     return;
2386 }
2387
2388 /*************************************************************************
2389  *      SHCreateShellPalette    [SHLWAPI.@]
2390  */
2391 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
2392 {
2393         FIXME("stub\n");
2394         return CreateHalftonePalette(hdc);
2395 }
2396
2397 /*************************************************************************
2398  *      SHGetInverseCMAP (SHLWAPI.@)
2399  */
2400 DWORD WINAPI SHGetInverseCMAP (LPDWORD* x, DWORD why)
2401 {
2402     if (why == 4) {
2403         FIXME(" - returning bogus address for SHGetInverseCMAP\n");
2404         *x = (LPDWORD)0xabba1249;
2405         return 0;
2406     }
2407     FIXME("(%p, %#lx)stub\n", x, why);
2408     return 0;
2409 }
2410
2411 /*************************************************************************
2412  *      SHIsLowMemoryMachine    [SHLWAPI.@]
2413  */
2414 DWORD WINAPI SHIsLowMemoryMachine (DWORD x)
2415 {
2416         FIXME("0x%08lx\n", x);
2417         return 0;
2418 }
2419
2420 /*************************************************************************
2421  *      GetMenuPosFromID        [SHLWAPI.@]
2422  */
2423 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
2424 {
2425  MENUITEMINFOA mi;
2426  INT nCount = GetMenuItemCount(hMenu), nIter = 0;
2427
2428  while (nIter < nCount)
2429  {
2430    mi.wID = 0;
2431    if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
2432      return nIter;
2433    nIter++;
2434  }
2435  return -1;
2436 }
2437
2438 /*************************************************************************
2439  *      _SHGetInstanceExplorer@4        [SHLWAPI.@]
2440  *
2441  * Late bound call to shell32.SHGetInstanceExplorer.
2442  */
2443 HRESULT WINAPI _SHGetInstanceExplorer (LPUNKNOWN *lpUnknown)
2444 {
2445   GET_FUNC(pSHGetInstanceExplorer, shell32, "SHGetInstanceExplorer", E_FAIL);
2446   return pSHGetInstanceExplorer(lpUnknown);
2447 }
2448
2449 /*************************************************************************
2450  *      SHGetThreadRef  [SHLWAPI.@]
2451  *
2452  * Retrieves the per-thread object reference set by SHSetThreadRef
2453  * "punk" - Address of a pointer to the IUnknown interface. Returns S_OK if
2454  *          successful or E_NOINTERFACE otherwise.
2455  */
2456 HRESULT WINAPI SHGetThreadRef (IUnknown ** ppunk)
2457 {
2458     if (SHLWAPI_ThreadRef_index < 0) return E_NOINTERFACE;
2459     *ppunk = (IUnknown *)TlsGetValue(SHLWAPI_ThreadRef_index);
2460     return S_OK;
2461 }
2462
2463 /*************************************************************************
2464  *      SHSetThreadRef  [SHLWAPI.@]
2465  *
2466  * Stores a per-thread reference to a COM object
2467  * "punk" - Pointer to the IUnknown interface of the object to
2468  *          which you want to store a reference. Returns S_OK if successful
2469  *          or an OLE error value.
2470  */
2471 HRESULT WINAPI SHSetThreadRef (IUnknown * punk)
2472 {
2473     if (SHLWAPI_ThreadRef_index < 0) return E_NOINTERFACE;
2474     TlsSetValue(SHLWAPI_ThreadRef_index, (LPVOID) punk);
2475     return S_OK;
2476 }