Wait for app to come up before attempting DDE connection.
[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 "config.h"
24 #include "wine/port.h"
25
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "docobj.h"
30 #include "shlguid.h"
31 #include "windef.h"
32 #include "winnls.h"
33 #include "winbase.h"
34 #include "ddeml.h"
35 #include "shlobj.h"
36 #include "shellapi.h"
37 #include "commdlg.h"
38 #include "wine/unicode.h"
39 #include "wine/obj_base.h"
40 #include "wine/obj_inplace.h"
41 #include "wine/obj_serviceprovider.h"
42 #include "wine/obj_control.h"
43 #include "wine/obj_connection.h"
44 #include "wine/obj_property.h"
45 #include "wingdi.h"
46 #include "winreg.h"
47 #include "winuser.h"
48 #include "wine/debug.h"
49 #include "ordinal.h"
50 #include "shlwapi.h"
51
52
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54
55 extern HINSTANCE shlwapi_hInstance;
56 extern HMODULE SHLWAPI_hshell32;
57 extern HMODULE SHLWAPI_hwinmm;
58 extern HMODULE SHLWAPI_hcomdlg32;
59 extern HMODULE SHLWAPI_hcomctl32;
60 extern HMODULE SHLWAPI_hmpr;
61 extern HMODULE SHLWAPI_hmlang;
62 extern HMODULE SHLWAPI_hversion;
63
64 extern DWORD SHLWAPI_ThreadRef_index;
65
66 typedef HANDLE HSHARED; /* Shared memory */
67
68 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
69 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
70 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
71 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
72
73 /* The following schemes were identified in the native version of
74  * SHLWAPI.DLL version 5.50
75  */
76 typedef enum {
77     URL_SCHEME_INVALID     = -1,
78     URL_SCHEME_UNKNOWN     =  0,
79     URL_SCHEME_FTP,
80     URL_SCHEME_HTTP,
81     URL_SCHEME_GOPHER,
82     URL_SCHEME_MAILTO,
83     URL_SCHEME_NEWS,
84     URL_SCHEME_NNTP,
85     URL_SCHEME_TELNET,
86     URL_SCHEME_WAIS,
87     URL_SCHEME_FILE,
88     URL_SCHEME_MK,
89     URL_SCHEME_HTTPS,
90     URL_SCHEME_SHELL,
91     URL_SCHEME_SNEWS,
92     URL_SCHEME_LOCAL,
93     URL_SCHEME_JAVASCRIPT,
94     URL_SCHEME_VBSCRIPT,
95     URL_SCHEME_ABOUT,
96     URL_SCHEME_RES,
97     URL_SCHEME_MAXVALUE
98 } URL_SCHEME;
99
100 typedef struct {
101     URL_SCHEME  scheme_number;
102     LPCSTR scheme_name;
103 } SHL_2_inet_scheme;
104
105 static const SHL_2_inet_scheme shlwapi_schemes[] = {
106   {URL_SCHEME_FTP,        "ftp"},
107   {URL_SCHEME_HTTP,       "http"},
108   {URL_SCHEME_GOPHER,     "gopher"},
109   {URL_SCHEME_MAILTO,     "mailto"},
110   {URL_SCHEME_NEWS,       "news"},
111   {URL_SCHEME_NNTP,       "nntp"},
112   {URL_SCHEME_TELNET,     "telnet"},
113   {URL_SCHEME_WAIS,       "wais"},
114   {URL_SCHEME_FILE,       "file"},
115   {URL_SCHEME_MK,         "mk"},
116   {URL_SCHEME_HTTPS,      "https"},
117   {URL_SCHEME_SHELL,      "shell"},
118   {URL_SCHEME_SNEWS,      "snews"},
119   {URL_SCHEME_LOCAL,      "local"},
120   {URL_SCHEME_JAVASCRIPT, "javascript"},
121   {URL_SCHEME_VBSCRIPT,   "vbscript"},
122   {URL_SCHEME_ABOUT,      "about"},
123   {URL_SCHEME_RES,        "res"},
124   {0, 0}
125 };
126
127 /* function pointers for GET_FUNC macro; these need to be global because of gcc bug */
128 static LPITEMIDLIST (WINAPI *pSHBrowseForFolderW)(LPBROWSEINFOW);
129 static HRESULT (WINAPI *pConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
130 static BOOL    (WINAPI *pPlaySoundW)(LPCWSTR, HMODULE, DWORD);
131 static DWORD   (WINAPI *pSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
132 static UINT    (WINAPI *pDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
133 static BOOL    (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
134 static BOOL    (WINAPI *pShellExecuteExW)(LPSHELLEXECUTEINFOW);
135 static HICON   (WINAPI *pSHFileOperationW)(LPSHFILEOPSTRUCTW);
136 static HICON   (WINAPI *pExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
137 static BOOL    (WINAPI *pSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
138 static DWORD   (WINAPI *pSHDefExtractIconW)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID, LPVOID); /* FIXME: Correct args */
139 static HICON   (WINAPI *pExtractIconW)(HINSTANCE, LPCWSTR, UINT);
140 static BOOL    (WINAPI *pGetSaveFileNameW)(LPOPENFILENAMEW);
141 static DWORD   (WINAPI *pWNetRestoreConnectionW)(LPVOID, LPVOID); /* FIXME: Correct args */
142 static DWORD   (WINAPI *pWNetGetLastErrorW)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID); /* FIXME: Correct args */
143 static BOOL    (WINAPI *pPageSetupDlgW)(LPPAGESETUPDLGW);
144 static BOOL    (WINAPI *pPrintDlgW)(LPPRINTDLGW);
145 static BOOL    (WINAPI *pGetOpenFileNameW)(LPOPENFILENAMEW);
146 static DWORD   (WINAPI *pGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
147 static BOOL    (WINAPI *pGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
148 static WORD    (WINAPI *pVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
149 static BOOL    (WINAPI *pCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
150 static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO*);
151
152 /*
153  NOTES: Most functions exported by ordinal seem to be superflous.
154  The reason for these functions to be there is to provide a wrapper
155  for unicode functions to provide these functions on systems without
156  unicode functions eg. win95/win98. Since we have such functions we just
157  call these. If running Wine with native DLL's, some late bound calls may
158  fail. However, its better to implement the functions in the forward DLL
159  and recommend the builtin rather than reimplementing the calls here!
160 */
161
162 /*************************************************************************
163  *      @       [SHLWAPI.1]
164  *
165  * Identifies the Internet "scheme" in the passed string. ASCII based.
166  * Also determines start and length of item after the ':'
167  */
168 DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
169 {
170     DWORD cnt;
171     const SHL_2_inet_scheme *inet_pro;
172
173     y->fcncde = URL_SCHEME_INVALID;
174     if (y->size != 0x18) return E_INVALIDARG;
175     /* FIXME: leading white space generates error of 0x80041001 which
176      *        is undefined
177      */
178     if (*x <= ' ') return 0x80041001;
179     cnt = 0;
180     y->sizep1 = 0;
181     y->ap1 = x;
182     while (*x) {
183         if (*x == ':') {
184             y->sizep1 = cnt;
185             cnt = -1;
186             y->ap2 = x+1;
187             break;
188         }
189         x++;
190         cnt++;
191     }
192
193     /* check for no scheme in string start */
194     /* (apparently schemes *must* be larger than a single character)  */
195     if ((*x == '\0') || (y->sizep1 <= 1)) {
196         y->ap1 = 0;
197         return 0x80041001;
198     }
199
200     /* found scheme, set length of remainder */
201     y->sizep2 = lstrlenA(y->ap2);
202
203     /* see if known scheme and return indicator number */
204     y->fcncde = URL_SCHEME_UNKNOWN;
205     inet_pro = shlwapi_schemes;
206     while (inet_pro->scheme_name) {
207         if (!strncasecmp(inet_pro->scheme_name, y->ap1,
208                     min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
209             y->fcncde = inet_pro->scheme_number;
210             break;
211         }
212         inet_pro++;
213     }
214     return S_OK;
215 }
216
217 /*************************************************************************
218  *      @       [SHLWAPI.2]
219  *
220  * Identifies the Internet "scheme" in the passed string. UNICODE based.
221  * Also determines start and length of item after the ':'
222  */
223 DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
224 {
225     DWORD cnt;
226     const SHL_2_inet_scheme *inet_pro;
227     LPSTR cmpstr;
228     INT len;
229
230     y->fcncde = URL_SCHEME_INVALID;
231     if (y->size != 0x18) return E_INVALIDARG;
232     /* FIXME: leading white space generates error of 0x80041001 which
233      *        is undefined
234      */
235     if (*x <= L' ') return 0x80041001;
236     cnt = 0;
237     y->sizep1 = 0;
238     y->ap1 = x;
239     while (*x) {
240         if (*x == L':') {
241             y->sizep1 = cnt;
242             cnt = -1;
243             y->ap2 = x+1;
244             break;
245         }
246         x++;
247         cnt++;
248     }
249
250     /* check for no scheme in string start */
251     /* (apparently schemes *must* be larger than a single character)  */
252     if ((*x == L'\0') || (y->sizep1 <= 1)) {
253         y->ap1 = 0;
254         return 0x80041001;
255     }
256
257     /* found scheme, set length of remainder */
258     y->sizep2 = lstrlenW(y->ap2);
259
260     /* see if known scheme and return indicator number */
261     len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
262     cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
263     WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
264     y->fcncde = URL_SCHEME_UNKNOWN;
265     inet_pro = shlwapi_schemes;
266     while (inet_pro->scheme_name) {
267         if (!strncasecmp(inet_pro->scheme_name, cmpstr,
268                     min(len, lstrlenA(inet_pro->scheme_name)))) {
269             y->fcncde = inet_pro->scheme_number;
270             break;
271         }
272         inet_pro++;
273     }
274     HeapFree(GetProcessHeap(), 0, cmpstr);
275     return S_OK;
276 }
277
278 /*************************************************************************
279  * @    [SHLWAPI.3]
280  *
281  * Determine if a file exists locally and is of an executable type.
282  *
283  * PARAMS
284  *  lpszFile       [O] File to search for
285  *  dwWhich        [I] Type of executable to search for
286  *
287  * RETURNS
288  *  TRUE  If the file was found. lpszFile contains the file name.
289  *  FALSE Otherwise.
290  *
291  * NOTES
292  *  lpszPath is modified in place and must be at least MAX_PATH in length.
293  *  If the function returns FALSE, the path is modified to its orginal state.
294  *  If the given path contains an extension or dwWhich is 0, executable
295  *  extensions are not checked.
296  *
297  *  Ordinals 3-6 are a classic case of MS exposing limited functionality to
298  *  users (here through PathFindOnPath) and keeping advanced functionality for
299  *  their own developers exclusive use. Monopoly, anyone?
300  */
301 BOOL WINAPI SHLWAPI_3(LPSTR lpszFile,DWORD dwWhich)
302 {
303   return SHLWAPI_PathFindLocalExeA(lpszFile,dwWhich);
304 }
305
306 /*************************************************************************
307  * @    [SHLWAPI.4]
308  *
309  * Unicode version of SHLWAPI_3.
310  */
311 BOOL WINAPI SHLWAPI_4(LPWSTR lpszFile,DWORD dwWhich)
312 {
313   return SHLWAPI_PathFindLocalExeW(lpszFile,dwWhich);
314 }
315
316 /*************************************************************************
317  * @    [SHLWAPI.5]
318  *
319  * Search a range of paths for a specific type of executable.
320  *
321  * PARAMS
322  *  lpszFile       [O] File to search for
323  *  lppszOtherDirs [I] Other directories to look in
324  *  dwWhich        [I] Type of executable to search for
325  *
326  * RETURNS
327  *  Success: TRUE. The path to the executable is stored in sFile.
328  *  Failure: FALSE. The path to the executable is unchanged.
329  */
330 BOOL WINAPI SHLWAPI_5(LPSTR lpszFile,LPCSTR *lppszOtherDirs,DWORD dwWhich)
331 {
332   return SHLWAPI_PathFindOnPathExA(lpszFile,lppszOtherDirs,dwWhich);
333 }
334
335 /*************************************************************************
336  * @    [SHLWAPI.6]
337  *
338  * Unicode version of SHLWAPI_5.
339  */
340 BOOL WINAPI SHLWAPI_6(LPWSTR lpszFile,LPCWSTR *lppszOtherDirs,DWORD dwWhich)
341 {
342   return SHLWAPI_PathFindOnPathExW(lpszFile,lppszOtherDirs,dwWhich);
343 }
344
345 /*************************************************************************
346  * SHLWAPI_DupSharedHandle
347  *
348  * Internal implemetation of SHLWAPI_11.
349  */
350 static
351 HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
352                                        DWORD dwSrcProcId, DWORD dwAccess,
353                                        DWORD dwOptions)
354 {
355   HANDLE hDst, hSrc;
356   DWORD dwMyProcId = GetCurrentProcessId();
357   HSHARED hRet = (HSHARED)NULL;
358
359   TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
360         dwAccess, dwOptions);
361
362   /* Get dest process handle */
363   if (dwDstProcId == dwMyProcId)
364     hDst = GetCurrentProcess();
365   else
366     hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
367
368   if (hDst)
369   {
370     /* Get src process handle */
371     if (dwSrcProcId == dwMyProcId)
372       hSrc = GetCurrentProcess();
373     else
374       hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
375
376     if (hSrc)
377     {
378       /* Make handle available to dest process */
379       if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
380                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
381         hRet = (HSHARED)NULL;
382
383       if (dwSrcProcId != dwMyProcId)
384         CloseHandle(hSrc);
385     }
386
387     if (dwDstProcId != dwMyProcId)
388       CloseHandle(hDst);
389   }
390
391   TRACE("Returning handle %p\n", (PVOID)hRet);
392   return hRet;
393 }
394
395 /*************************************************************************
396  * @  [SHLWAPI.7]
397  *
398  * Create a block of sharable memory and initialise it with data.
399  *
400  * PARAMS
401  * dwProcId [I] ID of process owning data
402  * lpvData  [I] Pointer to data to write
403  * dwSize   [I] Size of data
404  *
405  * RETURNS
406  * Success: A shared memory handle
407  * Failure: NULL
408  *
409  * NOTES
410  * Ordinals 7-11 provide a set of calls to create shared memory between a
411  * group of processes. The shared memory is treated opaquely in that its size
412  * is not exposed to clients who map it. This is accomplished by storing
413  * the size of the map as the first DWORD of mapped data, and then offsetting
414  * the view pointer returned by this size.
415  *
416  * SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
417  * SHLWAPI_8/SHLWAPI_9  - Get/Release a pointer to the shared data
418  * SHLWAPI_11           - Helper function; Duplicate cross-process handles
419    */
420 HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
421 {
422   HANDLE hMap;
423   LPVOID pMapped;
424   HSHARED hRet = (HSHARED)NULL;
425
426   TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
427
428   /* Create file mapping of the correct length */
429   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
430                             dwSize + sizeof(dwSize), NULL);
431   if (!hMap)
432     return hRet;
433
434   /* Get a view in our process address space */
435   pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
436
437   if (pMapped)
438   {
439     /* Write size of data, followed by the data, to the view */
440     *((DWORD*)pMapped) = dwSize;
441     if (dwSize)
442       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
443
444     /* Release view. All further views mapped will be opaque */
445     UnmapViewOfFile(pMapped);
446     hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
447                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
448                                    DUPLICATE_SAME_ACCESS);
449   }
450
451   CloseHandle(hMap);
452   return hRet;
453 }
454
455 /*************************************************************************
456  * @ [SHLWAPI.8]
457  *
458  * Get a pointer to a block of shared memory from a shared memory handle.
459  *
460  * PARAMS
461  * hShared  [I] Shared memory handle
462  * dwProcId [I] ID of process owning hShared
463  *
464  * RETURNS
465  * Success: A pointer to the shared memory
466  * Failure: NULL
467  *
468  * NOTES
469  * See SHLWAPI_7.
470    */
471 PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
472   {
473   HSHARED hDup;
474   LPVOID pMapped;
475
476   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
477
478   /* Get handle to shared memory for current process */
479   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
480                                  FILE_MAP_ALL_ACCESS, 0);
481   /* Get View */
482   pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
483   CloseHandle(hDup);
484
485   if (pMapped)
486     return (char *) pMapped + sizeof(DWORD); /* Hide size */
487   return NULL;
488 }
489
490 /*************************************************************************
491  * @ [SHLWAPI.9]
492  *
493  * Release a pointer to a block of shared memory.
494  *
495  * PARAMS
496  * lpView [I] Shared memory pointer
497  *
498  * RETURNS
499  * Success: TRUE
500  * Failure: FALSE
501  *
502  * NOTES
503  * See SHLWAPI_7.
504  */
505 BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
506 {
507   TRACE("(%p)\n", lpView);
508   return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
509 }
510
511 /*************************************************************************
512  * @ [SHLWAPI.10]
513  *
514  * Destroy a block of sharable memory.
515  *
516  * PARAMS
517  * hShared  [I] Shared memory handle
518  * dwProcId [I] ID of process owning hShared
519  *
520  * RETURNS
521  * Success: TRUE
522  * Failure: FALSE
523  *
524  * NOTES
525  * See SHLWAPI_7.
526  */
527 BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
528 {
529   HSHARED hClose;
530
531   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
532
533   /* Get a copy of the handle for our process, closing the source handle */
534   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
535                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
536   /* Close local copy */
537   return CloseHandle((HANDLE)hClose);
538 }
539
540 /*************************************************************************
541  * @   [SHLWAPI.11]
542  *
543  * Copy a sharable memory handle from one process to another.
544  *
545  * PARAMS
546  * hShared     [I] Shared memory handle to duplicate
547  * dwDstProcId [I] ID of the process wanting the duplicated handle
548  * dwSrcProcId [I] ID of the process owning hShared
549  * dwAccess    [I] Desired DuplicateHandle access
550  * dwOptions   [I] Desired DuplicateHandle options
551  *
552  * RETURNS
553  * Success: A handle suitable for use by the dwDstProcId process.
554  * Failure: A NULL handle.
555  *
556  * NOTES
557  * See SHLWAPI_7.
558  */
559 HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
560                           DWORD dwAccess, DWORD dwOptions)
561 {
562   HSHARED hRet;
563
564   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
565                                  dwAccess, dwOptions);
566   return hRet;
567 }
568
569 /*************************************************************************
570  *      @       [SHLWAPI.13]
571  *
572  * Create and register a clipboard enumerator for a web browser.
573  *
574  * PARAMS
575  *  lpBC      [I] Binding context
576  *  lpUnknown [I] An object exposing the IWebBrowserApp interface
577  *
578  * RETURNS
579  *  Success: S_OK.
580  *  Failure: An HRESULT error code.
581  *
582  * NOTES
583  *  The enumerator is stored as a property of the web browser. If it does not
584  *  yet exist, it is created and set before being registered.
585  *
586  * BUGS
587  *  Unimplemented.
588  */
589 HRESULT WINAPI SHLWAPI_13(LPBC lpBC, IUnknown *lpUnknown)
590 {
591         FIXME("(%p,%p) stub\n", lpBC, lpUnknown);
592         return 1;
593 #if 0
594         /* pseudo code extracted from relay trace */
595         RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Accepted Documents", &newkey);
596         ret = 0;
597         i = 0;
598         size = 0;
599         while(!ret) {
600             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
601             size += ???;
602             i++;
603         }
604         b1 = LocalAlloc(0x40, size);
605         ret = 0;
606         i = 0;
607         while(!ret) {
608             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
609             RegisterClipBoardFormatA(a4);
610             i++;
611         }
612         hmod1 = GetModuleHandleA("URLMON.DLL");
613         proc = GetProcAddress(hmod1, "CreateFormatEnumerator");
614         HeapAlloc(??, 0, 0x14);
615         HeapAlloc(??, 0, 0x50);
616         LocalAlloc(0x40, 0x78);
617         /* FIXME: bad string below */
618         lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
619         StrCpyW(a6,  L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
620
621         GetTickCount();
622         IsBadReadPtr(c1 = 0x403fd210,4);
623         InterlockedIncrement(c1+4);
624         LocalFree(b1);
625         RegCloseKey(newkey);
626         IsBadReadPtr(c1 = 0x403fd210,4);
627         InterlockedIncrement(c1+4);
628
629         HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
630         HeapAlloc(40350000,00000000,00000050) retval=403feb44;
631         hmod1 = GetModuleHandleA("URLMON.DLL");
632         proc = GetProcAddress(hmod1, "RegisterFormatEnumerator");
633         /* 0x1a40c88c is in URLMON.DLL just before above proc
634          * content is L"_EnumFORMATETC_"
635          * label is d1
636          */
637         IsBadReadPtr(d1 = 0x1a40c88c,00000002);
638         lstrlenW(d1);
639         lstrlenW(d1);
640         HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
641         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
642         InterlockedIncrement(d2+4);
643         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
644         InterlockedDecrement(d2+4);
645         IsBadReadPtr(c1,00000004);
646         InterlockedDecrement(c1+4);
647         IsBadReadPtr(c1,00000004);
648         InterlockedDecrement(c1+4);
649
650 #endif
651 }
652
653 /*************************************************************************
654  *      @       [SHLWAPI.14]
655  *
656  * Get Explorers "AcceptLanguage" setting.
657  *
658  * PARAMS
659  *  langbuf [O] Destination for language string
660  *  buflen  [I] Length of langbuf
661  *
662  * RETURNS
663  *  Success: S_OK.   langbuf is set to the language string found.
664  *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
665  *           does not contain the setting.
666  */
667 HRESULT WINAPI SHLWAPI_14 (
668         LPSTR langbuf,
669         LPDWORD buflen)
670 {
671         CHAR *mystr;
672         DWORD mystrlen, mytype;
673         HKEY mykey;
674         LCID mylcid;
675
676         mystrlen = (*buflen > 6) ? *buflen : 6;
677         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
678                                  HEAP_ZERO_MEMORY, mystrlen);
679         RegOpenKeyA(HKEY_CURRENT_USER,
680                     "Software\\Microsoft\\Internet Explorer\\International",
681                     &mykey);
682         if (RegQueryValueExA(mykey, "AcceptLanguage",
683                               0, &mytype, mystr, &mystrlen)) {
684             /* Did not find value */
685             mylcid = GetUserDefaultLCID();
686             /* somehow the mylcid translates into "en-us"
687              *  this is similar to "LOCALE_SABBREVLANGNAME"
688              *  which could be gotten via GetLocaleInfo.
689              *  The only problem is LOCALE_SABBREVLANGUAGE" is
690              *  a 3 char string (first 2 are country code and third is
691              *  letter for "sublanguage", which does not come close to
692              *  "en-us"
693              */
694             lstrcpyA(mystr, "en-us");
695             mystrlen = lstrlenA(mystr);
696         }
697         else {
698             /* handle returned string */
699             FIXME("missing code\n");
700         }
701         if (mystrlen > *buflen)
702             lstrcpynA(langbuf, mystr, *buflen);
703         else {
704             lstrcpyA(langbuf, mystr);
705             *buflen = lstrlenA(langbuf);
706         }
707         RegCloseKey(mykey);
708         HeapFree(GetProcessHeap(), 0, mystr);
709         TRACE("language is %s\n", debugstr_a(langbuf));
710         return 0;
711 }
712
713 /*************************************************************************
714  *      @       [SHLWAPI.15]
715  *
716  * Unicode version of SHLWAPI_14.
717  */
718 HRESULT WINAPI SHLWAPI_15 (
719         LPWSTR langbuf,
720         LPDWORD buflen)
721 {
722         CHAR *mystr;
723         DWORD mystrlen, mytype;
724         HKEY mykey;
725         LCID mylcid;
726
727         mystrlen = (*buflen > 6) ? *buflen : 6;
728         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
729                                  HEAP_ZERO_MEMORY, mystrlen);
730         RegOpenKeyA(HKEY_CURRENT_USER,
731                     "Software\\Microsoft\\Internet Explorer\\International",
732                     &mykey);
733         if (RegQueryValueExA(mykey, "AcceptLanguage",
734                               0, &mytype, mystr, &mystrlen)) {
735             /* Did not find value */
736             mylcid = GetUserDefaultLCID();
737             /* somehow the mylcid translates into "en-us"
738              *  this is similar to "LOCALE_SABBREVLANGNAME"
739              *  which could be gotten via GetLocaleInfo.
740              *  The only problem is LOCALE_SABBREVLANGUAGE" is
741              *  a 3 char string (first 2 are country code and third is
742              *  letter for "sublanguage", which does not come close to
743              *  "en-us"
744              */
745             lstrcpyA(mystr, "en-us");
746             mystrlen = lstrlenA(mystr);
747         }
748         else {
749             /* handle returned string */
750             FIXME("missing code\n");
751         }
752         RegCloseKey(mykey);
753         *buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
754         HeapFree(GetProcessHeap(), 0, mystr);
755         TRACE("language is %s\n", debugstr_w(langbuf));
756         return 0;
757 }
758
759 /*************************************************************************
760  *      @       [SHLWAPI.23]
761  *
762  * NOTES
763  *      converts a guid to a string
764  *      returns strlen(str)
765  */
766 DWORD WINAPI SHLWAPI_23 (
767         REFGUID guid,   /* [in]  clsid */
768         LPSTR str,      /* [out] buffer */
769         INT cmax)       /* [in]  size of buffer */
770 {
771         char xguid[40];
772
773         sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
774                  guid->Data1, guid->Data2, guid->Data3,
775                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
776                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
777         TRACE("(%s %p 0x%08x)stub\n", xguid, str, cmax);
778         if (strlen(xguid)>=cmax) return 0;
779         strcpy(str,xguid);
780         return strlen(xguid) + 1;
781 }
782
783 /*************************************************************************
784  *      @       [SHLWAPI.24]
785  *
786  * NOTES
787  *      converts a guid to a string
788  *      returns strlen(str)
789  */
790 DWORD WINAPI SHLWAPI_24 (
791         REFGUID guid,   /* [in]  clsid */
792         LPWSTR str,     /* [out] buffer */
793         INT cmax)       /* [in]  size of buffer */
794 {
795     char xguid[40];
796
797     sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
798              guid->Data1, guid->Data2, guid->Data3,
799              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
800              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
801     return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
802 }
803
804 /*************************************************************************
805  *      @       [SHLWAPI.25]
806  *
807  * Seems to be iswalpha
808  */
809 BOOL WINAPI SHLWAPI_25(WCHAR wc)
810 {
811     return (get_char_typeW(wc) & C1_ALPHA) != 0;
812 }
813
814 /*************************************************************************
815  *      @       [SHLWAPI.26]
816  *
817  * Seems to be iswupper
818  */
819 BOOL WINAPI SHLWAPI_26(WCHAR wc)
820 {
821     return (get_char_typeW(wc) & C1_UPPER) != 0;
822 }
823
824 /*************************************************************************
825  *      @       [SHLWAPI.27]
826  *
827  * Seems to be iswlower
828  */
829 BOOL WINAPI SHLWAPI_27(WCHAR wc)
830 {
831     return (get_char_typeW(wc) & C1_LOWER) != 0;
832 }
833
834 /*************************************************************************
835  *      @       [SHLWAPI.28]
836  *
837  * Seems to be iswalnum
838  */
839 BOOL WINAPI SHLWAPI_28(WCHAR wc)
840 {
841     return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
842 }
843
844 /*************************************************************************
845  *      @       [SHLWAPI.29]
846  *
847  * Seems to be iswspace
848  */
849 BOOL WINAPI SHLWAPI_29(WCHAR wc)
850 {
851     return (get_char_typeW(wc) & C1_SPACE) != 0;
852 }
853
854 /*************************************************************************
855  *      @       [SHLWAPI.30]
856  *
857  * Seems to be iswblank
858  */
859 BOOL WINAPI SHLWAPI_30(WCHAR wc)
860 {
861     return (get_char_typeW(wc) & C1_BLANK) != 0;
862 }
863
864 /*************************************************************************
865  *      @       [SHLWAPI.31]
866  *
867  * Seems to be iswpunct
868  */
869 BOOL WINAPI SHLWAPI_31(WCHAR wc)
870 {
871     return (get_char_typeW(wc) & C1_PUNCT) != 0;
872 }
873
874 /*************************************************************************
875  *      @       [SHLWAPI.32]
876  *
877  * Seems to be iswcntrl
878  */
879 BOOL WINAPI SHLWAPI_32(WCHAR wc)
880 {
881     return (get_char_typeW(wc) & C1_CNTRL) != 0;
882 }
883
884 /*************************************************************************
885  *      @       [SHLWAPI.33]
886  *
887  * Seems to be iswdigit
888  */
889 BOOL WINAPI SHLWAPI_33(WCHAR wc)
890 {
891     return (get_char_typeW(wc) & C1_DIGIT) != 0;
892 }
893
894 /*************************************************************************
895  *      @       [SHLWAPI.34]
896  *
897  * Seems to be iswxdigit
898  */
899 BOOL WINAPI SHLWAPI_34(WCHAR wc)
900 {
901     return (get_char_typeW(wc) & C1_XDIGIT) != 0;
902 }
903
904 /*************************************************************************
905  *      @       [SHLWAPI.35]
906  *
907  */
908 BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
909 {
910     FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
911     return TRUE;
912 }
913
914 /*************************************************************************
915  *      @       [SHLWAPI.36]
916  *
917  * Insert a bitmap menu item at the bottom of a menu.
918  *
919  * PARAMS
920  *  hMenu [I] Menu to insert into
921  *  flags [I] Flags for insertion
922  *  id    [I] Menu ID of the item
923  *  str   [I] Menu text for the item
924  *
925  * RETURNS
926  *  Success: TRUE,  the item is inserted into the menu
927  *  Failure: FALSE, if any parameter is invalid
928  */
929 BOOL WINAPI SHLWAPI_36(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
930 {
931     TRACE("(0x%08x,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
932     return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
933 }
934
935 /*************************************************************************
936  *      @       [SHLWAPI.74]
937  *
938  * Get the text from a given dialog item.
939  *
940  * PARAMS
941  *  hWnd     [I] Handle of dialog
942  *  nItem    [I] Index of item
943  *  lpsDest  [O] Buffer for receiving window text
944  *  nDestLen [I] Length of buffer.
945  *
946  * RETURNS
947  *  Success: The length of the returned text.
948  *  Failure: 0.
949  */
950 INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
951 {
952   HWND hItem = GetDlgItem(hWnd, nItem);
953
954   if (hItem)
955     return GetWindowTextW(hItem, lpsDest, nDestLen);
956   if (nDestLen)
957     *lpsDest = (WCHAR)'\0';
958   return 0;
959 }
960
961 /*************************************************************************
962  *      @   [SHLWAPI.138]
963  *
964  * Set the text of a given dialog item.
965  *
966  * PARAMS
967  *  hWnd     [I] Handle of dialog
968  *  iItem    [I] Index of item
969  *  lpszText [O] Text to set
970  *
971  * RETURNS
972  *  Success: TRUE.  The text of the dialog is set to lpszText.
973  *  Failure: FALSE, Otherwise.
974  */
975 BOOL WINAPI SHLWAPI_138(HWND hWnd, INT iItem, LPCWSTR lpszText)
976 {
977     HWND hWndItem = GetDlgItem(hWnd, iItem);
978     if (hWndItem)
979         return SetWindowTextW(hWndItem, lpszText);
980     return FALSE;
981 }
982
983 /*************************************************************************
984  *      @       [SHLWAPI.151]
985  * Function:  Compare two ASCII strings for "len" bytes.
986  * Returns:   *str1-*str2  (case sensitive)
987  */
988 DWORD WINAPI SHLWAPI_151(LPCSTR str1, LPCSTR str2, INT len)
989 {
990     return strncmp( str1, str2, len );
991 }
992
993 /*************************************************************************
994  *      @       [SHLWAPI.152]
995  *
996  * Function:  Compare two WIDE strings for "len" bytes.
997  * Returns:   *str1-*str2  (case sensitive)
998  */
999 DWORD WINAPI SHLWAPI_152(LPCWSTR str1, LPCWSTR str2, INT len)
1000 {
1001     return strncmpW( str1, str2, len );
1002 }
1003
1004 /*************************************************************************
1005  *      @       [SHLWAPI.153]
1006  * Function:  Compare two ASCII strings for "len" bytes via caseless compare.
1007  * Returns:   *str1-*str2  (case insensitive)
1008  */
1009 DWORD WINAPI SHLWAPI_153(LPCSTR str1, LPCSTR str2, DWORD len)
1010 {
1011     return strncasecmp( str1, str2, len );
1012 }
1013
1014 /*************************************************************************
1015  *      @       [SHLWAPI.154]
1016  *
1017  * Function:  Compare two WIDE strings for "len" bytes via caseless compare.
1018  * Returns:   *str1-*str2  (case insensitive)
1019  */
1020 DWORD WINAPI SHLWAPI_154(LPCWSTR str1, LPCWSTR str2, DWORD len)
1021 {
1022     return strncmpiW( str1, str2, len );
1023 }
1024
1025 /*************************************************************************
1026  *      @       [SHLWAPI.155]
1027  *
1028  *      Case sensitive string compare (ASCII). Does not SetLastError().
1029  */
1030 DWORD WINAPI SHLWAPI_155(LPCSTR str1, LPCSTR str2)
1031 {
1032     return strcmp(str1, str2);
1033 }
1034
1035 /*************************************************************************
1036  *      @       [SHLWAPI.156]
1037  *
1038  *      Case sensitive string compare. Does not SetLastError().
1039  */
1040 DWORD WINAPI SHLWAPI_156(LPCWSTR str1, LPCWSTR str2)
1041 {
1042     return strcmpW( str1, str2 );
1043 }
1044
1045 /*************************************************************************
1046  *      @       [SHLWAPI.157]
1047  *
1048  *      Case insensitive string compare (ASCII). Does not SetLastError().
1049  */
1050 DWORD WINAPI SHLWAPI_157(LPCSTR str1, LPCSTR str2)
1051 {
1052     return strcasecmp(str1, str2);
1053 }
1054 /*************************************************************************
1055  *      @       [SHLWAPI.158]
1056  *
1057  *      Case insensitive string compare. Does not SetLastError(). ??
1058  */
1059 DWORD WINAPI SHLWAPI_158 (LPCWSTR str1, LPCWSTR str2)
1060 {
1061     return strcmpiW( str1, str2 );
1062 }
1063
1064 /*************************************************************************
1065  *      @       [SHLWAPI.162]
1066  *
1067  * Remove a hanging lead byte from the end of a string, if present.
1068  *
1069  * PARAMS
1070  *  lpStr [I] String to check for a hanging lead byte
1071  *  size  [I] Length of lpszStr
1072  *
1073  * RETURNS
1074  *  Success: The new size of the string. Any hanging lead bytes are removed.
1075  *  Failure: 0, if any parameters are invalid.
1076  */
1077 DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
1078 {
1079   if (lpStr && size)
1080   {
1081     LPSTR lastByte = lpStr + size - 1;
1082
1083     while(lpStr < lastByte)
1084       lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
1085
1086     if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
1087     {
1088       *lpStr = '\0';
1089       size--;
1090     }
1091     return size;
1092   }
1093   return 0;
1094 }
1095
1096 /*************************************************************************
1097  *      @       [SHLWAPI.163]
1098  *
1099  * Call IOleCommandTarget::QueryStatus() on an object.
1100  *
1101  * PARAMS
1102  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
1103  *  pguidCmdGroup [I] GUID for the command group
1104  *  cCmds         [I]
1105  *  prgCmds       [O] Commands
1106  *  pCmdText      [O] Command text
1107  *
1108  * RETURNS
1109  *  Success: S_OK.
1110  *  Failure: E_FAIL, if lpUnknown is NULL.
1111  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1112  *           Otherwise, an error code from IOleCommandTarget::QueryStatus().
1113  */
1114 HRESULT WINAPI SHLWAPI_163(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1115                            ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1116 {
1117   HRESULT hRet = E_FAIL;
1118
1119   TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1120
1121   if (lpUnknown)
1122   {
1123     IOleCommandTarget* lpOle;
1124
1125     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1126                                    (void**)&lpOle);
1127
1128     if (SUCCEEDED(hRet) && lpOle)
1129     {
1130       hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1131                                            prgCmds, pCmdText);
1132       IOleCommandTarget_Release(lpOle);
1133     }
1134   }
1135   return hRet;
1136 }
1137
1138 /*************************************************************************
1139  *      @               [SHLWAPI.164]
1140  *
1141  * Call IOleCommandTarget::Exec() on an object.
1142  *
1143  * PARAMS
1144  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
1145  *  pguidCmdGroup [I] GUID for the command group
1146  *
1147  * RETURNS
1148  *  Success: S_OK.
1149  *  Failure: E_FAIL, if lpUnknown is NULL.
1150  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1151  *           Otherwise, an error code from IOleCommandTarget::Exec().
1152  */
1153 HRESULT WINAPI SHLWAPI_164(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1154                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1155                            VARIANT* pvaOut)
1156 {
1157   HRESULT hRet = E_FAIL;
1158
1159   TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1160         nCmdexecopt, pvaIn, pvaOut);
1161
1162   if (lpUnknown)
1163   {
1164     IOleCommandTarget* lpOle;
1165
1166     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1167                                    (void**)&lpOle);
1168     if (SUCCEEDED(hRet) && lpOle)
1169     {
1170       hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1171                                     nCmdexecopt, pvaIn, pvaOut);
1172       IOleCommandTarget_Release(lpOle);
1173     }
1174   }
1175   return hRet;
1176 }
1177
1178 /*************************************************************************
1179  *      @       [SHLWAPI.165]
1180  *
1181  * Retrieve, modify, and re-set a value from a window.
1182  *
1183  * PARAMS
1184  *  hWnd   [I] Windows to get value from
1185  *  offset [I] Offset of value
1186  *  wMask  [I] Mask for uiFlags
1187  *  wFlags [I] Bits to set in window value
1188  *
1189  * RETURNS
1190  *  The new value as it was set, or 0 if any parameter is invalid.
1191  *
1192  * NOTES
1193  *  Any bits set in uiMask are cleared from the value, then any bits set in
1194  *  uiFlags are set in the value.
1195  */
1196 LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1197 {
1198   LONG ret = GetWindowLongA(hwnd, offset);
1199   UINT newFlags = (wFlags & wMask) | (ret & ~wFlags);
1200
1201   if (newFlags != ret)
1202     ret = SetWindowLongA(hwnd, offset, newFlags);
1203   return ret;
1204 }
1205
1206 /*************************************************************************
1207  *      @       [SHLWAPI.167]
1208  *
1209  * Change a windows parent.
1210  *
1211  * PARAMS
1212  *  hWnd       [I] Window to change parent of
1213  *  hWndParent [I] New parent window
1214  *
1215  * RETURNS
1216  *  Nothing.
1217  *
1218  * NOTES
1219  *  If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1220  */
1221 DWORD WINAPI SHLWAPI_167(HWND hWnd, HWND hWndParent)
1222 {
1223         FIXME("0x%08x,0x%08x\n", hWnd, hWndParent);
1224         return 0;
1225 }
1226
1227 /*************************************************************************
1228  *      @       [SHLWAPI.168]
1229  *
1230  * Locate and advise a connection point in an IConnectionPointContainer.
1231  *
1232  * PARAMS
1233  *  lpUnkSink   [I] Sink for the connection point advise call
1234  *  riid        [I] REFIID of connection point to advise
1235  *  bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1236  *  lpUnknown   [I] Object supporting the IConnectionPointContainer interface
1237  *  lpCookie    [O] Pointer to connection point cookie
1238  *  lppCP       [O] Destination for the IConnectionPoint found
1239  *
1240  * RETURNS
1241  *  Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1242  *           that was advised. The caller is responsable for releasing it.
1243  *  Failure: E_FAIL, if any arguments are invalid.
1244  *           E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1245  *           Or an HRESULT error code if any call fails.
1246  */
1247 HRESULT WINAPI SHLWAPI_168(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1248                            IUnknown* lpUnknown, LPDWORD lpCookie,
1249                            IConnectionPoint **lppCP)
1250 {
1251   HRESULT hRet;
1252   IConnectionPointContainer* lpContainer;
1253   IConnectionPoint *lpCP;
1254
1255   if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1256     return E_FAIL;
1257
1258   if(lppCP)
1259     *lppCP = NULL;
1260
1261   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1262                                  (void**)&lpContainer);
1263   if (SUCCEEDED(hRet))
1264   {
1265     hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1266
1267     if (SUCCEEDED(hRet))
1268     {
1269       if(!bAdviseOnly)
1270         hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1271       hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1272
1273       if (FAILED(hRet))
1274         *lpCookie = 0;
1275
1276       if (lppCP && SUCCEEDED(hRet))
1277         *lppCP = lpCP; /* Caller keeps the interface */
1278       else
1279         IConnectionPoint_Release(lpCP); /* Release it */
1280     }
1281
1282     IUnknown_Release(lpContainer);
1283   }
1284   return hRet;
1285 }
1286
1287 /*************************************************************************
1288  *      @       [SHLWAPI.169]
1289  *
1290  *
1291  * Release an interface.
1292  *
1293  * PARAMS
1294  *  lpUnknown [I] Object to release
1295  *
1296  * RETURNS
1297  *  Nothing.
1298  */
1299 DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
1300 {
1301         IUnknown *temp;
1302
1303         TRACE("(%p)\n",lpUnknown);
1304         if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1305         temp = *lpUnknown;
1306         *lpUnknown = NULL;
1307         TRACE("doing Release\n");
1308         return IUnknown_Release(temp);
1309 }
1310
1311 /*************************************************************************
1312  *      @       [SHLWAPI.170]
1313  *
1314  * Skip '//' if present in a string.
1315  *
1316  * PARAMS
1317  *  lpszSrc [I] String to check for '//'
1318  *
1319  * RETURNS
1320  *  Success: The next character after the '//' or the string if not present
1321  *  Failure: NULL, if lpszStr is NULL.
1322  */
1323 LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
1324 {
1325   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1326     lpszSrc += 2;
1327   return lpszSrc;
1328 }
1329
1330 /*************************************************************************
1331  *      @               [SHLWAPI.171]
1332  *
1333  * _SHIsSameObject
1334  */
1335 BOOL WINAPI SHLWAPI_171(LPVOID x, LPVOID y)
1336 {
1337         FIXME("%p %p\n",x,y);
1338         return 0;
1339 }
1340
1341 /*************************************************************************
1342  *      @       [SHLWAPI.172]
1343  *
1344  * Get the window handle of an object.
1345  *
1346  * PARAMS
1347  *  lpUnknown [I] Object to get the window handle of
1348  *  lphWnd    [O] Destination for window handle
1349  *
1350  * RETURNS
1351  *  Success: S_OK. lphWnd contains the objects window handle.
1352  *  Failure: An HRESULT error code.
1353  *
1354  * NOTES
1355  *  lpUnknown is expected to support one of the following interfaces:
1356  *   IOleWindow
1357  *   IInternetSecurityMgrSite
1358  *   IShellView
1359  */
1360 HRESULT WINAPI SHLWAPI_172(IUnknown *lpUnknown, LPHWND lphWnd)
1361 {
1362   /* FIXME: Wine has no header for this object */
1363   static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1364     0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1365   IUnknown *lpOle;
1366   HRESULT hRet = E_FAIL;
1367
1368   TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1369
1370   if (!lpUnknown)
1371     return hRet;
1372
1373   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1374
1375   if (FAILED(hRet))
1376   {
1377     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1378
1379     if (FAILED(hRet))
1380     {
1381       hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1382                                       (void**)&lpOle);
1383     }
1384   }
1385
1386   if (SUCCEEDED(hRet))
1387   {
1388     /* Lazyness here - Since GetWindow() is the first method for the above 3
1389      * interfaces, we use the same call for them all.
1390      */
1391     hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1392     IUnknown_Release(lpOle);
1393     if (lphWnd)
1394       TRACE("Returning HWND=%08x\n", *lphWnd);
1395   }
1396
1397   return hRet;
1398 }
1399
1400 /*************************************************************************
1401  *      @       [SHLWAPI.174]
1402  *
1403  * Seems to do call either IObjectWithSite::SetSite or
1404  *   IPersistMoniker::GetClassID.  But since we do not implement either
1405  *   of those classes in our headers, we will fake it out.
1406  */
1407 DWORD WINAPI SHLWAPI_174(
1408         IUnknown *p1,     /* [in]   OLE object                          */
1409         LPVOID *p2)       /* [out]  ptr to result of either GetClassID
1410                                     or SetSite call.                    */
1411 {
1412     DWORD ret, aa;
1413
1414     if (!p1) return E_FAIL;
1415
1416     /* see if SetSite interface exists for IObjectWithSite object */
1417     ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1418     TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1419     if (ret) {
1420
1421         /* see if GetClassId interface exists for IPersistMoniker object */
1422         ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1423         TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1424         if (ret) return ret;
1425
1426         /* fake a GetClassId call */
1427         ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1428         TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1429               *(LPDWORD)p2);
1430         IUnknown_Release((IUnknown *)aa);
1431     }
1432     else {
1433         /* fake a SetSite call */
1434         ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1435         TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1436               *(LPDWORD)p2);
1437         IUnknown_Release((IUnknown *)p1);
1438     }
1439     return ret;
1440 }
1441
1442 /*************************************************************************
1443  *      @       [SHLWAPI.175]
1444  *
1445  * Call IPersist::GetClassID on an object.
1446  *
1447  * PARAMS
1448  *  lpUnknown [I] Object supporting the IPersist interface
1449  *  lpClassId [O] Destination for Class Id
1450  *
1451  * RETURNS
1452  *  Success: S_OK. lpClassId contains the Class Id requested.
1453  *  Failure: E_FAIL, If lpUnknown is NULL,
1454  *           E_NOINTERFACE If lpUnknown does not support IPersist,
1455  *           Or an HRESULT error code.
1456  */
1457 HRESULT WINAPI SHLWAPI_175 (IUnknown *lpUnknown, CLSID* lpClassId)
1458 {
1459   IPersist* lpPersist;
1460   HRESULT hRet = E_FAIL;
1461
1462   TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1463
1464   if (lpUnknown)
1465   {
1466     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1467     if (SUCCEEDED(hRet))
1468     {
1469       IPersist_GetClassID(lpPersist, lpClassId);
1470       IPersist_Release(lpPersist);
1471     }
1472   }
1473   return hRet;
1474 }
1475
1476 /*************************************************************************
1477  *      @       [SHLWAPI.176]
1478  *
1479  * Retrieve a Service Interface from an object.
1480  *
1481  * PARAMS
1482  *  lpUnknown [I] Object to get an IServiceProvider interface from
1483  *  sid       [I] Service ID for QueryService call
1484  *  riid      [I] Function requested for QueryService call
1485  *  lppOut    [O] Destination for the service interface pointer
1486  *
1487  * Function appears to be interface to IServiceProvider::QueryService
1488  *
1489  * RETURNS
1490  *  Success: S_OK. lppOut contains an object providing the requested service
1491  *  Failure: An HRESULT error code
1492  *
1493  * NOTES
1494  *  lpUnknown is expected to support the IServiceProvider interface.
1495  */
1496 HRESULT WINAPI SHLWAPI_176(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1497                            LPVOID *lppOut)
1498 {
1499   IServiceProvider* pService = NULL;
1500   HRESULT hRet;
1501
1502   if (!lppOut)
1503     return E_FAIL;
1504
1505   *lppOut = NULL;
1506
1507   if (!lpUnknown)
1508     return E_FAIL;
1509
1510   /* Get an IServiceProvider interface from the object */
1511   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1512                                  (LPVOID*)&pService);
1513
1514   if (!hRet && pService)
1515   {
1516     TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1517
1518     /* Get a Service interface from the object */
1519     hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1520
1521     TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1522
1523     /* Release the IServiceProvider interface */
1524     IUnknown_Release(pService);
1525   }
1526   return hRet;
1527 }
1528
1529 /*************************************************************************
1530  *      @       [SHLWAPI.180]
1531  *
1532  * Remove all sub-menus from a menu.
1533  *
1534  * PARAMS
1535  *  hMenu [I] Menu to remove sub-menus from
1536  *
1537  * RETURNS
1538  *  Success: 0.  All sub-menus under hMenu are removed
1539  *  Failure: -1, if any parameter is invalid
1540  */
1541 DWORD WINAPI SHLWAPI_180(HMENU hMenu)
1542 {
1543   int iItemCount = GetMenuItemCount(hMenu) - 1;
1544   while (iItemCount >= 0)
1545   {
1546     HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1547     if (hSubMenu)
1548       RemoveMenu(hMenu, iItemCount, 0x400);
1549     iItemCount--;
1550   }
1551   return iItemCount;
1552 }
1553
1554 /*************************************************************************
1555  *      @       [SHLWAPI.181]
1556  *
1557  * Enable or disable a menu item.
1558  *
1559  * PARAMS
1560  *  hMenu   [I] Menu holding menu item
1561  *  uID     [I] ID of menu item to enable/disable
1562  *  bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1563  *
1564  * RETURNS
1565  *  The return code from CheckMenuItem.
1566  */
1567 UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
1568 {
1569   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1570 }
1571
1572 /*************************************************************************
1573  * @    [SHLWAPI.182]
1574  *
1575  * Check or uncheck a menu item.
1576  *
1577  * PARAMS
1578  *  hMenu  [I] Menu holding menu item
1579  *  uID    [I] ID of menu item to check/uncheck
1580  *  bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1581  *
1582  * RETURNS
1583  *  The return code from CheckMenuItem.
1584  */
1585 DWORD WINAPI SHLWAPI_182(HMENU hMenu, UINT uID, BOOL bCheck)
1586 {
1587   return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : 0);
1588 }
1589
1590 /*************************************************************************
1591  *      @       [SHLWAPI.183]
1592  *
1593  * Register a window class if it isn't already.
1594  *
1595  * PARAMS
1596  *  lpWndClass [I] Window class to register
1597  *
1598  * RETURNS
1599  *  The result of the RegisterClassA call.
1600  */
1601 DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
1602 {
1603   WNDCLASSA wca;
1604   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1605     return TRUE;
1606   return (DWORD)RegisterClassA(wndclass);
1607 }
1608
1609 /*************************************************************************
1610  *      @       [SHLWAPI.187]
1611  *
1612  * Call IPersistPropertyBag::Load on an object.
1613  *
1614  * PARAMS
1615  *  lpUnknown [I] Object supporting the IPersistPropertyBag interface
1616  *  lpPropBag [O] Destination for loaded IPropertyBag
1617  *
1618  * RETURNS
1619  *  Success: S_OK.
1620  *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1621  */
1622 DWORD WINAPI SHLWAPI_187(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1623 {
1624   IPersistPropertyBag* lpPPBag;
1625   HRESULT hRet = E_FAIL;
1626
1627   TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1628
1629   if (lpUnknown)
1630   {
1631     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1632                                    (void**)&lpPPBag);
1633     if (SUCCEEDED(hRet) && lpPPBag)
1634     {
1635       hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1636       IPersistPropertyBag_Release(lpPPBag);
1637     }
1638   }
1639   return hRet;
1640 }
1641
1642 /*************************************************************************
1643  *      @       [SHLWAPI.189]
1644  *
1645  * _IUnknown_OnFocusOCS
1646  */
1647 DWORD WINAPI SHLWAPI_189(LPVOID x, LPVOID y)
1648 {
1649         FIXME("%p %p\n", x, y);
1650         return 0;
1651 }
1652
1653 /*************************************************************************
1654  *      @       [SHLWAPI.193]
1655  *
1656  * Get the color depth of the primary display.
1657  *
1658  * PARAMS
1659  *  None.
1660  *
1661  * RETURNS
1662  *  The color depth of the primary display.
1663  */
1664 DWORD WINAPI SHLWAPI_193 ()
1665 {
1666         HDC hdc;
1667         DWORD ret;
1668
1669         TRACE("()\n");
1670
1671         hdc = GetDC(0);
1672         ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1673         ReleaseDC(0, hdc);
1674         return ret;
1675 }
1676
1677 /*************************************************************************
1678  *      @       [SHLWAPI.197]
1679  *
1680  * Blank out a region of text by drawing the background only.
1681  *
1682  * PARAMS
1683  *  hDC   [I] Device context to draw in
1684  *  pRect [I] Area to draw in
1685  *  cRef  [I] Color to draw in
1686  *
1687  * RETURNS
1688  *  Nothing.
1689  */
1690 DWORD WINAPI SHLWAPI_197(HDC hDC, LPCRECT pRect, COLORREF cRef)
1691 {
1692     COLORREF cOldColor = SetBkColor(hDC, cRef);
1693     ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
1694     SetBkColor(hDC, cOldColor);
1695     return 0;
1696 }
1697
1698 /*************************************************************************
1699  *      @       [SHLWAPI.199]
1700  *
1701  * Copy interface pointer
1702  *
1703  * PARAMS
1704  *   lppDest   [O] Destination for copy
1705  *   lpUnknown [I] Source for copy
1706  *
1707  * RETURNS
1708  *  Nothing.
1709  */
1710 VOID WINAPI SHLWAPI_199(IUnknown **lppDest, IUnknown *lpUnknown)
1711 {
1712   TRACE("(%p,%p)\n", lppDest, lpUnknown);
1713
1714   if (lppDest)
1715     SHLWAPI_169(lppDest); /* Release existing interface */
1716
1717   if (lpUnknown)
1718   {
1719     /* Copy */
1720     IUnknown_AddRef(lpUnknown);
1721     *lppDest = lpUnknown;
1722   }
1723 }
1724
1725 /*************************************************************************
1726  *      @       [SHLWAPI.201]
1727  *
1728  */
1729 HRESULT WINAPI SHLWAPI_201(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
1730                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1731                            VARIANT* pvaOut)
1732 {
1733   FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
1734         nCmdID, nCmdexecopt, pvaIn, pvaOut);
1735   return DRAGDROP_E_NOTREGISTERED;
1736 }
1737
1738 /*************************************************************************
1739  *      @       [SHLWAPI.202]
1740  *
1741  */
1742 HRESULT WINAPI SHLWAPI_202(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
1743 {
1744   FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
1745   return DRAGDROP_E_NOTREGISTERED;
1746 }
1747
1748 /*************************************************************************
1749  *      @       [SHLWAPI.203]
1750  *
1751  */
1752 VOID WINAPI SHLWAPI_203(LPCSTR lpszStr)
1753 {
1754   FIXME("(%s) - stub!\n", debugstr_a(lpszStr));
1755 }
1756
1757 /*************************************************************************
1758  * @    [SHLWAPI.204]
1759  *
1760  * Determine if a window is not a child of another window.
1761  *
1762  * PARAMS
1763  * hParent [I] Suspected parent window
1764  * hChild  [I] Suspected child window
1765  *
1766  * RETURNS
1767  * TRUE:  If hChild is a child window of hParent
1768  * FALSE: If hChild is not a child window of hParent, or they are equal
1769  */
1770 BOOL WINAPI SHLWAPI_204(HWND hParent, HWND hChild)
1771 {
1772   TRACE("(%08x,%08x)\n", hParent, hChild);
1773
1774   if (!hParent || !hChild)
1775     return TRUE;
1776   else if(hParent == hChild)
1777     return FALSE;
1778   return !IsChild(hParent, hChild);
1779 }
1780
1781 /*************************************************************************
1782  *      @       [SHLWAPI.208]
1783  *
1784  * Some sort of memory management process - associated with _210
1785  */
1786 DWORD WINAPI SHLWAPI_208 (
1787         DWORD    a,
1788         DWORD    b,
1789         LPVOID   c,
1790         LPVOID   d,
1791         DWORD    e)
1792 {
1793     FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
1794           a, b, c, d, e);
1795     return 1;
1796 }
1797
1798 /*************************************************************************
1799  *      @       [SHLWAPI.209]
1800  *
1801  * Some sort of memory management process - associated with _208
1802  */
1803 DWORD WINAPI SHLWAPI_209 (
1804         LPVOID   a)
1805 {
1806     FIXME("(%p) stub\n",
1807           a);
1808     return 1;
1809 }
1810
1811 /*************************************************************************
1812  *      @       [SHLWAPI.210]
1813  *
1814  * Some sort of memory management process - associated with _208
1815  */
1816 DWORD WINAPI SHLWAPI_210 (
1817         LPVOID   a,
1818         DWORD    b,
1819         LPVOID   c)
1820 {
1821     FIXME("(%p 0x%08lx %p) stub\n",
1822           a, b, c);
1823     return 0;
1824 }
1825
1826 /*************************************************************************
1827  *      @       [SHLWAPI.211]
1828  */
1829 DWORD WINAPI SHLWAPI_211 (
1830         LPVOID   a,
1831         DWORD    b)
1832 {
1833     FIXME("(%p 0x%08lx) stub\n",
1834           a, b);
1835     return 1;
1836 }
1837
1838 /*************************************************************************
1839  *      @       [SHLWAPI.215]
1840  *
1841  * NOTES
1842  *  check me!
1843  */
1844 DWORD WINAPI SHLWAPI_215 (
1845         LPCSTR lpStrSrc,
1846         LPWSTR lpwStrDest,
1847         int len)
1848 {
1849         INT len_a, ret;
1850
1851         len_a = lstrlenA(lpStrSrc);
1852         ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
1853         TRACE("%s %s %d, ret=%d\n",
1854               debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
1855         return ret;
1856 }
1857
1858 /*************************************************************************
1859  *      @       [SHLWAPI.218]
1860  *
1861  * WideCharToMultiByte with multi language support.
1862  */
1863 INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
1864                        LPINT lpnMultiCharCount)
1865 {
1866   WCHAR emptyW[] = { '\0' };
1867   int len , reqLen;
1868   LPSTR mem;
1869
1870   if (!lpDstStr || !lpnMultiCharCount)
1871     return 0;
1872
1873   if (!lpSrcStr)
1874     lpSrcStr = emptyW;
1875
1876   *lpDstStr = '\0';
1877
1878   len = strlenW(lpSrcStr) + 1;
1879
1880   switch (CodePage)
1881   {
1882   case CP_WINUNICODE:
1883     CodePage = CP_UTF8; /* Fall through... */
1884   case 0x0000C350: /* FIXME: CP_ #define */
1885   case CP_UTF7:
1886   case CP_UTF8:
1887     {
1888       DWORD dwMode = 0;
1889       INT nWideCharCount = len - 1;
1890
1891       GET_FUNC(pConvertINetUnicodeToMultiByte, mlang, "ConvertINetUnicodeToMultiByte", 0);
1892       if (!pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
1893                                           lpnMultiCharCount))
1894         return 0;
1895
1896       if (nWideCharCount < len - 1)
1897       {
1898         mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
1899         if (!mem)
1900           return 0;
1901
1902         *lpnMultiCharCount = 0;
1903
1904         if (pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
1905         {
1906           SHLWAPI_162 (mem, *lpnMultiCharCount);
1907           lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
1908           return *lpnMultiCharCount + 1;
1909         }
1910         HeapFree(GetProcessHeap(), 0, mem);
1911         return *lpnMultiCharCount;
1912       }
1913       lpDstStr[*lpnMultiCharCount] = '\0';
1914       return *lpnMultiCharCount;
1915     }
1916     break;
1917   default:
1918     break;
1919   }
1920
1921   reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
1922                                *lpnMultiCharCount, NULL, NULL);
1923
1924   if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1925   {
1926     reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
1927     if (reqLen)
1928     {
1929       mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
1930       if (mem)
1931       {
1932         reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
1933                                      reqLen, NULL, NULL);
1934
1935         reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
1936         reqLen++;
1937
1938         lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
1939
1940         HeapFree(GetProcessHeap(), 0, mem);
1941       }
1942     }
1943   }
1944   return reqLen;
1945 }
1946
1947 /*************************************************************************
1948  *      @       [SHLWAPI.217]
1949  *
1950  * Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
1951  * --> Crash. Something wrong here.
1952  *
1953  * It seems from OE v5 that the third param is the count. (GA 11/2001)
1954  */
1955 INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
1956 {
1957     INT myint = MultiCharCount;
1958
1959     return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
1960 }
1961
1962 /*************************************************************************
1963  *      @       [SHLWAPI.219]
1964  *
1965  * Seems to be "super" QueryInterface. Supplied with a table of interfaces
1966  * and an array of IIDs and offsets into the table.
1967  *
1968  * NOTES
1969  *  error codes: E_POINTER, E_NOINTERFACE
1970  */
1971 typedef struct {
1972     REFIID   refid;
1973     DWORD    indx;
1974 } IFACE_INDEX_TBL;
1975
1976 HRESULT WINAPI SHLWAPI_219 (
1977         LPVOID w,           /* [in]   table of interfaces                   */
1978         IFACE_INDEX_TBL *x, /* [in]   array of REFIIDs and indexes to above */
1979         REFIID riid,        /* [in]   REFIID to get interface for           */
1980         LPVOID *ppv)          /* [out]  location to get interface pointer     */
1981 {
1982         HRESULT ret;
1983         IUnknown *a_vtbl;
1984         IFACE_INDEX_TBL *xmove;
1985
1986         TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
1987         if (ppv) {
1988             xmove = x;
1989             while (xmove->refid) {
1990                 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
1991                 if (IsEqualIID(riid, xmove->refid)) {
1992                     a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
1993                     TRACE("matched, returning (%p)\n", a_vtbl);
1994                     *ppv = (LPVOID)a_vtbl;
1995                     IUnknown_AddRef(a_vtbl);
1996                     return S_OK;
1997                 }
1998                 xmove++;
1999             }
2000
2001             if (IsEqualIID(riid, &IID_IUnknown)) {
2002                 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2003                 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2004                 *ppv = (LPVOID)a_vtbl;
2005                 IUnknown_AddRef(a_vtbl);
2006                 return S_OK;
2007             }
2008             *ppv = 0;
2009             ret = E_NOINTERFACE;
2010         } else
2011             ret = E_POINTER;
2012
2013         TRACE("-- 0x%08lx\n", ret);
2014         return ret;
2015 }
2016
2017 /*************************************************************************
2018  *      @       [SHLWAPI.236]
2019  */
2020 HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
2021 {
2022     HKEY newkey;
2023     DWORD type, count;
2024     CHAR value[MAX_PATH], string[MAX_PATH];
2025
2026     strcpy(string, "CLSID\\");
2027     strcat(string, debugstr_guid(lpUnknown));
2028     strcat(string, "\\InProcServer32");
2029
2030     count = MAX_PATH;
2031     RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2032     RegQueryValueExA(newkey, 0, 0, &type, value, &count);
2033     RegCloseKey(newkey);
2034     return LoadLibraryExA(value, 0, 0);
2035 }
2036
2037 /*************************************************************************
2038  *      @       [SHLWAPI.237]
2039  *
2040  * Unicode version of SHLWAPI_183.
2041  */
2042 DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
2043 {
2044         WNDCLASSW WndClass;
2045
2046         TRACE("(0x%08x %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2047
2048         if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2049                 return TRUE;
2050         return RegisterClassW(lpWndClass);
2051 }
2052
2053 /*************************************************************************
2054  *      @       [SHLWAPI.239]
2055  */
2056 DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
2057 {
2058     FIXME("(0x%08x %p 0x%08lx) stub\n",
2059           hInstance, p2, dw3);
2060     return 0;
2061 #if 0
2062     /* pseudo code from relay trace */
2063     WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
2064     GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
2065     /* above pair repeated for:
2066            TridentThicketUrlDlClass
2067            Shell Embedding
2068            CIESplashScreen
2069            Inet Notify_Hidden
2070            OCHost
2071     */
2072 #endif
2073 }
2074
2075 /*************************************************************************
2076  *      @       [SHLWAPI.240]
2077  *
2078  * Call The correct (ASCII/Unicode) default window procedure for a window.
2079  *
2080  * PARAMS
2081  *  hWnd     [I] Window to call the default proceedure for
2082  *  uMessage [I] Message ID
2083  *  wParam   [I] WPARAM of message
2084  *  lParam   [I] LPARAM of message
2085  *
2086  * RETURNS
2087  *  The result of calling the window proceedure.
2088  */
2089 LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2090 {
2091         if (IsWindowUnicode(hWnd))
2092                 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2093         return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2094 }
2095
2096 /*************************************************************************
2097  *      @       [SHLWAPI.241]
2098  *
2099  */
2100 DWORD WINAPI SHLWAPI_241 ()
2101 {
2102         FIXME("()stub\n");
2103         return /* 0xabba1243 */ 0;
2104 }
2105
2106 /*************************************************************************
2107  *      @       [SHLWAPI.266]
2108  *
2109  * native does at least approximately:
2110  *     strcpyW(newstr, x);
2111  *     strcatW(newstr, "\\Restrictions");
2112  *     if (RegOpenKeyExA(80000001, newstr, 00000000,00000001,40520b78))
2113  *        return 0;
2114  *    *unknown*
2115  */
2116 DWORD WINAPI SHLWAPI_266 (
2117         LPVOID w,
2118         LPVOID x,   /* [in] partial registry key */
2119         LPVOID y,
2120         LPVOID z)
2121 {
2122         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
2123         return /* 0xabba1248 */ 0;
2124 }
2125
2126 /*************************************************************************
2127  *      @       [SHLWAPI.267]
2128  *
2129  * NOTES:
2130  *   This QueryInterface asks the inner object for a interface. In case
2131  *   of aggregation this request would be forwarded by the inner to the
2132  *   outer object. This function asks the inner object directly for the
2133  *   interface circumventing the forwarding to the outer object.
2134  */
2135 HRESULT WINAPI SHLWAPI_267 (
2136         IUnknown * pUnk,   /* [in] outer object */
2137         IUnknown * pInner, /* [in] inner object */
2138         IID * riid,
2139         LPVOID* ppv)
2140 {
2141         HRESULT hret = E_NOINTERFACE;
2142         TRACE("(pUnk=%p pInner=%p\n\tIID:  %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2143
2144         *ppv = NULL;
2145         if(pUnk && pInner) {
2146             hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2147             if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2148         }
2149         TRACE("-- 0x%08lx\n", hret);
2150         return hret;
2151 }
2152
2153 /*************************************************************************
2154  *      @       [SHLWAPI.268]
2155  *
2156  * Move a reference from one interface to another.
2157  *
2158  * PARAMS
2159  *   lpDest     [O] Destination to receive the reference
2160  *   lppUnknown [O] Source to give up the reference to lpDest
2161  *
2162  * RETURNS
2163  *  Nothing.
2164  */
2165 VOID WINAPI SHLWAPI_268(IUnknown *lpDest, IUnknown **lppUnknown)
2166 {
2167   TRACE("(%p,%p)\n", lpDest, lppUnknown);
2168
2169   if (*lppUnknown)
2170   {
2171     /* Copy Reference*/
2172     IUnknown_AddRef(lpDest);
2173     SHLWAPI_169(lppUnknown); /* Release existing interface */
2174   }
2175 }
2176
2177 /*************************************************************************
2178  *      @       [SHLWAPI.276]
2179  *
2180  * Determine if the browser is integrated into the shell, and set a registry
2181  * key accordingly.
2182  *
2183  * PARAMS
2184  *  None.
2185  *
2186  * RETURNS
2187  *  1, If the browser is not integrated.
2188  *  2, If the browser is integrated.
2189  *
2190  * NOTES
2191  *  The key HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser is
2192  *  either set to TRUE, or removed depending on whether the browser is deemed
2193  *  to be integrated.
2194  */
2195 DWORD WINAPI SHLWAPI_276()
2196 {
2197   static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2198   static DWORD dwState = 0;
2199   HKEY hKey;
2200   DWORD dwRet, dwData, dwSize;
2201
2202   if (dwState)
2203     return dwState;
2204
2205   /* If shell32 exports DllGetVersion(), the browser is integrated */
2206   GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2207   dwState = pDllGetVersion ? 2 : 1;
2208
2209   /* Set or delete the key accordinly */
2210   dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2211                         "Software\\Microsoft\\Internet Explorer", 0,
2212                          KEY_ALL_ACCESS, &hKey);
2213   if (!dwRet)
2214   {
2215     dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2216                              (LPBYTE)&dwData, &dwSize);
2217
2218     if (!dwRet && dwState == 1)
2219     {
2220       /* Value exists but browser is not integrated */
2221       RegDeleteValueA(hKey, szIntegratedBrowser);
2222     }
2223     else if (dwRet && dwState == 2)
2224     {
2225       /* Browser is integrated but value does not exist */
2226       dwData = TRUE;
2227       RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2228                      (LPBYTE)&dwData, sizeof(dwData));
2229     }
2230     RegCloseKey(hKey);
2231   }
2232   return dwState;
2233 }
2234
2235 /*************************************************************************
2236  *      @       [SHLWAPI.278]
2237  *
2238  */
2239 HWND WINAPI SHLWAPI_278 (
2240         LONG wndProc,
2241         HWND hWndParent,
2242         DWORD dwExStyle,
2243         DWORD dwStyle,
2244         HMENU hMenu,
2245         LONG z)
2246 {
2247         WNDCLASSA wndclass;
2248         HWND hwnd;
2249         HCURSOR hCursor;
2250         char * clsname = "WorkerA";
2251
2252         FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
2253           wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
2254
2255         hCursor = LoadCursorA(0x00000000,IDC_ARROWA);
2256
2257         if(!GetClassInfoA(shlwapi_hInstance, clsname, &wndclass))
2258         {
2259           RtlZeroMemory(&wndclass, sizeof(WNDCLASSA));
2260           wndclass.lpfnWndProc = DefWindowProcW;
2261           wndclass.cbWndExtra = 4;
2262           wndclass.hInstance = shlwapi_hInstance;
2263           wndclass.hCursor = hCursor;
2264           wndclass.hbrBackground = COLOR_BTNSHADOW;
2265           wndclass.lpszMenuName = NULL;
2266           wndclass.lpszClassName = clsname;
2267           RegisterClassA (&wndclass);
2268         }
2269         hwnd = CreateWindowExA(dwExStyle, clsname, 0,dwStyle,0,0,0,0,hWndParent,
2270                 hMenu,shlwapi_hInstance,0);
2271         SetWindowLongA(hwnd, 0, z);
2272         SetWindowLongA(hwnd, GWL_WNDPROC, wndProc);
2273         return hwnd;
2274 }
2275
2276 /*************************************************************************
2277  *      @       [SHLWAPI.281]
2278  *
2279  * _SHPackDispParamsV
2280  */
2281 HRESULT WINAPI SHLWAPI_281(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2282 {
2283         FIXME("%p %p %p %p\n",w,x,y,z);
2284         return E_FAIL;
2285 }
2286
2287 /*************************************************************************
2288  *      @       [SHLWAPI.284]
2289  *
2290  * _IConnectionPoint_SimpleInvoke
2291  */
2292 DWORD WINAPI SHLWAPI_284 (
2293         LPVOID x,
2294         LPVOID y,
2295         LPVOID z)
2296 {
2297         TRACE("(%p %p %p) stub\n",x,y,z);
2298         return 0;
2299 }
2300
2301 /*************************************************************************
2302  *      @       [SHLWAPI.287]
2303  *
2304  * _IUnknown_CPContainerOnChanged
2305  */
2306 HRESULT WINAPI SHLWAPI_287(LPVOID x, LPVOID y)
2307 {
2308         FIXME("%p %p\n", x,y);
2309         return E_FAIL;
2310 }
2311
2312 /*************************************************************************
2313  *      @       [SHLWAPI.289]
2314  *
2315  * Late bound call to winmm.PlaySoundW
2316  */
2317 BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2318 {
2319   GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
2320   return pPlaySoundW(pszSound, hmod, fdwSound);
2321 }
2322
2323 /*************************************************************************
2324  *      @       [SHLWAPI.294]
2325  */
2326 BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
2327 {
2328     /*
2329      * str1:            "I"     "I"     pushl esp+0x20
2330      * str2:            "U"     "I"     pushl 0x77c93810
2331      * (is "I" and "U" "integer" and "unsigned" ??)
2332      *
2333      * pStr:            ""      ""      pushl eax
2334      * some_len:        0x824   0x104   pushl 0x824
2335      * lpStr2:          "%l"    "%l"    pushl esp+0xc
2336      *
2337      * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
2338      * LocalAlloc(0x00, some_len) -> irrelevant_var
2339      * LocalAlloc(0x40, irrelevant_len) -> pStr
2340      * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
2341      * shlwapi.PathRemoveBlanksW(pStr);
2342      */
2343     FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
2344     return TRUE;
2345 }
2346
2347 /*************************************************************************
2348  *      @       [SHLWAPI.295]
2349  *
2350  * Called by ICQ2000b install via SHDOCVW:
2351  * str1: "InternetShortcut"
2352  * x: some unknown pointer
2353  * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
2354  * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
2355  *
2356  * In short: this one maybe creates a desktop link :-)
2357  */
2358 BOOL WINAPI SHLWAPI_295(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
2359 {
2360     FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
2361     return TRUE;
2362 }
2363
2364 /*************************************************************************
2365  *      @       [SHLWAPI.299]
2366  *
2367  * Late bound call to comctl32.417
2368  */
2369 BOOL WINAPI SHLWAPI_299(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2370                          LPCWSTR str, UINT count, const INT *lpDx)
2371 {
2372     GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
2373     return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
2374 }
2375
2376 /*************************************************************************
2377  *      @       [SHLWAPI.313]
2378  *
2379  * Late bound call to shell32.SHGetFileInfoW
2380  */
2381 DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
2382                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
2383 {
2384   GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
2385   return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
2386 }
2387
2388 /*************************************************************************
2389  *      @       [SHLWAPI.318]
2390  *
2391  * Late bound call to shell32.DragQueryFileW
2392  */
2393 UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2394 {
2395   GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
2396   return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
2397 }
2398
2399 /*************************************************************************
2400  *      @       [SHLWAPI.333]
2401  *
2402  * Late bound call to shell32.SHBrowseForFolderW
2403  */
2404 LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
2405 {
2406   GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
2407   return pSHBrowseForFolderW(lpBi);
2408 }
2409
2410 /*************************************************************************
2411  *      @       [SHLWAPI.334]
2412  *
2413  * Late bound call to shell32.SHGetPathFromIDListW
2414  */
2415 BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
2416 {
2417   GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
2418   return pSHGetPathFromIDListW(pidl, pszPath);
2419 }
2420
2421 /*************************************************************************
2422  *      @       [SHLWAPI.335]
2423  *
2424  * Late bound call to shell32.ShellExecuteExW
2425  */
2426 BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
2427 {
2428   GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
2429   return pShellExecuteExW(lpExecInfo);
2430 }
2431
2432 /*************************************************************************
2433  *      @       [SHLWAPI.336]
2434  *
2435  * Late bound call to shell32.SHFileOperationW.
2436  */
2437 DWORD WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
2438 {
2439   GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
2440   return pSHFileOperationW(lpFileOp);
2441 }
2442
2443 /*************************************************************************
2444  *      @       [SHLWAPI.337]
2445  *
2446  * Late bound call to shell32.ExtractIconExW.
2447  */
2448 HICON WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
2449                          HICON *phiconSmall, UINT nIcons)
2450 {
2451   GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", (HICON)0);
2452   return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
2453 }
2454
2455 /*************************************************************************
2456  *      @       [SHLWAPI.342]
2457  *
2458  */
2459 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
2460 {
2461         return InterlockedCompareExchange(dest, xchg, compare);
2462 }
2463
2464 /*************************************************************************
2465  *      @       [SHLWAPI.346]
2466  */
2467 DWORD WINAPI SHLWAPI_346 (
2468         LPCWSTR src,
2469         LPWSTR dest,
2470         int len)
2471 {
2472         FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
2473         lstrcpynW(dest, src, len);
2474         return lstrlenW(dest)+1;
2475 }
2476
2477 /*************************************************************************
2478  *      @       [SHLWAPI.350]
2479  *
2480  * seems to be late bound call to GetFileVersionInfoSizeW
2481  */
2482 DWORD WINAPI SHLWAPI_350 (
2483         LPWSTR x,
2484         LPVOID y)
2485 {
2486         DWORD ret;
2487
2488         GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
2489         ret = pGetFileVersionInfoSizeW(x, y);
2490         return 0x208 + ret;
2491 }
2492
2493 /*************************************************************************
2494  *      @       [SHLWAPI.351]
2495  *
2496  * seems to be late bound call to GetFileVersionInfoW
2497  */
2498 BOOL  WINAPI SHLWAPI_351 (
2499         LPWSTR w,   /* [in] path to dll */
2500         DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */
2501         DWORD  y,   /* [in] return value from .350 - assume length */
2502         LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA) */
2503 {
2504     GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
2505     return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
2506 }
2507
2508 /*************************************************************************
2509  *      @       [SHLWAPI.352]
2510  *
2511  * seems to be late bound call to VerQueryValueW
2512  */
2513 WORD WINAPI SHLWAPI_352 (
2514         LPVOID w,   /* [in] buffer from _351 */
2515         LPWSTR x,   /* [in]   value to retrieve -
2516                               converted and passed to VerQueryValueA as #2 */
2517         LPVOID y,   /* [out]  ver buffer - passed to VerQueryValueA as #3 */
2518         UINT*  z)   /* [in]   ver length - passed to VerQueryValueA as #4 */
2519 {
2520     GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
2521     return pVerQueryValueW((char*)w+0x208, x, y, z);
2522 }
2523
2524 /*************************************************************************
2525  *      @       [SHLWAPI.357]
2526  *
2527  * Late bound call to shell32.SHGetNewLinkInfoW
2528  */
2529 BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
2530                         BOOL *pfMustCopy, UINT uFlags)
2531 {
2532   GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
2533   return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
2534 }
2535
2536 /*************************************************************************
2537  *      @       [SHLWAPI.358]
2538  *
2539  * Late bound call to shell32.SHDefExtractIconW
2540  */
2541 DWORD WINAPI SHLWAPI_358(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2542                          LPVOID arg5, LPVOID arg6)
2543 {
2544   GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
2545   return pSHDefExtractIconW(arg1, arg2, arg3, arg4, arg5, arg6);
2546 }
2547
2548 /*************************************************************************
2549  *      @       [SHLWAPI.364]
2550  *
2551  * Wrapper for lstrcpynA with src and dst swapped.
2552  */
2553 DWORD WINAPI SHLWAPI_364(LPCSTR src, LPSTR dst, INT n)
2554 {
2555   lstrcpynA(dst, src, n);
2556   return TRUE;
2557 }
2558
2559 /*************************************************************************
2560  *      @       [SHLWAPI.370]
2561  *
2562  * Late bound call to shell32.ExtractIconW
2563  */
2564 HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
2565                          UINT nIconIndex)
2566 {
2567   GET_FUNC(pExtractIconW, shell32, "ExtractIconW", (HICON)0);
2568   return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
2569 }
2570
2571 /*************************************************************************
2572  *      @       [SHLWAPI.376]
2573  */
2574 LANGID WINAPI SHLWAPI_376 ()
2575 {
2576     FIXME("() stub\n");
2577     /* FIXME: This should be a forward in the .spec file to the win2k function
2578      * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
2579      */
2580     return GetUserDefaultLangID();
2581 }
2582
2583 /*************************************************************************
2584  *      @       [SHLWAPI.377]
2585  *
2586  * FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
2587  *        each call here.
2588  * FIXME: Native shows calls to:
2589  *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
2590  *                      CheckVersion
2591  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
2592  *  RegQueryValueExA for "LPKInstalled"
2593  *  RegCloseKey
2594  *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
2595  *  RegQueryValueExA for "ResourceLocale"
2596  *  RegCloseKey
2597  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
2598  *  RegQueryValueExA for "Locale"
2599  *  RegCloseKey
2600  *  and then tests the Locale ("en" for me).
2601  *     code below
2602  *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
2603  */
2604 DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
2605 {
2606     CHAR mod_path[2*MAX_PATH];
2607     LPSTR ptr;
2608
2609     GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
2610     ptr = strrchr(mod_path, '\\');
2611     if (ptr) {
2612         strcpy(ptr+1, new_mod);
2613         TRACE("loading %s\n", debugstr_a(mod_path));
2614         return (DWORD)LoadLibraryA(mod_path);
2615     }
2616     return 0;
2617 }
2618
2619 /*************************************************************************
2620  *      @       [SHLWAPI.378]
2621  *
2622  *  This is Unicode version of .377
2623  */
2624 DWORD WINAPI SHLWAPI_378 (
2625         LPCWSTR   new_mod,          /* [in] new module name        */
2626         HMODULE   inst_hwnd,        /* [in] calling module handle  */
2627         LPVOID z)                   /* [???] 4 */
2628 {
2629     WCHAR mod_path[2*MAX_PATH];
2630     LPWSTR ptr;
2631
2632     GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
2633     ptr = strrchrW(mod_path, '\\');
2634     if (ptr) {
2635         strcpyW(ptr+1, new_mod);
2636         TRACE("loading %s\n", debugstr_w(mod_path));
2637         return (DWORD)LoadLibraryW(mod_path);
2638     }
2639     return 0;
2640 }
2641
2642 /*************************************************************************
2643  *      @       [SHLWAPI.389]
2644  *
2645  * Late bound call to comdlg32.GetSaveFileNameW
2646  */
2647 BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
2648 {
2649   GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
2650   return pGetSaveFileNameW(ofn);
2651 }
2652
2653 /*************************************************************************
2654  *      @       [SHLWAPI.390]
2655  *
2656  * Late bound call to mpr.WNetRestoreConnectionW
2657  */
2658 DWORD WINAPI SHLWAPI_390(LPVOID arg1, LPVOID arg2)
2659 {
2660   GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
2661   return pWNetRestoreConnectionW(arg1, arg2);
2662 }
2663
2664 /*************************************************************************
2665  *      @       [SHLWAPI.391]
2666  *
2667  * Late bound call to mpr.WNetGetLastErrorW
2668  */
2669 DWORD WINAPI SHLWAPI_391(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2670                          LPVOID arg5)
2671 {
2672   GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
2673   return pWNetGetLastErrorW(arg1, arg2, arg3, arg4, arg5);
2674 }
2675
2676 /*************************************************************************
2677  *      @       [SHLWAPI.401]
2678  *
2679  * Late bound call to comdlg32.PageSetupDlgW
2680  */
2681 BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
2682 {
2683   GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
2684   return pPageSetupDlgW(pagedlg);
2685 }
2686
2687 /*************************************************************************
2688  *      @       [SHLWAPI.402]
2689  *
2690  * Late bound call to comdlg32.PrintDlgW
2691  */
2692 BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
2693 {
2694   GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
2695   return pPrintDlgW(printdlg);
2696 }
2697
2698 /*************************************************************************
2699  *      @       [SHLWAPI.403]
2700  *
2701  * Late bound call to comdlg32.GetOpenFileNameW
2702  */
2703 BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
2704 {
2705   GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
2706   return pGetOpenFileNameW(ofn);
2707 }
2708
2709 /* INTERNAL: Map from HLS color space to RGB */
2710 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
2711 {
2712   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
2713
2714   if (wHue > 160)
2715     return wMid1;
2716   else if (wHue > 120)
2717     wHue = 160 - wHue;
2718   else if (wHue > 40)
2719     return wMid2;
2720
2721   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
2722 }
2723
2724 /* Convert to RGB and scale into RGB range (0..255) */
2725 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
2726
2727 /*************************************************************************
2728  *      ColorHLSToRGB   [SHLWAPI.404]
2729  *
2730  * Convert from HLS color space into an RGB COLORREF.
2731  *
2732  * NOTES
2733  * Input HLS values are constrained to the range (0..240).
2734  */
2735 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
2736 {
2737   WORD wRed;
2738
2739   if (wSaturation)
2740   {
2741     WORD wGreen, wBlue, wMid1, wMid2;
2742
2743     if (wLuminosity > 120)
2744       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
2745     else
2746       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
2747
2748     wMid1 = wLuminosity * 2 - wMid2;
2749
2750     wRed   = GET_RGB(wHue + 80);
2751     wGreen = GET_RGB(wHue);
2752     wBlue  = GET_RGB(wHue - 80);
2753
2754     return RGB(wRed, wGreen, wBlue);
2755   }
2756
2757   wRed = wLuminosity * 255 / 240;
2758   return RGB(wRed, wRed, wRed);
2759 }
2760
2761 /*************************************************************************
2762  *      @       [SHLWAPI.413]
2763  *
2764  * Function unknown seems to always to return 0
2765  * x can be 0x3.
2766  */
2767 DWORD WINAPI SHLWAPI_413 (DWORD x)
2768 {
2769         FIXME("(0x%08lx)stub\n", x);
2770         return 0;
2771 }
2772
2773 /*************************************************************************
2774  *      @       [SHLWAPI.418]
2775  *
2776  * Function seems to do FreeLibrary plus other things.
2777  *
2778  * FIXME native shows the following calls:
2779  *   RtlEnterCriticalSection
2780  *   LocalFree
2781  *   GetProcAddress(Comctl32??, 150L)
2782  *   DPA_DeletePtr
2783  *   RtlLeaveCriticalSection
2784  *  followed by the FreeLibrary.
2785  *  The above code may be related to .377 above.
2786  */
2787 BOOL  WINAPI SHLWAPI_418 (HMODULE x)
2788 {
2789         FIXME("(0x%08lx) partial stub\n", (LONG)x);
2790         return FreeLibrary(x);
2791 }
2792
2793 /*************************************************************************
2794  *      @       [SHLWAPI.430]
2795  */
2796 DWORD WINAPI SHLWAPI_430 (HINSTANCE hModule, HANDLE heap)
2797 {
2798         FIXME("(0x%08lx 0x%08lx) stub\n", (DWORD)hModule, (DWORD)heap);
2799         return E_FAIL;   /* This is what is used if shlwapi not loaded */
2800 }
2801
2802 /*************************************************************************
2803  *      @       [SHLWAPI.431]
2804  */
2805 DWORD WINAPI SHLWAPI_431 (DWORD x)
2806 {
2807         FIXME("(0x%08lx)stub\n", x);
2808         return 0xabba1247;
2809 }
2810
2811 /*************************************************************************
2812  *      @       [SHLWAPI.436]
2813  *
2814  *  This is really CLSIDFromString which is exported by ole32.dll,
2815  *  however the native shlwapi.dll does *not* import ole32. Nor does
2816  *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude
2817  *  that MS duplicated the code for CLSIDFromString.
2818  *
2819  *  This is a duplicate (with changes for UNICODE) of CLSIDFromString16
2820  *  in dlls/ole32/compobj.c
2821  */
2822 DWORD WINAPI SHLWAPI_436 (LPWSTR idstr, CLSID *id)
2823 {
2824     LPWSTR s = idstr;
2825     BYTE *p;
2826     INT i;
2827     WCHAR table[256];
2828
2829     if (!s) {
2830         memset(s, 0, sizeof(CLSID));
2831         return S_OK;
2832     }
2833     else {  /* validate the CLSID string */
2834
2835         if (strlenW(s) != 38)
2836             return CO_E_CLASSSTRING;
2837
2838         if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
2839             return CO_E_CLASSSTRING;
2840
2841         for (i=1; i<37; i++)
2842             {
2843                 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
2844                 if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||
2845                       ((s[i] >= L'a') && (s[i] <= L'f'))  ||
2846                       ((s[i] >= L'A') && (s[i] <= L'F')))
2847                     )
2848                     return CO_E_CLASSSTRING;
2849             }
2850     }
2851
2852     TRACE("%s -> %p\n", debugstr_w(s), id);
2853
2854   /* quick lookup table */
2855     memset(table, 0, 256*sizeof(WCHAR));
2856
2857     for (i = 0; i < 10; i++) {
2858         table['0' + i] = i;
2859     }
2860     for (i = 0; i < 6; i++) {
2861         table['A' + i] = i+10;
2862         table['a' + i] = i+10;
2863     }
2864
2865     /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
2866
2867     p = (BYTE *) id;
2868
2869     s++;        /* skip leading brace  */
2870     for (i = 0; i < 4; i++) {
2871         p[3 - i] = table[*s]<<4 | table[*(s+1)];
2872         s += 2;
2873     }
2874     p += 4;
2875     s++;        /* skip - */
2876
2877     for (i = 0; i < 2; i++) {
2878         p[1-i] = table[*s]<<4 | table[*(s+1)];
2879         s += 2;
2880     }
2881     p += 2;
2882     s++;        /* skip - */
2883
2884     for (i = 0; i < 2; i++) {
2885         p[1-i] = table[*s]<<4 | table[*(s+1)];
2886         s += 2;
2887     }
2888     p += 2;
2889     s++;        /* skip - */
2890
2891     /* these are just sequential bytes */
2892     for (i = 0; i < 2; i++) {
2893         *p++ = table[*s]<<4 | table[*(s+1)];
2894         s += 2;
2895     }
2896     s++;        /* skip - */
2897
2898     for (i = 0; i < 6; i++) {
2899         *p++ = table[*s]<<4 | table[*(s+1)];
2900         s += 2;
2901     }
2902
2903     return S_OK;
2904 }
2905
2906 /*************************************************************************
2907  *      @       [SHLWAPI.437]
2908  *
2909  * Determine if the OS supports a given feature.
2910  *
2911  * PARAMS
2912  *  dwFeature [I] Feature requested (undocumented)
2913  *
2914  * RETURNS
2915  *  TRUE  If the feature is available.
2916  *  FALSE If the feature is not available.
2917  */
2918 DWORD WINAPI SHLWAPI_437 (DWORD feature)
2919 {
2920   FIXME("(0x%08lx) stub\n", feature);
2921   return FALSE;
2922 }
2923
2924 /*************************************************************************
2925  *      ColorRGBToHLS   [SHLWAPI.445]
2926  *
2927  * Convert from RGB COLORREF into the HLS color space.
2928  *
2929  * NOTES
2930  * Input HLS values are constrained to the range (0..240).
2931  */
2932 VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue,
2933                           LPWORD wLuminance, LPWORD pwSaturation)
2934 {
2935     FIXME("stub\n");
2936     return;
2937 }
2938
2939 /*************************************************************************
2940  *      SHCreateShellPalette    [SHLWAPI.@]
2941  */
2942 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
2943 {
2944         FIXME("stub\n");
2945         return CreateHalftonePalette(hdc);
2946 }
2947
2948 /*************************************************************************
2949  *      SHGetInverseCMAP (SHLWAPI.@)
2950  */
2951 DWORD WINAPI SHGetInverseCMAP (LPDWORD* x, DWORD why)
2952 {
2953     if (why == 4) {
2954         FIXME(" - returning bogus address for SHGetInverseCMAP\n");
2955         *x = (LPDWORD)0xabba1249;
2956         return 0;
2957     }
2958     FIXME("(%p, %#lx)stub\n", x, why);
2959     return 0;
2960 }
2961
2962 /*************************************************************************
2963  *      SHIsLowMemoryMachine    [SHLWAPI.@]
2964  */
2965 DWORD WINAPI SHIsLowMemoryMachine (DWORD x)
2966 {
2967         FIXME("0x%08lx\n", x);
2968         return 0;
2969 }
2970
2971 /*************************************************************************
2972  *      GetMenuPosFromID        [SHLWAPI.@]
2973  */
2974 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
2975 {
2976  MENUITEMINFOA mi;
2977  INT nCount = GetMenuItemCount(hMenu), nIter = 0;
2978
2979  while (nIter < nCount)
2980  {
2981    mi.wID = 0;
2982    if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
2983      return nIter;
2984    nIter++;
2985  }
2986  return -1;
2987 }
2988
2989 /*************************************************************************
2990  * SHSkipJunction       [SHLWAPI.@]
2991  *
2992  * Determine if a bind context can be bound to an object
2993  *
2994  * PARAMS
2995  *  pbc    [I] Bind context to check
2996  *  pclsid [I] CLSID of object to be bound to
2997  *
2998  * RETURNS
2999  *  TRUE: If it is safe to bind
3000  *  FALSE: If pbc is invalid or binding would not be safe
3001  *
3002  */
3003 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
3004 {
3005   static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
3006     'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
3007   BOOL bRet = FALSE;
3008
3009   if (pbc)
3010   {
3011     IUnknown* lpUnk;
3012
3013     if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
3014     {
3015       CLSID clsid;
3016
3017       if (SUCCEEDED(SHLWAPI_175(lpUnk, &clsid)) &&
3018           IsEqualGUID(pclsid, &clsid))
3019         bRet = TRUE;
3020
3021       IUnknown_Release(lpUnk);
3022     }
3023   }
3024   return bRet;
3025 }