push(c) 7dcddf6204ed5518706a76fe66fd836d81e70dd4
[wine/hacks.git] / dlls / shlwapi / ordinal.c
blobd3e5825b2ab8f6f989a9b19d9e5110505cc909ab
1 /*
2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
5 * 1998 Jürgen Schmied
6 * 2001-2003 Jon Griffiths
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
30 #define COBJMACROS
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winreg.h"
37 #include "wingdi.h"
38 #include "winuser.h"
39 #include "winver.h"
40 #include "winnetwk.h"
41 #include "mmsystem.h"
42 #include "objbase.h"
43 #include "exdisp.h"
44 #include "shlobj.h"
45 #include "shlwapi.h"
46 #include "shellapi.h"
47 #include "commdlg.h"
48 #include "wine/unicode.h"
49 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54 /* DLL handles for late bound calls */
55 extern HINSTANCE shlwapi_hInstance;
56 extern DWORD SHLWAPI_ThreadRef_index;
58 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
59 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
60 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
63 NOTES: Most functions exported by ordinal seem to be superflous.
64 The reason for these functions to be there is to provide a wrapper
65 for unicode functions to provide these functions on systems without
66 unicode functions eg. win95/win98. Since we have such functions we just
67 call these. If running Wine with native DLLs, some late bound calls may
68 fail. However, it is better to implement the functions in the forward DLL
69 and recommend the builtin rather than reimplementing the calls here!
72 /*************************************************************************
73 * SHLWAPI_DupSharedHandle
75 * Internal implemetation of SHLWAPI_11.
77 static
78 HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
79 DWORD dwSrcProcId, DWORD dwAccess,
80 DWORD dwOptions)
82 HANDLE hDst, hSrc;
83 DWORD dwMyProcId = GetCurrentProcessId();
84 HANDLE hRet = NULL;
86 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
87 dwAccess, dwOptions);
89 /* Get dest process handle */
90 if (dwDstProcId == dwMyProcId)
91 hDst = GetCurrentProcess();
92 else
93 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
95 if (hDst)
97 /* Get src process handle */
98 if (dwSrcProcId == dwMyProcId)
99 hSrc = GetCurrentProcess();
100 else
101 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
103 if (hSrc)
105 /* Make handle available to dest process */
106 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
107 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
108 hRet = NULL;
110 if (dwSrcProcId != dwMyProcId)
111 CloseHandle(hSrc);
114 if (dwDstProcId != dwMyProcId)
115 CloseHandle(hDst);
118 TRACE("Returning handle %p\n", hRet);
119 return hRet;
122 /*************************************************************************
123 * @ [SHLWAPI.7]
125 * Create a block of sharable memory and initialise it with data.
127 * PARAMS
128 * lpvData [I] Pointer to data to write
129 * dwSize [I] Size of data
130 * dwProcId [I] ID of process owning data
132 * RETURNS
133 * Success: A shared memory handle
134 * Failure: NULL
136 * NOTES
137 * Ordinals 7-11 provide a set of calls to create shared memory between a
138 * group of processes. The shared memory is treated opaquely in that its size
139 * is not exposed to clients who map it. This is accomplished by storing
140 * the size of the map as the first DWORD of mapped data, and then offsetting
141 * the view pointer returned by this size.
144 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
146 HANDLE hMap;
147 LPVOID pMapped;
148 HANDLE hRet = NULL;
150 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
152 /* Create file mapping of the correct length */
153 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
154 dwSize + sizeof(dwSize), NULL);
155 if (!hMap)
156 return hRet;
158 /* Get a view in our process address space */
159 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
161 if (pMapped)
163 /* Write size of data, followed by the data, to the view */
164 *((DWORD*)pMapped) = dwSize;
165 if (lpvData)
166 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
168 /* Release view. All further views mapped will be opaque */
169 UnmapViewOfFile(pMapped);
170 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
171 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
172 DUPLICATE_SAME_ACCESS);
175 CloseHandle(hMap);
176 return hRet;
179 /*************************************************************************
180 * @ [SHLWAPI.8]
182 * Get a pointer to a block of shared memory from a shared memory handle.
184 * PARAMS
185 * hShared [I] Shared memory handle
186 * dwProcId [I] ID of process owning hShared
188 * RETURNS
189 * Success: A pointer to the shared memory
190 * Failure: NULL
193 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
195 HANDLE hDup;
196 LPVOID pMapped;
198 TRACE("(%p %d)\n", hShared, dwProcId);
200 /* Get handle to shared memory for current process */
201 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
202 FILE_MAP_ALL_ACCESS, 0);
203 /* Get View */
204 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
205 CloseHandle(hDup);
207 if (pMapped)
208 return (char *) pMapped + sizeof(DWORD); /* Hide size */
209 return NULL;
212 /*************************************************************************
213 * @ [SHLWAPI.9]
215 * Release a pointer to a block of shared memory.
217 * PARAMS
218 * lpView [I] Shared memory pointer
220 * RETURNS
221 * Success: TRUE
222 * Failure: FALSE
225 BOOL WINAPI SHUnlockShared(LPVOID lpView)
227 TRACE("(%p)\n", lpView);
228 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
231 /*************************************************************************
232 * @ [SHLWAPI.10]
234 * Destroy a block of sharable memory.
236 * PARAMS
237 * hShared [I] Shared memory handle
238 * dwProcId [I] ID of process owning hShared
240 * RETURNS
241 * Success: TRUE
242 * Failure: FALSE
245 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
247 HANDLE hClose;
249 TRACE("(%p %d)\n", hShared, dwProcId);
251 /* Get a copy of the handle for our process, closing the source handle */
252 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
253 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
254 /* Close local copy */
255 return CloseHandle(hClose);
258 /*************************************************************************
259 * @ [SHLWAPI.11]
261 * Copy a sharable memory handle from one process to another.
263 * PARAMS
264 * hShared [I] Shared memory handle to duplicate
265 * dwDstProcId [I] ID of the process wanting the duplicated handle
266 * dwSrcProcId [I] ID of the process owning hShared
267 * dwAccess [I] Desired DuplicateHandle() access
268 * dwOptions [I] Desired DuplicateHandle() options
270 * RETURNS
271 * Success: A handle suitable for use by the dwDstProcId process.
272 * Failure: A NULL handle.
275 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
276 DWORD dwAccess, DWORD dwOptions)
278 HANDLE hRet;
280 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
281 dwAccess, dwOptions);
282 return hRet;
285 /*************************************************************************
286 * @ [SHLWAPI.13]
288 * Create and register a clipboard enumerator for a web browser.
290 * PARAMS
291 * lpBC [I] Binding context
292 * lpUnknown [I] An object exposing the IWebBrowserApp interface
294 * RETURNS
295 * Success: S_OK.
296 * Failure: An HRESULT error code.
298 * NOTES
299 * The enumerator is stored as a property of the web browser. If it does not
300 * yet exist, it is created and set before being registered.
302 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
304 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
305 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
306 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
307 BSTR property;
308 IEnumFORMATETC* pIEnumFormatEtc = NULL;
309 VARIANTARG var;
310 HRESULT hRet;
311 IWebBrowserApp* pBrowser = NULL;
313 TRACE("(%p, %p)\n", lpBC, lpUnknown);
315 /* Get An IWebBrowserApp interface from lpUnknown */
316 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
317 if (FAILED(hRet) || !pBrowser)
318 return E_NOINTERFACE;
320 V_VT(&var) = VT_EMPTY;
322 /* The property we get is the browsers clipboard enumerator */
323 property = SysAllocString(szProperty);
324 hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
325 SysFreeString(property);
326 if (FAILED(hRet))
327 return hRet;
329 if (V_VT(&var) == VT_EMPTY)
331 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
332 char szKeyBuff[128], szValueBuff[128];
333 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
334 FORMATETC* formatList, *format;
335 HKEY hDocs;
337 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
339 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
340 "Version\\Internet Settings\\Accepted Documents", &hDocs))
341 return E_FAIL;
343 /* Get count of values in key */
344 while (!dwRet)
346 dwKeySize = sizeof(szKeyBuff);
347 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
348 dwCount++;
351 dwNumValues = dwCount;
353 /* Note: dwCount = number of items + 1; The extra item is the end node */
354 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
355 if (!formatList)
356 return E_OUTOFMEMORY;
358 if (dwNumValues > 1)
360 dwRet = 0;
361 dwCount = 0;
363 dwNumValues--;
365 /* Register clipboard formats for the values and populate format list */
366 while(!dwRet && dwCount < dwNumValues)
368 dwKeySize = sizeof(szKeyBuff);
369 dwValueSize = sizeof(szValueBuff);
370 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
371 (PBYTE)szValueBuff, &dwValueSize);
372 if (!dwRet)
373 return E_FAIL;
375 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
376 format->ptd = NULL;
377 format->dwAspect = 1;
378 format->lindex = 4;
379 format->tymed = -1;
381 format++;
382 dwCount++;
386 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
387 format->cfFormat = 0;
388 format->ptd = NULL;
389 format->dwAspect = 1;
390 format->lindex = 4;
391 format->tymed = -1;
393 /* Create a clipboard enumerator */
394 hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
396 if (FAILED(hRet) || !pIEnumFormatEtc)
397 return hRet;
399 /* Set our enumerator as the browsers property */
400 V_VT(&var) = VT_UNKNOWN;
401 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
403 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
404 if (FAILED(hRet))
406 IEnumFORMATETC_Release(pIEnumFormatEtc);
407 goto RegisterDefaultAcceptHeaders_Exit;
411 if (V_VT(&var) == VT_UNKNOWN)
413 /* Our variant is holding the clipboard enumerator */
414 IUnknown* pIUnknown = V_UNKNOWN(&var);
415 IEnumFORMATETC* pClone = NULL;
417 TRACE("Retrieved IEnumFORMATETC property\n");
419 /* Get an IEnumFormatEtc interface from the variants value */
420 pIEnumFormatEtc = NULL;
421 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
422 (PVOID)&pIEnumFormatEtc);
423 if (!hRet && pIEnumFormatEtc)
425 /* Clone and register the enumerator */
426 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
427 if (!hRet && pClone)
429 RegisterFormatEnumerator(lpBC, pClone, 0);
431 IEnumFORMATETC_Release(pClone);
434 /* Release the IEnumFormatEtc interface */
435 IEnumFORMATETC_Release(pIUnknown);
437 IUnknown_Release(V_UNKNOWN(&var));
440 RegisterDefaultAcceptHeaders_Exit:
441 IWebBrowserApp_Release(pBrowser);
442 return hRet;
445 /*************************************************************************
446 * @ [SHLWAPI.15]
448 * Get Explorers "AcceptLanguage" setting.
450 * PARAMS
451 * langbuf [O] Destination for language string
452 * buflen [I] Length of langbuf
453 * [0] Success: used length of langbuf
455 * RETURNS
456 * Success: S_OK. langbuf is set to the language string found.
457 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
458 * does not contain the setting.
459 * E_INVALIDARG, If the buffer is not big enough
461 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
463 static const WCHAR szkeyW[] = {
464 'S','o','f','t','w','a','r','e','\\',
465 'M','i','c','r','o','s','o','f','t','\\',
466 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
467 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
468 static const WCHAR valueW[] = {
469 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
470 static const WCHAR enusW[] = {'e','n','-','u','s',0};
471 DWORD mystrlen, mytype;
472 HKEY mykey;
473 HRESULT retval;
474 LCID mylcid;
475 WCHAR *mystr;
477 if(!langbuf || !buflen || !*buflen)
478 return E_FAIL;
480 mystrlen = (*buflen > 20) ? *buflen : 20 ;
481 mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
482 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
483 if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
484 /* Did not find value */
485 mylcid = GetUserDefaultLCID();
486 /* somehow the mylcid translates into "en-us"
487 * this is similar to "LOCALE_SABBREVLANGNAME"
488 * which could be gotten via GetLocaleInfo.
489 * The only problem is LOCALE_SABBREVLANGUAGE" is
490 * a 3 char string (first 2 are country code and third is
491 * letter for "sublanguage", which does not come close to
492 * "en-us"
494 lstrcpyW(mystr, enusW);
495 mystrlen = lstrlenW(mystr);
496 } else {
497 /* handle returned string */
498 FIXME("missing code\n");
500 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
502 if(*buflen > strlenW(mystr)) {
503 *buflen = strlenW(mystr);
504 retval = S_OK;
505 } else {
506 *buflen = 0;
507 retval = E_INVALIDARG;
508 SetLastError(ERROR_INSUFFICIENT_BUFFER);
510 RegCloseKey(mykey);
511 HeapFree(GetProcessHeap(), 0, mystr);
512 return retval;
515 /*************************************************************************
516 * @ [SHLWAPI.14]
518 * Ascii version of GetAcceptLanguagesW.
520 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
522 WCHAR *langbufW;
523 DWORD buflenW, convlen;
524 HRESULT retval;
526 if(!langbuf || !buflen || !*buflen) return E_FAIL;
528 buflenW = *buflen;
529 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
530 retval = GetAcceptLanguagesW(langbufW, &buflenW);
532 if (retval == S_OK)
534 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
536 else /* copy partial string anyway */
538 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
539 if (convlen < *buflen) langbuf[convlen] = 0;
541 *buflen = buflenW ? convlen : 0;
543 HeapFree(GetProcessHeap(), 0, langbufW);
544 return retval;
547 /*************************************************************************
548 * @ [SHLWAPI.23]
550 * Convert a GUID to a string.
552 * PARAMS
553 * guid [I] GUID to convert
554 * lpszDest [O] Destination for string
555 * cchMax [I] Length of output buffer
557 * RETURNS
558 * The length of the string created.
560 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
562 char xguid[40];
563 INT iLen;
565 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
567 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
568 guid->Data1, guid->Data2, guid->Data3,
569 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
570 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
572 iLen = strlen(xguid) + 1;
574 if (iLen > cchMax)
575 return 0;
576 memcpy(lpszDest, xguid, iLen);
577 return iLen;
580 /*************************************************************************
581 * @ [SHLWAPI.24]
583 * Convert a GUID to a string.
585 * PARAMS
586 * guid [I] GUID to convert
587 * str [O] Destination for string
588 * cmax [I] Length of output buffer
590 * RETURNS
591 * The length of the string created.
593 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
595 WCHAR xguid[40];
596 INT iLen;
597 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
598 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
599 'X','%','0','2','X','%','0','2','X','}',0};
601 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
603 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
604 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
605 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
607 iLen = strlenW(xguid) + 1;
609 if (iLen > cchMax)
610 return 0;
611 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
612 return iLen;
615 /*************************************************************************
616 * @ [SHLWAPI.29]
618 * Determine if a Unicode character is a space.
620 * PARAMS
621 * wc [I] Character to check.
623 * RETURNS
624 * TRUE, if wc is a space,
625 * FALSE otherwise.
627 BOOL WINAPI IsCharSpaceW(WCHAR wc)
629 WORD CharType;
631 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
634 /*************************************************************************
635 * @ [SHLWAPI.30]
637 * Determine if a Unicode character is a blank.
639 * PARAMS
640 * wc [I] Character to check.
642 * RETURNS
643 * TRUE, if wc is a blank,
644 * FALSE otherwise.
647 BOOL WINAPI IsCharBlankW(WCHAR wc)
649 WORD CharType;
651 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
654 /*************************************************************************
655 * @ [SHLWAPI.31]
657 * Determine if a Unicode character is punctuation.
659 * PARAMS
660 * wc [I] Character to check.
662 * RETURNS
663 * TRUE, if wc is punctuation,
664 * FALSE otherwise.
666 BOOL WINAPI IsCharPunctW(WCHAR wc)
668 WORD CharType;
670 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
673 /*************************************************************************
674 * @ [SHLWAPI.32]
676 * Determine if a Unicode character is a control character.
678 * PARAMS
679 * wc [I] Character to check.
681 * RETURNS
682 * TRUE, if wc is a control character,
683 * FALSE otherwise.
685 BOOL WINAPI IsCharCntrlW(WCHAR wc)
687 WORD CharType;
689 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
692 /*************************************************************************
693 * @ [SHLWAPI.33]
695 * Determine if a Unicode character is a digit.
697 * PARAMS
698 * wc [I] Character to check.
700 * RETURNS
701 * TRUE, if wc is a digit,
702 * FALSE otherwise.
704 BOOL WINAPI IsCharDigitW(WCHAR wc)
706 WORD CharType;
708 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
711 /*************************************************************************
712 * @ [SHLWAPI.34]
714 * Determine if a Unicode character is a hex digit.
716 * PARAMS
717 * wc [I] Character to check.
719 * RETURNS
720 * TRUE, if wc is a hex digit,
721 * FALSE otherwise.
723 BOOL WINAPI IsCharXDigitW(WCHAR wc)
725 WORD CharType;
727 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
730 /*************************************************************************
731 * @ [SHLWAPI.35]
734 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
736 FIXME("(%s,0x%08x,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
737 return TRUE;
740 /*************************************************************************
741 * @ [SHLWAPI.36]
743 * Insert a bitmap menu item at the bottom of a menu.
745 * PARAMS
746 * hMenu [I] Menu to insert into
747 * flags [I] Flags for insertion
748 * id [I] Menu ID of the item
749 * str [I] Menu text for the item
751 * RETURNS
752 * Success: TRUE, the item is inserted into the menu
753 * Failure: FALSE, if any parameter is invalid
755 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
757 TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
758 return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
761 /*************************************************************************
762 * @ [SHLWAPI.138]
764 * Set the text of a given dialog item.
766 * PARAMS
767 * hWnd [I] Handle of dialog
768 * iItem [I] Index of item
769 * lpszText [O] Text to set
771 * RETURNS
772 * Success: TRUE. The text of the dialog is set to lpszText.
773 * Failure: FALSE, Otherwise.
775 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
777 HWND hWndItem = GetDlgItem(hWnd, iItem);
778 if (hWndItem)
779 return SetWindowTextW(hWndItem, lpszText);
780 return FALSE;
783 /*************************************************************************
784 * @ [SHLWAPI.151]
786 * Compare two Ascii strings up to a given length.
788 * PARAMS
789 * lpszSrc [I] Source string
790 * lpszCmp [I] String to compare to lpszSrc
791 * len [I] Maximum length
793 * RETURNS
794 * A number greater than, less than or equal to 0 depending on whether
795 * lpszSrc is greater than, less than or equal to lpszCmp.
797 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
799 return strncmp(lpszSrc, lpszCmp, len);
802 /*************************************************************************
803 * @ [SHLWAPI.152]
805 * Unicode version of StrCmpNCA.
807 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
809 return strncmpW(lpszSrc, lpszCmp, len);
812 /*************************************************************************
813 * @ [SHLWAPI.153]
815 * Compare two Ascii strings up to a given length, ignoring case.
817 * PARAMS
818 * lpszSrc [I] Source string
819 * lpszCmp [I] String to compare to lpszSrc
820 * len [I] Maximum length
822 * RETURNS
823 * A number greater than, less than or equal to 0 depending on whether
824 * lpszSrc is greater than, less than or equal to lpszCmp.
826 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
828 return strncasecmp(lpszSrc, lpszCmp, len);
831 /*************************************************************************
832 * @ [SHLWAPI.154]
834 * Unicode version of StrCmpNICA.
836 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
838 return strncmpiW(lpszSrc, lpszCmp, len);
841 /*************************************************************************
842 * @ [SHLWAPI.155]
844 * Compare two Ascii strings.
846 * PARAMS
847 * lpszSrc [I] Source string
848 * lpszCmp [I] String to compare to lpszSrc
850 * RETURNS
851 * A number greater than, less than or equal to 0 depending on whether
852 * lpszSrc is greater than, less than or equal to lpszCmp.
854 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
856 return strcmp(lpszSrc, lpszCmp);
859 /*************************************************************************
860 * @ [SHLWAPI.156]
862 * Unicode version of StrCmpCA.
864 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
866 return strcmpW(lpszSrc, lpszCmp);
869 /*************************************************************************
870 * @ [SHLWAPI.157]
872 * Compare two Ascii strings, ignoring case.
874 * PARAMS
875 * lpszSrc [I] Source string
876 * lpszCmp [I] String to compare to lpszSrc
878 * RETURNS
879 * A number greater than, less than or equal to 0 depending on whether
880 * lpszSrc is greater than, less than or equal to lpszCmp.
882 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
884 return strcasecmp(lpszSrc, lpszCmp);
887 /*************************************************************************
888 * @ [SHLWAPI.158]
890 * Unicode version of StrCmpICA.
892 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
894 return strcmpiW(lpszSrc, lpszCmp);
897 /*************************************************************************
898 * @ [SHLWAPI.160]
900 * Get an identification string for the OS and explorer.
902 * PARAMS
903 * lpszDest [O] Destination for Id string
904 * dwDestLen [I] Length of lpszDest
906 * RETURNS
907 * TRUE, If the string was created successfully
908 * FALSE, Otherwise
910 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
912 WCHAR buff[2084];
914 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
916 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
918 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
919 return TRUE;
921 return FALSE;
924 /*************************************************************************
925 * @ [SHLWAPI.161]
927 * Unicode version of SHAboutInfoA.
929 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
931 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
932 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
933 ' ','E','x','p','l','o','r','e','r','\0' };
934 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
935 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
936 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
937 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
938 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
939 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
940 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
941 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
942 ' ','E','x','p','l','o','r','e','r','\\',
943 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
944 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
945 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
946 'V','e','r','s','i','o','n','\0' };
947 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
948 'O','w','n','e','r','\0' };
949 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
950 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
951 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
952 static const WCHAR szUpdate[] = { 'I','E','A','K',
953 'U','p','d','a','t','e','U','r','l','\0' };
954 static const WCHAR szHelp[] = { 'I','E','A','K',
955 'H','e','l','p','S','t','r','i','n','g','\0' };
956 WCHAR buff[2084];
957 HKEY hReg;
958 DWORD dwType, dwLen;
960 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
962 if (!lpszDest)
963 return FALSE;
965 *lpszDest = '\0';
967 /* Try the NT key first, followed by 95/98 key */
968 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
969 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
970 return FALSE;
972 /* OS Version */
973 buff[0] = '\0';
974 dwLen = 30;
975 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
977 DWORD dwStrLen = strlenW(buff);
978 dwLen = 30 - dwStrLen;
979 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
980 szCustomized, &dwType, buff+dwStrLen, &dwLen);
982 StrCatBuffW(lpszDest, buff, dwDestLen);
984 /* ~Registered Owner */
985 buff[0] = '~';
986 dwLen = 256;
987 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
988 buff[1] = '\0';
989 StrCatBuffW(lpszDest, buff, dwDestLen);
991 /* ~Registered Organization */
992 dwLen = 256;
993 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
994 buff[1] = '\0';
995 StrCatBuffW(lpszDest, buff, dwDestLen);
997 /* FIXME: Not sure where this number comes from */
998 buff[0] = '~';
999 buff[1] = '0';
1000 buff[2] = '\0';
1001 StrCatBuffW(lpszDest, buff, dwDestLen);
1003 /* ~Product Id */
1004 dwLen = 256;
1005 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1006 buff[1] = '\0';
1007 StrCatBuffW(lpszDest, buff, dwDestLen);
1009 /* ~IE Update Url */
1010 dwLen = 2048;
1011 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1012 buff[1] = '\0';
1013 StrCatBuffW(lpszDest, buff, dwDestLen);
1015 /* ~IE Help String */
1016 dwLen = 256;
1017 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1018 buff[1] = '\0';
1019 StrCatBuffW(lpszDest, buff, dwDestLen);
1021 RegCloseKey(hReg);
1022 return TRUE;
1025 /*************************************************************************
1026 * @ [SHLWAPI.163]
1028 * Call IOleCommandTarget_QueryStatus() on an object.
1030 * PARAMS
1031 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1032 * pguidCmdGroup [I] GUID for the command group
1033 * cCmds [I]
1034 * prgCmds [O] Commands
1035 * pCmdText [O] Command text
1037 * RETURNS
1038 * Success: S_OK.
1039 * Failure: E_FAIL, if lpUnknown is NULL.
1040 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1041 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1043 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1044 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1046 HRESULT hRet = E_FAIL;
1048 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1050 if (lpUnknown)
1052 IOleCommandTarget* lpOle;
1054 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1055 (void**)&lpOle);
1057 if (SUCCEEDED(hRet) && lpOle)
1059 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1060 prgCmds, pCmdText);
1061 IOleCommandTarget_Release(lpOle);
1064 return hRet;
1067 /*************************************************************************
1068 * @ [SHLWAPI.164]
1070 * Call IOleCommandTarget_Exec() on an object.
1072 * PARAMS
1073 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1074 * pguidCmdGroup [I] GUID for the command group
1076 * RETURNS
1077 * Success: S_OK.
1078 * Failure: E_FAIL, if lpUnknown is NULL.
1079 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1080 * Otherwise, an error code from IOleCommandTarget_Exec().
1082 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1083 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1084 VARIANT* pvaOut)
1086 HRESULT hRet = E_FAIL;
1088 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1089 nCmdexecopt, pvaIn, pvaOut);
1091 if (lpUnknown)
1093 IOleCommandTarget* lpOle;
1095 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1096 (void**)&lpOle);
1097 if (SUCCEEDED(hRet) && lpOle)
1099 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1100 nCmdexecopt, pvaIn, pvaOut);
1101 IOleCommandTarget_Release(lpOle);
1104 return hRet;
1107 /*************************************************************************
1108 * @ [SHLWAPI.165]
1110 * Retrieve, modify, and re-set a value from a window.
1112 * PARAMS
1113 * hWnd [I] Window to get value from
1114 * offset [I] Offset of value
1115 * wMask [I] Mask for uiFlags
1116 * wFlags [I] Bits to set in window value
1118 * RETURNS
1119 * The new value as it was set, or 0 if any parameter is invalid.
1121 * NOTES
1122 * Any bits set in uiMask are cleared from the value, then any bits set in
1123 * uiFlags are set in the value.
1125 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1127 LONG ret = GetWindowLongA(hwnd, offset);
1128 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1130 if (newFlags != ret)
1131 ret = SetWindowLongA(hwnd, offset, newFlags);
1132 return ret;
1135 /*************************************************************************
1136 * @ [SHLWAPI.167]
1138 * Change a window's parent.
1140 * PARAMS
1141 * hWnd [I] Window to change parent of
1142 * hWndParent [I] New parent window
1144 * RETURNS
1145 * The old parent of hWnd.
1147 * NOTES
1148 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1149 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1151 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1153 TRACE("%p, %p\n", hWnd, hWndParent);
1155 if(GetParent(hWnd) == hWndParent)
1156 return 0;
1158 if(hWndParent)
1159 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1160 else
1161 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1163 return SetParent(hWnd, hWndParent);
1166 /*************************************************************************
1167 * @ [SHLWAPI.168]
1169 * Locate and advise a connection point in an IConnectionPointContainer object.
1171 * PARAMS
1172 * lpUnkSink [I] Sink for the connection point advise call
1173 * riid [I] REFIID of connection point to advise
1174 * bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1175 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1176 * lpCookie [O] Pointer to connection point cookie
1177 * lppCP [O] Destination for the IConnectionPoint found
1179 * RETURNS
1180 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1181 * that was advised. The caller is responsible for releasing it.
1182 * Failure: E_FAIL, if any arguments are invalid.
1183 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1184 * Or an HRESULT error code if any call fails.
1186 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1187 IUnknown* lpUnknown, LPDWORD lpCookie,
1188 IConnectionPoint **lppCP)
1190 HRESULT hRet;
1191 IConnectionPointContainer* lpContainer;
1192 IConnectionPoint *lpCP;
1194 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1195 return E_FAIL;
1197 if(lppCP)
1198 *lppCP = NULL;
1200 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1201 (void**)&lpContainer);
1202 if (SUCCEEDED(hRet))
1204 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1206 if (SUCCEEDED(hRet))
1208 if(!bAdviseOnly)
1209 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1210 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1212 if (FAILED(hRet))
1213 *lpCookie = 0;
1215 if (lppCP && SUCCEEDED(hRet))
1216 *lppCP = lpCP; /* Caller keeps the interface */
1217 else
1218 IConnectionPoint_Release(lpCP); /* Release it */
1221 IUnknown_Release(lpContainer);
1223 return hRet;
1226 /*************************************************************************
1227 * @ [SHLWAPI.169]
1229 * Release an interface.
1231 * PARAMS
1232 * lpUnknown [I] Object to release
1234 * RETURNS
1235 * Nothing.
1237 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1239 IUnknown *temp;
1241 TRACE("(%p)\n",lpUnknown);
1243 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1244 temp = *lpUnknown;
1245 *lpUnknown = NULL;
1247 TRACE("doing Release\n");
1249 return IUnknown_Release(temp);
1252 /*************************************************************************
1253 * @ [SHLWAPI.170]
1255 * Skip '//' if present in a string.
1257 * PARAMS
1258 * lpszSrc [I] String to check for '//'
1260 * RETURNS
1261 * Success: The next character after the '//' or the string if not present
1262 * Failure: NULL, if lpszStr is NULL.
1264 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1266 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1267 lpszSrc += 2;
1268 return lpszSrc;
1271 /*************************************************************************
1272 * @ [SHLWAPI.171]
1274 * Check if two interfaces come from the same object.
1276 * PARAMS
1277 * lpInt1 [I] Interface to check against lpInt2.
1278 * lpInt2 [I] Interface to check against lpInt1.
1280 * RETURNS
1281 * TRUE, If the interfaces come from the same object.
1282 * FALSE Otherwise.
1284 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1286 LPVOID lpUnknown1, lpUnknown2;
1288 TRACE("%p %p\n", lpInt1, lpInt2);
1290 if (!lpInt1 || !lpInt2)
1291 return FALSE;
1293 if (lpInt1 == lpInt2)
1294 return TRUE;
1296 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1297 (LPVOID *)&lpUnknown1)))
1298 return FALSE;
1300 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1301 (LPVOID *)&lpUnknown2)))
1302 return FALSE;
1304 if (lpUnknown1 == lpUnknown2)
1305 return TRUE;
1307 return FALSE;
1310 /*************************************************************************
1311 * @ [SHLWAPI.172]
1313 * Get the window handle of an object.
1315 * PARAMS
1316 * lpUnknown [I] Object to get the window handle of
1317 * lphWnd [O] Destination for window handle
1319 * RETURNS
1320 * Success: S_OK. lphWnd contains the objects window handle.
1321 * Failure: An HRESULT error code.
1323 * NOTES
1324 * lpUnknown is expected to support one of the following interfaces:
1325 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1327 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1329 /* FIXME: Wine has no header for this object */
1330 static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1331 0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1332 IUnknown *lpOle;
1333 HRESULT hRet = E_FAIL;
1335 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1337 if (!lpUnknown)
1338 return hRet;
1340 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1342 if (FAILED(hRet))
1344 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1346 if (FAILED(hRet))
1348 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1349 (void**)&lpOle);
1353 if (SUCCEEDED(hRet))
1355 /* Lazyness here - Since GetWindow() is the first method for the above 3
1356 * interfaces, we use the same call for them all.
1358 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1359 IUnknown_Release(lpOle);
1360 if (lphWnd)
1361 TRACE("Returning HWND=%p\n", *lphWnd);
1364 return hRet;
1367 /*************************************************************************
1368 * @ [SHLWAPI.173]
1370 * Call a method on as as yet unidentified object.
1372 * PARAMS
1373 * pUnk [I] Object supporting the unidentified interface,
1374 * arg [I] Argument for the call on the object.
1376 * RETURNS
1377 * S_OK.
1379 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1381 static const GUID guid_173 = {
1382 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1384 IMalloc *pUnk2;
1386 TRACE("(%p,%d)\n", pUnk, arg);
1388 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1389 * We use this interface as its vtable entry is compatible with the
1390 * object in question.
1391 * FIXME: Find out what this object is and where it should be defined.
1393 if (pUnk &&
1394 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1396 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1397 IMalloc_Release(pUnk2);
1399 return S_OK;
1402 /*************************************************************************
1403 * @ [SHLWAPI.174]
1405 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1406 * an object.
1409 HRESULT WINAPI IUnknown_SetSite(
1410 IUnknown *obj, /* [in] OLE object */
1411 IUnknown *site) /* [in] Site interface */
1413 HRESULT hr;
1414 IObjectWithSite *iobjwithsite;
1415 IInternetSecurityManager *isecmgr;
1417 if (!obj) return E_FAIL;
1419 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1420 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1421 if (SUCCEEDED(hr))
1423 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1424 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1425 IUnknown_Release(iobjwithsite);
1427 else
1429 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1430 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1431 if (FAILED(hr)) return hr;
1433 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1434 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1435 IUnknown_Release(isecmgr);
1437 return hr;
1440 /*************************************************************************
1441 * @ [SHLWAPI.175]
1443 * Call IPersist_GetClassID() on an object.
1445 * PARAMS
1446 * lpUnknown [I] Object supporting the IPersist interface
1447 * lpClassId [O] Destination for Class Id
1449 * RETURNS
1450 * Success: S_OK. lpClassId contains the Class Id requested.
1451 * Failure: E_FAIL, If lpUnknown is NULL,
1452 * E_NOINTERFACE If lpUnknown does not support IPersist,
1453 * Or an HRESULT error code.
1455 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1457 IPersist* lpPersist;
1458 HRESULT hRet = E_FAIL;
1460 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1462 if (lpUnknown)
1464 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1465 if (SUCCEEDED(hRet))
1467 IPersist_GetClassID(lpPersist, lpClassId);
1468 IPersist_Release(lpPersist);
1471 return hRet;
1474 /*************************************************************************
1475 * @ [SHLWAPI.176]
1477 * Retrieve a Service Interface from an object.
1479 * PARAMS
1480 * lpUnknown [I] Object to get an IServiceProvider interface from
1481 * sid [I] Service ID for IServiceProvider_QueryService() call
1482 * riid [I] Function requested for QueryService call
1483 * lppOut [O] Destination for the service interface pointer
1485 * RETURNS
1486 * Success: S_OK. lppOut contains an object providing the requested service
1487 * Failure: An HRESULT error code
1489 * NOTES
1490 * lpUnknown is expected to support the IServiceProvider interface.
1492 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1493 LPVOID *lppOut)
1495 IServiceProvider* pService = NULL;
1496 HRESULT hRet;
1498 if (!lppOut)
1499 return E_FAIL;
1501 *lppOut = NULL;
1503 if (!lpUnknown)
1504 return E_FAIL;
1506 /* Get an IServiceProvider interface from the object */
1507 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1508 (LPVOID*)&pService);
1510 if (!hRet && pService)
1512 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1514 /* Get a Service interface from the object */
1515 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1517 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1519 /* Release the IServiceProvider interface */
1520 IUnknown_Release(pService);
1522 return hRet;
1525 /*************************************************************************
1526 * @ [SHLWAPI.177]
1528 * Loads a popup menu.
1530 * PARAMS
1531 * hInst [I] Instance handle
1532 * szName [I] Menu name
1534 * RETURNS
1535 * Success: TRUE.
1536 * Failure: FALSE.
1538 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1540 HMENU hMenu, hSubMenu;
1542 if ((hMenu = LoadMenuW(hInst, szName)))
1544 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1545 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1547 DestroyMenu(hMenu);
1548 return TRUE;
1550 return FALSE;
1553 typedef struct _enumWndData
1555 UINT uiMsgId;
1556 WPARAM wParam;
1557 LPARAM lParam;
1558 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1559 } enumWndData;
1561 /* Callback for SHLWAPI_178 */
1562 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1564 enumWndData *data = (enumWndData *)lParam;
1566 TRACE("(%p,%p)\n", hWnd, data);
1567 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1568 return TRUE;
1571 /*************************************************************************
1572 * @ [SHLWAPI.178]
1574 * Send or post a message to every child of a window.
1576 * PARAMS
1577 * hWnd [I] Window whose children will get the messages
1578 * uiMsgId [I] Message Id
1579 * wParam [I] WPARAM of message
1580 * lParam [I] LPARAM of message
1581 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1583 * RETURNS
1584 * Nothing.
1586 * NOTES
1587 * The appropriate ASCII or Unicode function is called for the window.
1589 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1591 enumWndData data;
1593 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1595 if(hWnd)
1597 data.uiMsgId = uiMsgId;
1598 data.wParam = wParam;
1599 data.lParam = lParam;
1601 if (bSend)
1602 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1603 else
1604 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1606 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1610 /*************************************************************************
1611 * @ [SHLWAPI.180]
1613 * Remove all sub-menus from a menu.
1615 * PARAMS
1616 * hMenu [I] Menu to remove sub-menus from
1618 * RETURNS
1619 * Success: 0. All sub-menus under hMenu are removed
1620 * Failure: -1, if any parameter is invalid
1622 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1624 int iItemCount = GetMenuItemCount(hMenu) - 1;
1625 while (iItemCount >= 0)
1627 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1628 if (hSubMenu)
1629 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1630 iItemCount--;
1632 return iItemCount;
1635 /*************************************************************************
1636 * @ [SHLWAPI.181]
1638 * Enable or disable a menu item.
1640 * PARAMS
1641 * hMenu [I] Menu holding menu item
1642 * uID [I] ID of menu item to enable/disable
1643 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1645 * RETURNS
1646 * The return code from EnableMenuItem.
1648 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1650 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1653 /*************************************************************************
1654 * @ [SHLWAPI.182]
1656 * Check or uncheck a menu item.
1658 * PARAMS
1659 * hMenu [I] Menu holding menu item
1660 * uID [I] ID of menu item to check/uncheck
1661 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1663 * RETURNS
1664 * The return code from CheckMenuItem.
1666 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1668 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1671 /*************************************************************************
1672 * @ [SHLWAPI.183]
1674 * Register a window class if it isn't already.
1676 * PARAMS
1677 * lpWndClass [I] Window class to register
1679 * RETURNS
1680 * The result of the RegisterClassA call.
1682 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1684 WNDCLASSA wca;
1685 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1686 return TRUE;
1687 return (DWORD)RegisterClassA(wndclass);
1690 /*************************************************************************
1691 * @ [SHLWAPI.186]
1693 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1694 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1696 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1697 POINTL pt = { 0, 0 };
1699 if (!lpPt)
1700 lpPt = &pt;
1702 if (!pdwEffect)
1703 pdwEffect = &dwEffect;
1705 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1707 if (*pdwEffect)
1708 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1710 IDropTarget_DragLeave(pDrop);
1711 return TRUE;
1714 /*************************************************************************
1715 * @ [SHLWAPI.187]
1717 * Call IPersistPropertyBag_Load() on an object.
1719 * PARAMS
1720 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1721 * lpPropBag [O] Destination for loaded IPropertyBag
1723 * RETURNS
1724 * Success: S_OK.
1725 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1727 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1729 IPersistPropertyBag* lpPPBag;
1730 HRESULT hRet = E_FAIL;
1732 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1734 if (lpUnknown)
1736 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1737 (void**)&lpPPBag);
1738 if (SUCCEEDED(hRet) && lpPPBag)
1740 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1741 IPersistPropertyBag_Release(lpPPBag);
1744 return hRet;
1747 /*************************************************************************
1748 * @ [SHLWAPI.188]
1750 * Call IOleControlSite_TranslateAccelerator() on an object.
1752 * PARAMS
1753 * lpUnknown [I] Object supporting the IOleControlSite interface.
1754 * lpMsg [I] Key message to be processed.
1755 * dwModifiers [I] Flags containing the state of the modifier keys.
1757 * RETURNS
1758 * Success: S_OK.
1759 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1761 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1763 IOleControlSite* lpCSite = NULL;
1764 HRESULT hRet = E_INVALIDARG;
1766 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1767 if (lpUnknown)
1769 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1770 (void**)&lpCSite);
1771 if (SUCCEEDED(hRet) && lpCSite)
1773 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1774 IOleControlSite_Release(lpCSite);
1777 return hRet;
1781 /*************************************************************************
1782 * @ [SHLWAPI.189]
1784 * Call IOleControlSite_OnFocus() on an object.
1786 * PARAMS
1787 * lpUnknown [I] Object supporting the IOleControlSite interface.
1788 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1790 * RETURNS
1791 * Success: S_OK.
1792 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1794 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1796 IOleControlSite* lpCSite = NULL;
1797 HRESULT hRet = E_FAIL;
1799 TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
1800 if (lpUnknown)
1802 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1803 (void**)&lpCSite);
1804 if (SUCCEEDED(hRet) && lpCSite)
1806 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1807 IOleControlSite_Release(lpCSite);
1810 return hRet;
1813 /*************************************************************************
1814 * @ [SHLWAPI.190]
1816 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1817 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1819 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1820 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1821 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1822 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1823 HRESULT hRet = E_INVALIDARG;
1824 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1826 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1828 if (lpUnknown && lpArg4)
1830 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1831 (REFGUID)function_id, (void**)&lpUnkInner);
1833 if (SUCCEEDED(hRet) && lpUnkInner)
1835 /* FIXME: The type of service object requested is unknown, however
1836 * testing shows that its first method is called with 4 parameters.
1837 * Fake this by using IParseDisplayName_ParseDisplayName since the
1838 * signature and position in the vtable matches our unknown object type.
1840 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1841 lpArg1, lpArg2, lpArg3, lpArg4);
1842 IUnknown_Release(lpUnkInner);
1845 return hRet;
1848 /*************************************************************************
1849 * @ [SHLWAPI.192]
1851 * Get a sub-menu from a menu item.
1853 * PARAMS
1854 * hMenu [I] Menu to get sub-menu from
1855 * uID [I] ID of menu item containing sub-menu
1857 * RETURNS
1858 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1860 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1862 MENUITEMINFOW mi;
1864 TRACE("(%p,%u)\n", hMenu, uID);
1866 mi.cbSize = sizeof(mi);
1867 mi.fMask = MIIM_SUBMENU;
1869 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1870 return NULL;
1872 return mi.hSubMenu;
1875 /*************************************************************************
1876 * @ [SHLWAPI.193]
1878 * Get the color depth of the primary display.
1880 * PARAMS
1881 * None.
1883 * RETURNS
1884 * The color depth of the primary display.
1886 DWORD WINAPI SHGetCurColorRes(void)
1888 HDC hdc;
1889 DWORD ret;
1891 TRACE("()\n");
1893 hdc = GetDC(0);
1894 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1895 ReleaseDC(0, hdc);
1896 return ret;
1899 /*************************************************************************
1900 * @ [SHLWAPI.194]
1902 * Wait for a message to arrive, with a timeout.
1904 * PARAMS
1905 * hand [I] Handle to query
1906 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1908 * RETURNS
1909 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1910 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1911 * message is available.
1913 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1915 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1916 DWORD dwRet;
1918 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1920 MSG msg;
1922 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1924 if (dwTimeout != INFINITE)
1926 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1927 return WAIT_TIMEOUT;
1931 return dwRet;
1934 /*************************************************************************
1935 * @ [SHLWAPI.195]
1937 * Determine if a shell folder can be expanded.
1939 * PARAMS
1940 * lpFolder [I] Parent folder containing the object to test.
1941 * pidl [I] Id of the object to test.
1943 * RETURNS
1944 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1945 * Failure: E_INVALIDARG, if any argument is invalid.
1947 * NOTES
1948 * If the object to be tested does not expose the IQueryInfo() interface it
1949 * will not be identified as an expandable folder.
1951 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
1953 HRESULT hRet = E_INVALIDARG;
1954 IQueryInfo *lpInfo;
1956 if (lpFolder && pidl)
1958 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
1959 NULL, (void**)&lpInfo);
1960 if (FAILED(hRet))
1961 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
1962 else
1964 DWORD dwFlags = 0;
1966 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
1967 * currently used". Really? You wouldn't be holding out on me would you?
1969 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
1971 if (SUCCEEDED(hRet))
1973 /* 0x2 is an undocumented flag apparently indicating expandability */
1974 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
1977 IQueryInfo_Release(lpInfo);
1980 return hRet;
1983 /*************************************************************************
1984 * @ [SHLWAPI.197]
1986 * Blank out a region of text by drawing the background only.
1988 * PARAMS
1989 * hDC [I] Device context to draw in
1990 * pRect [I] Area to draw in
1991 * cRef [I] Color to draw in
1993 * RETURNS
1994 * Nothing.
1996 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
1998 COLORREF cOldColor = SetBkColor(hDC, cRef);
1999 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2000 SetBkColor(hDC, cOldColor);
2001 return 0;
2004 /*************************************************************************
2005 * @ [SHLWAPI.198]
2007 * Return the value asociated with a key in a map.
2009 * PARAMS
2010 * lpKeys [I] A list of keys of length iLen
2011 * lpValues [I] A list of values associated with lpKeys, of length iLen
2012 * iLen [I] Length of both lpKeys and lpValues
2013 * iKey [I] The key value to look up in lpKeys
2015 * RETURNS
2016 * The value in lpValues associated with iKey, or -1 if iKey is not
2017 * found in lpKeys.
2019 * NOTES
2020 * - If two elements in the map share the same key, this function returns
2021 * the value closest to the start of the map
2022 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2024 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2026 if (lpKeys && lpValues)
2028 int i = 0;
2030 while (i < iLen)
2032 if (lpKeys[i] == iKey)
2033 return lpValues[i]; /* Found */
2034 i++;
2037 return -1; /* Not found */
2041 /*************************************************************************
2042 * @ [SHLWAPI.199]
2044 * Copy an interface pointer
2046 * PARAMS
2047 * lppDest [O] Destination for copy
2048 * lpUnknown [I] Source for copy
2050 * RETURNS
2051 * Nothing.
2053 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2055 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2057 if (lppDest)
2058 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2060 if (lpUnknown)
2062 /* Copy */
2063 IUnknown_AddRef(lpUnknown);
2064 *lppDest = lpUnknown;
2068 /*************************************************************************
2069 * @ [SHLWAPI.200]
2072 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2073 REFGUID riidCmdGrp, ULONG cCmds,
2074 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2076 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2077 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2079 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2080 return DRAGDROP_E_NOTREGISTERED;
2083 /*************************************************************************
2084 * @ [SHLWAPI.201]
2087 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2088 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2089 VARIANT* pvaOut)
2091 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2092 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2093 return DRAGDROP_E_NOTREGISTERED;
2096 /*************************************************************************
2097 * @ [SHLWAPI.202]
2100 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2102 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2103 return DRAGDROP_E_NOTREGISTERED;
2106 /*************************************************************************
2107 * @ [SHLWAPI.204]
2109 * Determine if a window is not a child of another window.
2111 * PARAMS
2112 * hParent [I] Suspected parent window
2113 * hChild [I] Suspected child window
2115 * RETURNS
2116 * TRUE: If hChild is a child window of hParent
2117 * FALSE: If hChild is not a child window of hParent, or they are equal
2119 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2121 TRACE("(%p,%p)\n", hParent, hChild);
2123 if (!hParent || !hChild)
2124 return TRUE;
2125 else if(hParent == hChild)
2126 return FALSE;
2127 return !IsChild(hParent, hChild);
2130 /*************************************************************************
2131 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2134 typedef struct
2136 DWORD num_items; /* Number of elements inserted */
2137 void *mem; /* Ptr to array */
2138 DWORD blocks_alloced; /* Number of elements allocated */
2139 BYTE inc; /* Number of elements to grow by when we need to expand */
2140 BYTE block_size; /* Size in bytes of an element */
2141 BYTE flags; /* Flags */
2142 } FDSA_info;
2144 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2146 /*************************************************************************
2147 * @ [SHLWAPI.208]
2149 * Initialize an FDSA arrary.
2151 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2152 DWORD init_blocks)
2154 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2156 if(inc == 0)
2157 inc = 1;
2159 if(mem)
2160 memset(mem, 0, block_size * init_blocks);
2162 info->num_items = 0;
2163 info->inc = inc;
2164 info->mem = mem;
2165 info->blocks_alloced = init_blocks;
2166 info->block_size = block_size;
2167 info->flags = 0;
2169 return TRUE;
2172 /*************************************************************************
2173 * @ [SHLWAPI.209]
2175 * Destroy an FDSA array
2177 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2179 TRACE("(%p)\n", info);
2181 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2183 HeapFree(GetProcessHeap(), 0, info->mem);
2184 return FALSE;
2187 return TRUE;
2190 /*************************************************************************
2191 * @ [SHLWAPI.210]
2193 * Insert element into an FDSA array
2195 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2197 TRACE("(%p 0x%08x %p)\n", info, where, block);
2198 if(where > info->num_items)
2199 where = info->num_items;
2201 if(info->num_items >= info->blocks_alloced)
2203 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2204 if(info->flags & 0x1)
2205 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2206 else
2208 void *old_mem = info->mem;
2209 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2210 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2212 info->blocks_alloced += info->inc;
2213 info->flags |= 0x1;
2216 if(where < info->num_items)
2218 memmove((char*)info->mem + (where + 1) * info->block_size,
2219 (char*)info->mem + where * info->block_size,
2220 (info->num_items - where) * info->block_size);
2222 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2224 info->num_items++;
2225 return where;
2228 /*************************************************************************
2229 * @ [SHLWAPI.211]
2231 * Delete an element from an FDSA array.
2233 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2235 TRACE("(%p 0x%08x)\n", info, where);
2237 if(where >= info->num_items)
2238 return FALSE;
2240 if(where < info->num_items - 1)
2242 memmove((char*)info->mem + where * info->block_size,
2243 (char*)info->mem + (where + 1) * info->block_size,
2244 (info->num_items - where - 1) * info->block_size);
2246 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2247 0, info->block_size);
2248 info->num_items--;
2249 return TRUE;
2253 typedef struct {
2254 REFIID refid;
2255 DWORD indx;
2256 } IFACE_INDEX_TBL;
2258 /*************************************************************************
2259 * @ [SHLWAPI.219]
2261 * Call IUnknown_QueryInterface() on a table of objects.
2263 * RETURNS
2264 * Success: S_OK.
2265 * Failure: E_POINTER or E_NOINTERFACE.
2267 HRESULT WINAPI QISearch(
2268 LPVOID w, /* [in] Table of interfaces */
2269 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2270 REFIID riid, /* [in] REFIID to get interface for */
2271 LPVOID *ppv) /* [out] Destination for interface pointer */
2273 HRESULT ret;
2274 IUnknown *a_vtbl;
2275 IFACE_INDEX_TBL *xmove;
2277 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2278 if (ppv) {
2279 xmove = x;
2280 while (xmove->refid) {
2281 TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2282 if (IsEqualIID(riid, xmove->refid)) {
2283 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2284 TRACE("matched, returning (%p)\n", a_vtbl);
2285 *ppv = (LPVOID)a_vtbl;
2286 IUnknown_AddRef(a_vtbl);
2287 return S_OK;
2289 xmove++;
2292 if (IsEqualIID(riid, &IID_IUnknown)) {
2293 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2294 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2295 *ppv = (LPVOID)a_vtbl;
2296 IUnknown_AddRef(a_vtbl);
2297 return S_OK;
2299 *ppv = 0;
2300 ret = E_NOINTERFACE;
2301 } else
2302 ret = E_POINTER;
2304 TRACE("-- 0x%08x\n", ret);
2305 return ret;
2308 /*************************************************************************
2309 * @ [SHLWAPI.221]
2311 * Remove the "PropDlgFont" property from a window.
2313 * PARAMS
2314 * hWnd [I] Window to remove the property from
2316 * RETURNS
2317 * A handle to the removed property, or NULL if it did not exist.
2319 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2321 HANDLE hProp;
2323 TRACE("(%p)\n", hWnd);
2325 hProp = GetPropA(hWnd, "PropDlgFont");
2327 if(hProp)
2329 DeleteObject(hProp);
2330 hProp = RemovePropA(hWnd, "PropDlgFont");
2332 return hProp;
2335 /*************************************************************************
2336 * @ [SHLWAPI.236]
2338 * Load the in-process server of a given GUID.
2340 * PARAMS
2341 * refiid [I] GUID of the server to load.
2343 * RETURNS
2344 * Success: A handle to the loaded server dll.
2345 * Failure: A NULL handle.
2347 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2349 HKEY newkey;
2350 DWORD type, count;
2351 CHAR value[MAX_PATH], string[MAX_PATH];
2353 strcpy(string, "CLSID\\");
2354 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2355 strcat(string, "\\InProcServer32");
2357 count = MAX_PATH;
2358 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2359 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2360 RegCloseKey(newkey);
2361 return LoadLibraryExA(value, 0, 0);
2364 /*************************************************************************
2365 * @ [SHLWAPI.237]
2367 * Unicode version of SHLWAPI_183.
2369 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2371 WNDCLASSW WndClass;
2373 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2375 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2376 return TRUE;
2377 return RegisterClassW(lpWndClass);
2380 /*************************************************************************
2381 * @ [SHLWAPI.238]
2383 * Unregister a list of classes.
2385 * PARAMS
2386 * hInst [I] Application instance that registered the classes
2387 * lppClasses [I] List of class names
2388 * iCount [I] Number of names in lppClasses
2390 * RETURNS
2391 * Nothing.
2393 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2395 WNDCLASSA WndClass;
2397 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2399 while (iCount > 0)
2401 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2402 UnregisterClassA(*lppClasses, hInst);
2403 lppClasses++;
2404 iCount--;
2408 /*************************************************************************
2409 * @ [SHLWAPI.239]
2411 * Unicode version of SHUnregisterClassesA.
2413 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2415 WNDCLASSW WndClass;
2417 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2419 while (iCount > 0)
2421 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2422 UnregisterClassW(*lppClasses, hInst);
2423 lppClasses++;
2424 iCount--;
2428 /*************************************************************************
2429 * @ [SHLWAPI.240]
2431 * Call The correct (Ascii/Unicode) default window procedure for a window.
2433 * PARAMS
2434 * hWnd [I] Window to call the default procedure for
2435 * uMessage [I] Message ID
2436 * wParam [I] WPARAM of message
2437 * lParam [I] LPARAM of message
2439 * RETURNS
2440 * The result of calling DefWindowProcA() or DefWindowProcW().
2442 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2444 if (IsWindowUnicode(hWnd))
2445 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2446 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2449 /*************************************************************************
2450 * @ [SHLWAPI.256]
2452 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2454 HRESULT hRet = E_INVALIDARG;
2455 LPOBJECTWITHSITE lpSite = NULL;
2457 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2459 if (lpUnknown && iid && lppSite)
2461 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2462 (void**)&lpSite);
2463 if (SUCCEEDED(hRet) && lpSite)
2465 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2466 IObjectWithSite_Release(lpSite);
2469 return hRet;
2472 /*************************************************************************
2473 * @ [SHLWAPI.257]
2475 * Create a worker window using CreateWindowExA().
2477 * PARAMS
2478 * wndProc [I] Window procedure
2479 * hWndParent [I] Parent window
2480 * dwExStyle [I] Extra style flags
2481 * dwStyle [I] Style flags
2482 * hMenu [I] Window menu
2483 * z [I] Unknown
2485 * RETURNS
2486 * Success: The window handle of the newly created window.
2487 * Failure: 0.
2489 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2490 DWORD dwStyle, HMENU hMenu, LONG z)
2492 static const char szClass[] = "WorkerA";
2493 WNDCLASSA wc;
2494 HWND hWnd;
2496 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2497 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2499 /* Create Window class */
2500 wc.style = 0;
2501 wc.lpfnWndProc = DefWindowProcA;
2502 wc.cbClsExtra = 0;
2503 wc.cbWndExtra = 4;
2504 wc.hInstance = shlwapi_hInstance;
2505 wc.hIcon = NULL;
2506 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2507 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2508 wc.lpszMenuName = NULL;
2509 wc.lpszClassName = szClass;
2511 SHRegisterClassA(&wc); /* Register class */
2513 /* FIXME: Set extra bits in dwExStyle */
2515 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2516 hWndParent, hMenu, shlwapi_hInstance, 0);
2517 if (hWnd)
2519 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2521 if (wndProc)
2522 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2524 return hWnd;
2527 typedef struct tagPOLICYDATA
2529 DWORD policy; /* flags value passed to SHRestricted */
2530 LPCWSTR appstr; /* application str such as "Explorer" */
2531 LPCWSTR keystr; /* name of the actual registry key / policy */
2532 } POLICYDATA, *LPPOLICYDATA;
2534 #define SHELL_NO_POLICY 0xffffffff
2536 /* default shell policy registry key */
2537 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2538 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2539 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2540 '\\','P','o','l','i','c','i','e','s',0};
2542 /*************************************************************************
2543 * @ [SHLWAPI.271]
2545 * Retrieve a policy value from the registry.
2547 * PARAMS
2548 * lpSubKey [I] registry key name
2549 * lpSubName [I] subname of registry key
2550 * lpValue [I] value name of registry value
2552 * RETURNS
2553 * the value associated with the registry key or 0 if not found
2555 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2557 DWORD retval, datsize = sizeof(retval);
2558 HKEY hKey;
2560 if (!lpSubKey)
2561 lpSubKey = strRegistryPolicyW;
2563 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2564 if (retval != ERROR_SUCCESS)
2565 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2566 if (retval != ERROR_SUCCESS)
2567 return 0;
2569 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2570 RegCloseKey(hKey);
2571 return retval;
2574 /*************************************************************************
2575 * @ [SHLWAPI.266]
2577 * Helper function to retrieve the possibly cached value for a specific policy
2579 * PARAMS
2580 * policy [I] The policy to look for
2581 * initial [I] Main registry key to open, if NULL use default
2582 * polTable [I] Table of known policies, 0 terminated
2583 * polArr [I] Cache array of policy values
2585 * RETURNS
2586 * The retrieved policy value or 0 if not successful
2588 * NOTES
2589 * This function is used by the native SHRestricted function to search for the
2590 * policy and cache it once retrieved. The current Wine implementation uses a
2591 * different POLICYDATA structure and implements a similar algorithme adapted to
2592 * that structure.
2594 DWORD WINAPI SHRestrictionLookup(
2595 DWORD policy,
2596 LPCWSTR initial,
2597 LPPOLICYDATA polTable,
2598 LPDWORD polArr)
2600 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2602 if (!polTable || !polArr)
2603 return 0;
2605 for (;polTable->policy; polTable++, polArr++)
2607 if (policy == polTable->policy)
2609 /* we have a known policy */
2611 /* check if this policy has been cached */
2612 if (*polArr == SHELL_NO_POLICY)
2613 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2614 return *polArr;
2617 /* we don't know this policy, return 0 */
2618 TRACE("unknown policy: (%08x)\n", policy);
2619 return 0;
2622 /*************************************************************************
2623 * @ [SHLWAPI.267]
2625 * Get an interface from an object.
2627 * RETURNS
2628 * Success: S_OK. ppv contains the requested interface.
2629 * Failure: An HRESULT error code.
2631 * NOTES
2632 * This QueryInterface asks the inner object for an interface. In case
2633 * of aggregation this request would be forwarded by the inner to the
2634 * outer object. This function asks the inner object directly for the
2635 * interface circumventing the forwarding to the outer object.
2637 HRESULT WINAPI SHWeakQueryInterface(
2638 IUnknown * pUnk, /* [in] Outer object */
2639 IUnknown * pInner, /* [in] Inner object */
2640 IID * riid, /* [in] Interface GUID to query for */
2641 LPVOID* ppv) /* [out] Destination for queried interface */
2643 HRESULT hret = E_NOINTERFACE;
2644 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2646 *ppv = NULL;
2647 if(pUnk && pInner) {
2648 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2649 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2651 TRACE("-- 0x%08x\n", hret);
2652 return hret;
2655 /*************************************************************************
2656 * @ [SHLWAPI.268]
2658 * Move a reference from one interface to another.
2660 * PARAMS
2661 * lpDest [O] Destination to receive the reference
2662 * lppUnknown [O] Source to give up the reference to lpDest
2664 * RETURNS
2665 * Nothing.
2667 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2669 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2671 if (*lppUnknown)
2673 /* Copy Reference*/
2674 IUnknown_AddRef(lpDest);
2675 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2679 /*************************************************************************
2680 * @ [SHLWAPI.269]
2682 * Convert an ASCII string of a CLSID into a CLSID.
2684 * PARAMS
2685 * idstr [I] String representing a CLSID in registry format
2686 * id [O] Destination for the converted CLSID
2688 * RETURNS
2689 * Success: TRUE. id contains the converted CLSID.
2690 * Failure: FALSE.
2692 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2694 WCHAR wClsid[40];
2695 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2696 return SUCCEEDED(CLSIDFromString(wClsid, id));
2699 /*************************************************************************
2700 * @ [SHLWAPI.270]
2702 * Unicode version of GUIDFromStringA.
2704 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2706 return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
2709 /*************************************************************************
2710 * @ [SHLWAPI.276]
2712 * Determine if the browser is integrated into the shell, and set a registry
2713 * key accordingly.
2715 * PARAMS
2716 * None.
2718 * RETURNS
2719 * 1, If the browser is not integrated.
2720 * 2, If the browser is integrated.
2722 * NOTES
2723 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2724 * either set to TRUE, or removed depending on whether the browser is deemed
2725 * to be integrated.
2727 DWORD WINAPI WhichPlatform(void)
2729 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2730 static DWORD dwState = 0;
2731 HKEY hKey;
2732 DWORD dwRet, dwData, dwSize;
2733 HMODULE hshell32;
2735 if (dwState)
2736 return dwState;
2738 /* If shell32 exports DllGetVersion(), the browser is integrated */
2739 dwState = 1;
2740 hshell32 = LoadLibraryA("shell32.dll");
2741 if (hshell32)
2743 FARPROC pDllGetVersion;
2744 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2745 dwState = pDllGetVersion ? 2 : 1;
2746 FreeLibrary(hshell32);
2749 /* Set or delete the key accordingly */
2750 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2751 "Software\\Microsoft\\Internet Explorer", 0,
2752 KEY_ALL_ACCESS, &hKey);
2753 if (!dwRet)
2755 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2756 (LPBYTE)&dwData, &dwSize);
2758 if (!dwRet && dwState == 1)
2760 /* Value exists but browser is not integrated */
2761 RegDeleteValueA(hKey, szIntegratedBrowser);
2763 else if (dwRet && dwState == 2)
2765 /* Browser is integrated but value does not exist */
2766 dwData = TRUE;
2767 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2768 (LPBYTE)&dwData, sizeof(dwData));
2770 RegCloseKey(hKey);
2772 return dwState;
2775 /*************************************************************************
2776 * @ [SHLWAPI.278]
2778 * Unicode version of SHCreateWorkerWindowA.
2780 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2781 DWORD dwStyle, HMENU hMenu, LONG z)
2783 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2784 WNDCLASSW wc;
2785 HWND hWnd;
2787 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2788 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2790 /* If our OS is natively ASCII, use the ASCII version */
2791 if (!(GetVersion() & 0x80000000)) /* NT */
2792 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2794 /* Create Window class */
2795 wc.style = 0;
2796 wc.lpfnWndProc = DefWindowProcW;
2797 wc.cbClsExtra = 0;
2798 wc.cbWndExtra = 4;
2799 wc.hInstance = shlwapi_hInstance;
2800 wc.hIcon = NULL;
2801 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2802 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2803 wc.lpszMenuName = NULL;
2804 wc.lpszClassName = szClass;
2806 SHRegisterClassW(&wc); /* Register class */
2808 /* FIXME: Set extra bits in dwExStyle */
2810 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2811 hWndParent, hMenu, shlwapi_hInstance, 0);
2812 if (hWnd)
2814 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2816 if (wndProc)
2817 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2819 return hWnd;
2822 /*************************************************************************
2823 * @ [SHLWAPI.279]
2825 * Get and show a context menu from a shell folder.
2827 * PARAMS
2828 * hWnd [I] Window displaying the shell folder
2829 * lpFolder [I] IShellFolder interface
2830 * lpApidl [I] Id for the particular folder desired
2832 * RETURNS
2833 * Success: S_OK.
2834 * Failure: An HRESULT error code indicating the error.
2836 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2838 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2841 /*************************************************************************
2842 * @ [SHLWAPI.281]
2844 * _SHPackDispParamsV
2846 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2848 FIXME("%p %p %p %p\n",w,x,y,z);
2849 return E_FAIL;
2852 /*************************************************************************
2853 * @ [SHLWAPI.282]
2855 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2856 * function does...).
2858 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2860 FIXME("%p %p %p %p\n", w, x, y, z);
2861 return E_FAIL;
2864 /*************************************************************************
2865 * SHLWAPI_InvokeByIID
2867 * This helper function calls IDispatch::Invoke for each sink
2868 * which implements given iid or IDispatch.
2871 static HRESULT SHLWAPI_InvokeByIID(
2872 IConnectionPoint* iCP,
2873 REFIID iid,
2874 DISPID dispId,
2875 DISPPARAMS* dispParams)
2877 IEnumConnections *enumerator;
2878 CONNECTDATA rgcd;
2880 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
2881 if (FAILED(result))
2882 return result;
2884 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
2886 IDispatch *dispIface;
2887 if (SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface)) ||
2888 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
2890 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, dispParams, NULL, NULL, NULL);
2891 IDispatch_Release(dispIface);
2895 IEnumConnections_Release(enumerator);
2897 return S_OK;
2900 /*************************************************************************
2901 * @ [SHLWAPI.284]
2903 * IConnectionPoint_SimpleInvoke
2905 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
2906 IConnectionPoint* iCP,
2907 DISPID dispId,
2908 DISPPARAMS* dispParams)
2910 IID iid;
2911 HRESULT result;
2913 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
2915 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
2916 if (SUCCEEDED(result))
2917 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
2919 return result;
2922 /*************************************************************************
2923 * @ [SHLWAPI.285]
2925 * Notify an IConnectionPoint object of changes.
2927 * PARAMS
2928 * lpCP [I] Object to notify
2929 * dispID [I]
2931 * RETURNS
2932 * Success: S_OK.
2933 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2934 * IConnectionPoint interface.
2936 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2938 IEnumConnections *lpEnum;
2939 HRESULT hRet = E_NOINTERFACE;
2941 TRACE("(%p,0x%8X)\n", lpCP, dispID);
2943 /* Get an enumerator for the connections */
2944 if (lpCP)
2945 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2947 if (SUCCEEDED(hRet))
2949 IPropertyNotifySink *lpSink;
2950 CONNECTDATA connData;
2951 ULONG ulFetched;
2953 /* Call OnChanged() for every notify sink in the connection point */
2954 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2956 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2957 lpSink)
2959 IPropertyNotifySink_OnChanged(lpSink, dispID);
2960 IPropertyNotifySink_Release(lpSink);
2962 IUnknown_Release(connData.pUnk);
2965 IEnumConnections_Release(lpEnum);
2967 return hRet;
2970 /*************************************************************************
2971 * @ [SHLWAPI.286]
2973 * IUnknown_CPContainerInvokeParam
2975 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
2976 IUnknown *container,
2977 REFIID riid,
2978 DISPID dispId,
2979 VARIANTARG* buffer,
2980 DWORD cParams, ...)
2982 HRESULT result;
2983 IConnectionPoint *iCP;
2984 IConnectionPointContainer *iCPC;
2986 if (!container)
2987 return E_NOINTERFACE;
2989 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
2990 if (SUCCEEDED(result))
2992 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
2993 IConnectionPointContainer_Release(iCPC);
2996 if (SUCCEEDED(result))
2998 ULONG cnt;
2999 VARIANTARG *curvar = buffer+cParams-1;
3000 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3001 va_list valist;
3003 va_start(valist, cParams);
3004 for(cnt=cParams;cnt>0;cnt--,curvar--) /* backwards for some reason */
3006 enum VARENUM vt = va_arg(valist, enum VARENUM);
3007 memset(curvar, 0, sizeof(*curvar));
3008 if (vt & VT_BYREF)
3010 V_VT(curvar) = vt;
3011 V_BYREF(curvar) = va_arg(valist, LPVOID);
3012 } else
3013 switch(vt)
3015 case VT_BSTR:
3016 V_VT(curvar) = vt;
3017 V_BSTR(curvar) = va_arg(valist, BSTR);
3018 break;
3019 case VT_DISPATCH:
3020 V_VT(curvar) = vt;
3021 V_DISPATCH(curvar) = va_arg(valist, IDispatch*);
3022 break;
3023 case VT_BOOL:
3024 V_VT(curvar) = vt;
3025 V_BOOL(curvar) = va_arg(valist, int);
3026 break;
3027 case VT_UNKNOWN:
3028 V_VT(curvar) = vt;
3029 V_UNKNOWN(curvar) = va_arg(valist, IUnknown*);
3030 break;
3031 case VT_I4:
3032 default:
3033 V_VT(curvar) = VT_I4;
3034 V_I4(curvar) = va_arg(valist, LONG);
3035 break;
3038 va_end(valist);
3040 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3041 IConnectionPoint_Release(iCP);
3044 return result;
3047 /*************************************************************************
3048 * @ [SHLWAPI.287]
3050 * Notify an IConnectionPointContainer object of changes.
3052 * PARAMS
3053 * lpUnknown [I] Object to notify
3054 * dispID [I]
3056 * RETURNS
3057 * Success: S_OK.
3058 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3059 * IConnectionPointContainer interface.
3061 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3063 IConnectionPointContainer* lpCPC = NULL;
3064 HRESULT hRet = E_NOINTERFACE;
3066 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3068 if (lpUnknown)
3069 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3071 if (SUCCEEDED(hRet))
3073 IConnectionPoint* lpCP;
3075 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3076 IConnectionPointContainer_Release(lpCPC);
3078 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3079 IConnectionPoint_Release(lpCP);
3081 return hRet;
3084 /*************************************************************************
3085 * @ [SHLWAPI.289]
3087 * See PlaySoundW.
3089 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3091 return PlaySoundW(pszSound, hmod, fdwSound);
3094 /*************************************************************************
3095 * @ [SHLWAPI.294]
3097 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3099 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3100 pStr, some_len, debugstr_w(lpStr2));
3101 return TRUE;
3104 /*************************************************************************
3105 * @ [SHLWAPI.295]
3107 * Called by ICQ2000b install via SHDOCVW:
3108 * str1: "InternetShortcut"
3109 * x: some unknown pointer
3110 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3111 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3113 * In short: this one maybe creates a desktop link :-)
3115 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3117 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3118 return TRUE;
3121 /*************************************************************************
3122 * @ [SHLWAPI.313]
3124 * See SHGetFileInfoW.
3126 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3127 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3129 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3132 /*************************************************************************
3133 * @ [SHLWAPI.318]
3135 * See DragQueryFileW.
3137 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3139 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3142 /*************************************************************************
3143 * @ [SHLWAPI.333]
3145 * See SHBrowseForFolderW.
3147 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3149 return SHBrowseForFolderW(lpBi);
3152 /*************************************************************************
3153 * @ [SHLWAPI.334]
3155 * See SHGetPathFromIDListW.
3157 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3159 return SHGetPathFromIDListW(pidl, pszPath);
3162 /*************************************************************************
3163 * @ [SHLWAPI.335]
3165 * See ShellExecuteExW.
3167 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3169 return ShellExecuteExW(lpExecInfo);
3172 /*************************************************************************
3173 * @ [SHLWAPI.336]
3175 * See SHFileOperationW.
3177 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3179 return SHFileOperationW(lpFileOp);
3182 /*************************************************************************
3183 * @ [SHLWAPI.342]
3186 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3188 return InterlockedCompareExchangePointer( dest, xchg, compare );
3191 /*************************************************************************
3192 * @ [SHLWAPI.350]
3194 * See GetFileVersionInfoSizeW.
3196 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3198 return GetFileVersionInfoSizeW( filename, handle );
3201 /*************************************************************************
3202 * @ [SHLWAPI.351]
3204 * See GetFileVersionInfoW.
3206 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3207 DWORD datasize, LPVOID data )
3209 return GetFileVersionInfoW( filename, handle, datasize, data );
3212 /*************************************************************************
3213 * @ [SHLWAPI.352]
3215 * See VerQueryValueW.
3217 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3218 LPVOID *lplpBuffer, UINT *puLen )
3220 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3223 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3224 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3225 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3227 /*************************************************************************
3228 * @ [SHLWAPI.355]
3230 * Change the modality of a shell object.
3232 * PARAMS
3233 * lpUnknown [I] Object to make modeless
3234 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3236 * RETURNS
3237 * Success: S_OK. The modality lpUnknown is changed.
3238 * Failure: An HRESULT error code indicating the error.
3240 * NOTES
3241 * lpUnknown must support the IOleInPlaceFrame interface, the
3242 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3243 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3244 * or this call will fail.
3246 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3248 IUnknown *lpObj;
3249 HRESULT hRet;
3251 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3253 if (!lpUnknown)
3254 return E_FAIL;
3256 if (IsIface(IOleInPlaceActiveObject))
3257 EnableModeless(IOleInPlaceActiveObject);
3258 else if (IsIface(IOleInPlaceFrame))
3259 EnableModeless(IOleInPlaceFrame);
3260 else if (IsIface(IShellBrowser))
3261 EnableModeless(IShellBrowser);
3262 #if 0
3263 /* FIXME: Wine has no headers for these objects yet */
3264 else if (IsIface(IInternetSecurityMgrSite))
3265 EnableModeless(IInternetSecurityMgrSite);
3266 else if (IsIface(IDocHostUIHandler))
3267 EnableModeless(IDocHostUIHandler);
3268 #endif
3269 else
3270 return hRet;
3272 IUnknown_Release(lpObj);
3273 return S_OK;
3276 /*************************************************************************
3277 * @ [SHLWAPI.357]
3279 * See SHGetNewLinkInfoW.
3281 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3282 BOOL *pfMustCopy, UINT uFlags)
3284 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3287 /*************************************************************************
3288 * @ [SHLWAPI.358]
3290 * See SHDefExtractIconW.
3292 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3293 HICON* phiconSmall, UINT nIconSize)
3295 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3298 /*************************************************************************
3299 * @ [SHLWAPI.363]
3301 * Get and show a context menu from a shell folder.
3303 * PARAMS
3304 * hWnd [I] Window displaying the shell folder
3305 * lpFolder [I] IShellFolder interface
3306 * lpApidl [I] Id for the particular folder desired
3307 * bInvokeDefault [I] Whether to invoke the default menu item
3309 * RETURNS
3310 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3311 * executed.
3312 * Failure: An HRESULT error code indicating the error.
3314 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3316 IContextMenu *iContext;
3317 HRESULT hRet = E_FAIL;
3319 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3321 if (!lpFolder)
3322 return hRet;
3324 /* Get the context menu from the shell folder */
3325 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3326 &IID_IContextMenu, 0, (void**)&iContext);
3327 if (SUCCEEDED(hRet))
3329 HMENU hMenu;
3330 if ((hMenu = CreatePopupMenu()))
3332 HRESULT hQuery;
3333 DWORD dwDefaultId = 0;
3335 /* Add the context menu entries to the popup */
3336 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3337 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3339 if (SUCCEEDED(hQuery))
3341 if (bInvokeDefault &&
3342 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3344 CMINVOKECOMMANDINFO cmIci;
3345 /* Invoke the default item */
3346 memset(&cmIci,0,sizeof(cmIci));
3347 cmIci.cbSize = sizeof(cmIci);
3348 cmIci.fMask = CMIC_MASK_ASYNCOK;
3349 cmIci.hwnd = hWnd;
3350 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3351 cmIci.nShow = SW_SCROLLCHILDREN;
3353 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3356 DestroyMenu(hMenu);
3358 IContextMenu_Release(iContext);
3360 return hRet;
3363 /*************************************************************************
3364 * @ [SHLWAPI.370]
3366 * See ExtractIconW.
3368 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3369 UINT nIconIndex)
3371 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3374 /*************************************************************************
3375 * @ [SHLWAPI.377]
3377 * Load a library from the directory of a particular process.
3379 * PARAMS
3380 * new_mod [I] Library name
3381 * inst_hwnd [I] Module whose directory is to be used
3382 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3384 * RETURNS
3385 * Success: A handle to the loaded module
3386 * Failure: A NULL handle.
3388 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3390 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3391 * each call here.
3392 * FIXME: Native shows calls to:
3393 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3394 * CheckVersion
3395 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3396 * RegQueryValueExA for "LPKInstalled"
3397 * RegCloseKey
3398 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3399 * RegQueryValueExA for "ResourceLocale"
3400 * RegCloseKey
3401 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3402 * RegQueryValueExA for "Locale"
3403 * RegCloseKey
3404 * and then tests the Locale ("en" for me).
3405 * code below
3406 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3408 CHAR mod_path[2*MAX_PATH];
3409 LPSTR ptr;
3410 DWORD len;
3412 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3413 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3414 if (!len || len >= sizeof(mod_path)) return NULL;
3416 ptr = strrchr(mod_path, '\\');
3417 if (ptr) {
3418 strcpy(ptr+1, new_mod);
3419 TRACE("loading %s\n", debugstr_a(mod_path));
3420 return LoadLibraryA(mod_path);
3422 return NULL;
3425 /*************************************************************************
3426 * @ [SHLWAPI.378]
3428 * Unicode version of MLLoadLibraryA.
3430 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3432 WCHAR mod_path[2*MAX_PATH];
3433 LPWSTR ptr;
3434 DWORD len;
3436 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3437 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3438 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3440 ptr = strrchrW(mod_path, '\\');
3441 if (ptr) {
3442 strcpyW(ptr+1, new_mod);
3443 TRACE("loading %s\n", debugstr_w(mod_path));
3444 return LoadLibraryW(mod_path);
3446 return NULL;
3449 /*************************************************************************
3450 * ColorAdjustLuma [SHLWAPI.@]
3452 * Adjust the luminosity of a color
3454 * PARAMS
3455 * cRGB [I] RGB value to convert
3456 * dwLuma [I] Luma adjustment
3457 * bUnknown [I] Unknown
3459 * RETURNS
3460 * The adjusted RGB color.
3462 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3464 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3466 if (dwLuma)
3468 WORD wH, wL, wS;
3470 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3472 FIXME("Ignoring luma adjustment\n");
3474 /* FIXME: The ajdustment is not linear */
3476 cRGB = ColorHLSToRGB(wH, wL, wS);
3478 return cRGB;
3481 /*************************************************************************
3482 * @ [SHLWAPI.389]
3484 * See GetSaveFileNameW.
3486 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3488 return GetSaveFileNameW(ofn);
3491 /*************************************************************************
3492 * @ [SHLWAPI.390]
3494 * See WNetRestoreConnectionW.
3496 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3498 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3501 /*************************************************************************
3502 * @ [SHLWAPI.391]
3504 * See WNetGetLastErrorW.
3506 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3507 LPWSTR lpNameBuf, DWORD nNameBufSize)
3509 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3512 /*************************************************************************
3513 * @ [SHLWAPI.401]
3515 * See PageSetupDlgW.
3517 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3519 return PageSetupDlgW(pagedlg);
3522 /*************************************************************************
3523 * @ [SHLWAPI.402]
3525 * See PrintDlgW.
3527 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3529 return PrintDlgW(printdlg);
3532 /*************************************************************************
3533 * @ [SHLWAPI.403]
3535 * See GetOpenFileNameW.
3537 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3539 return GetOpenFileNameW(ofn);
3542 /*************************************************************************
3543 * @ [SHLWAPI.404]
3545 HRESULT WINAPI IUnknown_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3547 IPersist *persist;
3548 HRESULT hr;
3550 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3551 if(SUCCEEDED(hr))
3553 CLSID clsid;
3554 hr = IPersist_GetClassID(persist, &clsid);
3555 if(SUCCEEDED(hr))
3557 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3558 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3559 else
3560 hr = E_FAIL;
3562 IPersist_Release(persist);
3564 return hr;
3567 /* INTERNAL: Map from HLS color space to RGB */
3568 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3570 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3572 if (wHue > 160)
3573 return wMid1;
3574 else if (wHue > 120)
3575 wHue = 160 - wHue;
3576 else if (wHue > 40)
3577 return wMid2;
3579 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3582 /* Convert to RGB and scale into RGB range (0..255) */
3583 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3585 /*************************************************************************
3586 * ColorHLSToRGB [SHLWAPI.@]
3588 * Convert from hls color space into an rgb COLORREF.
3590 * PARAMS
3591 * wHue [I] Hue amount
3592 * wLuminosity [I] Luminosity amount
3593 * wSaturation [I] Saturation amount
3595 * RETURNS
3596 * A COLORREF representing the converted color.
3598 * NOTES
3599 * Input hls values are constrained to the range (0..240).
3601 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3603 WORD wRed;
3605 if (wSaturation)
3607 WORD wGreen, wBlue, wMid1, wMid2;
3609 if (wLuminosity > 120)
3610 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3611 else
3612 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3614 wMid1 = wLuminosity * 2 - wMid2;
3616 wRed = GET_RGB(wHue + 80);
3617 wGreen = GET_RGB(wHue);
3618 wBlue = GET_RGB(wHue - 80);
3620 return RGB(wRed, wGreen, wBlue);
3623 wRed = wLuminosity * 255 / 240;
3624 return RGB(wRed, wRed, wRed);
3627 /*************************************************************************
3628 * @ [SHLWAPI.413]
3630 * Get the current docking status of the system.
3632 * PARAMS
3633 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3635 * RETURNS
3636 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3637 * a notebook.
3639 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3641 HW_PROFILE_INFOA hwInfo;
3643 TRACE("(0x%08x)\n", dwFlags);
3645 GetCurrentHwProfileA(&hwInfo);
3646 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3648 case DOCKINFO_DOCKED:
3649 case DOCKINFO_UNDOCKED:
3650 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3651 default:
3652 return 0;
3656 /*************************************************************************
3657 * @ [SHLWAPI.418]
3659 * Function seems to do FreeLibrary plus other things.
3661 * FIXME native shows the following calls:
3662 * RtlEnterCriticalSection
3663 * LocalFree
3664 * GetProcAddress(Comctl32??, 150L)
3665 * DPA_DeletePtr
3666 * RtlLeaveCriticalSection
3667 * followed by the FreeLibrary.
3668 * The above code may be related to .377 above.
3670 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3672 FIXME("(%p) semi-stub\n", hModule);
3673 return FreeLibrary(hModule);
3676 /*************************************************************************
3677 * @ [SHLWAPI.419]
3679 BOOL WINAPI SHFlushSFCacheWrap(void) {
3680 FIXME(": stub\n");
3681 return TRUE;
3684 /*************************************************************************
3685 * @ [SHLWAPI.425]
3687 BOOL WINAPI DeleteMenuWrap(HMENU hmenu, UINT pos, UINT flags)
3689 /* FIXME: This should do more than simply call DeleteMenu */
3690 FIXME("%p %08x %08x): semi-stub\n", hmenu, pos, flags);
3691 return DeleteMenu(hmenu, pos, flags);
3694 /*************************************************************************
3695 * @ [SHLWAPI.429]
3696 * FIXME I have no idea what this function does or what its arguments are.
3698 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3700 FIXME("(%p) stub\n", hInst);
3701 return FALSE;
3705 /*************************************************************************
3706 * @ [SHLWAPI.430]
3708 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3710 FIXME("(%p,%p) stub\n", hInst, hHeap);
3711 return E_FAIL; /* This is what is used if shlwapi not loaded */
3714 /*************************************************************************
3715 * @ [SHLWAPI.431]
3717 DWORD WINAPI MLClearMLHInstance(DWORD x)
3719 FIXME("(0x%08x)stub\n", x);
3720 return 0xabba1247;
3723 /*************************************************************************
3724 * @ [SHLWAPI.436]
3726 * Convert an Unicode string CLSID into a CLSID.
3728 * PARAMS
3729 * idstr [I] string containing a CLSID in text form
3730 * id [O] CLSID extracted from the string
3732 * RETURNS
3733 * S_OK on success or E_INVALIDARG on failure
3735 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3737 return CLSIDFromString((LPOLESTR)idstr, id);
3740 /*************************************************************************
3741 * @ [SHLWAPI.437]
3743 * Determine if the OS supports a given feature.
3745 * PARAMS
3746 * dwFeature [I] Feature requested (undocumented)
3748 * RETURNS
3749 * TRUE If the feature is available.
3750 * FALSE If the feature is not available.
3752 BOOL WINAPI IsOS(DWORD feature)
3754 OSVERSIONINFOA osvi;
3755 DWORD platform, majorv, minorv;
3757 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3758 if(!GetVersionExA(&osvi)) {
3759 ERR("GetVersionEx failed\n");
3760 return FALSE;
3763 majorv = osvi.dwMajorVersion;
3764 minorv = osvi.dwMinorVersion;
3765 platform = osvi.dwPlatformId;
3767 #define ISOS_RETURN(x) \
3768 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3769 return (x);
3771 switch(feature) {
3772 case OS_WIN32SORGREATER:
3773 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3774 || platform == VER_PLATFORM_WIN32_WINDOWS)
3775 case OS_NT:
3776 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3777 case OS_WIN95ORGREATER:
3778 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3779 case OS_NT4ORGREATER:
3780 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3781 case OS_WIN2000ORGREATER_ALT:
3782 case OS_WIN2000ORGREATER:
3783 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3784 case OS_WIN98ORGREATER:
3785 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3786 case OS_WIN98_GOLD:
3787 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3788 case OS_WIN2000PRO:
3789 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3790 case OS_WIN2000SERVER:
3791 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3792 case OS_WIN2000ADVSERVER:
3793 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3794 case OS_WIN2000DATACENTER:
3795 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3796 case OS_WIN2000TERMINAL:
3797 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3798 case OS_EMBEDDED:
3799 FIXME("(OS_EMBEDDED) What should we return here?\n");
3800 return FALSE;
3801 case OS_TERMINALCLIENT:
3802 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3803 return FALSE;
3804 case OS_TERMINALREMOTEADMIN:
3805 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3806 return FALSE;
3807 case OS_WIN95_GOLD:
3808 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3809 case OS_MEORGREATER:
3810 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3811 case OS_XPORGREATER:
3812 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3813 case OS_HOME:
3814 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3815 case OS_PROFESSIONAL:
3816 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3817 case OS_DATACENTER:
3818 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3819 case OS_ADVSERVER:
3820 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3821 case OS_SERVER:
3822 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3823 case OS_TERMINALSERVER:
3824 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3825 case OS_PERSONALTERMINALSERVER:
3826 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3827 case OS_FASTUSERSWITCHING:
3828 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3829 return TRUE;
3830 case OS_WELCOMELOGONUI:
3831 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3832 return FALSE;
3833 case OS_DOMAINMEMBER:
3834 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3835 return TRUE;
3836 case OS_ANYSERVER:
3837 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3838 case OS_WOW6432:
3839 FIXME("(OS_WOW6432) Should we check this?\n");
3840 return FALSE;
3841 case OS_WEBSERVER:
3842 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3843 case OS_SMALLBUSINESSSERVER:
3844 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3845 case OS_TABLETPC:
3846 FIXME("(OS_TABLEPC) What should we return here?\n");
3847 return FALSE;
3848 case OS_SERVERADMINUI:
3849 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3850 return FALSE;
3851 case OS_MEDIACENTER:
3852 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3853 return FALSE;
3854 case OS_APPLIANCE:
3855 FIXME("(OS_APPLIANCE) What should we return here?\n");
3856 return FALSE;
3859 #undef ISOS_RETURN
3861 WARN("(0x%x) unknown parameter\n",feature);
3863 return FALSE;
3866 /*************************************************************************
3867 * @ [SHLWAPI.439]
3869 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
3871 DWORD type, sz = size;
3873 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
3874 return E_FAIL;
3876 return SHLoadIndirectString(buf, buf, size, NULL);
3879 /*************************************************************************
3880 * @ [SHLWAPI.478]
3882 * Call IInputObject_TranslateAcceleratorIO() on an object.
3884 * PARAMS
3885 * lpUnknown [I] Object supporting the IInputObject interface.
3886 * lpMsg [I] Key message to be processed.
3888 * RETURNS
3889 * Success: S_OK.
3890 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3892 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
3894 IInputObject* lpInput = NULL;
3895 HRESULT hRet = E_INVALIDARG;
3897 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
3898 if (lpUnknown)
3900 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3901 (void**)&lpInput);
3902 if (SUCCEEDED(hRet) && lpInput)
3904 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3905 IInputObject_Release(lpInput);
3908 return hRet;
3911 /*************************************************************************
3912 * @ [SHLWAPI.481]
3914 * Call IInputObject_HasFocusIO() on an object.
3916 * PARAMS
3917 * lpUnknown [I] Object supporting the IInputObject interface.
3919 * RETURNS
3920 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3921 * or S_FALSE otherwise.
3922 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3924 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
3926 IInputObject* lpInput = NULL;
3927 HRESULT hRet = E_INVALIDARG;
3929 TRACE("(%p)\n", lpUnknown);
3930 if (lpUnknown)
3932 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3933 (void**)&lpInput);
3934 if (SUCCEEDED(hRet) && lpInput)
3936 hRet = IInputObject_HasFocusIO(lpInput);
3937 IInputObject_Release(lpInput);
3940 return hRet;
3943 /*************************************************************************
3944 * ColorRGBToHLS [SHLWAPI.@]
3946 * Convert an rgb COLORREF into the hls color space.
3948 * PARAMS
3949 * cRGB [I] Source rgb value
3950 * pwHue [O] Destination for converted hue
3951 * pwLuminance [O] Destination for converted luminance
3952 * pwSaturation [O] Destination for converted saturation
3954 * RETURNS
3955 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3956 * values.
3958 * NOTES
3959 * Output HLS values are constrained to the range (0..240).
3960 * For Achromatic conversions, Hue is set to 160.
3962 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3963 LPWORD pwLuminance, LPWORD pwSaturation)
3965 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3967 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3969 wR = GetRValue(cRGB);
3970 wG = GetGValue(cRGB);
3971 wB = GetBValue(cRGB);
3973 wMax = max(wR, max(wG, wB));
3974 wMin = min(wR, min(wG, wB));
3976 /* Luminosity */
3977 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3979 if (wMax == wMin)
3981 /* Achromatic case */
3982 wSaturation = 0;
3983 /* Hue is now unrepresentable, but this is what native returns... */
3984 wHue = 160;
3986 else
3988 /* Chromatic case */
3989 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3991 /* Saturation */
3992 if (wLuminosity <= 120)
3993 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3994 else
3995 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3997 /* Hue */
3998 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3999 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4000 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4002 if (wR == wMax)
4003 wHue = wBNorm - wGNorm;
4004 else if (wG == wMax)
4005 wHue = 80 + wRNorm - wBNorm;
4006 else
4007 wHue = 160 + wGNorm - wRNorm;
4008 if (wHue < 0)
4009 wHue += 240;
4010 else if (wHue > 240)
4011 wHue -= 240;
4013 if (pwHue)
4014 *pwHue = wHue;
4015 if (pwLuminance)
4016 *pwLuminance = wLuminosity;
4017 if (pwSaturation)
4018 *pwSaturation = wSaturation;
4021 /*************************************************************************
4022 * SHCreateShellPalette [SHLWAPI.@]
4024 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4026 FIXME("stub\n");
4027 return CreateHalftonePalette(hdc);
4030 /*************************************************************************
4031 * SHGetInverseCMAP (SHLWAPI.@)
4033 * Get an inverse color map table.
4035 * PARAMS
4036 * lpCmap [O] Destination for color map
4037 * dwSize [I] Size of memory pointed to by lpCmap
4039 * RETURNS
4040 * Success: S_OK.
4041 * Failure: E_POINTER, If lpCmap is invalid.
4042 * E_INVALIDARG, If dwFlags is invalid
4043 * E_OUTOFMEMORY, If there is no memory available
4045 * NOTES
4046 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4047 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4048 * internal CMap.
4049 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4050 * this DLL's internal CMap.
4052 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4054 if (dwSize == 4) {
4055 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4056 *dest = (DWORD)0xabba1249;
4057 return 0;
4059 FIXME("(%p, %#x) stub\n", dest, dwSize);
4060 return 0;
4063 /*************************************************************************
4064 * SHIsLowMemoryMachine [SHLWAPI.@]
4066 * Determine if the current computer has low memory.
4068 * PARAMS
4069 * x [I] FIXME
4071 * RETURNS
4072 * TRUE if the users machine has 16 Megabytes of memory or less,
4073 * FALSE otherwise.
4075 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4077 FIXME("(0x%08x) stub\n", x);
4078 return FALSE;
4081 /*************************************************************************
4082 * GetMenuPosFromID [SHLWAPI.@]
4084 * Return the position of a menu item from its Id.
4086 * PARAMS
4087 * hMenu [I] Menu containing the item
4088 * wID [I] Id of the menu item
4090 * RETURNS
4091 * Success: The index of the menu item in hMenu.
4092 * Failure: -1, If the item is not found.
4094 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4096 MENUITEMINFOW mi;
4097 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4099 while (nIter < nCount)
4101 mi.cbSize = sizeof(mi);
4102 mi.fMask = MIIM_ID;
4103 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4104 return nIter;
4105 nIter++;
4107 return -1;
4110 /*************************************************************************
4111 * @ [SHLWAPI.179]
4113 * Same as SHLWAPI.GetMenuPosFromID
4115 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4117 return GetMenuPosFromID(hMenu, uID);
4121 /*************************************************************************
4122 * @ [SHLWAPI.448]
4124 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4126 while (*lpwstr)
4128 if (*lpwstr == '/')
4129 *lpwstr = '\\';
4130 lpwstr++;
4135 /*************************************************************************
4136 * @ [SHLWAPI.461]
4138 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4140 FIXME("(0x%08x) stub\n", dwUnknown);
4141 return 0;
4145 /*************************************************************************
4146 * @ [SHLWAPI.549]
4148 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4149 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4151 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4154 /*************************************************************************
4155 * SHSkipJunction [SHLWAPI.@]
4157 * Determine if a bind context can be bound to an object
4159 * PARAMS
4160 * pbc [I] Bind context to check
4161 * pclsid [I] CLSID of object to be bound to
4163 * RETURNS
4164 * TRUE: If it is safe to bind
4165 * FALSE: If pbc is invalid or binding would not be safe
4168 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4170 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4171 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4172 BOOL bRet = FALSE;
4174 if (pbc)
4176 IUnknown* lpUnk;
4178 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4180 CLSID clsid;
4182 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4183 IsEqualGUID(pclsid, &clsid))
4184 bRet = TRUE;
4186 IUnknown_Release(lpUnk);
4189 return bRet;
4192 /***********************************************************************
4193 * SHGetShellKey (SHLWAPI.@)
4195 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4197 FIXME("(%x, %x, %x): stub\n", a, b, c);
4198 return 0x50;
4201 /***********************************************************************
4202 * SHQueueUserWorkItem (SHLWAPI.@)
4204 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4205 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4206 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4208 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4209 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4211 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4212 FIXME("Unsupported arguments\n");
4214 return QueueUserWorkItem(pfnCallback, pContext, 0);
4217 /***********************************************************************
4218 * SHSetTimerQueueTimer (SHLWAPI.263)
4220 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4221 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4222 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4224 HANDLE hNewTimer;
4226 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4227 if (dwFlags & TPS_LONGEXECTIME) {
4228 dwFlags &= ~TPS_LONGEXECTIME;
4229 dwFlags |= WT_EXECUTELONGFUNCTION;
4231 if (dwFlags & TPS_EXECUTEIO) {
4232 dwFlags &= ~TPS_EXECUTEIO;
4233 dwFlags |= WT_EXECUTEINIOTHREAD;
4236 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4237 dwDueTime, dwPeriod, dwFlags))
4238 return NULL;
4240 return hNewTimer;
4243 /***********************************************************************
4244 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4246 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4248 IInputObjectSite *pIOS = NULL;
4249 HRESULT hRet = E_INVALIDARG;
4251 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4253 if (lpUnknown)
4255 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4256 (void **)&pIOS);
4257 if (SUCCEEDED(hRet) && pIOS)
4259 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4260 IInputObjectSite_Release(pIOS);
4263 return hRet;
4266 /***********************************************************************
4267 * SHGetValueW (SHLWAPI.@)
4269 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4271 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4272 return E_FAIL;
4275 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4277 /***********************************************************************
4278 * GetUIVersion (SHLWAPI.452)
4280 DWORD WINAPI GetUIVersion(void)
4282 static DWORD version;
4284 if (!version)
4286 DllGetVersion_func pDllGetVersion;
4287 HMODULE dll = LoadLibraryA("shell32.dll");
4288 if (!dll) return 0;
4290 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4291 if (pDllGetVersion)
4293 DLLVERSIONINFO dvi;
4294 dvi.cbSize = sizeof(DLLVERSIONINFO);
4295 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4297 FreeLibrary( dll );
4298 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4300 return version;
4303 /***********************************************************************
4304 * ShellMessageBoxWrapW [SHLWAPI.388]
4306 * See shell32.ShellMessageBoxW
4308 * NOTE:
4309 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4310 * because we can't forward to it in the .spec file since it's exported by
4311 * ordinal. If you change the implementation here please update the code in
4312 * shell32 as well.
4314 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4315 LPCWSTR lpCaption, UINT uType, ...)
4317 WCHAR szText[100], szTitle[100];
4318 LPCWSTR pszText = szText, pszTitle = szTitle;
4319 LPWSTR pszTemp;
4320 va_list args;
4321 int ret;
4323 va_start(args, uType);
4325 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4327 if (IS_INTRESOURCE(lpCaption))
4328 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4329 else
4330 pszTitle = lpCaption;
4332 if (IS_INTRESOURCE(lpText))
4333 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4334 else
4335 pszText = lpText;
4337 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4338 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4340 va_end(args);
4342 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4343 LocalFree((HLOCAL)pszTemp);
4344 return ret;
4347 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
4348 DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
4350 FIXME("%p %s %s %08x %08x %08x %p\n", unk,
4351 debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
4352 return E_NOTIMPL;
4355 HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
4357 FIXME("%p %p %p %p\n", unk, x0, x1, x2);
4358 return E_NOTIMPL;
4361 /***********************************************************************
4362 * ZoneComputePaneSize [SHLWAPI.382]
4364 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4366 FIXME("\n");
4367 return 0x95;
4370 void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4372 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4375 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4376 SID_IDENTIFIER_AUTHORITY sidAuthority;
4377 DWORD dwUserGroupID;
4378 DWORD dwUserID;
4379 } SHELL_USER_SID, *PSHELL_USER_SID;
4381 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4382 SHELL_USER_SID susID;
4383 DWORD dwAccessType;
4384 BOOL fInherit;
4385 DWORD dwAccessMask;
4386 DWORD dwInheritMask;
4387 DWORD dwInheritAccessMask;
4388 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4390 /***********************************************************************
4391 * GetShellSecurityDescriptor [SHLWAPI.475]
4393 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4395 * PARAMS
4396 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4397 * each of which describes permissions to apply
4398 * cUserPerm [I] number of entries in apUserPerm array
4400 * RETURNS
4401 * success: pointer to SECURITY_DESCRIPTOR
4402 * failure: NULL
4404 * NOTES
4405 * Call should free returned descriptor with LocalFree
4407 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4409 PSID *sidlist;
4410 PSID cur_user = NULL;
4411 BYTE tuUser[2000];
4412 DWORD acl_size;
4413 int sid_count, i;
4414 PSECURITY_DESCRIPTOR psd = NULL;
4416 TRACE("%p %d\n", apUserPerm, cUserPerm);
4418 if (apUserPerm == NULL || cUserPerm <= 0)
4419 return NULL;
4421 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4422 if (!sidlist)
4423 return NULL;
4425 acl_size = sizeof(ACL);
4427 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4429 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4430 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4431 PSHELL_USER_SID sid = &perm->susID;
4432 PSID pSid;
4433 BOOL ret = TRUE;
4435 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4436 { /* current user's SID */
4437 if (!cur_user)
4439 HANDLE Token;
4440 DWORD bufsize = sizeof(tuUser);
4442 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4443 if (ret)
4445 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4446 if (ret)
4447 cur_user = ((PTOKEN_USER)&tuUser)->User.Sid;
4448 CloseHandle(Token);
4451 pSid = cur_user;
4452 } else if (sid->dwUserID==0) /* one sub-authority */
4453 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4454 0, 0, 0, 0, 0, 0, &pSid);
4455 else
4456 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4457 0, 0, 0, 0, 0, 0, &pSid);
4458 if (!ret)
4459 goto free_sids;
4461 sidlist[sid_count] = pSid;
4462 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4463 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4466 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4468 if (psd != NULL)
4470 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4472 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4473 goto error;
4475 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4476 goto error;
4478 for(i = 0; i < sid_count; i++)
4480 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4481 PSID sid = sidlist[i];
4483 switch(sup->dwAccessType)
4485 case ACCESS_ALLOWED_ACE_TYPE:
4486 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4487 goto error;
4488 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4489 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4490 goto error;
4491 break;
4492 case ACCESS_DENIED_ACE_TYPE:
4493 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4494 goto error;
4495 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4496 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4497 goto error;
4498 break;
4499 default:
4500 goto error;
4504 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4505 goto error;
4507 goto free_sids;
4509 error:
4510 LocalFree(psd);
4511 psd = NULL;
4512 free_sids:
4513 for(i = 0; i < sid_count; i++)
4515 if (!cur_user || sidlist[i] != cur_user)
4516 FreeSid(sidlist[i]);
4518 HeapFree(GetProcessHeap(), 0, sidlist);
4520 return psd;