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