ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ordinal.c
Go to the documentation of this file.
00001 /*
00002  * SHLWAPI ordinal functions
00003  *
00004  * Copyright 1997 Marcus Meissner
00005  *           1998 Jürgen Schmied
00006  *           2001-2003 Jon Griffiths
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #include "config.h"
00024 #include "wine/port.h"
00025 
00026 #include <stdarg.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 
00030 #define COBJMACROS
00031 #define NONAMELESSUNION
00032 #define NONAMELESSSTRUCT
00033 
00034 #include "windef.h"
00035 #include "winbase.h"
00036 #include "winnls.h"
00037 #include "winreg.h"
00038 #include "wingdi.h"
00039 #include "winuser.h"
00040 #include "winver.h"
00041 #include "winnetwk.h"
00042 #include "mmsystem.h"
00043 #include "objbase.h"
00044 #include "exdisp.h"
00045 #include "shdeprecated.h"
00046 #include "shlobj.h"
00047 #include "shlwapi.h"
00048 #include "shellapi.h"
00049 #include "commdlg.h"
00050 #include "mlang.h"
00051 #include "mshtmhst.h"
00052 #include "wine/unicode.h"
00053 #include "wine/debug.h"
00054 
00055 
00056 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00057 
00058 /* DLL handles for late bound calls */
00059 extern HINSTANCE shlwapi_hInstance;
00060 extern DWORD SHLWAPI_ThreadRef_index;
00061 
00062 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
00063 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
00064 BOOL    WINAPI SHAboutInfoW(LPWSTR,DWORD);
00065 
00066 /*
00067  NOTES: Most functions exported by ordinal seem to be superfluous.
00068  The reason for these functions to be there is to provide a wrapper
00069  for unicode functions to provide these functions on systems without
00070  unicode functions eg. win95/win98. Since we have such functions we just
00071  call these. If running Wine with native DLLs, some late bound calls may
00072  fail. However, it is better to implement the functions in the forward DLL
00073  and recommend the builtin rather than reimplementing the calls here!
00074 */
00075 
00076 /*************************************************************************
00077  * SHLWAPI_DupSharedHandle
00078  *
00079  * Internal implemetation of SHLWAPI_11.
00080  */
00081 static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
00082                                       DWORD dwSrcProcId, DWORD dwAccess,
00083                                       DWORD dwOptions)
00084 {
00085   HANDLE hDst, hSrc;
00086   DWORD dwMyProcId = GetCurrentProcessId();
00087   HANDLE hRet = NULL;
00088 
00089   TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
00090         dwAccess, dwOptions);
00091 
00092   /* Get dest process handle */
00093   if (dwDstProcId == dwMyProcId)
00094     hDst = GetCurrentProcess();
00095   else
00096     hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
00097 
00098   if (hDst)
00099   {
00100     /* Get src process handle */
00101     if (dwSrcProcId == dwMyProcId)
00102       hSrc = GetCurrentProcess();
00103     else
00104       hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
00105 
00106     if (hSrc)
00107     {
00108       /* Make handle available to dest process */
00109       if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
00110                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
00111         hRet = NULL;
00112 
00113       if (dwSrcProcId != dwMyProcId)
00114         CloseHandle(hSrc);
00115     }
00116 
00117     if (dwDstProcId != dwMyProcId)
00118       CloseHandle(hDst);
00119   }
00120 
00121   TRACE("Returning handle %p\n", hRet);
00122   return hRet;
00123 }
00124 
00125 /*************************************************************************
00126  * @  [SHLWAPI.7]
00127  *
00128  * Create a block of sharable memory and initialise it with data.
00129  *
00130  * PARAMS
00131  * lpvData  [I] Pointer to data to write
00132  * dwSize   [I] Size of data
00133  * dwProcId [I] ID of process owning data
00134  *
00135  * RETURNS
00136  * Success: A shared memory handle
00137  * Failure: NULL
00138  *
00139  * NOTES
00140  * Ordinals 7-11 provide a set of calls to create shared memory between a
00141  * group of processes. The shared memory is treated opaquely in that its size
00142  * is not exposed to clients who map it. This is accomplished by storing
00143  * the size of the map as the first DWORD of mapped data, and then offsetting
00144  * the view pointer returned by this size.
00145  *
00146  */
00147 HANDLE WINAPI SHAllocShared(LPVOID lpvData, ULONG dwSize, DWORD dwProcId)
00148 {
00149   HANDLE hMap;
00150   LPVOID pMapped;
00151   HANDLE hRet = NULL;
00152 
00153   TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
00154 
00155   /* Create file mapping of the correct length */
00156   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
00157                             dwSize + sizeof(dwSize), NULL);
00158   if (!hMap)
00159     return hRet;
00160 
00161   /* Get a view in our process address space */
00162   pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
00163 
00164   if (pMapped)
00165   {
00166     /* Write size of data, followed by the data, to the view */
00167     *((DWORD*)pMapped) = dwSize;
00168     if (lpvData)
00169       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
00170 
00171     /* Release view. All further views mapped will be opaque */
00172     UnmapViewOfFile(pMapped);
00173     hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
00174                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
00175                                    DUPLICATE_SAME_ACCESS);
00176   }
00177 
00178   CloseHandle(hMap);
00179   return hRet;
00180 }
00181 
00182 /*************************************************************************
00183  * @ [SHLWAPI.8]
00184  *
00185  * Get a pointer to a block of shared memory from a shared memory handle.
00186  *
00187  * PARAMS
00188  * hShared  [I] Shared memory handle
00189  * dwProcId [I] ID of process owning hShared
00190  *
00191  * RETURNS
00192  * Success: A pointer to the shared memory
00193  * Failure: NULL
00194  *
00195  */
00196 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
00197 {
00198   HANDLE hDup;
00199   LPVOID pMapped;
00200 
00201   TRACE("(%p %d)\n", hShared, dwProcId);
00202 
00203   /* Get handle to shared memory for current process */
00204   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
00205                                  FILE_MAP_ALL_ACCESS, 0);
00206   /* Get View */
00207   pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
00208   CloseHandle(hDup);
00209 
00210   if (pMapped)
00211     return (char *) pMapped + sizeof(DWORD); /* Hide size */
00212   return NULL;
00213 }
00214 
00215 /*************************************************************************
00216  * @ [SHLWAPI.9]
00217  *
00218  * Release a pointer to a block of shared memory.
00219  *
00220  * PARAMS
00221  * lpView [I] Shared memory pointer
00222  *
00223  * RETURNS
00224  * Success: TRUE
00225  * Failure: FALSE
00226  *
00227  */
00228 BOOL WINAPI SHUnlockShared(LPVOID lpView)
00229 {
00230   TRACE("(%p)\n", lpView);
00231   return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
00232 }
00233 
00234 /*************************************************************************
00235  * @ [SHLWAPI.10]
00236  *
00237  * Destroy a block of sharable memory.
00238  *
00239  * PARAMS
00240  * hShared  [I] Shared memory handle
00241  * dwProcId [I] ID of process owning hShared
00242  *
00243  * RETURNS
00244  * Success: TRUE
00245  * Failure: FALSE
00246  *
00247  */
00248 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
00249 {
00250   HANDLE hClose;
00251 
00252   TRACE("(%p %d)\n", hShared, dwProcId);
00253 
00254   /* Get a copy of the handle for our process, closing the source handle */
00255   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
00256                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
00257   /* Close local copy */
00258   return CloseHandle(hClose);
00259 }
00260 
00261 /*************************************************************************
00262  * @   [SHLWAPI.11]
00263  *
00264  * Copy a sharable memory handle from one process to another.
00265  *
00266  * PARAMS
00267  * hShared     [I] Shared memory handle to duplicate
00268  * dwDstProcId [I] ID of the process wanting the duplicated handle
00269  * dwSrcProcId [I] ID of the process owning hShared
00270  * dwAccess    [I] Desired DuplicateHandle() access
00271  * dwOptions   [I] Desired DuplicateHandle() options
00272  *
00273  * RETURNS
00274  * Success: A handle suitable for use by the dwDstProcId process.
00275  * Failure: A NULL handle.
00276  *
00277  */
00278 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
00279                           DWORD dwAccess, DWORD dwOptions)
00280 {
00281   HANDLE hRet;
00282 
00283   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
00284                                  dwAccess, dwOptions);
00285   return hRet;
00286 }
00287 
00288 /*************************************************************************
00289  *      @   [SHLWAPI.13]
00290  *
00291  * Create and register a clipboard enumerator for a web browser.
00292  *
00293  * PARAMS
00294  *  lpBC      [I] Binding context
00295  *  lpUnknown [I] An object exposing the IWebBrowserApp interface
00296  *
00297  * RETURNS
00298  *  Success: S_OK.
00299  *  Failure: An HRESULT error code.
00300  *
00301  * NOTES
00302  *  The enumerator is stored as a property of the web browser. If it does not
00303  *  yet exist, it is created and set before being registered.
00304  */
00305 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
00306 {
00307   static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
00308       '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
00309       '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
00310   BSTR property;
00311   IEnumFORMATETC* pIEnumFormatEtc = NULL;
00312   VARIANTARG var;
00313   HRESULT hr;
00314   IWebBrowserApp* pBrowser;
00315 
00316   TRACE("(%p, %p)\n", lpBC, lpUnknown);
00317 
00318   hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
00319   if (FAILED(hr))
00320     return hr;
00321 
00322   V_VT(&var) = VT_EMPTY;
00323 
00324   /* The property we get is the browsers clipboard enumerator */
00325   property = SysAllocString(szProperty);
00326   hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
00327   SysFreeString(property);
00328   if (FAILED(hr)) goto exit;
00329 
00330   if (V_VT(&var) == VT_EMPTY)
00331   {
00332     /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
00333     char szKeyBuff[128], szValueBuff[128];
00334     DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
00335     FORMATETC* formatList, *format;
00336     HKEY hDocs;
00337 
00338     TRACE("Registering formats and creating IEnumFORMATETC instance\n");
00339 
00340     if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
00341                      "Version\\Internet Settings\\Accepted Documents", &hDocs))
00342     {
00343       hr = E_FAIL;
00344       goto exit;
00345     }
00346 
00347     /* Get count of values in key */
00348     while (!dwRet)
00349     {
00350       dwKeySize = sizeof(szKeyBuff);
00351       dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
00352       dwCount++;
00353     }
00354 
00355     dwNumValues = dwCount;
00356 
00357     /* Note: dwCount = number of items + 1; The extra item is the end node */
00358     format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
00359     if (!formatList)
00360     {
00361       RegCloseKey(hDocs);
00362       hr = E_OUTOFMEMORY;
00363       goto exit;
00364     }
00365 
00366     if (dwNumValues > 1)
00367     {
00368       dwRet = 0;
00369       dwCount = 0;
00370 
00371       dwNumValues--;
00372 
00373       /* Register clipboard formats for the values and populate format list */
00374       while(!dwRet && dwCount < dwNumValues)
00375       {
00376         dwKeySize = sizeof(szKeyBuff);
00377         dwValueSize = sizeof(szValueBuff);
00378         dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
00379                               (PBYTE)szValueBuff, &dwValueSize);
00380         if (!dwRet)
00381         {
00382           HeapFree(GetProcessHeap(), 0, formatList);
00383           RegCloseKey(hDocs);
00384           hr = E_FAIL;
00385           goto exit;
00386         }
00387 
00388         format->cfFormat = RegisterClipboardFormatA(szValueBuff);
00389         format->ptd = NULL;
00390         format->dwAspect = 1;
00391         format->lindex = 4;
00392         format->tymed = -1;
00393 
00394         format++;
00395         dwCount++;
00396       }
00397     }
00398 
00399     RegCloseKey(hDocs);
00400 
00401     /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
00402     format->cfFormat = 0;
00403     format->ptd = NULL;
00404     format->dwAspect = 1;
00405     format->lindex = 4;
00406     format->tymed = -1;
00407 
00408     /* Create a clipboard enumerator */
00409     hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
00410     HeapFree(GetProcessHeap(), 0, formatList);
00411     if (FAILED(hr)) goto exit;
00412 
00413     /* Set our enumerator as the browsers property */
00414     V_VT(&var) = VT_UNKNOWN;
00415     V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
00416 
00417     property = SysAllocString(szProperty);
00418     hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
00419     SysFreeString(property);
00420     if (FAILED(hr))
00421     {
00422        IEnumFORMATETC_Release(pIEnumFormatEtc);
00423        goto exit;
00424     }
00425   }
00426 
00427   if (V_VT(&var) == VT_UNKNOWN)
00428   {
00429     /* Our variant is holding the clipboard enumerator */
00430     IUnknown* pIUnknown = V_UNKNOWN(&var);
00431     IEnumFORMATETC* pClone = NULL;
00432 
00433     TRACE("Retrieved IEnumFORMATETC property\n");
00434 
00435     /* Get an IEnumFormatEtc interface from the variants value */
00436     pIEnumFormatEtc = NULL;
00437     hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
00438     if (hr == S_OK && pIEnumFormatEtc)
00439     {
00440       /* Clone and register the enumerator */
00441       hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
00442       if (hr == S_OK && pClone)
00443       {
00444         RegisterFormatEnumerator(lpBC, pClone, 0);
00445 
00446         IEnumFORMATETC_Release(pClone);
00447       }
00448 
00449       IEnumFORMATETC_Release(pIUnknown);
00450     }
00451     IUnknown_Release(V_UNKNOWN(&var));
00452   }
00453 
00454 exit:
00455   IWebBrowserApp_Release(pBrowser);
00456   return hr;
00457 }
00458 
00459 /*************************************************************************
00460  *      @   [SHLWAPI.15]
00461  *
00462  * Get Explorers "AcceptLanguage" setting.
00463  *
00464  * PARAMS
00465  *  langbuf [O] Destination for language string
00466  *  buflen  [I] Length of langbuf in characters
00467  *          [0] Success: used length of langbuf
00468  *
00469  * RETURNS
00470  *  Success: S_OK.   langbuf is set to the language string found.
00471  *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
00472  *           does not contain the setting.
00473  *           HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
00474  */
00475 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
00476 {
00477     static const WCHAR szkeyW[] = {
00478     'S','o','f','t','w','a','r','e','\\',
00479     'M','i','c','r','o','s','o','f','t','\\',
00480     'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
00481     'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
00482     static const WCHAR valueW[] = {
00483     'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
00484     DWORD mystrlen, mytype;
00485     DWORD len;
00486     HKEY mykey;
00487     LCID mylcid;
00488     WCHAR *mystr;
00489     LONG lres;
00490 
00491     TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
00492 
00493     if(!langbuf || !buflen || !*buflen)
00494     return E_FAIL;
00495 
00496     mystrlen = (*buflen > 20) ? *buflen : 20 ;
00497     len = mystrlen * sizeof(WCHAR);
00498     mystr = HeapAlloc(GetProcessHeap(), 0, len);
00499     mystr[0] = 0;
00500     RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
00501     lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
00502     RegCloseKey(mykey);
00503     len = lstrlenW(mystr);
00504 
00505     if (!lres && (*buflen > len)) {
00506         lstrcpyW(langbuf, mystr);
00507         *buflen = len;
00508         HeapFree(GetProcessHeap(), 0, mystr);
00509         return S_OK;
00510     }
00511 
00512     /* Did not find a value in the registry or the user buffer is too small */
00513     mylcid = GetUserDefaultLCID();
00514     LcidToRfc1766W(mylcid, mystr, mystrlen);
00515     len = lstrlenW(mystr);
00516 
00517     memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
00518     HeapFree(GetProcessHeap(), 0, mystr);
00519 
00520     if (*buflen > len) {
00521         *buflen = len;
00522         return S_OK;
00523     }
00524 
00525     *buflen = 0;
00526     return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
00527 }
00528 
00529 /*************************************************************************
00530  *      @   [SHLWAPI.14]
00531  *
00532  * Ascii version of GetAcceptLanguagesW.
00533  */
00534 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
00535 {
00536     WCHAR *langbufW;
00537     DWORD buflenW, convlen;
00538     HRESULT retval;
00539 
00540     TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
00541 
00542     if(!langbuf || !buflen || !*buflen) return E_FAIL;
00543 
00544     buflenW = *buflen;
00545     langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
00546     retval = GetAcceptLanguagesW(langbufW, &buflenW);
00547 
00548     if (retval == S_OK)
00549     {
00550         convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
00551         convlen--;  /* do not count the terminating 0 */
00552     }
00553     else  /* copy partial string anyway */
00554     {
00555         convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
00556         if (convlen < *buflen)
00557         {
00558             langbuf[convlen] = 0;
00559             convlen--;  /* do not count the terminating 0 */
00560         }
00561         else
00562         {
00563             convlen = *buflen;
00564         }
00565     }
00566     *buflen = buflenW ? convlen : 0;
00567 
00568     HeapFree(GetProcessHeap(), 0, langbufW);
00569     return retval;
00570 }
00571 
00572 /*************************************************************************
00573  *      @   [SHLWAPI.23]
00574  *
00575  * Convert a GUID to a string.
00576  *
00577  * PARAMS
00578  *  guid     [I] GUID to convert
00579  *  lpszDest [O] Destination for string
00580  *  cchMax   [I] Length of output buffer
00581  *
00582  * RETURNS
00583  *  The length of the string created.
00584  */
00585 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
00586 {
00587   char xguid[40];
00588   INT iLen;
00589 
00590   TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
00591 
00592   sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
00593           guid->Data1, guid->Data2, guid->Data3,
00594           guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
00595           guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
00596 
00597   iLen = strlen(xguid) + 1;
00598 
00599   if (iLen > cchMax)
00600     return 0;
00601   memcpy(lpszDest, xguid, iLen);
00602   return iLen;
00603 }
00604 
00605 /*************************************************************************
00606  *      @   [SHLWAPI.24]
00607  *
00608  * Convert a GUID to a string.
00609  *
00610  * PARAMS
00611  *  guid [I] GUID to convert
00612  *  str  [O] Destination for string
00613  *  cmax [I] Length of output buffer
00614  *
00615  * RETURNS
00616  *  The length of the string created.
00617  */
00618 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
00619 {
00620   WCHAR xguid[40];
00621   INT iLen;
00622   static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
00623       '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
00624       'X','%','0','2','X','%','0','2','X','}',0};
00625 
00626   TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
00627 
00628   sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
00629           guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
00630           guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
00631 
00632   iLen = strlenW(xguid) + 1;
00633 
00634   if (iLen > cchMax)
00635     return 0;
00636   memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
00637   return iLen;
00638 }
00639 
00640 /*************************************************************************
00641  *      @   [SHLWAPI.29]
00642  *
00643  * Determine if a Unicode character is a space.
00644  *
00645  * PARAMS
00646  *  wc [I] Character to check.
00647  *
00648  * RETURNS
00649  *  TRUE, if wc is a space,
00650  *  FALSE otherwise.
00651  */
00652 BOOL WINAPI IsCharSpaceW(WCHAR wc)
00653 {
00654     WORD CharType;
00655 
00656     return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
00657 }
00658 
00659 /*************************************************************************
00660  *      @   [SHLWAPI.30]
00661  *
00662  * Determine if a Unicode character is a blank.
00663  *
00664  * PARAMS
00665  *  wc [I] Character to check.
00666  *
00667  * RETURNS
00668  *  TRUE, if wc is a blank,
00669  *  FALSE otherwise.
00670  *
00671  */
00672 BOOL WINAPI IsCharBlankW(WCHAR wc)
00673 {
00674     WORD CharType;
00675 
00676     return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
00677 }
00678 
00679 /*************************************************************************
00680  *      @   [SHLWAPI.31]
00681  *
00682  * Determine if a Unicode character is punctuation.
00683  *
00684  * PARAMS
00685  *  wc [I] Character to check.
00686  *
00687  * RETURNS
00688  *  TRUE, if wc is punctuation,
00689  *  FALSE otherwise.
00690  */
00691 BOOL WINAPI IsCharPunctW(WCHAR wc)
00692 {
00693     WORD CharType;
00694 
00695     return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
00696 }
00697 
00698 /*************************************************************************
00699  *      @   [SHLWAPI.32]
00700  *
00701  * Determine if a Unicode character is a control character.
00702  *
00703  * PARAMS
00704  *  wc [I] Character to check.
00705  *
00706  * RETURNS
00707  *  TRUE, if wc is a control character,
00708  *  FALSE otherwise.
00709  */
00710 BOOL WINAPI IsCharCntrlW(WCHAR wc)
00711 {
00712     WORD CharType;
00713 
00714     return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
00715 }
00716 
00717 /*************************************************************************
00718  *      @   [SHLWAPI.33]
00719  *
00720  * Determine if a Unicode character is a digit.
00721  *
00722  * PARAMS
00723  *  wc [I] Character to check.
00724  *
00725  * RETURNS
00726  *  TRUE, if wc is a digit,
00727  *  FALSE otherwise.
00728  */
00729 BOOL WINAPI IsCharDigitW(WCHAR wc)
00730 {
00731     WORD CharType;
00732 
00733     return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
00734 }
00735 
00736 /*************************************************************************
00737  *      @   [SHLWAPI.34]
00738  *
00739  * Determine if a Unicode character is a hex digit.
00740  *
00741  * PARAMS
00742  *  wc [I] Character to check.
00743  *
00744  * RETURNS
00745  *  TRUE, if wc is a hex digit,
00746  *  FALSE otherwise.
00747  */
00748 BOOL WINAPI IsCharXDigitW(WCHAR wc)
00749 {
00750     WORD CharType;
00751 
00752     return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
00753 }
00754 
00755 /*************************************************************************
00756  *      @   [SHLWAPI.35]
00757  *
00758  */
00759 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
00760 {
00761     return GetStringTypeW(CT_CTYPE3, src, count, type);
00762 }
00763 
00764 /*************************************************************************
00765  *      @   [SHLWAPI.151]
00766  *
00767  * Compare two Ascii strings up to a given length.
00768  *
00769  * PARAMS
00770  *  lpszSrc [I] Source string
00771  *  lpszCmp [I] String to compare to lpszSrc
00772  *  len     [I] Maximum length
00773  *
00774  * RETURNS
00775  *  A number greater than, less than or equal to 0 depending on whether
00776  *  lpszSrc is greater than, less than or equal to lpszCmp.
00777  */
00778 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
00779 {
00780     return StrCmpNA(lpszSrc, lpszCmp, len);
00781 }
00782 
00783 /*************************************************************************
00784  *      @   [SHLWAPI.152]
00785  *
00786  * Unicode version of StrCmpNCA.
00787  */
00788 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
00789 {
00790     return StrCmpNW(lpszSrc, lpszCmp, len);
00791 }
00792 
00793 /*************************************************************************
00794  *      @   [SHLWAPI.153]
00795  *
00796  * Compare two Ascii strings up to a given length, ignoring case.
00797  *
00798  * PARAMS
00799  *  lpszSrc [I] Source string
00800  *  lpszCmp [I] String to compare to lpszSrc
00801  *  len     [I] Maximum length
00802  *
00803  * RETURNS
00804  *  A number greater than, less than or equal to 0 depending on whether
00805  *  lpszSrc is greater than, less than or equal to lpszCmp.
00806  */
00807 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
00808 {
00809     return StrCmpNIA(lpszSrc, lpszCmp, len);
00810 }
00811 
00812 /*************************************************************************
00813  *      @   [SHLWAPI.154]
00814  *
00815  * Unicode version of StrCmpNICA.
00816  */
00817 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
00818 {
00819     return StrCmpNIW(lpszSrc, lpszCmp, len);
00820 }
00821 
00822 /*************************************************************************
00823  *      @   [SHLWAPI.155]
00824  *
00825  * Compare two Ascii strings.
00826  *
00827  * PARAMS
00828  *  lpszSrc [I] Source string
00829  *  lpszCmp [I] String to compare to lpszSrc
00830  *
00831  * RETURNS
00832  *  A number greater than, less than or equal to 0 depending on whether
00833  *  lpszSrc is greater than, less than or equal to lpszCmp.
00834  */
00835 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
00836 {
00837     return lstrcmpA(lpszSrc, lpszCmp);
00838 }
00839 
00840 /*************************************************************************
00841  *      @   [SHLWAPI.156]
00842  *
00843  * Unicode version of StrCmpCA.
00844  */
00845 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
00846 {
00847     return lstrcmpW(lpszSrc, lpszCmp);
00848 }
00849 
00850 /*************************************************************************
00851  *      @   [SHLWAPI.157]
00852  *
00853  * Compare two Ascii strings, ignoring case.
00854  *
00855  * PARAMS
00856  *  lpszSrc [I] Source string
00857  *  lpszCmp [I] String to compare to lpszSrc
00858  *
00859  * RETURNS
00860  *  A number greater than, less than or equal to 0 depending on whether
00861  *  lpszSrc is greater than, less than or equal to lpszCmp.
00862  */
00863 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
00864 {
00865     return lstrcmpiA(lpszSrc, lpszCmp);
00866 }
00867 
00868 /*************************************************************************
00869  *      @   [SHLWAPI.158]
00870  *
00871  * Unicode version of StrCmpICA.
00872  */
00873 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
00874 {
00875     return lstrcmpiW(lpszSrc, lpszCmp);
00876 }
00877 
00878 /*************************************************************************
00879  *      @   [SHLWAPI.160]
00880  *
00881  * Get an identification string for the OS and explorer.
00882  *
00883  * PARAMS
00884  *  lpszDest  [O] Destination for Id string
00885  *  dwDestLen [I] Length of lpszDest
00886  *
00887  * RETURNS
00888  *  TRUE,  If the string was created successfully
00889  *  FALSE, Otherwise
00890  */
00891 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
00892 {
00893   WCHAR buff[2084];
00894 
00895   TRACE("(%p,%d)\n", lpszDest, dwDestLen);
00896 
00897   if (lpszDest && SHAboutInfoW(buff, dwDestLen))
00898   {
00899     WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
00900     return TRUE;
00901   }
00902   return FALSE;
00903 }
00904 
00905 /*************************************************************************
00906  *      @   [SHLWAPI.161]
00907  *
00908  * Unicode version of SHAboutInfoA.
00909  */
00910 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
00911 {
00912   static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
00913     'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
00914     ' ','E','x','p','l','o','r','e','r','\0' };
00915   static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
00916     'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
00917     'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
00918   static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
00919     'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
00920     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
00921   static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
00922     'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
00923     ' ','E','x','p','l','o','r','e','r','\\',
00924     'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
00925   static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
00926   static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
00927     'V','e','r','s','i','o','n','\0' };
00928   static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
00929     'O','w','n','e','r','\0' };
00930   static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
00931     'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
00932   static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
00933   static const WCHAR szUpdate[] = { 'I','E','A','K',
00934     'U','p','d','a','t','e','U','r','l','\0' };
00935   static const WCHAR szHelp[] = { 'I','E','A','K',
00936     'H','e','l','p','S','t','r','i','n','g','\0' };
00937   WCHAR buff[2084];
00938   HKEY hReg;
00939   DWORD dwType, dwLen;
00940 
00941   TRACE("(%p,%d)\n", lpszDest, dwDestLen);
00942 
00943   if (!lpszDest)
00944     return FALSE;
00945 
00946   *lpszDest = '\0';
00947 
00948   /* Try the NT key first, followed by 95/98 key */
00949   if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
00950       RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
00951     return FALSE;
00952 
00953   /* OS Version */
00954   buff[0] = '\0';
00955   dwLen = 30;
00956   if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
00957   {
00958     DWORD dwStrLen = strlenW(buff);
00959     dwLen = 30 - dwStrLen;
00960     SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
00961                 szCustomized, &dwType, buff+dwStrLen, &dwLen);
00962   }
00963   StrCatBuffW(lpszDest, buff, dwDestLen);
00964 
00965   /* ~Registered Owner */
00966   buff[0] = '~';
00967   dwLen = 256;
00968   if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
00969     buff[1] = '\0';
00970   StrCatBuffW(lpszDest, buff, dwDestLen);
00971 
00972   /* ~Registered Organization */
00973   dwLen = 256;
00974   if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
00975     buff[1] = '\0';
00976   StrCatBuffW(lpszDest, buff, dwDestLen);
00977 
00978   /* FIXME: Not sure where this number comes from  */
00979   buff[0] = '~';
00980   buff[1] = '0';
00981   buff[2] = '\0';
00982   StrCatBuffW(lpszDest, buff, dwDestLen);
00983 
00984   /* ~Product Id */
00985   dwLen = 256;
00986   if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
00987     buff[1] = '\0';
00988   StrCatBuffW(lpszDest, buff, dwDestLen);
00989 
00990   /* ~IE Update Url */
00991   dwLen = 2048;
00992   if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
00993     buff[1] = '\0';
00994   StrCatBuffW(lpszDest, buff, dwDestLen);
00995 
00996   /* ~IE Help String */
00997   dwLen = 256;
00998   if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
00999     buff[1] = '\0';
01000   StrCatBuffW(lpszDest, buff, dwDestLen);
01001 
01002   RegCloseKey(hReg);
01003   return TRUE;
01004 }
01005 
01006 /*************************************************************************
01007  *      @   [SHLWAPI.163]
01008  *
01009  * Call IOleCommandTarget_QueryStatus() on an object.
01010  *
01011  * PARAMS
01012  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
01013  *  pguidCmdGroup [I] GUID for the command group
01014  *  cCmds         [I]
01015  *  prgCmds       [O] Commands
01016  *  pCmdText      [O] Command text
01017  *
01018  * RETURNS
01019  *  Success: S_OK.
01020  *  Failure: E_FAIL, if lpUnknown is NULL.
01021  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
01022  *           Otherwise, an error code from IOleCommandTarget_QueryStatus().
01023  */
01024 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
01025                            ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
01026 {
01027   HRESULT hRet = E_FAIL;
01028 
01029   TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
01030 
01031   if (lpUnknown)
01032   {
01033     IOleCommandTarget* lpOle;
01034 
01035     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
01036                                    (void**)&lpOle);
01037 
01038     if (SUCCEEDED(hRet) && lpOle)
01039     {
01040       hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
01041                                            prgCmds, pCmdText);
01042       IOleCommandTarget_Release(lpOle);
01043     }
01044   }
01045   return hRet;
01046 }
01047 
01048 /*************************************************************************
01049  *      @       [SHLWAPI.164]
01050  *
01051  * Call IOleCommandTarget_Exec() on an object.
01052  *
01053  * PARAMS
01054  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
01055  *  pguidCmdGroup [I] GUID for the command group
01056  *
01057  * RETURNS
01058  *  Success: S_OK.
01059  *  Failure: E_FAIL, if lpUnknown is NULL.
01060  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
01061  *           Otherwise, an error code from IOleCommandTarget_Exec().
01062  */
01063 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
01064                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
01065                            VARIANT* pvaOut)
01066 {
01067   HRESULT hRet = E_FAIL;
01068 
01069   TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
01070         nCmdexecopt, pvaIn, pvaOut);
01071 
01072   if (lpUnknown)
01073   {
01074     IOleCommandTarget* lpOle;
01075 
01076     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
01077                                    (void**)&lpOle);
01078     if (SUCCEEDED(hRet) && lpOle)
01079     {
01080       hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
01081                                     nCmdexecopt, pvaIn, pvaOut);
01082       IOleCommandTarget_Release(lpOle);
01083     }
01084   }
01085   return hRet;
01086 }
01087 
01088 /*************************************************************************
01089  *      @   [SHLWAPI.165]
01090  *
01091  * Retrieve, modify, and re-set a value from a window.
01092  *
01093  * PARAMS
01094  *  hWnd   [I] Window to get value from
01095  *  offset [I] Offset of value
01096  *  mask   [I] Mask for flags
01097  *  flags  [I] Bits to set in window value
01098  *
01099  * RETURNS
01100  *  The new value as it was set, or 0 if any parameter is invalid.
01101  *
01102  * NOTES
01103  *  Only bits specified in mask are affected - set if present in flags and
01104  *  reset otherwise.
01105  */
01106 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
01107 {
01108   LONG ret = GetWindowLongW(hwnd, offset);
01109   LONG new_flags = (flags & mask) | (ret & ~mask);
01110 
01111   TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
01112 
01113   if (new_flags != ret)
01114     ret = SetWindowLongW(hwnd, offset, new_flags);
01115   return ret;
01116 }
01117 
01118 /*************************************************************************
01119  *      @   [SHLWAPI.167]
01120  *
01121  * Change a window's parent.
01122  *
01123  * PARAMS
01124  *  hWnd       [I] Window to change parent of
01125  *  hWndParent [I] New parent window
01126  *
01127  * RETURNS
01128  *  The old parent of hWnd.
01129  *
01130  * NOTES
01131  *  If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
01132  *  If hWndParent is NOT NULL then we set the WS_CHILD style.
01133  */
01134 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
01135 {
01136   TRACE("%p, %p\n", hWnd, hWndParent);
01137 
01138   if(GetParent(hWnd) == hWndParent)
01139     return 0;
01140 
01141   if(hWndParent)
01142     SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
01143   else
01144     SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
01145 
01146   return SetParent(hWnd, hWndParent);
01147 }
01148 
01149 /*************************************************************************
01150  *      @       [SHLWAPI.168]
01151  *
01152  * Locate and advise a connection point in an IConnectionPointContainer object.
01153  *
01154  * PARAMS
01155  *  lpUnkSink   [I] Sink for the connection point advise call
01156  *  riid        [I] REFIID of connection point to advise
01157  *  fConnect    [I] TRUE = Connection being establisted, FALSE = broken
01158  *  lpUnknown   [I] Object supporting the IConnectionPointContainer interface
01159  *  lpCookie    [O] Pointer to connection point cookie
01160  *  lppCP       [O] Destination for the IConnectionPoint found
01161  *
01162  * RETURNS
01163  *  Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
01164  *           that was advised. The caller is responsible for releasing it.
01165  *  Failure: E_FAIL, if any arguments are invalid.
01166  *           E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
01167  *           Or an HRESULT error code if any call fails.
01168  */
01169 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
01170                            IUnknown* lpUnknown, LPDWORD lpCookie,
01171                            IConnectionPoint **lppCP)
01172 {
01173   HRESULT hRet;
01174   IConnectionPointContainer* lpContainer;
01175   IConnectionPoint *lpCP;
01176 
01177   if(!lpUnknown || (fConnect && !lpUnkSink))
01178     return E_FAIL;
01179 
01180   if(lppCP)
01181     *lppCP = NULL;
01182 
01183   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
01184                                  (void**)&lpContainer);
01185   if (SUCCEEDED(hRet))
01186   {
01187     hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
01188 
01189     if (SUCCEEDED(hRet))
01190     {
01191       if(!fConnect)
01192         hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
01193       else
01194         hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
01195 
01196       if (FAILED(hRet))
01197         *lpCookie = 0;
01198 
01199       if (lppCP && SUCCEEDED(hRet))
01200         *lppCP = lpCP; /* Caller keeps the interface */
01201       else
01202         IConnectionPoint_Release(lpCP); /* Release it */
01203     }
01204 
01205     IUnknown_Release(lpContainer);
01206   }
01207   return hRet;
01208 }
01209 
01210 /*************************************************************************
01211  *  @   [SHLWAPI.169]
01212  *
01213  * Release an interface and zero a supplied pointer.
01214  *
01215  * PARAMS
01216  *  lpUnknown [I] Object to release
01217  *
01218  * RETURNS
01219  *  Nothing.
01220  */
01221 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
01222 {
01223     TRACE("(%p)\n", lpUnknown);
01224 
01225     if(!lpUnknown || !*lpUnknown) return;
01226 
01227     TRACE("doing Release\n");
01228 
01229     IUnknown_Release(*lpUnknown);
01230     *lpUnknown = NULL;
01231 }
01232 
01233 /*************************************************************************
01234  *      @   [SHLWAPI.170]
01235  *
01236  * Skip '//' if present in a string.
01237  *
01238  * PARAMS
01239  *  lpszSrc [I] String to check for '//'
01240  *
01241  * RETURNS
01242  *  Success: The next character after the '//' or the string if not present
01243  *  Failure: NULL, if lpszStr is NULL.
01244  */
01245 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
01246 {
01247   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
01248     lpszSrc += 2;
01249   return lpszSrc;
01250 }
01251 
01252 /*************************************************************************
01253  *      @       [SHLWAPI.171]
01254  *
01255  * Check if two interfaces come from the same object.
01256  *
01257  * PARAMS
01258  *   lpInt1 [I] Interface to check against lpInt2.
01259  *   lpInt2 [I] Interface to check against lpInt1.
01260  *
01261  * RETURNS
01262  *   TRUE, If the interfaces come from the same object.
01263  *   FALSE Otherwise.
01264  */
01265 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
01266 {
01267   IUnknown *lpUnknown1, *lpUnknown2;
01268   BOOL ret;
01269 
01270   TRACE("(%p %p)\n", lpInt1, lpInt2);
01271 
01272   if (!lpInt1 || !lpInt2)
01273     return FALSE;
01274 
01275   if (lpInt1 == lpInt2)
01276     return TRUE;
01277 
01278   if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
01279     return FALSE;
01280 
01281   if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
01282   {
01283     IUnknown_Release(lpUnknown1);
01284     return FALSE;
01285   }
01286 
01287   ret = lpUnknown1 == lpUnknown2;
01288 
01289   IUnknown_Release(lpUnknown1);
01290   IUnknown_Release(lpUnknown2);
01291 
01292   return ret;
01293 }
01294 
01295 /*************************************************************************
01296  *      @   [SHLWAPI.172]
01297  *
01298  * Get the window handle of an object.
01299  *
01300  * PARAMS
01301  *  lpUnknown [I] Object to get the window handle of
01302  *  lphWnd    [O] Destination for window handle
01303  *
01304  * RETURNS
01305  *  Success: S_OK. lphWnd contains the objects window handle.
01306  *  Failure: An HRESULT error code.
01307  *
01308  * NOTES
01309  *  lpUnknown is expected to support one of the following interfaces:
01310  *  IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
01311  */
01312 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
01313 {
01314   IUnknown *lpOle;
01315   HRESULT hRet = E_FAIL;
01316 
01317   TRACE("(%p,%p)\n", lpUnknown, lphWnd);
01318 
01319   if (!lpUnknown)
01320     return hRet;
01321 
01322   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
01323 
01324   if (FAILED(hRet))
01325   {
01326     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
01327 
01328     if (FAILED(hRet))
01329     {
01330       hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
01331                                       (void**)&lpOle);
01332     }
01333   }
01334 
01335   if (SUCCEEDED(hRet))
01336   {
01337     /* Lazyness here - Since GetWindow() is the first method for the above 3
01338      * interfaces, we use the same call for them all.
01339      */
01340     hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
01341     IUnknown_Release(lpOle);
01342     if (lphWnd)
01343       TRACE("Returning HWND=%p\n", *lphWnd);
01344   }
01345 
01346   return hRet;
01347 }
01348 
01349 /*************************************************************************
01350  *      @   [SHLWAPI.173]
01351  *
01352  * Call a SetOwner method of IShellService from specified object.
01353  *
01354  * PARAMS
01355  *  iface [I] Object that supports IShellService
01356  *  pUnk  [I] Argument for the SetOwner call
01357  *
01358  * RETURNS
01359  *  Corresponding return value from last call or E_FAIL for null input
01360  */
01361 HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk)
01362 {
01363   IShellService *service;
01364   HRESULT hr;
01365 
01366   TRACE("(%p, %p)\n", iface, pUnk);
01367 
01368   if (!iface) return E_FAIL;
01369 
01370   hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
01371   if (hr == S_OK)
01372   {
01373     hr = IShellService_SetOwner(service, pUnk);
01374     IShellService_Release(service);
01375   }
01376 
01377   return hr;
01378 }
01379 
01380 /*************************************************************************
01381  *      @   [SHLWAPI.174]
01382  *
01383  * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
01384  * an object.
01385  *
01386  */
01387 HRESULT WINAPI IUnknown_SetSite(
01388         IUnknown *obj,        /* [in]   OLE object     */
01389         IUnknown *site)       /* [in]   Site interface */
01390 {
01391     HRESULT hr;
01392     IObjectWithSite *iobjwithsite;
01393     IInternetSecurityManager *isecmgr;
01394 
01395     if (!obj) return E_FAIL;
01396 
01397     hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
01398     TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
01399     if (SUCCEEDED(hr))
01400     {
01401     hr = IObjectWithSite_SetSite(iobjwithsite, site);
01402     TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
01403     IUnknown_Release(iobjwithsite);
01404     }
01405     else
01406     {
01407     hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
01408     TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
01409     if (FAILED(hr)) return hr;
01410 
01411     hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
01412     TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
01413     IUnknown_Release(isecmgr);
01414     }
01415     return hr;
01416 }
01417 
01418 /*************************************************************************
01419  *      @   [SHLWAPI.175]
01420  *
01421  * Call IPersist_GetClassID() on an object.
01422  *
01423  * PARAMS
01424  *  lpUnknown [I] Object supporting the IPersist interface
01425  *  lpClassId [O] Destination for Class Id
01426  *
01427  * RETURNS
01428  *  Success: S_OK. lpClassId contains the Class Id requested.
01429  *  Failure: E_FAIL, If lpUnknown is NULL,
01430  *           E_NOINTERFACE If lpUnknown does not support IPersist,
01431  *           Or an HRESULT error code.
01432  */
01433 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
01434 {
01435   IPersist* lpPersist;
01436   HRESULT hRet = E_FAIL;
01437 
01438   TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
01439 
01440   if (lpUnknown)
01441   {
01442     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
01443     if (SUCCEEDED(hRet))
01444     {
01445       IPersist_GetClassID(lpPersist, lpClassId);
01446       IPersist_Release(lpPersist);
01447     }
01448   }
01449   return hRet;
01450 }
01451 
01452 /*************************************************************************
01453  *      @   [SHLWAPI.176]
01454  *
01455  * Retrieve a Service Interface from an object.
01456  *
01457  * PARAMS
01458  *  lpUnknown [I] Object to get an IServiceProvider interface from
01459  *  sid       [I] Service ID for IServiceProvider_QueryService() call
01460  *  riid      [I] Function requested for QueryService call
01461  *  lppOut    [O] Destination for the service interface pointer
01462  *
01463  * RETURNS
01464  *  Success: S_OK. lppOut contains an object providing the requested service
01465  *  Failure: An HRESULT error code
01466  *
01467  * NOTES
01468  *  lpUnknown is expected to support the IServiceProvider interface.
01469  */
01470 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
01471                            LPVOID *lppOut)
01472 {
01473   IServiceProvider* pService = NULL;
01474   HRESULT hRet;
01475 
01476   if (!lppOut)
01477     return E_FAIL;
01478 
01479   *lppOut = NULL;
01480 
01481   if (!lpUnknown)
01482     return E_FAIL;
01483 
01484   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
01485                                  (LPVOID*)&pService);
01486 
01487   if (hRet == S_OK && pService)
01488   {
01489     TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
01490 
01491     /* Get a Service interface from the object */
01492     hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
01493 
01494     TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
01495 
01496     IUnknown_Release(pService);
01497   }
01498   return hRet;
01499 }
01500 
01501 /*************************************************************************
01502  *      @   [SHLWAPI.484]
01503  *
01504  * Calls IOleCommandTarget::Exec() for specified service object.
01505  *
01506  * PARAMS
01507  *  lpUnknown [I] Object to get an IServiceProvider interface from
01508  *  service   [I] Service ID for IServiceProvider_QueryService() call
01509  *  group     [I] Group ID for IOleCommandTarget::Exec() call
01510  *  cmdId     [I] Command ID for IOleCommandTarget::Exec() call
01511  *  cmdOpt    [I] Options flags for command
01512  *  pIn       [I] Input arguments for command
01513  *  pOut      [O] Output arguments for command
01514  *
01515  * RETURNS
01516  *  Success: S_OK. lppOut contains an object providing the requested service
01517  *  Failure: An HRESULT error code
01518  *
01519  * NOTES
01520  *  lpUnknown is expected to support the IServiceProvider interface.
01521  */
01522 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
01523     const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
01524 {
01525     IOleCommandTarget *target;
01526     HRESULT hr;
01527 
01528     TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
01529         debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
01530 
01531     hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
01532     if (hr == S_OK)
01533     {
01534         hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
01535         IOleCommandTarget_Release(target);
01536     }
01537 
01538     TRACE("<-- hr=0x%08x\n", hr);
01539 
01540     return hr;
01541 }
01542 
01543 /*************************************************************************
01544  *      @   [SHLWAPI.514]
01545  *
01546  * Calls IProfferService methods to proffer/revoke specified service.
01547  *
01548  * PARAMS
01549  *  lpUnknown [I]  Object to get an IServiceProvider interface from
01550  *  service   [I]  Service ID for IProfferService::Proffer/Revoke calls
01551  *  pService  [I]  Service to proffer. If NULL ::Revoke is called
01552  *  pCookie   [IO] Group ID for IOleCommandTarget::Exec() call
01553  *
01554  * RETURNS
01555  *  Success: S_OK. IProffer method returns S_OK
01556  *  Failure: An HRESULT error code
01557  *
01558  * NOTES
01559  *  lpUnknown is expected to support the IServiceProvider interface.
01560  */
01561 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
01562 {
01563     IProfferService *proffer;
01564     HRESULT hr;
01565 
01566     TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
01567 
01568     hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
01569     if (hr == S_OK)
01570     {
01571         if (pService)
01572             hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
01573         else
01574             hr = IProfferService_RevokeService(proffer, *pCookie);
01575 
01576         IProfferService_Release(proffer);
01577     }
01578 
01579     return hr;
01580 }
01581 
01582 /*************************************************************************
01583  *      @   [SHLWAPI.479]
01584  *
01585  * Call an object's UIActivateIO method.
01586  *
01587  * PARAMS
01588  *  unknown  [I] Object to call the UIActivateIO method on
01589  *  activate [I] Parameter for UIActivateIO call
01590  *  msg      [I] Parameter for UIActivateIO call
01591  *
01592  * RETURNS
01593  *  Success: Value of UI_ActivateIO call
01594  *  Failure: An HRESULT error code
01595  *
01596  * NOTES
01597  *  unknown is expected to support the IInputObject interface.
01598  */
01599 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
01600 {
01601     IInputObject* object = NULL;
01602     HRESULT ret;
01603 
01604     if (!unknown)
01605         return E_FAIL;
01606 
01607     /* Get an IInputObject interface from the object */
01608     ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
01609 
01610     if (ret == S_OK)
01611     {
01612         ret = IInputObject_UIActivateIO(object, activate, msg);
01613         IUnknown_Release(object);
01614     }
01615 
01616     return ret;
01617 }
01618 
01619 /*************************************************************************
01620  *      @   [SHLWAPI.177]
01621  *
01622  * Loads a popup menu.
01623  *
01624  * PARAMS
01625  *  hInst  [I] Instance handle
01626  *  szName [I] Menu name
01627  *
01628  * RETURNS
01629  *  Success: TRUE.
01630  *  Failure: FALSE.
01631  */
01632 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
01633 {
01634   HMENU hMenu;
01635 
01636   TRACE("%p %s\n", hInst, debugstr_w(szName));
01637 
01638   if ((hMenu = LoadMenuW(hInst, szName)))
01639   {
01640     if (GetSubMenu(hMenu, 0))
01641       RemoveMenu(hMenu, 0, MF_BYPOSITION);
01642 
01643     DestroyMenu(hMenu);
01644     return TRUE;
01645   }
01646   return FALSE;
01647 }
01648 
01649 typedef struct _enumWndData
01650 {
01651   UINT   uiMsgId;
01652   WPARAM wParam;
01653   LPARAM lParam;
01654   LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
01655 } enumWndData;
01656 
01657 /* Callback for SHLWAPI_178 */
01658 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
01659 {
01660   enumWndData *data = (enumWndData *)lParam;
01661 
01662   TRACE("(%p,%p)\n", hWnd, data);
01663   data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
01664   return TRUE;
01665 }
01666 
01667 /*************************************************************************
01668  * @  [SHLWAPI.178]
01669  *
01670  * Send or post a message to every child of a window.
01671  *
01672  * PARAMS
01673  *  hWnd    [I] Window whose children will get the messages
01674  *  uiMsgId [I] Message Id
01675  *  wParam  [I] WPARAM of message
01676  *  lParam  [I] LPARAM of message
01677  *  bSend   [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
01678  *
01679  * RETURNS
01680  *  Nothing.
01681  *
01682  * NOTES
01683  *  The appropriate ASCII or Unicode function is called for the window.
01684  */
01685 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
01686 {
01687   enumWndData data;
01688 
01689   TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
01690 
01691   if(hWnd)
01692   {
01693     data.uiMsgId = uiMsgId;
01694     data.wParam  = wParam;
01695     data.lParam  = lParam;
01696 
01697     if (bSend)
01698       data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
01699     else
01700       data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
01701 
01702     EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
01703   }
01704 }
01705 
01706 /*************************************************************************
01707  *      @   [SHLWAPI.180]
01708  *
01709  * Remove all sub-menus from a menu.
01710  *
01711  * PARAMS
01712  *  hMenu [I] Menu to remove sub-menus from
01713  *
01714  * RETURNS
01715  *  Success: 0.  All sub-menus under hMenu are removed
01716  *  Failure: -1, if any parameter is invalid
01717  */
01718 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
01719 {
01720   int iItemCount = GetMenuItemCount(hMenu) - 1;
01721 
01722   TRACE("%p\n", hMenu);
01723 
01724   while (iItemCount >= 0)
01725   {
01726     HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
01727     if (hSubMenu)
01728       RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
01729     iItemCount--;
01730   }
01731   return iItemCount;
01732 }
01733 
01734 /*************************************************************************
01735  *      @   [SHLWAPI.181]
01736  *
01737  * Enable or disable a menu item.
01738  *
01739  * PARAMS
01740  *  hMenu   [I] Menu holding menu item
01741  *  uID     [I] ID of menu item to enable/disable
01742  *  bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
01743  *
01744  * RETURNS
01745  *  The return code from EnableMenuItem.
01746  */
01747 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
01748 {
01749   TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
01750   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
01751 }
01752 
01753 /*************************************************************************
01754  * @    [SHLWAPI.182]
01755  *
01756  * Check or uncheck a menu item.
01757  *
01758  * PARAMS
01759  *  hMenu  [I] Menu holding menu item
01760  *  uID    [I] ID of menu item to check/uncheck
01761  *  bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
01762  *
01763  * RETURNS
01764  *  The return code from CheckMenuItem.
01765  */
01766 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
01767 {
01768   TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
01769   return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
01770 }
01771 
01772 /*************************************************************************
01773  *      @   [SHLWAPI.183]
01774  *
01775  * Register a window class if it isn't already.
01776  *
01777  * PARAMS
01778  *  lpWndClass [I] Window class to register
01779  *
01780  * RETURNS
01781  *  The result of the RegisterClassA call.
01782  */
01783 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
01784 {
01785   WNDCLASSA wca;
01786   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
01787     return TRUE;
01788   return (DWORD)RegisterClassA(wndclass);
01789 }
01790 
01791 /*************************************************************************
01792  *      @   [SHLWAPI.186]
01793  */
01794 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
01795                            DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
01796 {
01797   DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
01798   POINTL pt = { 0, 0 };
01799 
01800   TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
01801 
01802   if (!lpPt)
01803     lpPt = &pt;
01804 
01805   if (!pdwEffect)
01806     pdwEffect = &dwEffect;
01807 
01808   IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
01809 
01810   if (*pdwEffect != DROPEFFECT_NONE)
01811     return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
01812 
01813   IDropTarget_DragLeave(pDrop);
01814   return TRUE;
01815 }
01816 
01817 /*************************************************************************
01818  *      @   [SHLWAPI.187]
01819  *
01820  * Call IPersistPropertyBag_Load() on an object.
01821  *
01822  * PARAMS
01823  *  lpUnknown [I] Object supporting the IPersistPropertyBag interface
01824  *  lpPropBag [O] Destination for loaded IPropertyBag
01825  *
01826  * RETURNS
01827  *  Success: S_OK.
01828  *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
01829  */
01830 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
01831 {
01832   IPersistPropertyBag* lpPPBag;
01833   HRESULT hRet = E_FAIL;
01834 
01835   TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
01836 
01837   if (lpUnknown)
01838   {
01839     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
01840                                    (void**)&lpPPBag);
01841     if (SUCCEEDED(hRet) && lpPPBag)
01842     {
01843       hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
01844       IPersistPropertyBag_Release(lpPPBag);
01845     }
01846   }
01847   return hRet;
01848 }
01849 
01850 /*************************************************************************
01851  * @  [SHLWAPI.188]
01852  *
01853  * Call IOleControlSite_TranslateAccelerator()  on an object.
01854  *
01855  * PARAMS
01856  *  lpUnknown   [I] Object supporting the IOleControlSite interface.
01857  *  lpMsg       [I] Key message to be processed.
01858  *  dwModifiers [I] Flags containing the state of the modifier keys.
01859  *
01860  * RETURNS
01861  *  Success: S_OK.
01862  *  Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
01863  */
01864 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
01865 {
01866   IOleControlSite* lpCSite = NULL;
01867   HRESULT hRet = E_INVALIDARG;
01868 
01869   TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
01870   if (lpUnknown)
01871   {
01872     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
01873                                    (void**)&lpCSite);
01874     if (SUCCEEDED(hRet) && lpCSite)
01875     {
01876       hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
01877       IOleControlSite_Release(lpCSite);
01878     }
01879   }
01880   return hRet;
01881 }
01882 
01883 
01884 /*************************************************************************
01885  * @  [SHLWAPI.189]
01886  *
01887  * Call IOleControlSite_OnFocus() on an object.
01888  *
01889  * PARAMS
01890  *  lpUnknown [I] Object supporting the IOleControlSite interface.
01891  *  fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
01892  *
01893  * RETURNS
01894  *  Success: S_OK.
01895  *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
01896  */
01897 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
01898 {
01899   IOleControlSite* lpCSite = NULL;
01900   HRESULT hRet = E_FAIL;
01901 
01902   TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
01903   if (lpUnknown)
01904   {
01905     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
01906                                    (void**)&lpCSite);
01907     if (SUCCEEDED(hRet) && lpCSite)
01908     {
01909       hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
01910       IOleControlSite_Release(lpCSite);
01911     }
01912   }
01913   return hRet;
01914 }
01915 
01916 /*************************************************************************
01917  * @    [SHLWAPI.190]
01918  */
01919 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
01920                                         PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
01921 {
01922   /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
01923   static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
01924   /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
01925   static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
01926   HRESULT hRet = E_INVALIDARG;
01927   LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
01928 
01929   TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
01930 
01931   if (lpUnknown && lpArg4)
01932   {
01933      hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
01934                                   (REFGUID)function_id, (void**)&lpUnkInner);
01935 
01936      if (SUCCEEDED(hRet) && lpUnkInner)
01937      {
01938        /* FIXME: The type of service object requested is unknown, however
01939     * testing shows that its first method is called with 4 parameters.
01940     * Fake this by using IParseDisplayName_ParseDisplayName since the
01941     * signature and position in the vtable matches our unknown object type.
01942     */
01943        hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
01944                                                  lpArg1, lpArg2, lpArg3, lpArg4);
01945        IUnknown_Release(lpUnkInner);
01946      }
01947   }
01948   return hRet;
01949 }
01950 
01951 /*************************************************************************
01952  * @    [SHLWAPI.192]
01953  *
01954  * Get a sub-menu from a menu item.
01955  *
01956  * PARAMS
01957  *  hMenu [I] Menu to get sub-menu from
01958  *  uID   [I] ID of menu item containing sub-menu
01959  *
01960  * RETURNS
01961  *  The sub-menu of the item, or a NULL handle if any parameters are invalid.
01962  */
01963 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
01964 {
01965   MENUITEMINFOW mi;
01966 
01967   TRACE("(%p,%u)\n", hMenu, uID);
01968 
01969   mi.cbSize = sizeof(mi);
01970   mi.fMask = MIIM_SUBMENU;
01971 
01972   if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
01973     return NULL;
01974 
01975   return mi.hSubMenu;
01976 }
01977 
01978 /*************************************************************************
01979  *      @   [SHLWAPI.193]
01980  *
01981  * Get the color depth of the primary display.
01982  *
01983  * PARAMS
01984  *  None.
01985  *
01986  * RETURNS
01987  *  The color depth of the primary display.
01988  */
01989 DWORD WINAPI SHGetCurColorRes(void)
01990 {
01991     HDC hdc;
01992     DWORD ret;
01993 
01994     TRACE("()\n");
01995 
01996     hdc = GetDC(0);
01997     ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
01998     ReleaseDC(0, hdc);
01999     return ret;
02000 }
02001 
02002 /*************************************************************************
02003  *      @   [SHLWAPI.194]
02004  *
02005  * Wait for a message to arrive, with a timeout.
02006  *
02007  * PARAMS
02008  *  hand      [I] Handle to query
02009  *  dwTimeout [I] Timeout in ticks or INFINITE to never timeout
02010  *
02011  * RETURNS
02012  *  STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
02013  *  Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
02014  *  message is available.
02015  */
02016 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
02017 {
02018   DWORD dwEndTicks = GetTickCount() + dwTimeout;
02019   DWORD dwRet;
02020 
02021   while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
02022   {
02023     MSG msg;
02024 
02025     PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
02026 
02027     if (dwTimeout != INFINITE)
02028     {
02029         if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
02030             return WAIT_TIMEOUT;
02031     }
02032   }
02033 
02034   return dwRet;
02035 }
02036 
02037 /*************************************************************************
02038  *      @       [SHLWAPI.195]
02039  *
02040  * Determine if a shell folder can be expanded.
02041  *
02042  * PARAMS
02043  *  lpFolder [I] Parent folder containing the object to test.
02044  *  pidl     [I] Id of the object to test.
02045  *
02046  * RETURNS
02047  *  Success: S_OK, if the object is expandable, S_FALSE otherwise.
02048  *  Failure: E_INVALIDARG, if any argument is invalid.
02049  *
02050  * NOTES
02051  *  If the object to be tested does not expose the IQueryInfo() interface it
02052  *  will not be identified as an expandable folder.
02053  */
02054 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
02055 {
02056   HRESULT hRet = E_INVALIDARG;
02057   IQueryInfo *lpInfo;
02058 
02059   if (lpFolder && pidl)
02060   {
02061     hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
02062                                       NULL, (void**)&lpInfo);
02063     if (FAILED(hRet))
02064       hRet = S_FALSE; /* Doesn't expose IQueryInfo */
02065     else
02066     {
02067       DWORD dwFlags = 0;
02068 
02069       /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
02070        * currently used". Really? You wouldn't be holding out on me would you?
02071        */
02072       hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
02073 
02074       if (SUCCEEDED(hRet))
02075       {
02076         /* 0x2 is an undocumented flag apparently indicating expandability */
02077         hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
02078       }
02079 
02080       IQueryInfo_Release(lpInfo);
02081     }
02082   }
02083   return hRet;
02084 }
02085 
02086 /*************************************************************************
02087  *      @       [SHLWAPI.197]
02088  *
02089  * Blank out a region of text by drawing the background only.
02090  *
02091  * PARAMS
02092  *  hDC   [I] Device context to draw in
02093  *  pRect [I] Area to draw in
02094  *  cRef  [I] Color to draw in
02095  *
02096  * RETURNS
02097  *  Nothing.
02098  */
02099 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
02100 {
02101     COLORREF cOldColor = SetBkColor(hDC, cRef);
02102     ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
02103     SetBkColor(hDC, cOldColor);
02104     return 0;
02105 }
02106 
02107 /*************************************************************************
02108  *      @   [SHLWAPI.198]
02109  *
02110  * Return the value associated with a key in a map.
02111  *
02112  * PARAMS
02113  *  lpKeys   [I] A list of keys of length iLen
02114  *  lpValues [I] A list of values associated with lpKeys, of length iLen
02115  *  iLen     [I] Length of both lpKeys and lpValues
02116  *  iKey     [I] The key value to look up in lpKeys
02117  *
02118  * RETURNS
02119  *  The value in lpValues associated with iKey, or -1 if iKey is not
02120  *  found in lpKeys.
02121  *
02122  * NOTES
02123  *  - If two elements in the map share the same key, this function returns
02124  *    the value closest to the start of the map
02125  *  - The native version of this function crashes if lpKeys or lpValues is NULL.
02126  */
02127 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
02128 {
02129   if (lpKeys && lpValues)
02130   {
02131     int i = 0;
02132 
02133     while (i < iLen)
02134     {
02135       if (lpKeys[i] == iKey)
02136         return lpValues[i]; /* Found */
02137       i++;
02138     }
02139   }
02140   return -1; /* Not found */
02141 }
02142 
02143 
02144 /*************************************************************************
02145  *      @   [SHLWAPI.199]
02146  *
02147  * Copy an interface pointer
02148  *
02149  * PARAMS
02150  *   lppDest   [O] Destination for copy
02151  *   lpUnknown [I] Source for copy
02152  *
02153  * RETURNS
02154  *  Nothing.
02155  */
02156 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
02157 {
02158   TRACE("(%p,%p)\n", lppDest, lpUnknown);
02159 
02160   IUnknown_AtomicRelease(lppDest);
02161 
02162   if (lpUnknown)
02163   {
02164     IUnknown_AddRef(lpUnknown);
02165     *lppDest = lpUnknown;
02166   }
02167 }
02168 
02169 /*************************************************************************
02170  *      @   [SHLWAPI.200]
02171  *
02172  */
02173 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
02174                             REFGUID riidCmdGrp, ULONG cCmds,
02175                             OLECMD *prgCmds, OLECMDTEXT* pCmdText)
02176 {
02177   FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
02178         lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
02179 
02180   /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
02181   return DRAGDROP_E_NOTREGISTERED;
02182 }
02183 
02184 /*************************************************************************
02185  *      @   [SHLWAPI.201]
02186  *
02187  */
02188 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
02189                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
02190                            VARIANT* pvaOut)
02191 {
02192   FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
02193         nCmdID, nCmdexecopt, pvaIn, pvaOut);
02194   return DRAGDROP_E_NOTREGISTERED;
02195 }
02196 
02197 /*************************************************************************
02198  *      @   [SHLWAPI.202]
02199  *
02200  */
02201 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
02202 {
02203   FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
02204   return DRAGDROP_E_NOTREGISTERED;
02205 }
02206 
02207 /*************************************************************************
02208  * @    [SHLWAPI.204]
02209  *
02210  * Determine if a window is not a child of another window.
02211  *
02212  * PARAMS
02213  * hParent [I] Suspected parent window
02214  * hChild  [I] Suspected child window
02215  *
02216  * RETURNS
02217  * TRUE:  If hChild is a child window of hParent
02218  * FALSE: If hChild is not a child window of hParent, or they are equal
02219  */
02220 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
02221 {
02222   TRACE("(%p,%p)\n", hParent, hChild);
02223 
02224   if (!hParent || !hChild)
02225     return TRUE;
02226   else if(hParent == hChild)
02227     return FALSE;
02228   return !IsChild(hParent, hChild);
02229 }
02230 
02231 /*************************************************************************
02232  *    FDSA functions.  Manage a dynamic array of fixed size memory blocks.
02233  */
02234 
02235 typedef struct
02236 {
02237     DWORD num_items;       /* Number of elements inserted */
02238     void *mem;             /* Ptr to array */
02239     DWORD blocks_alloced;  /* Number of elements allocated */
02240     BYTE inc;              /* Number of elements to grow by when we need to expand */
02241     BYTE block_size;       /* Size in bytes of an element */
02242     BYTE flags;            /* Flags */
02243 } FDSA_info;
02244 
02245 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
02246 
02247 /*************************************************************************
02248  *      @   [SHLWAPI.208]
02249  *
02250  * Initialize an FDSA array.
02251  */
02252 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
02253                             DWORD init_blocks)
02254 {
02255     TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
02256 
02257     if(inc == 0)
02258         inc = 1;
02259 
02260     if(mem)
02261         memset(mem, 0, block_size * init_blocks);
02262     
02263     info->num_items = 0;
02264     info->inc = inc;
02265     info->mem = mem;
02266     info->blocks_alloced = init_blocks;
02267     info->block_size = block_size;
02268     info->flags = 0;
02269 
02270     return TRUE;
02271 }
02272 
02273 /*************************************************************************
02274  *      @   [SHLWAPI.209]
02275  *
02276  * Destroy an FDSA array
02277  */
02278 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
02279 {
02280     TRACE("(%p)\n", info);
02281 
02282     if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
02283     {
02284         HeapFree(GetProcessHeap(), 0, info->mem);
02285         return FALSE;
02286     }
02287 
02288     return TRUE;
02289 }
02290 
02291 /*************************************************************************
02292  *      @   [SHLWAPI.210]
02293  *
02294  * Insert element into an FDSA array
02295  */
02296 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
02297 {
02298     TRACE("(%p 0x%08x %p)\n", info, where, block);
02299     if(where > info->num_items)
02300         where = info->num_items;
02301 
02302     if(info->num_items >= info->blocks_alloced)
02303     {
02304         DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
02305         if(info->flags & 0x1)
02306             info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
02307         else
02308         {
02309             void *old_mem = info->mem;
02310             info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
02311             memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
02312         }
02313         info->blocks_alloced += info->inc;
02314         info->flags |= 0x1;
02315     }
02316 
02317     if(where < info->num_items)
02318     {
02319         memmove((char*)info->mem + (where + 1) * info->block_size,
02320                 (char*)info->mem + where * info->block_size,
02321                 (info->num_items - where) * info->block_size);
02322     }
02323     memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
02324 
02325     info->num_items++;
02326     return where;
02327 }
02328 
02329 /*************************************************************************
02330  *      @   [SHLWAPI.211]
02331  *
02332  * Delete an element from an FDSA array.
02333  */
02334 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
02335 {
02336     TRACE("(%p 0x%08x)\n", info, where);
02337 
02338     if(where >= info->num_items)
02339         return FALSE;
02340 
02341     if(where < info->num_items - 1)
02342     {
02343         memmove((char*)info->mem + where * info->block_size,
02344                 (char*)info->mem + (where + 1) * info->block_size,
02345                 (info->num_items - where - 1) * info->block_size);
02346     }
02347     memset((char*)info->mem + (info->num_items - 1) * info->block_size,
02348            0, info->block_size);
02349     info->num_items--;
02350     return TRUE;
02351 }
02352 
02353 /*************************************************************************
02354  *      @   [SHLWAPI.219]
02355  *
02356  * Call IUnknown_QueryInterface() on a table of objects.
02357  *
02358  * RETURNS
02359  *  Success: S_OK.
02360  *  Failure: E_POINTER or E_NOINTERFACE.
02361  */
02362 HRESULT WINAPI QISearch(
02363     void *base,         /* [in]   Table of interfaces */
02364     const QITAB *table, /* [in]   Array of REFIIDs and indexes into the table */
02365     REFIID riid,        /* [in]   REFIID to get interface for */
02366     void **ppv)         /* [out]  Destination for interface pointer */
02367 {
02368     HRESULT ret;
02369     IUnknown *a_vtbl;
02370     const QITAB *xmove;
02371 
02372     TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
02373     if (ppv) {
02374         xmove = table;
02375         while (xmove->piid) {
02376         TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
02377         if (IsEqualIID(riid, xmove->piid)) {
02378             a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
02379             TRACE("matched, returning (%p)\n", a_vtbl);
02380                     *ppv = a_vtbl;
02381             IUnknown_AddRef(a_vtbl);
02382             return S_OK;
02383         }
02384         xmove++;
02385         }
02386 
02387         if (IsEqualIID(riid, &IID_IUnknown)) {
02388         a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
02389         TRACE("returning first for IUnknown (%p)\n", a_vtbl);
02390                 *ppv = a_vtbl;
02391         IUnknown_AddRef(a_vtbl);
02392         return S_OK;
02393         }
02394         *ppv = 0;
02395         ret = E_NOINTERFACE;
02396     } else
02397         ret = E_POINTER;
02398 
02399     TRACE("-- 0x%08x\n", ret);
02400     return ret;
02401 }
02402 
02403 /*************************************************************************
02404  * @ [SHLWAPI.220]
02405  *
02406  * Set the Font for a window and the "PropDlgFont" property of the parent window.
02407  *
02408  * PARAMS
02409  *  hWnd [I] Parent Window to set the property
02410  *  id   [I] Index of child Window to set the Font
02411  *
02412  * RETURNS
02413  *  Success: S_OK
02414  *
02415  */
02416 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
02417 {
02418     FIXME("(%p, %d) stub\n", hWnd, id);
02419     return S_OK;
02420 }
02421 
02422 /*************************************************************************
02423  *      @   [SHLWAPI.221]
02424  *
02425  * Remove the "PropDlgFont" property from a window.
02426  *
02427  * PARAMS
02428  *  hWnd [I] Window to remove the property from
02429  *
02430  * RETURNS
02431  *  A handle to the removed property, or NULL if it did not exist.
02432  */
02433 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
02434 {
02435   HANDLE hProp;
02436 
02437   TRACE("(%p)\n", hWnd);
02438 
02439   hProp = GetPropA(hWnd, "PropDlgFont");
02440 
02441   if(hProp)
02442   {
02443     DeleteObject(hProp);
02444     hProp = RemovePropA(hWnd, "PropDlgFont");
02445   }
02446   return hProp;
02447 }
02448 
02449 /*************************************************************************
02450  *      @   [SHLWAPI.236]
02451  *
02452  * Load the in-process server of a given GUID.
02453  *
02454  * PARAMS
02455  *  refiid [I] GUID of the server to load.
02456  *
02457  * RETURNS
02458  *  Success: A handle to the loaded server dll.
02459  *  Failure: A NULL handle.
02460  */
02461 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
02462 {
02463     HKEY newkey;
02464     DWORD type, count;
02465     CHAR value[MAX_PATH], string[MAX_PATH];
02466 
02467     strcpy(string, "CLSID\\");
02468     SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
02469     strcat(string, "\\InProcServer32");
02470 
02471     count = MAX_PATH;
02472     RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
02473     RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
02474     RegCloseKey(newkey);
02475     return LoadLibraryExA(value, 0, 0);
02476 }
02477 
02478 /*************************************************************************
02479  *      @   [SHLWAPI.237]
02480  *
02481  * Unicode version of SHLWAPI_183.
02482  */
02483 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
02484 {
02485     WNDCLASSW WndClass;
02486 
02487     TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
02488 
02489     if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
02490         return TRUE;
02491     return RegisterClassW(lpWndClass);
02492 }
02493 
02494 /*************************************************************************
02495  *      @   [SHLWAPI.238]
02496  *
02497  * Unregister a list of classes.
02498  *
02499  * PARAMS
02500  *  hInst      [I] Application instance that registered the classes
02501  *  lppClasses [I] List of class names
02502  *  iCount     [I] Number of names in lppClasses
02503  *
02504  * RETURNS
02505  *  Nothing.
02506  */
02507 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
02508 {
02509   WNDCLASSA WndClass;
02510 
02511   TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
02512 
02513   while (iCount > 0)
02514   {
02515     if (GetClassInfoA(hInst, *lppClasses, &WndClass))
02516       UnregisterClassA(*lppClasses, hInst);
02517     lppClasses++;
02518     iCount--;
02519   }
02520 }
02521 
02522 /*************************************************************************
02523  *      @   [SHLWAPI.239]
02524  *
02525  * Unicode version of SHUnregisterClassesA.
02526  */
02527 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
02528 {
02529   WNDCLASSW WndClass;
02530 
02531   TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
02532 
02533   while (iCount > 0)
02534   {
02535     if (GetClassInfoW(hInst, *lppClasses, &WndClass))
02536       UnregisterClassW(*lppClasses, hInst);
02537     lppClasses++;
02538     iCount--;
02539   }
02540 }
02541 
02542 /*************************************************************************
02543  *      @   [SHLWAPI.240]
02544  *
02545  * Call The correct (Ascii/Unicode) default window procedure for a window.
02546  *
02547  * PARAMS
02548  *  hWnd     [I] Window to call the default procedure for
02549  *  uMessage [I] Message ID
02550  *  wParam   [I] WPARAM of message
02551  *  lParam   [I] LPARAM of message
02552  *
02553  * RETURNS
02554  *  The result of calling DefWindowProcA() or DefWindowProcW().
02555  */
02556 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
02557 {
02558     if (IsWindowUnicode(hWnd))
02559         return DefWindowProcW(hWnd, uMessage, wParam, lParam);
02560     return DefWindowProcA(hWnd, uMessage, wParam, lParam);
02561 }
02562 
02563 /*************************************************************************
02564  *      @       [SHLWAPI.256]
02565  */
02566 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
02567 {
02568   HRESULT hRet = E_INVALIDARG;
02569   LPOBJECTWITHSITE lpSite = NULL;
02570 
02571   TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
02572 
02573   if (lpUnknown && iid && lppSite)
02574   {
02575     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
02576                                    (void**)&lpSite);
02577     if (SUCCEEDED(hRet) && lpSite)
02578     {
02579       hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
02580       IObjectWithSite_Release(lpSite);
02581     }
02582   }
02583   return hRet;
02584 }
02585 
02586 /*************************************************************************
02587  *      @   [SHLWAPI.257]
02588  *
02589  * Create a worker window using CreateWindowExA().
02590  *
02591  * PARAMS
02592  *  wndProc    [I] Window procedure
02593  *  hWndParent [I] Parent window
02594  *  dwExStyle  [I] Extra style flags
02595  *  dwStyle    [I] Style flags
02596  *  hMenu      [I] Window menu
02597  *  wnd_extra  [I] Window extra bytes value
02598  *
02599  * RETURNS
02600  *  Success: The window handle of the newly created window.
02601  *  Failure: 0.
02602  */
02603 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
02604                                   DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
02605 {
02606   static const char szClass[] = "WorkerA";
02607   WNDCLASSA wc;
02608   HWND hWnd;
02609 
02610   TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
02611          wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
02612 
02613   /* Create Window class */
02614   wc.style         = 0;
02615   wc.lpfnWndProc   = DefWindowProcA;
02616   wc.cbClsExtra    = 0;
02617   wc.cbWndExtra    = sizeof(LONG_PTR);
02618   wc.hInstance     = shlwapi_hInstance;
02619   wc.hIcon         = NULL;
02620   wc.hCursor       = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
02621   wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
02622   wc.lpszMenuName  = NULL;
02623   wc.lpszClassName = szClass;
02624 
02625   SHRegisterClassA(&wc);
02626 
02627   hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
02628                          hWndParent, hMenu, shlwapi_hInstance, 0);
02629   if (hWnd)
02630   {
02631     SetWindowLongPtrW(hWnd, 0, wnd_extra);
02632 
02633     if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
02634   }
02635 
02636   return hWnd;
02637 }
02638 
02639 typedef struct tagPOLICYDATA
02640 {
02641   DWORD policy;        /* flags value passed to SHRestricted */
02642   LPCWSTR appstr;      /* application str such as "Explorer" */
02643   LPCWSTR keystr;      /* name of the actual registry key / policy */
02644 } POLICYDATA, *LPPOLICYDATA;
02645 
02646 #define SHELL_NO_POLICY 0xffffffff
02647 
02648 /* default shell policy registry key */
02649 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
02650                                       's','o','f','t','\\','W','i','n','d','o','w','s','\\',
02651                                       'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
02652                                       '\\','P','o','l','i','c','i','e','s',0};
02653 
02654 /*************************************************************************
02655  * @                          [SHLWAPI.271]
02656  *
02657  * Retrieve a policy value from the registry.
02658  *
02659  * PARAMS
02660  *  lpSubKey   [I]   registry key name
02661  *  lpSubName  [I]   subname of registry key
02662  *  lpValue    [I]   value name of registry value
02663  *
02664  * RETURNS
02665  *  the value associated with the registry key or 0 if not found
02666  */
02667 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
02668 {
02669     DWORD retval, datsize = sizeof(retval);
02670     HKEY hKey;
02671 
02672     if (!lpSubKey)
02673       lpSubKey = strRegistryPolicyW;
02674 
02675     retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
02676     if (retval != ERROR_SUCCESS)
02677       retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
02678     if (retval != ERROR_SUCCESS)
02679       return 0;
02680 
02681         SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
02682     RegCloseKey(hKey);
02683     return retval;
02684 }
02685 
02686 /*************************************************************************
02687  * @                         [SHLWAPI.266]
02688  *
02689  * Helper function to retrieve the possibly cached value for a specific policy
02690  *
02691  * PARAMS
02692  *  policy     [I]   The policy to look for
02693  *  initial    [I]   Main registry key to open, if NULL use default
02694  *  polTable   [I]   Table of known policies, 0 terminated
02695  *  polArr     [I]   Cache array of policy values
02696  *
02697  * RETURNS
02698  *  The retrieved policy value or 0 if not successful
02699  *
02700  * NOTES
02701  *  This function is used by the native SHRestricted function to search for the
02702  *  policy and cache it once retrieved. The current Wine implementation uses a
02703  *  different POLICYDATA structure and implements a similar algorithm adapted to
02704  *  that structure.
02705  */
02706 DWORD WINAPI SHRestrictionLookup(
02707     DWORD policy,
02708     LPCWSTR initial,
02709     LPPOLICYDATA polTable,
02710     LPDWORD polArr)
02711 {
02712     TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
02713 
02714     if (!polTable || !polArr)
02715       return 0;
02716 
02717     for (;polTable->policy; polTable++, polArr++)
02718     {
02719       if (policy == polTable->policy)
02720       {
02721         /* we have a known policy */
02722 
02723         /* check if this policy has been cached */
02724         if (*polArr == SHELL_NO_POLICY)
02725           *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
02726         return *polArr;
02727       }
02728     }
02729     /* we don't know this policy, return 0 */
02730     TRACE("unknown policy: (%08x)\n", policy);
02731     return 0;
02732 }
02733 
02734 /*************************************************************************
02735  *      @   [SHLWAPI.267]
02736  *
02737  * Get an interface from an object.
02738  *
02739  * RETURNS
02740  *  Success: S_OK. ppv contains the requested interface.
02741  *  Failure: An HRESULT error code.
02742  *
02743  * NOTES
02744  *   This QueryInterface asks the inner object for an interface. In case
02745  *   of aggregation this request would be forwarded by the inner to the
02746  *   outer object. This function asks the inner object directly for the
02747  *   interface circumventing the forwarding to the outer object.
02748  */
02749 HRESULT WINAPI SHWeakQueryInterface(
02750     IUnknown * pUnk,   /* [in] Outer object */
02751     IUnknown * pInner, /* [in] Inner object */
02752     IID * riid, /* [in] Interface GUID to query for */
02753     LPVOID* ppv) /* [out] Destination for queried interface */
02754 {
02755     HRESULT hret = E_NOINTERFACE;
02756     TRACE("(pUnk=%p pInner=%p\n\tIID:  %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
02757 
02758     *ppv = NULL;
02759     if(pUnk && pInner) {
02760             hret = IUnknown_QueryInterface(pInner, riid, ppv);
02761         if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
02762     }
02763     TRACE("-- 0x%08x\n", hret);
02764     return hret;
02765 }
02766 
02767 /*************************************************************************
02768  *      @   [SHLWAPI.268]
02769  *
02770  * Move a reference from one interface to another.
02771  *
02772  * PARAMS
02773  *   lpDest     [O] Destination to receive the reference
02774  *   lppUnknown [O] Source to give up the reference to lpDest
02775  *
02776  * RETURNS
02777  *  Nothing.
02778  */
02779 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
02780 {
02781   TRACE("(%p,%p)\n", lpDest, lppUnknown);
02782 
02783   if (*lppUnknown)
02784   {
02785     /* Copy Reference*/
02786     IUnknown_AddRef(lpDest);
02787     IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
02788   }
02789 }
02790 
02791 /*************************************************************************
02792  *      @   [SHLWAPI.269]
02793  *
02794  * Convert an ASCII string of a CLSID into a CLSID.
02795  *
02796  * PARAMS
02797  *  idstr [I] String representing a CLSID in registry format
02798  *  id    [O] Destination for the converted CLSID
02799  *
02800  * RETURNS
02801  *  Success: TRUE. id contains the converted CLSID.
02802  *  Failure: FALSE.
02803  */
02804 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
02805 {
02806   WCHAR wClsid[40];
02807   MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
02808   return SUCCEEDED(CLSIDFromString(wClsid, id));
02809 }
02810 
02811 /*************************************************************************
02812  *      @   [SHLWAPI.270]
02813  *
02814  * Unicode version of GUIDFromStringA.
02815  */
02816 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
02817 {
02818     return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
02819 }
02820 
02821 /*************************************************************************
02822  *      @   [SHLWAPI.276]
02823  *
02824  * Determine if the browser is integrated into the shell, and set a registry
02825  * key accordingly.
02826  *
02827  * PARAMS
02828  *  None.
02829  *
02830  * RETURNS
02831  *  1, If the browser is not integrated.
02832  *  2, If the browser is integrated.
02833  *
02834  * NOTES
02835  *  The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
02836  *  either set to TRUE, or removed depending on whether the browser is deemed
02837  *  to be integrated.
02838  */
02839 DWORD WINAPI WhichPlatform(void)
02840 {
02841   static const char szIntegratedBrowser[] = "IntegratedBrowser";
02842   static DWORD dwState = 0;
02843   HKEY hKey;
02844   DWORD dwRet, dwData, dwSize;
02845   HMODULE hshell32;
02846 
02847   if (dwState)
02848     return dwState;
02849 
02850   /* If shell32 exports DllGetVersion(), the browser is integrated */
02851   dwState = 1;
02852   hshell32 = LoadLibraryA("shell32.dll");
02853   if (hshell32)
02854   {
02855     FARPROC pDllGetVersion;
02856     pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
02857     dwState = pDllGetVersion ? 2 : 1;
02858     FreeLibrary(hshell32);
02859   }
02860 
02861   /* Set or delete the key accordingly */
02862   dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
02863                         "Software\\Microsoft\\Internet Explorer", 0,
02864                          KEY_ALL_ACCESS, &hKey);
02865   if (!dwRet)
02866   {
02867     dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
02868                              (LPBYTE)&dwData, &dwSize);
02869 
02870     if (!dwRet && dwState == 1)
02871     {
02872       /* Value exists but browser is not integrated */
02873       RegDeleteValueA(hKey, szIntegratedBrowser);
02874     }
02875     else if (dwRet && dwState == 2)
02876     {
02877       /* Browser is integrated but value does not exist */
02878       dwData = TRUE;
02879       RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
02880                      (LPBYTE)&dwData, sizeof(dwData));
02881     }
02882     RegCloseKey(hKey);
02883   }
02884   return dwState;
02885 }
02886 
02887 /*************************************************************************
02888  *      @   [SHLWAPI.278]
02889  *
02890  * Unicode version of SHCreateWorkerWindowA.
02891  */
02892 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
02893                         DWORD dwStyle, HMENU hMenu, LONG msg_result)
02894 {
02895   static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
02896   WNDCLASSW wc;
02897   HWND hWnd;
02898 
02899   TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
02900          wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
02901 
02902   /* If our OS is natively ANSI, use the ANSI version */
02903   if (GetVersion() & 0x80000000)  /* not NT */
02904   {
02905     TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
02906     return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
02907   }
02908 
02909   /* Create Window class */
02910   wc.style         = 0;
02911   wc.lpfnWndProc   = DefWindowProcW;
02912   wc.cbClsExtra    = 0;
02913   wc.cbWndExtra    = 4;
02914   wc.hInstance     = shlwapi_hInstance;
02915   wc.hIcon         = NULL;
02916   wc.hCursor       = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
02917   wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
02918   wc.lpszMenuName  = NULL;
02919   wc.lpszClassName = szClass;
02920 
02921   SHRegisterClassW(&wc);
02922 
02923   hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
02924                          hWndParent, hMenu, shlwapi_hInstance, 0);
02925   if (hWnd)
02926   {
02927     SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, msg_result);
02928 
02929     if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
02930   }
02931 
02932   return hWnd;
02933 }
02934 
02935 /*************************************************************************
02936  *      @   [SHLWAPI.279]
02937  *
02938  * Get and show a context menu from a shell folder.
02939  *
02940  * PARAMS
02941  *  hWnd           [I] Window displaying the shell folder
02942  *  lpFolder       [I] IShellFolder interface
02943  *  lpApidl        [I] Id for the particular folder desired
02944  *
02945  * RETURNS
02946  *  Success: S_OK.
02947  *  Failure: An HRESULT error code indicating the error.
02948  */
02949 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
02950 {
02951     TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
02952     return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
02953 }
02954 
02955 /*************************************************************************
02956  *      @   [SHLWAPI.281]
02957  *
02958  * _SHPackDispParamsV
02959  */
02960 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
02961 {
02962   VARIANTARG *iter;
02963 
02964   TRACE("(%p %p %u ...)\n", params, args, cnt);
02965 
02966   params->rgvarg = args;
02967   params->rgdispidNamedArgs = NULL;
02968   params->cArgs = cnt;
02969   params->cNamedArgs = 0;
02970 
02971   iter = args+cnt;
02972 
02973   while(iter-- > args) {
02974     V_VT(iter) = va_arg(valist, enum VARENUM);
02975 
02976     TRACE("vt=%d\n", V_VT(iter));
02977 
02978     if(V_VT(iter) & VT_BYREF) {
02979       V_BYREF(iter) = va_arg(valist, LPVOID);
02980     } else {
02981       switch(V_VT(iter)) {
02982       case VT_I4:
02983         V_I4(iter) = va_arg(valist, LONG);
02984         break;
02985       case VT_BSTR:
02986         V_BSTR(iter) = va_arg(valist, BSTR);
02987         break;
02988       case VT_DISPATCH:
02989         V_DISPATCH(iter) = va_arg(valist, IDispatch*);
02990         break;
02991       case VT_BOOL:
02992         V_BOOL(iter) = va_arg(valist, int);
02993         break;
02994       case VT_UNKNOWN:
02995         V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
02996         break;
02997       default:
02998         V_VT(iter) = VT_I4;
02999         V_I4(iter) = va_arg(valist, LONG);
03000       }
03001     }
03002   }
03003 
03004   return S_OK;
03005 }
03006 
03007 /*************************************************************************
03008  *      @       [SHLWAPI.282]
03009  *
03010  * SHPackDispParams
03011  */
03012 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
03013 {
03014   __ms_va_list valist;
03015   HRESULT hres;
03016 
03017   __ms_va_start(valist, cnt);
03018   hres = SHPackDispParamsV(params, args, cnt, valist);
03019   __ms_va_end(valist);
03020   return hres;
03021 }
03022 
03023 /*************************************************************************
03024  *      SHLWAPI_InvokeByIID
03025  *
03026  *   This helper function calls IDispatch::Invoke for each sink
03027  * which implements given iid or IDispatch.
03028  *
03029  */
03030 static HRESULT SHLWAPI_InvokeByIID(
03031         IConnectionPoint* iCP,
03032         REFIID iid,
03033         DISPID dispId,
03034         DISPPARAMS* dispParams)
03035 {
03036   IEnumConnections *enumerator;
03037   CONNECTDATA rgcd;
03038   static DISPPARAMS empty = {NULL, NULL, 0, 0};
03039   DISPPARAMS* params = dispParams;
03040 
03041   HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
03042   if (FAILED(result))
03043     return result;
03044 
03045   /* Invoke is never happening with an NULL dispParams */
03046   if (!params)
03047     params = &empty;
03048 
03049   while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
03050   {
03051     IDispatch *dispIface;
03052     if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
03053         SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
03054     {
03055       IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
03056       IDispatch_Release(dispIface);
03057     }
03058     IUnknown_Release(rgcd.pUnk);
03059   }
03060 
03061   IEnumConnections_Release(enumerator);
03062 
03063   return S_OK;
03064 }
03065 
03066 /*************************************************************************
03067  *  IConnectionPoint_InvokeWithCancel   [SHLWAPI.283]
03068  */
03069 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
03070                                                   DISPID dispId, DISPPARAMS* dispParams,
03071                                                   DWORD unknown1, DWORD unknown2 )
03072 {
03073     IID iid;
03074     HRESULT result;
03075 
03076     FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
03077 
03078     result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
03079     if (SUCCEEDED(result))
03080         result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
03081     else
03082         result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
03083 
03084     return result;
03085 }
03086 
03087 
03088 /*************************************************************************
03089  *      @   [SHLWAPI.284]
03090  *
03091  *  IConnectionPoint_SimpleInvoke
03092  */
03093 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
03094         IConnectionPoint* iCP,
03095         DISPID dispId,
03096         DISPPARAMS* dispParams)
03097 {
03098   IID iid;
03099   HRESULT result;
03100 
03101   TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
03102 
03103   result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
03104   if (SUCCEEDED(result))
03105     result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
03106   else
03107     result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
03108 
03109   return result;
03110 }
03111 
03112 /*************************************************************************
03113  *      @   [SHLWAPI.285]
03114  *
03115  * Notify an IConnectionPoint object of changes.
03116  *
03117  * PARAMS
03118  *  lpCP   [I] Object to notify
03119  *  dispID [I]
03120  *
03121  * RETURNS
03122  *  Success: S_OK.
03123  *  Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
03124  *           IConnectionPoint interface.
03125  */
03126 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
03127 {
03128   IEnumConnections *lpEnum;
03129   HRESULT hRet = E_NOINTERFACE;
03130 
03131   TRACE("(%p,0x%8X)\n", lpCP, dispID);
03132 
03133   /* Get an enumerator for the connections */
03134   if (lpCP)
03135     hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
03136 
03137   if (SUCCEEDED(hRet))
03138   {
03139     IPropertyNotifySink *lpSink;
03140     CONNECTDATA connData;
03141     ULONG ulFetched;
03142 
03143     /* Call OnChanged() for every notify sink in the connection point */
03144     while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
03145     {
03146       if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
03147           lpSink)
03148       {
03149         IPropertyNotifySink_OnChanged(lpSink, dispID);
03150         IPropertyNotifySink_Release(lpSink);
03151       }
03152       IUnknown_Release(connData.pUnk);
03153     }
03154 
03155     IEnumConnections_Release(lpEnum);
03156   }
03157   return hRet;
03158 }
03159 
03160 /*************************************************************************
03161  *      @   [SHLWAPI.286]
03162  *
03163  *  IUnknown_CPContainerInvokeParam
03164  */
03165 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
03166         IUnknown *container,
03167         REFIID riid,
03168         DISPID dispId,
03169         VARIANTARG* buffer,
03170         DWORD cParams, ...)
03171 {
03172   HRESULT result;
03173   IConnectionPoint *iCP;
03174   IConnectionPointContainer *iCPC;
03175   DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
03176   __ms_va_list valist;
03177 
03178   if (!container)
03179     return E_NOINTERFACE;
03180 
03181   result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
03182   if (FAILED(result))
03183       return result;
03184 
03185   result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
03186   IConnectionPointContainer_Release(iCPC);
03187   if(FAILED(result))
03188       return result;
03189 
03190   __ms_va_start(valist, cParams);
03191   SHPackDispParamsV(&dispParams, buffer, cParams, valist);
03192   __ms_va_end(valist);
03193 
03194   result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
03195   IConnectionPoint_Release(iCP);
03196 
03197   return result;
03198 }
03199 
03200 /*************************************************************************
03201  *      @   [SHLWAPI.287]
03202  *
03203  * Notify an IConnectionPointContainer object of changes.
03204  *
03205  * PARAMS
03206  *  lpUnknown [I] Object to notify
03207  *  dispID    [I]
03208  *
03209  * RETURNS
03210  *  Success: S_OK.
03211  *  Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
03212  *           IConnectionPointContainer interface.
03213  */
03214 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
03215 {
03216   IConnectionPointContainer* lpCPC = NULL;
03217   HRESULT hRet = E_NOINTERFACE;
03218 
03219   TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
03220 
03221   if (lpUnknown)
03222     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
03223 
03224   if (SUCCEEDED(hRet))
03225   {
03226     IConnectionPoint* lpCP;
03227 
03228     hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
03229     IConnectionPointContainer_Release(lpCPC);
03230 
03231     hRet = IConnectionPoint_OnChanged(lpCP, dispID);
03232     IConnectionPoint_Release(lpCP);
03233   }
03234   return hRet;
03235 }
03236 
03237 /*************************************************************************
03238  *      @   [SHLWAPI.289]
03239  *
03240  * See PlaySoundW.
03241  */
03242 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
03243 {
03244     return PlaySoundW(pszSound, hmod, fdwSound);
03245 }
03246 
03247 /*************************************************************************
03248  *      @   [SHLWAPI.294]
03249  *
03250  * Retrieve a key value from an INI file.  See GetPrivateProfileString for
03251  * more information.
03252  *
03253  * PARAMS
03254  *  appName   [I] The section in the INI file that contains the key
03255  *  keyName   [I] The key to be retrieved
03256  *  out       [O] The buffer into which the key's value will be copied
03257  *  outLen    [I] The length of the `out' buffer
03258  *  filename  [I] The location of the INI file
03259  *
03260  * RETURNS
03261  *  Length of string copied into `out'.
03262  */
03263 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
03264         DWORD outLen, LPCWSTR filename)
03265 {
03266     INT ret;
03267     WCHAR *buf;
03268 
03269     TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
03270         out, outLen, debugstr_w(filename));
03271 
03272     if(outLen == 0)
03273         return 0;
03274 
03275     buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR));
03276     if(!buf){
03277         *out = 0;
03278         return 0;
03279     }
03280 
03281     ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
03282     if(ret)
03283         strcpyW(out, buf);
03284     else
03285         *out = 0;
03286 
03287     HeapFree(GetProcessHeap(), 0, buf);
03288 
03289     return strlenW(out);
03290 }
03291 
03292 /*************************************************************************
03293  *      @   [SHLWAPI.295]
03294  *
03295  * Set a key value in an INI file.  See WritePrivateProfileString for
03296  * more information.
03297  *
03298  * PARAMS
03299  *  appName   [I] The section in the INI file that contains the key
03300  *  keyName   [I] The key to be set
03301  *  str       [O] The value of the key
03302  *  filename  [I] The location of the INI file
03303  *
03304  * RETURNS
03305  *   Success: TRUE
03306  *   Failure: FALSE
03307  */
03308 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
03309         LPCWSTR filename)
03310 {
03311     TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
03312             debugstr_w(filename));
03313 
03314     return WritePrivateProfileStringW(appName, keyName, str, filename);
03315 }
03316 
03317 /*************************************************************************
03318  *      @   [SHLWAPI.313]
03319  *
03320  * See SHGetFileInfoW.
03321  */
03322 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
03323                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
03324 {
03325     return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
03326 }
03327 
03328 /*************************************************************************
03329  *      @   [SHLWAPI.318]
03330  *
03331  * See DragQueryFileW.
03332  */
03333 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
03334 {
03335     return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
03336 }
03337 
03338 /*************************************************************************
03339  *      @   [SHLWAPI.333]
03340  *
03341  * See SHBrowseForFolderW.
03342  */
03343 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
03344 {
03345     return SHBrowseForFolderW(lpBi);
03346 }
03347 
03348 /*************************************************************************
03349  *      @   [SHLWAPI.334]
03350  *
03351  * See SHGetPathFromIDListW.
03352  */
03353 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
03354 {
03355     return SHGetPathFromIDListW(pidl, pszPath);
03356 }
03357 
03358 /*************************************************************************
03359  *      @   [SHLWAPI.335]
03360  *
03361  * See ShellExecuteExW.
03362  */
03363 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
03364 {
03365     return ShellExecuteExW(lpExecInfo);
03366 }
03367 
03368 /*************************************************************************
03369  *      @   [SHLWAPI.336]
03370  *
03371  * See SHFileOperationW.
03372  */
03373 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
03374 {
03375     return SHFileOperationW(lpFileOp);
03376 }
03377 
03378 /*************************************************************************
03379  *      @   [SHLWAPI.342]
03380  *
03381  */
03382 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
03383 {
03384     return InterlockedCompareExchangePointer( dest, xchg, compare );
03385 }
03386 
03387 /*************************************************************************
03388  *      @   [SHLWAPI.350]
03389  *
03390  * See GetFileVersionInfoSizeW.
03391  */
03392 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
03393 {
03394     return GetFileVersionInfoSizeW( filename, handle );
03395 }
03396 
03397 /*************************************************************************
03398  *      @   [SHLWAPI.351]
03399  *
03400  * See GetFileVersionInfoW.
03401  */
03402 BOOL  WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
03403                                       DWORD datasize, LPVOID data )
03404 {
03405     return GetFileVersionInfoW( filename, handle, datasize, data );
03406 }
03407 
03408 /*************************************************************************
03409  *      @   [SHLWAPI.352]
03410  *
03411  * See VerQueryValueW.
03412  */
03413 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
03414                                 LPVOID *lplpBuffer, UINT *puLen )
03415 {
03416     return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
03417 }
03418 
03419 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
03420 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
03421 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
03422 
03423 /*************************************************************************
03424  *      @   [SHLWAPI.355]
03425  *
03426  * Change the modality of a shell object.
03427  *
03428  * PARAMS
03429  *  lpUnknown [I] Object to make modeless
03430  *  bModeless [I] TRUE=Make modeless, FALSE=Make modal
03431  *
03432  * RETURNS
03433  *  Success: S_OK. The modality lpUnknown is changed.
03434  *  Failure: An HRESULT error code indicating the error.
03435  *
03436  * NOTES
03437  *  lpUnknown must support the IOleInPlaceFrame interface, the
03438  *  IInternetSecurityMgrSite interface, the IShellBrowser interface
03439  *  the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
03440  *  or this call will fail.
03441  */
03442 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
03443 {
03444   IUnknown *lpObj;
03445   HRESULT hRet;
03446 
03447   TRACE("(%p,%d)\n", lpUnknown, bModeless);
03448 
03449   if (!lpUnknown)
03450     return E_FAIL;
03451 
03452   if (IsIface(IOleInPlaceActiveObject))
03453     EnableModeless(IOleInPlaceActiveObject);
03454   else if (IsIface(IOleInPlaceFrame))
03455     EnableModeless(IOleInPlaceFrame);
03456   else if (IsIface(IShellBrowser))
03457     EnableModeless(IShellBrowser);
03458   else if (IsIface(IInternetSecurityMgrSite))
03459     EnableModeless(IInternetSecurityMgrSite);
03460   else if (IsIface(IDocHostUIHandler))
03461     EnableModeless(IDocHostUIHandler);
03462   else
03463     return hRet;
03464 
03465   IUnknown_Release(lpObj);
03466   return S_OK;
03467 }
03468 
03469 /*************************************************************************
03470  *      @   [SHLWAPI.357]
03471  *
03472  * See SHGetNewLinkInfoW.
03473  */
03474 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
03475                         BOOL *pfMustCopy, UINT uFlags)
03476 {
03477     return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
03478 }
03479 
03480 /*************************************************************************
03481  *      @   [SHLWAPI.358]
03482  *
03483  * See SHDefExtractIconW.
03484  */
03485 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
03486                          HICON* phiconSmall, UINT nIconSize)
03487 {
03488     return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
03489 }
03490 
03491 /*************************************************************************
03492  *      @   [SHLWAPI.363]
03493  *
03494  * Get and show a context menu from a shell folder.
03495  *
03496  * PARAMS
03497  *  hWnd           [I] Window displaying the shell folder
03498  *  lpFolder       [I] IShellFolder interface
03499  *  lpApidl        [I] Id for the particular folder desired
03500  *  bInvokeDefault [I] Whether to invoke the default menu item
03501  *
03502  * RETURNS
03503  *  Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
03504  *           executed.
03505  *  Failure: An HRESULT error code indicating the error.
03506  */
03507 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
03508 {
03509   IContextMenu *iContext;
03510   HRESULT hRet;
03511 
03512   TRACE("(%p, %p, %p, %d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
03513 
03514   if (!lpFolder)
03515     return E_FAIL;
03516 
03517   /* Get the context menu from the shell folder */
03518   hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
03519                                     &IID_IContextMenu, 0, (void**)&iContext);
03520   if (SUCCEEDED(hRet))
03521   {
03522     HMENU hMenu;
03523     if ((hMenu = CreatePopupMenu()))
03524     {
03525       HRESULT hQuery;
03526       DWORD dwDefaultId = 0;
03527 
03528       /* Add the context menu entries to the popup */
03529       hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
03530                                              bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
03531 
03532       if (SUCCEEDED(hQuery))
03533       {
03534         if (bInvokeDefault &&
03535             (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != (UINT)-1)
03536         {
03537           CMINVOKECOMMANDINFO cmIci;
03538           /* Invoke the default item */
03539           memset(&cmIci,0,sizeof(cmIci));
03540           cmIci.cbSize = sizeof(cmIci);
03541           cmIci.fMask = CMIC_MASK_ASYNCOK;
03542           cmIci.hwnd = hWnd;
03543           cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
03544           cmIci.nShow = SW_SCROLLCHILDREN;
03545 
03546           hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
03547         }
03548       }
03549       DestroyMenu(hMenu);
03550     }
03551     IContextMenu_Release(iContext);
03552   }
03553   return hRet;
03554 }
03555 
03556 /*************************************************************************
03557  *      @   [SHLWAPI.370]
03558  *
03559  * See ExtractIconW.
03560  */
03561 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
03562                          UINT nIconIndex)
03563 {
03564     return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
03565 }
03566 
03567 /*************************************************************************
03568  *      @   [SHLWAPI.377]
03569  *
03570  * Load a library from the directory of a particular process.
03571  *
03572  * PARAMS
03573  *  new_mod        [I] Library name
03574  *  inst_hwnd      [I] Module whose directory is to be used
03575  *  dwCrossCodePage [I] Should be FALSE (currently ignored)
03576  *
03577  * RETURNS
03578  *  Success: A handle to the loaded module
03579  *  Failure: A NULL handle.
03580  */
03581 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
03582 {
03583   /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
03584    *        each call here.
03585    * FIXME: Native shows calls to:
03586    *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
03587    *                      CheckVersion
03588    *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
03589    *  RegQueryValueExA for "LPKInstalled"
03590    *  RegCloseKey
03591    *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
03592    *  RegQueryValueExA for "ResourceLocale"
03593    *  RegCloseKey
03594    *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
03595    *  RegQueryValueExA for "Locale"
03596    *  RegCloseKey
03597    *  and then tests the Locale ("en" for me).
03598    *     code below
03599    *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
03600    */
03601     CHAR mod_path[2*MAX_PATH];
03602     LPSTR ptr;
03603     DWORD len;
03604 
03605     FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
03606     len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
03607     if (!len || len >= sizeof(mod_path)) return NULL;
03608 
03609     ptr = strrchr(mod_path, '\\');
03610     if (ptr) {
03611     strcpy(ptr+1, new_mod);
03612     TRACE("loading %s\n", debugstr_a(mod_path));
03613     return LoadLibraryA(mod_path);
03614     }
03615     return NULL;
03616 }
03617 
03618 /*************************************************************************
03619  *      @   [SHLWAPI.378]
03620  *
03621  * Unicode version of MLLoadLibraryA.
03622  */
03623 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
03624 {
03625     WCHAR mod_path[2*MAX_PATH];
03626     LPWSTR ptr;
03627     DWORD len;
03628 
03629     FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
03630     len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
03631     if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
03632 
03633     ptr = strrchrW(mod_path, '\\');
03634     if (ptr) {
03635     strcpyW(ptr+1, new_mod);
03636     TRACE("loading %s\n", debugstr_w(mod_path));
03637     return LoadLibraryW(mod_path);
03638     }
03639     return NULL;
03640 }
03641 
03642 /*************************************************************************
03643  * ColorAdjustLuma      [SHLWAPI.@]
03644  *
03645  * Adjust the luminosity of a color
03646  *
03647  * PARAMS
03648  *  cRGB         [I] RGB value to convert
03649  *  dwLuma       [I] Luma adjustment
03650  *  bUnknown     [I] Unknown
03651  *
03652  * RETURNS
03653  *  The adjusted RGB color.
03654  */
03655 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
03656 {
03657   TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
03658 
03659   if (dwLuma)
03660   {
03661     WORD wH, wL, wS;
03662 
03663     ColorRGBToHLS(cRGB, &wH, &wL, &wS);
03664 
03665     FIXME("Ignoring luma adjustment\n");
03666 
03667     /* FIXME: The adjustment is not linear */
03668 
03669     cRGB = ColorHLSToRGB(wH, wL, wS);
03670   }
03671   return cRGB;
03672 }
03673 
03674 /*************************************************************************
03675  *      @   [SHLWAPI.389]
03676  *
03677  * See GetSaveFileNameW.
03678  */
03679 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
03680 {
03681     return GetSaveFileNameW(ofn);
03682 }
03683 
03684 /*************************************************************************
03685  *      @   [SHLWAPI.390]
03686  *
03687  * See WNetRestoreConnectionW.
03688  */
03689 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
03690 {
03691     return WNetRestoreConnectionW(hwndOwner, lpszDevice);
03692 }
03693 
03694 /*************************************************************************
03695  *      @   [SHLWAPI.391]
03696  *
03697  * See WNetGetLastErrorW.
03698  */
03699 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
03700                          LPWSTR lpNameBuf, DWORD nNameBufSize)
03701 {
03702     return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
03703 }
03704 
03705 /*************************************************************************
03706  *      @   [SHLWAPI.401]
03707  *
03708  * See PageSetupDlgW.
03709  */
03710 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
03711 {
03712     return PageSetupDlgW(pagedlg);
03713 }
03714 
03715 /*************************************************************************
03716  *      @   [SHLWAPI.402]
03717  *
03718  * See PrintDlgW.
03719  */
03720 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
03721 {
03722     return PrintDlgW(printdlg);
03723 }
03724 
03725 /*************************************************************************
03726  *      @   [SHLWAPI.403]
03727  *
03728  * See GetOpenFileNameW.
03729  */
03730 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
03731 {
03732     return GetOpenFileNameW(ofn);
03733 }
03734 
03735 /*************************************************************************
03736  *      @   [SHLWAPI.404]
03737  */
03738 #if 1
03739 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
03740 {
03741     /* Windows attempts to get an IPersist interface and, if that fails, an
03742      * IPersistFolder interface on the folder passed-in here.  If one of those
03743      * interfaces is available, it then calls GetClassID on the folder... and
03744      * then calls IShellFolder_EnumObjects no matter what, even crashing if
03745      * lpFolder isn't actually an IShellFolder object.  The purpose of getting
03746      * the ClassID is unknown, so we don't do it here.
03747      *
03748      * For discussion and detailed tests, see:
03749      * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
03750      * wine-devel mailing list, 3 Jun 2010
03751      */
03752 
03753     return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
03754 }
03755 #else
03756 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
03757 {
03758     IPersist *persist;
03759     HRESULT hr;
03760 
03761     hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
03762     if(SUCCEEDED(hr))
03763     {
03764         CLSID clsid;
03765         hr = IPersist_GetClassID(persist, &clsid);
03766         if(SUCCEEDED(hr))
03767         {
03768             if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
03769                 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
03770             else
03771                 hr = E_FAIL;
03772         }
03773         IPersist_Release(persist);
03774     }
03775     return hr;
03776 }
03777 #endif
03778 
03779 /* INTERNAL: Map from HLS color space to RGB */
03780 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
03781 {
03782   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
03783 
03784   if (wHue > 160)
03785     return wMid1;
03786   else if (wHue > 120)
03787     wHue = 160 - wHue;
03788   else if (wHue > 40)
03789     return wMid2;
03790 
03791   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
03792 }
03793 
03794 /* Convert to RGB and scale into RGB range (0..255) */
03795 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
03796 
03797 /*************************************************************************
03798  *      ColorHLSToRGB   [SHLWAPI.@]
03799  *
03800  * Convert from hls color space into an rgb COLORREF.
03801  *
03802  * PARAMS
03803  *  wHue        [I] Hue amount
03804  *  wLuminosity [I] Luminosity amount
03805  *  wSaturation [I] Saturation amount
03806  *
03807  * RETURNS
03808  *  A COLORREF representing the converted color.
03809  *
03810  * NOTES
03811  *  Input hls values are constrained to the range (0..240).
03812  */
03813 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
03814 {
03815   WORD wRed;
03816 
03817   if (wSaturation)
03818   {
03819     WORD wGreen, wBlue, wMid1, wMid2;
03820 
03821     if (wLuminosity > 120)
03822       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
03823     else
03824       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
03825 
03826     wMid1 = wLuminosity * 2 - wMid2;
03827 
03828     wRed   = GET_RGB(wHue + 80);
03829     wGreen = GET_RGB(wHue);
03830     wBlue  = GET_RGB(wHue - 80);
03831 
03832     return RGB(wRed, wGreen, wBlue);
03833   }
03834 
03835   wRed = wLuminosity * 255 / 240;
03836   return RGB(wRed, wRed, wRed);
03837 }
03838 
03839 /*************************************************************************
03840  *      @   [SHLWAPI.413]
03841  *
03842  * Get the current docking status of the system.
03843  *
03844  * PARAMS
03845  *  dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
03846  *
03847  * RETURNS
03848  *  One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
03849  *  a notebook.
03850  */
03851 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
03852 {
03853   HW_PROFILE_INFOA hwInfo;
03854 
03855   TRACE("(0x%08x)\n", dwFlags);
03856 
03857   GetCurrentHwProfileA(&hwInfo);
03858   switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
03859   {
03860   case DOCKINFO_DOCKED:
03861   case DOCKINFO_UNDOCKED:
03862     return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
03863   default:
03864     return 0;
03865   }
03866 }
03867 
03868 /*************************************************************************
03869  *      @   [SHLWAPI.418]
03870  *
03871  * Function seems to do FreeLibrary plus other things.
03872  *
03873  * FIXME native shows the following calls:
03874  *   RtlEnterCriticalSection
03875  *   LocalFree
03876  *   GetProcAddress(Comctl32??, 150L)
03877  *   DPA_DeletePtr
03878  *   RtlLeaveCriticalSection
03879  *  followed by the FreeLibrary.
03880  *  The above code may be related to .377 above.
03881  */
03882 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
03883 {
03884     FIXME("(%p) semi-stub\n", hModule);
03885     return FreeLibrary(hModule);
03886 }
03887 
03888 /*************************************************************************
03889  *      @   [SHLWAPI.419]
03890  */
03891 BOOL WINAPI SHFlushSFCacheWrap(void) {
03892   FIXME(": stub\n");
03893   return TRUE;
03894 }
03895 
03896 /*************************************************************************
03897  *      @      [SHLWAPI.429]
03898  * FIXME I have no idea what this function does or what its arguments are.
03899  */
03900 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
03901 {
03902        FIXME("(%p) stub\n", hInst);
03903        return FALSE;
03904 }
03905 
03906 
03907 /*************************************************************************
03908  *      @   [SHLWAPI.430]
03909  */
03910 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
03911 {
03912     FIXME("(%p,%p) stub\n", hInst, hHeap);
03913     return E_FAIL;   /* This is what is used if shlwapi not loaded */
03914 }
03915 
03916 /*************************************************************************
03917  *      @   [SHLWAPI.431]
03918  */
03919 DWORD WINAPI MLClearMLHInstance(DWORD x)
03920 {
03921     FIXME("(0x%08x)stub\n", x);
03922     return 0xabba1247;
03923 }
03924 
03925 /*************************************************************************
03926  * @ [SHLWAPI.432]
03927  *
03928  * See SHSendMessageBroadcastW
03929  *
03930  */
03931 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
03932 {
03933     return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
03934                                SMTO_ABORTIFHUNG, 2000, NULL);
03935 }
03936 
03937 /*************************************************************************
03938  * @ [SHLWAPI.433]
03939  *
03940  * A wrapper for sending Broadcast Messages to all top level Windows
03941  *
03942  */
03943 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
03944 {
03945     return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
03946                                SMTO_ABORTIFHUNG, 2000, NULL);
03947 }
03948 
03949 /*************************************************************************
03950  *      @   [SHLWAPI.436]
03951  *
03952  * Convert a Unicode string CLSID into a CLSID.
03953  *
03954  * PARAMS
03955  *  idstr      [I]   string containing a CLSID in text form
03956  *  id         [O]   CLSID extracted from the string
03957  *
03958  * RETURNS
03959  *  S_OK on success or E_INVALIDARG on failure
03960  */
03961 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
03962 {
03963     return CLSIDFromString((LPCOLESTR)idstr, id);
03964 }
03965 
03966 /*************************************************************************
03967  *      @   [SHLWAPI.437]
03968  *
03969  * Determine if the OS supports a given feature.
03970  *
03971  * PARAMS
03972  *  dwFeature [I] Feature requested (undocumented)
03973  *
03974  * RETURNS
03975  *  TRUE  If the feature is available.
03976  *  FALSE If the feature is not available.
03977  */
03978 BOOL WINAPI IsOS(DWORD feature)
03979 {
03980     OSVERSIONINFOA osvi;
03981     DWORD platform, majorv, minorv;
03982 
03983     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
03984     if(!GetVersionExA(&osvi))  {
03985         ERR("GetVersionEx failed\n");
03986         return FALSE;
03987     }
03988 
03989     majorv = osvi.dwMajorVersion;
03990     minorv = osvi.dwMinorVersion;
03991     platform = osvi.dwPlatformId;
03992 
03993 #define ISOS_RETURN(x) \
03994     TRACE("(0x%x) ret=%d\n",feature,(x)); \
03995     return (x);
03996 
03997     switch(feature)  {
03998     case OS_WIN32SORGREATER:
03999         ISOS_RETURN(platform == VER_PLATFORM_WIN32s
04000                  || platform == VER_PLATFORM_WIN32_WINDOWS)
04001     case OS_NT:
04002         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04003     case OS_WIN95ORGREATER:
04004         ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
04005     case OS_NT4ORGREATER:
04006         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
04007     case OS_WIN2000ORGREATER_ALT:
04008     case OS_WIN2000ORGREATER:
04009         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
04010     case OS_WIN98ORGREATER:
04011         ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
04012     case OS_WIN98_GOLD:
04013         ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
04014     case OS_WIN2000PRO:
04015         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
04016     case OS_WIN2000SERVER:
04017         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
04018     case OS_WIN2000ADVSERVER:
04019         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
04020     case OS_WIN2000DATACENTER:
04021         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
04022     case OS_WIN2000TERMINAL:
04023         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
04024     case OS_EMBEDDED:
04025         FIXME("(OS_EMBEDDED) What should we return here?\n");
04026         return FALSE;
04027     case OS_TERMINALCLIENT:
04028         FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
04029         return FALSE;
04030     case OS_TERMINALREMOTEADMIN:
04031         FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
04032         return FALSE;
04033     case OS_WIN95_GOLD:
04034         ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
04035     case OS_MEORGREATER:
04036         ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
04037     case OS_XPORGREATER:
04038         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
04039     case OS_HOME:
04040         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
04041     case OS_PROFESSIONAL:
04042         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04043     case OS_DATACENTER:
04044         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04045     case OS_ADVSERVER:
04046         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
04047     case OS_SERVER:
04048         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04049     case OS_TERMINALSERVER:
04050         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04051     case OS_PERSONALTERMINALSERVER:
04052         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
04053     case OS_FASTUSERSWITCHING:
04054         FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
04055         return TRUE;
04056     case OS_WELCOMELOGONUI:
04057         FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
04058         return FALSE;
04059     case OS_DOMAINMEMBER:
04060         FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
04061         return TRUE;
04062     case OS_ANYSERVER:
04063         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04064     case OS_WOW6432:
04065         FIXME("(OS_WOW6432) Should we check this?\n");
04066         return FALSE;
04067     case OS_WEBSERVER:
04068         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04069     case OS_SMALLBUSINESSSERVER:
04070         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
04071     case OS_TABLETPC:
04072         FIXME("(OS_TABLEPC) What should we return here?\n");
04073         return FALSE;
04074     case OS_SERVERADMINUI:
04075         FIXME("(OS_SERVERADMINUI) What should we return here?\n");
04076         return FALSE;
04077     case OS_MEDIACENTER:
04078         FIXME("(OS_MEDIACENTER) What should we return here?\n");
04079         return FALSE;
04080     case OS_APPLIANCE:
04081         FIXME("(OS_APPLIANCE) What should we return here?\n");
04082         return FALSE;
04083     case 0x25: /*OS_VISTAORGREATER*/
04084         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
04085     }
04086 
04087 #undef ISOS_RETURN
04088 
04089     WARN("(0x%x) unknown parameter\n",feature);
04090 
04091     return FALSE;
04092 }
04093 
04094 /*************************************************************************
04095  * @  [SHLWAPI.439]
04096  */
04097 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
04098 {
04099     DWORD type, sz = size;
04100 
04101     if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
04102         return E_FAIL;
04103 
04104     return SHLoadIndirectString(buf, buf, size, NULL);
04105 }
04106 
04107 /*************************************************************************
04108  * @  [SHLWAPI.478]
04109  *
04110  * Call IInputObject_TranslateAcceleratorIO() on an object.
04111  *
04112  * PARAMS
04113  *  lpUnknown [I] Object supporting the IInputObject interface.
04114  *  lpMsg     [I] Key message to be processed.
04115  *
04116  * RETURNS
04117  *  Success: S_OK.
04118  *  Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
04119  */
04120 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
04121 {
04122   IInputObject* lpInput = NULL;
04123   HRESULT hRet = E_INVALIDARG;
04124 
04125   TRACE("(%p,%p)\n", lpUnknown, lpMsg);
04126   if (lpUnknown)
04127   {
04128     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
04129                                    (void**)&lpInput);
04130     if (SUCCEEDED(hRet) && lpInput)
04131     {
04132       hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
04133       IInputObject_Release(lpInput);
04134     }
04135   }
04136   return hRet;
04137 }
04138 
04139 /*************************************************************************
04140  * @  [SHLWAPI.481]
04141  *
04142  * Call IInputObject_HasFocusIO() on an object.
04143  *
04144  * PARAMS
04145  *  lpUnknown [I] Object supporting the IInputObject interface.
04146  *
04147  * RETURNS
04148  *  Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
04149  *           or S_FALSE otherwise.
04150  *  Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
04151  */
04152 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
04153 {
04154   IInputObject* lpInput = NULL;
04155   HRESULT hRet = E_INVALIDARG;
04156 
04157   TRACE("(%p)\n", lpUnknown);
04158   if (lpUnknown)
04159   {
04160     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
04161                                    (void**)&lpInput);
04162     if (SUCCEEDED(hRet) && lpInput)
04163     {
04164       hRet = IInputObject_HasFocusIO(lpInput);
04165       IInputObject_Release(lpInput);
04166     }
04167   }
04168   return hRet;
04169 }
04170 
04171 /*************************************************************************
04172  *      ColorRGBToHLS   [SHLWAPI.@]
04173  *
04174  * Convert an rgb COLORREF into the hls color space.
04175  *
04176  * PARAMS
04177  *  cRGB         [I] Source rgb value
04178  *  pwHue        [O] Destination for converted hue
04179  *  pwLuminance  [O] Destination for converted luminance
04180  *  pwSaturation [O] Destination for converted saturation
04181  *
04182  * RETURNS
04183  *  Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
04184  *  values.
04185  *
04186  * NOTES
04187  *  Output HLS values are constrained to the range (0..240).
04188  *  For Achromatic conversions, Hue is set to 160.
04189  */
04190 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
04191               LPWORD pwLuminance, LPWORD pwSaturation)
04192 {
04193   int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
04194 
04195   TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
04196 
04197   wR = GetRValue(cRGB);
04198   wG = GetGValue(cRGB);
04199   wB = GetBValue(cRGB);
04200 
04201   wMax = max(wR, max(wG, wB));
04202   wMin = min(wR, min(wG, wB));
04203 
04204   /* Luminosity */
04205   wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
04206 
04207   if (wMax == wMin)
04208   {
04209     /* Achromatic case */
04210     wSaturation = 0;
04211     /* Hue is now unrepresentable, but this is what native returns... */
04212     wHue = 160;
04213   }
04214   else
04215   {
04216     /* Chromatic case */
04217     int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
04218 
04219     /* Saturation */
04220     if (wLuminosity <= 120)
04221       wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
04222     else
04223       wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
04224 
04225     /* Hue */
04226     wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
04227     wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
04228     wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
04229 
04230     if (wR == wMax)
04231       wHue = wBNorm - wGNorm;
04232     else if (wG == wMax)
04233       wHue = 80 + wRNorm - wBNorm;
04234     else
04235       wHue = 160 + wGNorm - wRNorm;
04236     if (wHue < 0)
04237       wHue += 240;
04238     else if (wHue > 240)
04239       wHue -= 240;
04240   }
04241   if (pwHue)
04242     *pwHue = wHue;
04243   if (pwLuminance)
04244     *pwLuminance = wLuminosity;
04245   if (pwSaturation)
04246     *pwSaturation = wSaturation;
04247 }
04248 
04249 /*************************************************************************
04250  *      SHCreateShellPalette    [SHLWAPI.@]
04251  */
04252 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
04253 {
04254     FIXME("stub\n");
04255     return CreateHalftonePalette(hdc);
04256 }
04257 
04258 /*************************************************************************
04259  *  SHGetInverseCMAP (SHLWAPI.@)
04260  *
04261  * Get an inverse color map table.
04262  *
04263  * PARAMS
04264  *  lpCmap  [O] Destination for color map
04265  *  dwSize  [I] Size of memory pointed to by lpCmap
04266  *
04267  * RETURNS
04268  *  Success: S_OK.
04269  *  Failure: E_POINTER,    If lpCmap is invalid.
04270  *           E_INVALIDARG, If dwFlags is invalid
04271  *           E_OUTOFMEMORY, If there is no memory available
04272  *
04273  * NOTES
04274  *  dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
04275  *  If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
04276  *  internal CMap.
04277  *  If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
04278  *  this DLL's internal CMap.
04279  */
04280 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
04281 {
04282     if (dwSize == 4) {
04283     FIXME(" - returning bogus address for SHGetInverseCMAP\n");
04284     *dest = (DWORD)0xabba1249;
04285     return 0;
04286     }
04287     FIXME("(%p, %#x) stub\n", dest, dwSize);
04288     return 0;
04289 }
04290 
04291 /*************************************************************************
04292  *      SHIsLowMemoryMachine    [SHLWAPI.@]
04293  *
04294  * Determine if the current computer has low memory.
04295  *
04296  * PARAMS
04297  *  x [I] FIXME
04298  *
04299  * RETURNS
04300  *  TRUE if the users machine has 16 Megabytes of memory or less,
04301  *  FALSE otherwise.
04302  */
04303 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
04304 {
04305   FIXME("(0x%08x) stub\n", x);
04306   return FALSE;
04307 }
04308 
04309 /*************************************************************************
04310  *      GetMenuPosFromID    [SHLWAPI.@]
04311  *
04312  * Return the position of a menu item from its Id.
04313  *
04314  * PARAMS
04315  *   hMenu [I] Menu containing the item
04316  *   wID   [I] Id of the menu item
04317  *
04318  * RETURNS
04319  *  Success: The index of the menu item in hMenu.
04320  *  Failure: -1, If the item is not found.
04321  */
04322 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
04323 {
04324     MENUITEMINFOW mi;
04325     INT nCount = GetMenuItemCount(hMenu), nIter = 0;
04326 
04327     TRACE("%p %u\n", hMenu, wID);
04328 
04329     while (nIter < nCount)
04330     {
04331         mi.cbSize = sizeof(mi);
04332         mi.fMask = MIIM_ID;
04333         if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
04334         {
04335             TRACE("ret %d\n", nIter);
04336             return nIter;
04337         }
04338         nIter++;
04339     }
04340 
04341     return -1;
04342 }
04343 
04344 /*************************************************************************
04345  *      @   [SHLWAPI.179]
04346  *
04347  * Same as SHLWAPI.GetMenuPosFromID
04348  */
04349 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
04350 {
04351     TRACE("%p %u\n", hMenu, uID);
04352     return GetMenuPosFromID(hMenu, uID);
04353 }
04354 
04355 
04356 /*************************************************************************
04357  *      @   [SHLWAPI.448]
04358  */
04359 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
04360 {
04361     while (*lpwstr)
04362     {
04363         if (*lpwstr == '/')
04364             *lpwstr = '\\';
04365         lpwstr++;
04366     }
04367 }
04368 
04369 
04370 /*************************************************************************
04371  *      @   [SHLWAPI.461]
04372  */
04373 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
04374 {
04375   FIXME("(0x%08x) stub\n", dwUnknown);
04376   return 0;
04377 }
04378 
04379 
04380 /*************************************************************************
04381  *      @   [SHLWAPI.549]
04382  */
04383 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
04384                                     DWORD dwClsContext, REFIID iid, LPVOID *ppv)
04385 {
04386     return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
04387 }
04388 
04389 /*************************************************************************
04390  * SHSkipJunction   [SHLWAPI.@]
04391  *
04392  * Determine if a bind context can be bound to an object
04393  *
04394  * PARAMS
04395  *  pbc    [I] Bind context to check
04396  *  pclsid [I] CLSID of object to be bound to
04397  *
04398  * RETURNS
04399  *  TRUE: If it is safe to bind
04400  *  FALSE: If pbc is invalid or binding would not be safe
04401  *
04402  */
04403 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
04404 {
04405   static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
04406     'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
04407   BOOL bRet = FALSE;
04408 
04409   if (pbc)
04410   {
04411     IUnknown* lpUnk;
04412 
04413     if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
04414     {
04415       CLSID clsid;
04416 
04417       if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
04418           IsEqualGUID(pclsid, &clsid))
04419         bRet = TRUE;
04420 
04421       IUnknown_Release(lpUnk);
04422     }
04423   }
04424   return bRet;
04425 }
04426 
04427 /***********************************************************************
04428  *      SHGetShellKey (SHLWAPI.@)
04429  */
04430 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
04431 {
04432     FIXME("(0x%08x, %s, %d): stub\n", flags, debugstr_w(sub_key), create);
04433     return (HKEY)0x50;
04434 }
04435 
04436 /***********************************************************************
04437  *      SHQueueUserWorkItem (SHLWAPI.@)
04438  */
04439 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback, 
04440         LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
04441         DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
04442 {
04443     TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
04444           lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
04445 
04446     if(lPriority || dwTag || pdwId || pszModule || dwFlags)
04447         FIXME("Unsupported arguments\n");
04448 
04449     return QueueUserWorkItem(pfnCallback, pContext, 0);
04450 }
04451 
04452 /***********************************************************************
04453  *      SHSetTimerQueueTimer (SHLWAPI.263)
04454  */
04455 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
04456         WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
04457         DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
04458 {
04459     HANDLE hNewTimer;
04460 
04461     /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
04462     if (dwFlags & TPS_LONGEXECTIME) {
04463         dwFlags &= ~TPS_LONGEXECTIME;
04464         dwFlags |= WT_EXECUTELONGFUNCTION;
04465     }
04466     if (dwFlags & TPS_EXECUTEIO) {
04467         dwFlags &= ~TPS_EXECUTEIO;
04468         dwFlags |= WT_EXECUTEINIOTHREAD;
04469     }
04470 
04471     if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
04472                                dwDueTime, dwPeriod, dwFlags))
04473         return NULL;
04474 
04475     return hNewTimer;
04476 }
04477 
04478 /***********************************************************************
04479  *      IUnknown_OnFocusChangeIS (SHLWAPI.@)
04480  */
04481 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
04482 {
04483     IInputObjectSite *pIOS = NULL;
04484     HRESULT hRet = E_INVALIDARG;
04485 
04486     TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
04487 
04488     if (lpUnknown)
04489     {
04490         hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
04491                                        (void **)&pIOS);
04492         if (SUCCEEDED(hRet) && pIOS)
04493         {
04494             hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
04495             IInputObjectSite_Release(pIOS);
04496         }
04497     }
04498     return hRet;
04499 }
04500 
04501 /***********************************************************************
04502  *      SHGetValueW (SHLWAPI.@)
04503  */
04504 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
04505 {
04506     FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
04507     return E_FAIL;
04508 }
04509 
04510 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
04511 
04512 /***********************************************************************
04513  *              GetUIVersion (SHLWAPI.452)
04514  */
04515 DWORD WINAPI GetUIVersion(void)
04516 {
04517     static DWORD version;
04518 
04519     if (!version)
04520     {
04521         DllGetVersion_func pDllGetVersion;
04522         HMODULE dll = LoadLibraryA("shell32.dll");
04523         if (!dll) return 0;
04524 
04525         pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
04526         if (pDllGetVersion)
04527         {
04528             DLLVERSIONINFO dvi;
04529             dvi.cbSize = sizeof(DLLVERSIONINFO);
04530             if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
04531         }
04532         FreeLibrary( dll );
04533         if (!version) version = 3;  /* old shell dlls don't have DllGetVersion */
04534     }
04535     return version;
04536 }
04537 
04538 /***********************************************************************
04539  *              ShellMessageBoxWrapW [SHLWAPI.388]
04540  *
04541  * See shell32.ShellMessageBoxW
04542  *
04543  * NOTE:
04544  * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
04545  * because we can't forward to it in the .spec file since it's exported by
04546  * ordinal. If you change the implementation here please update the code in
04547  * shell32 as well.
04548  */
04549 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
04550                                  LPCWSTR lpCaption, UINT uType, ...)
04551 {
04552     WCHAR *szText = NULL, szTitle[100];
04553     LPCWSTR pszText, pszTitle = szTitle;
04554     LPWSTR pszTemp;
04555     __ms_va_list args;
04556     int ret;
04557 
04558     __ms_va_start(args, uType);
04559 
04560     TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
04561 
04562     if (IS_INTRESOURCE(lpCaption))
04563         LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
04564     else
04565         pszTitle = lpCaption;
04566 
04567     if (IS_INTRESOURCE(lpText))
04568     {
04569         const WCHAR *ptr;
04570         UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0);
04571 
04572         if (len)
04573         {
04574             szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
04575             if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1);
04576         }
04577         pszText = szText;
04578         if (!pszText) {
04579             WARN("Failed to load id %d\n", LOWORD(lpText));
04580             __ms_va_end(args);
04581             return 0;
04582         }
04583     }
04584     else
04585         pszText = lpText;
04586 
04587     FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
04588                    pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
04589 
04590     __ms_va_end(args);
04591 
04592     ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
04593 
04594     HeapFree(GetProcessHeap(), 0, szText);
04595     LocalFree(pszTemp);
04596     return ret;
04597 }
04598 
04599 /***********************************************************************
04600  *              ZoneComputePaneSize [SHLWAPI.382]
04601  */
04602 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
04603 {
04604     FIXME("\n");
04605     return 0x95;
04606 }
04607 
04608 /***********************************************************************
04609  *              SHChangeNotifyWrap [SHLWAPI.394]
04610  */
04611 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
04612 {
04613     SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
04614 }
04615 
04616 typedef struct SHELL_USER_SID {   /* according to MSDN this should be in shlobj.h... */
04617     SID_IDENTIFIER_AUTHORITY sidAuthority;
04618     DWORD                    dwUserGroupID;
04619     DWORD                    dwUserID;
04620 } SHELL_USER_SID, *PSHELL_USER_SID;
04621 
04622 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
04623     SHELL_USER_SID susID;
04624     DWORD          dwAccessType;
04625     BOOL           fInherit;
04626     DWORD          dwAccessMask;
04627     DWORD          dwInheritMask;
04628     DWORD          dwInheritAccessMask;
04629 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
04630 
04631 /***********************************************************************
04632  *             GetShellSecurityDescriptor [SHLWAPI.475]
04633  *
04634  * prepares SECURITY_DESCRIPTOR from a set of ACEs
04635  *
04636  * PARAMS
04637  *  apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
04638  *                 each of which describes permissions to apply
04639  *  cUserPerm  [I] number of entries in apUserPerm array
04640  *
04641  * RETURNS
04642  *  success: pointer to SECURITY_DESCRIPTOR
04643  *  failure: NULL
04644  *
04645  * NOTES
04646  *  Call should free returned descriptor with LocalFree
04647  */
04648 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
04649 {
04650     PSID *sidlist;
04651     PSID  cur_user = NULL;
04652     BYTE  tuUser[2000];
04653     DWORD acl_size;
04654     int   sid_count, i;
04655     PSECURITY_DESCRIPTOR psd = NULL;
04656 
04657     TRACE("%p %d\n", apUserPerm, cUserPerm);
04658 
04659     if (apUserPerm == NULL || cUserPerm <= 0)
04660         return NULL;
04661 
04662     sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
04663     if (!sidlist)
04664         return NULL;
04665 
04666     acl_size = sizeof(ACL);
04667 
04668     for(sid_count = 0; sid_count < cUserPerm; sid_count++)
04669     {
04670         static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
04671         PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
04672         PSHELL_USER_SID sid = &perm->susID;
04673         PSID pSid;
04674         BOOL ret = TRUE;
04675 
04676         if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
04677         {  /* current user's SID */ 
04678             if (!cur_user)
04679             {
04680                 HANDLE Token;
04681                 DWORD bufsize = sizeof(tuUser);
04682 
04683                 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
04684                 if (ret)
04685                 {
04686                     ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
04687                     if (ret)
04688                         cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
04689                     CloseHandle(Token);
04690                 }
04691             }
04692             pSid = cur_user;
04693         } else if (sid->dwUserID==0) /* one sub-authority */
04694             ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
04695                     0, 0, 0, 0, 0, 0, &pSid);
04696         else
04697             ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
04698                     0, 0, 0, 0, 0, 0, &pSid);
04699         if (!ret)
04700             goto free_sids;
04701 
04702         sidlist[sid_count] = pSid;
04703         /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
04704         acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
04705     }
04706 
04707     psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
04708 
04709     if (psd != NULL)
04710     {
04711         PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
04712 
04713         if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
04714             goto error;
04715 
04716         if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
04717             goto error;
04718 
04719         for(i = 0; i < sid_count; i++)
04720         {
04721             PSHELL_USER_PERMISSION sup = apUserPerm[i];
04722             PSID sid = sidlist[i];
04723 
04724             switch(sup->dwAccessType)
04725             {
04726                 case ACCESS_ALLOWED_ACE_TYPE:
04727                     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
04728                         goto error;
04729                     if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION, 
04730                                 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
04731                         goto error;
04732                     break;
04733                 case ACCESS_DENIED_ACE_TYPE:
04734                     if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
04735                         goto error;
04736                     if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION, 
04737                                 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
04738                         goto error;
04739                     break;
04740                 default:
04741                     goto error;
04742             }
04743         }
04744 
04745         if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
04746             goto error;
04747     }
04748     goto free_sids;
04749 
04750 error:
04751     LocalFree(psd);
04752     psd = NULL;
04753 free_sids:
04754     for(i = 0; i < sid_count; i++)
04755     {
04756         if (!cur_user || sidlist[i] != cur_user)
04757             FreeSid(sidlist[i]);
04758     }
04759     HeapFree(GetProcessHeap(), 0, sidlist);
04760 
04761     return psd;
04762 }
04763 
04764 /***********************************************************************
04765  *             SHCreatePropertyBagOnRegKey [SHLWAPI.471]
04766  *
04767  * Creates a property bag from a registry key
04768  *
04769  * PARAMS
04770  *  hKey       [I] Handle to the desired registry key
04771  *  subkey     [I] Name of desired subkey, or NULL to open hKey directly
04772  *  grfMode    [I] Optional flags
04773  *  riid       [I] IID of requested property bag interface
04774  *  ppv        [O] Address to receive pointer to the new interface
04775  *
04776  * RETURNS
04777  *  success: 0
04778  *  failure: error code
04779  *
04780  */
04781 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
04782     DWORD grfMode, REFIID riid, void **ppv)
04783 {
04784     FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
04785           debugstr_guid(riid), ppv);
04786 
04787     return E_NOTIMPL;
04788 }
04789 
04790 /***********************************************************************
04791  *             SHGetViewStatePropertyBag [SHLWAPI.515]
04792  *
04793  * Retrieves a property bag in which the view state information of a folder
04794  * can be stored.
04795  *
04796  * PARAMS
04797  *  pidl        [I] PIDL of the folder requested
04798  *  bag_name    [I] Name of the property bag requested
04799  *  flags       [I] Optional flags
04800  *  riid        [I] IID of requested property bag interface
04801  *  ppv         [O] Address to receive pointer to the new interface
04802  *
04803  * RETURNS
04804  *  success: S_OK
04805  *  failure: error code
04806  *
04807  */
04808 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
04809     DWORD flags, REFIID riid, void **ppv)
04810 {
04811     FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
04812           debugstr_guid(riid), ppv);
04813 
04814     return E_NOTIMPL;
04815 }
04816 
04817 /***********************************************************************
04818  *             SHFormatDateTimeW [SHLWAPI.354]
04819  *
04820  * Produces a string representation of a time.
04821  *
04822  * PARAMS
04823  *  fileTime   [I] Pointer to FILETIME structure specifying the time
04824  *  flags      [I] Flags specifying the desired output
04825  *  buf        [O] Pointer to buffer for output
04826  *  size       [I] Number of characters that can be contained in buffer
04827  *
04828  * RETURNS
04829  *  success: number of characters written to the buffer
04830  *  failure: 0
04831  *
04832  */
04833 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
04834     LPWSTR buf, UINT size)
04835 {
04836 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
04837     DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
04838     SYSTEMTIME st;
04839     FILETIME ft;
04840     INT ret = 0;
04841 
04842     TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
04843 
04844     if (!buf || !size)
04845         return 0;
04846 
04847     if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
04848         FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
04849 
04850     FileTimeToLocalFileTime(fileTime, &ft);
04851     FileTimeToSystemTime(&ft, &st);
04852 
04853     /* first of all date */
04854     if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
04855     {
04856         static const WCHAR sep1[] = {',',' ',0};
04857         static const WCHAR sep2[] = {' ',0};
04858 
04859         DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
04860         ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
04861         if (ret >= size) return ret;
04862 
04863         /* add separator */
04864         if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
04865         {
04866             if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
04867             {
04868                 if (ret < size + 2)
04869                 {
04870                    lstrcatW(&buf[ret-1], sep1);
04871                    ret += 2;
04872                 }
04873             }
04874             else
04875             {
04876                 lstrcatW(&buf[ret-1], sep2);
04877                 ret++;
04878             }
04879         }
04880     }
04881     /* time part */
04882     if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
04883     {
04884         DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
04885 
04886         if (ret) ret--;
04887         ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
04888     }
04889 
04890     return ret;
04891 
04892 #undef SHFORMATDT_UNSUPPORTED_FLAGS
04893 }
04894 
04895 /***********************************************************************
04896  *             SHFormatDateTimeA [SHLWAPI.353]
04897  *
04898  * See SHFormatDateTimeW.
04899  *
04900  */
04901 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
04902     LPSTR buf, UINT size)
04903 {
04904     WCHAR *bufW;
04905     INT retval;
04906 
04907     if (!buf || !size)
04908         return 0;
04909 
04910     bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
04911     retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
04912 
04913     if (retval != 0)
04914         WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
04915 
04916     HeapFree(GetProcessHeap(), 0, bufW);
04917     return retval;
04918 }
04919 
04920 /***********************************************************************
04921  *             ZoneCheckUrlExW [SHLWAPI.231]
04922  *
04923  * Checks the details of the security zone for the supplied site. (?)
04924  *
04925  * PARAMS
04926  *
04927  *  szURL   [I] Pointer to the URL to check
04928  *
04929  *  Other parameters currently unknown.
04930  *
04931  * RETURNS
04932  *  unknown
04933  */
04934 
04935 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
04936     DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
04937     DWORD dwUnknown7)
04938 {
04939     FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
04940         dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
04941 
04942     return 0;
04943 }
04944 
04945 /***********************************************************************
04946  *             SHVerbExistsNA [SHLWAPI.196]
04947  *
04948  *
04949  * PARAMS
04950  *
04951  *  verb [I] a string, often appears to be an extension.
04952  *
04953  *  Other parameters currently unknown.
04954  *
04955  * RETURNS
04956  *  unknown
04957  */
04958 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
04959 {
04960     FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
04961     return 0;
04962 }
04963 
04964 /*************************************************************************
04965  *      @   [SHLWAPI.538]
04966  *
04967  *  Undocumented:  Implementation guessed at via Name and behavior
04968  *
04969  * PARAMS
04970  *  lpUnknown [I] Object to get an IServiceProvider interface from
04971  *  riid      [I] Function requested for QueryService call
04972  *  lppOut    [O] Destination for the service interface pointer
04973  *
04974  * RETURNS
04975  *  Success: S_OK. lppOut contains an object providing the requested service
04976  *  Failure: An HRESULT error code
04977  *
04978  * NOTES
04979  *  lpUnknown is expected to support the IServiceProvider interface.
04980  */
04981 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
04982         REFGUID riid, LPVOID *lppOut)
04983 {
04984     FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
04985     return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
04986 }
04987 
04988 /**************************************************************************
04989  *  SHPropertyBag_ReadLONG (SHLWAPI.496)
04990  *
04991  * This function asks a property bag to read a named property as a LONG.
04992  *
04993  * PARAMS
04994  *  ppb: a IPropertyBag interface
04995  *  pszPropName:  Unicode string that names the property
04996  *  pValue: address to receive the property value as a 32-bit signed integer
04997  *
04998  * RETURNS
04999  *  0 for Success
05000  */
05001 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
05002 {
05003     VARIANT var;
05004     HRESULT hr;
05005     TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
05006     if (!pszPropName || !ppb || !pValue)
05007         return E_INVALIDARG;
05008     V_VT(&var) = VT_I4;
05009     hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
05010     if (SUCCEEDED(hr))
05011     {
05012         if (V_VT(&var) == VT_I4)
05013             *pValue = V_I4(&var);
05014         else
05015             hr = DISP_E_BADVARTYPE;
05016     }
05017     return hr;
05018 }
05019 
05020 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
05021 #define OBJCOMPAT_OTNEEDSSFCACHE           0x00000001
05022 #define OBJCOMPAT_NO_WEBVIEW               0x00000002
05023 #define OBJCOMPAT_UNBINDABLE               0x00000004
05024 #define OBJCOMPAT_PINDLL                   0x00000008
05025 #define OBJCOMPAT_NEEDSFILESYSANCESTOR     0x00000010
05026 #define OBJCOMPAT_NOTAFILESYSTEM           0x00000020
05027 #define OBJCOMPAT_CTXMENU_NOVERBS          0x00000040
05028 #define OBJCOMPAT_CTXMENU_LIMITEDQI        0x00000080
05029 #define OBJCOMPAT_COCREATESHELLFOLDERONLY  0x00000100
05030 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR     0x00000200
05031 #define OBJCOMPAT_NOLEGACYWEBVIEW          0x00000400
05032 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS       0x00001000
05033 #define OBJCOMPAT_NOIPROPERTYSTORE         0x00002000
05034 
05035 /* a search table for compatibility flags */
05036 struct objcompat_entry {
05037     const WCHAR name[30];
05038     DWORD value;
05039 };
05040 
05041 /* expected to be sorted by name */
05042 static const struct objcompat_entry objcompat_table[] = {
05043     { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
05044       OBJCOMPAT_COCREATESHELLFOLDERONLY },
05045     { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
05046       OBJCOMPAT_CTXMENU_LIMITEDQI },
05047     { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
05048       OBJCOMPAT_CTXMENU_LIMITEDQI },
05049     { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
05050       OBJCOMPAT_CTXMENU_XPQCMFLAGS },
05051     { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
05052       OBJCOMPAT_NEEDSFILESYSANCESTOR },
05053     { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
05054       OBJCOMPAT_NEEDSSTORAGEANCESTOR },
05055     { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
05056       OBJCOMPAT_NOIPROPERTYSTORE },
05057     { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
05058       OBJCOMPAT_NOLEGACYWEBVIEW },
05059     { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
05060       OBJCOMPAT_NOTAFILESYSTEM },
05061     { {'N','O','_','W','E','B','V','I','E','W',0},
05062       OBJCOMPAT_NO_WEBVIEW },
05063     { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
05064       OBJCOMPAT_OTNEEDSSFCACHE },
05065     { {'P','I','N','D','L','L',0},
05066       OBJCOMPAT_PINDLL },
05067     { {'U','N','B','I','N','D','A','B','L','E',0},
05068       OBJCOMPAT_UNBINDABLE }
05069 };
05070 
05071 /**************************************************************************
05072  *  SHGetObjectCompatFlags (SHLWAPI.476)
05073  *
05074  * Function returns an integer representation of compatibility flags stored
05075  * in registry for CLSID under ShellCompatibility subkey.
05076  *
05077  * PARAMS
05078  *  pUnk:  pointer to object IUnknown interface, idetifies CLSID
05079  *  clsid: pointer to CLSID to retrieve data for
05080  *
05081  * RETURNS
05082  *  0 on failure, flags set on success
05083  */
05084 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
05085 {
05086     static const WCHAR compatpathW[] =
05087         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
05088          'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
05089          'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
05090          'O','b','j','e','c','t','s','\\','%','s',0};
05091     WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
05092     DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
05093     OLECHAR *clsid_str;
05094     HKEY key;
05095     INT i;
05096 
05097     TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
05098 
05099     if (!pUnk && !clsid) return 0;
05100 
05101     if (pUnk && !clsid)
05102     {
05103         FIXME("iface not handled\n");
05104         return 0;
05105     }
05106 
05107     StringFromCLSID(clsid, &clsid_str);
05108     sprintfW(strW, compatpathW, clsid_str);
05109     CoTaskMemFree(clsid_str);
05110 
05111     ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
05112     if (ret != ERROR_SUCCESS) return 0;
05113 
05114     /* now collect flag values */
05115     ret = 0;
05116     for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
05117     {
05118         INT left, right, res, x;
05119 
05120         /* search in table */
05121         left  = 0;
05122         right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
05123 
05124         while (right >= left) {
05125             x = (left + right) / 2;
05126             res = strcmpW(strW, objcompat_table[x].name);
05127             if (res == 0)
05128             {
05129                 ret |= objcompat_table[x].value;
05130                 break;
05131             }
05132             else if (res < 0)
05133                 right = x - 1;
05134             else
05135                 left = x + 1;
05136         }
05137 
05138         length = sizeof(strW)/sizeof(WCHAR);
05139     }
05140 
05141     return ret;
05142 }

Generated on Wed May 23 2012 04:24:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.