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