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

shellord.cpp
Go to the documentation of this file.
00001 /*
00002  * The parameters of many functions changes between different OS versions
00003  * (NT uses Unicode strings, 95 uses ASCII strings)
00004  *
00005  * Copyright 1997 Marcus Meissner
00006  *           1998 Jürgen Schmied
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 <precomp.h>
00024 
00025 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00026 WINE_DECLARE_DEBUG_CHANNEL(pidl);
00027 
00028 /* FIXME: !!! move flags to header file !!! */
00029 /* dwFlags */
00030 #define MRUF_STRING_LIST  0 /* list will contain strings */
00031 #define MRUF_BINARY_LIST  1 /* list will contain binary data */
00032 #define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
00033 
00034 EXTERN_C HANDLE WINAPI CreateMRUListA(LPCREATEMRULISTA lpcml);
00035 EXTERN_C INT    WINAPI AddMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData);
00036 EXTERN_C INT    WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum);
00037 EXTERN_C INT    WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize);
00038 
00039 
00040 /* Get a function pointer from a DLL handle */
00041 #define GET_FUNC(func, funcType, module, name, fail) \
00042   do { \
00043     if (!func) { \
00044       if (!SHELL32_h##module && !(SHELL32_h##module = LoadLibraryA(#module ".dll"))) return fail; \
00045       func = (funcType)GetProcAddress(SHELL32_h##module, name); \
00046       if (!func) return fail; \
00047     } \
00048   } while (0)
00049 
00050 /* Function pointers for GET_FUNC macro */
00051 static HMODULE SHELL32_hshlwapi=NULL;
00052 
00053 
00054 /*************************************************************************
00055  * ParseFieldA                    [internal]
00056  *
00057  * copies a field from a ',' delimited string
00058  *
00059  * first field is nField = 1
00060  */
00061 DWORD WINAPI ParseFieldA(
00062     LPCSTR src,
00063     DWORD nField,
00064     LPSTR dst,
00065     DWORD len)
00066 {
00067     WARN("(%s,0x%08x,%p,%d) semi-stub.\n",debugstr_a(src),nField,dst,len);
00068 
00069     if (!src || !src[0] || !dst || !len)
00070       return 0;
00071 
00072     /* skip n fields delimited by ',' */
00073     while (nField > 1)
00074     {
00075       if (*src=='\0') return FALSE;
00076       if (*(src++)==',') nField--;
00077     }
00078 
00079     /* copy part till the next ',' to dst */
00080     while ( *src!='\0' && *src!=',' && (len--)>0 ) *(dst++)=*(src++);
00081 
00082     /* finalize the string */
00083     *dst=0x0;
00084 
00085     return TRUE;
00086 }
00087 
00088 /*************************************************************************
00089  * ParseFieldW            [internal]
00090  *
00091  * copies a field from a ',' delimited string
00092  *
00093  * first field is nField = 1
00094  */
00095 DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len)
00096 {
00097     WARN("(%s,0x%08x,%p,%d) semi-stub.\n", debugstr_w(src), nField, dst, len);
00098 
00099     if (!src || !src[0] || !dst || !len)
00100       return 0;
00101 
00102     /* skip n fields delimited by ',' */
00103     while (nField > 1)
00104     {
00105       if (*src == 0x0) return FALSE;
00106       if (*src++ == ',') nField--;
00107     }
00108 
00109     /* copy part till the next ',' to dst */
00110     while ( *src != 0x0 && *src != ',' && (len--)>0 ) *(dst++) = *(src++);
00111 
00112     /* finalize the string */
00113     *dst = 0x0;
00114 
00115     return TRUE;
00116 }
00117 
00118 /*************************************************************************
00119  * ParseField            [SHELL32.58]
00120  */
00121 EXTERN_C DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len)
00122 {
00123     if (SHELL_OsIsUnicode())
00124       return ParseFieldW((LPCWSTR)src, nField, (LPWSTR)dst, len);
00125     return ParseFieldA((LPCSTR)src, nField, (LPSTR)dst, len);
00126 }
00127 
00128 /*************************************************************************
00129  * GetFileNameFromBrowse            [SHELL32.63]
00130  *
00131  */
00132 BOOL WINAPI GetFileNameFromBrowse(
00133     HWND hwndOwner,
00134     LPWSTR lpstrFile,
00135     UINT nMaxFile,
00136     LPCWSTR lpstrInitialDir,
00137     LPCWSTR lpstrDefExt,
00138     LPCWSTR lpstrFilter,
00139     LPCWSTR lpstrTitle)
00140 {
00141 typedef BOOL (WINAPI *GetOpenFileNameProc)(OPENFILENAMEW *ofn);
00142     HMODULE hmodule;
00143     GetOpenFileNameProc pGetOpenFileNameW;
00144     OPENFILENAMEW ofn;
00145     BOOL ret;
00146 
00147     TRACE("%p, %s, %d, %s, %s, %s, %s)\n",
00148       hwndOwner, debugstr_w(lpstrFile), nMaxFile, lpstrInitialDir, lpstrDefExt,
00149       lpstrFilter, lpstrTitle);
00150 
00151     hmodule = LoadLibraryW(L"comdlg32.dll");
00152     if(!hmodule) return FALSE;
00153     pGetOpenFileNameW = (GetOpenFileNameProc)GetProcAddress(hmodule, "GetOpenFileNameW");
00154     if(!pGetOpenFileNameW)
00155     {
00156     FreeLibrary(hmodule);
00157     return FALSE;
00158     }
00159 
00160     memset(&ofn, 0, sizeof(ofn));
00161 
00162     ofn.lStructSize = sizeof(ofn);
00163     ofn.hwndOwner = hwndOwner;
00164     ofn.lpstrFilter = lpstrFilter;
00165     ofn.lpstrFile = lpstrFile;
00166     ofn.nMaxFile = nMaxFile;
00167     ofn.lpstrInitialDir = lpstrInitialDir;
00168     ofn.lpstrTitle = lpstrTitle;
00169     ofn.lpstrDefExt = lpstrDefExt;
00170     ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
00171     ret = pGetOpenFileNameW(&ofn);
00172 
00173     FreeLibrary(hmodule);
00174     return ret;
00175 }
00176 
00177 /*************************************************************************
00178  * SHGetSetSettings                [SHELL32.68]
00179  */
00180 EXTERN_C VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet)
00181 {
00182   if(bSet)
00183   {
00184     FIXME("%p 0x%08x TRUE\n", lpss, dwMask);
00185   }
00186   else
00187   {
00188     SHGetSettings((LPSHELLFLAGSTATE)lpss,dwMask);
00189   }
00190 }
00191 
00192 /*************************************************************************
00193  * SHGetSettings                [SHELL32.@]
00194  *
00195  * NOTES
00196  *  the registry path are for win98 (tested)
00197  *  and possibly are the same in nt40
00198  *
00199  */
00200 EXTERN_C VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask)
00201 {
00202     HKEY    hKey;
00203     DWORD    dwData;
00204     DWORD    dwDataSize = sizeof (DWORD);
00205 
00206     TRACE("(%p 0x%08x)\n",lpsfs,dwMask);
00207 
00208     if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
00209                  0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
00210       return;
00211 
00212     if ( (SSF_SHOWEXTENSIONS & dwMask) && !RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00213       lpsfs->fShowExtensions  = ((dwData == 0) ?  0 : 1);
00214 
00215     if ( (SSF_SHOWINFOTIP & dwMask) && !RegQueryValueExA(hKey, "ShowInfoTip", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00216       lpsfs->fShowInfoTip  = ((dwData == 0) ?  0 : 1);
00217 
00218     if ( (SSF_DONTPRETTYPATH & dwMask) && !RegQueryValueExA(hKey, "DontPrettyPath", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00219       lpsfs->fDontPrettyPath  = ((dwData == 0) ?  0 : 1);
00220 
00221     if ( (SSF_HIDEICONS & dwMask) && !RegQueryValueExA(hKey, "HideIcons", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00222       lpsfs->fHideIcons  = ((dwData == 0) ?  0 : 1);
00223 
00224     if ( (SSF_MAPNETDRVBUTTON & dwMask) && !RegQueryValueExA(hKey, "MapNetDrvBtn", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00225       lpsfs->fMapNetDrvBtn  = ((dwData == 0) ?  0 : 1);
00226 
00227     if ( (SSF_SHOWATTRIBCOL & dwMask) && !RegQueryValueExA(hKey, "ShowAttribCol", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00228       lpsfs->fShowAttribCol  = ((dwData == 0) ?  0 : 1);
00229 
00230     if (((SSF_SHOWALLOBJECTS | SSF_SHOWSYSFILES) & dwMask) && !RegQueryValueExA(hKey, "Hidden", 0, 0, (LPBYTE)&dwData, &dwDataSize))
00231     { if (dwData == 0)
00232       { if (SSF_SHOWALLOBJECTS & dwMask)    lpsfs->fShowAllObjects  = 0;
00233         if (SSF_SHOWSYSFILES & dwMask)    lpsfs->fShowSysFiles  = 0;
00234       }
00235       else if (dwData == 1)
00236       { if (SSF_SHOWALLOBJECTS & dwMask)    lpsfs->fShowAllObjects  = 1;
00237         if (SSF_SHOWSYSFILES & dwMask)    lpsfs->fShowSysFiles  = 0;
00238       }
00239       else if (dwData == 2)
00240       { if (SSF_SHOWALLOBJECTS & dwMask)    lpsfs->fShowAllObjects  = 0;
00241         if (SSF_SHOWSYSFILES & dwMask)    lpsfs->fShowSysFiles  = 1;
00242       }
00243     }
00244     RegCloseKey (hKey);
00245 
00246     TRACE("-- 0x%04x\n", *(WORD*)lpsfs);
00247 }
00248 
00249 /*************************************************************************
00250  * SHShellFolderView_Message            [SHELL32.73]
00251  *
00252  * Send a message to an explorer cabinet window.
00253  *
00254  * PARAMS
00255  *  hwndCabinet [I] The window containing the shellview to communicate with
00256  *  dwMessage   [I] The SFVM message to send
00257  *  dwParam     [I] Message parameter
00258  *
00259  * RETURNS
00260  *  fixme.
00261  *
00262  * NOTES
00263  *  Message SFVM_REARRANGE = 1
00264  *
00265  *    This message gets sent when a column gets clicked to instruct the
00266  *    shell view to re-sort the item list. dwParam identifies the column
00267  *    that was clicked.
00268  */
00269 LRESULT WINAPI SHShellFolderView_Message(
00270     HWND hwndCabinet,
00271     UINT uMessage,
00272     LPARAM lParam)
00273 {
00274     FIXME("%p %08x %08lx stub\n",hwndCabinet, uMessage, lParam);
00275     return 0;
00276 }
00277 
00278 /*************************************************************************
00279  * RegisterShellHook                [SHELL32.181]
00280  *
00281  * Register a shell hook.
00282  *
00283  * PARAMS
00284  *      hwnd   [I]  Window handle
00285  *      dwType [I]  Type of hook.
00286  *
00287  * NOTES
00288  *     Exported by ordinal
00289  */
00290 BOOL WINAPI RegisterShellHook(
00291     HWND hWnd,
00292     DWORD dwType)
00293 {
00294     FIXME("(%p,0x%08x):stub.\n",hWnd, dwType);
00295     return TRUE;
00296 }
00297 
00298 /*************************************************************************
00299  * ShellMessageBoxW                [SHELL32.182]
00300  *
00301  * See ShellMessageBoxA.
00302  *
00303  * NOTE:
00304  * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
00305  * because we can't forward to it in the .spec file since it's exported by
00306  * ordinal. If you change the implementation here please update the code in
00307  * shlwapi as well.
00308  */
00309 EXTERN_C int WINAPI ShellMessageBoxW(
00310     HINSTANCE hInstance,
00311     HWND hWnd,
00312     LPCWSTR lpText,
00313     LPCWSTR lpCaption,
00314     UINT uType,
00315     ...)
00316 {
00317     WCHAR    szText[100],szTitle[100];
00318     LPCWSTR pszText = szText, pszTitle = szTitle;
00319     LPWSTR  pszTemp;
00320     va_list args;
00321     int    ret;
00322 
00323     va_start(args, uType);
00324     /* wvsprintfA(buf,fmt, args); */
00325 
00326     TRACE("(%p,%p,%p,%p,%08x)\n",
00327         hInstance,hWnd,lpText,lpCaption,uType);
00328 
00329     if (IS_INTRESOURCE(lpCaption))
00330       LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
00331     else
00332       pszTitle = lpCaption;
00333 
00334     if (IS_INTRESOURCE(lpText))
00335       LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
00336     else
00337       pszText = lpText;
00338 
00339     FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
00340                pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
00341 
00342     va_end(args);
00343 
00344     ret = MessageBoxW(hWnd,pszTemp,pszTitle,uType);
00345     LocalFree(pszTemp);
00346     return ret;
00347 }
00348 
00349 /*************************************************************************
00350  * ShellMessageBoxA                [SHELL32.183]
00351  *
00352  * Format and output an error message.
00353  *
00354  * PARAMS
00355  *  hInstance [I] Instance handle of message creator
00356  *  hWnd      [I] Window handle of message creator
00357  *  lpText    [I] Resource Id of title or LPSTR
00358  *  lpCaption [I] Resource Id of title or LPSTR
00359  *  uType     [I] Type of error message
00360  *
00361  * RETURNS
00362  *  A return value from MessageBoxA().
00363  *
00364  * NOTES
00365  *     Exported by ordinal
00366  */
00367 EXTERN_C int WINAPI ShellMessageBoxA(
00368     HINSTANCE hInstance,
00369     HWND hWnd,
00370     LPCSTR lpText,
00371     LPCSTR lpCaption,
00372     UINT uType,
00373     ...)
00374 {
00375     char    szText[100],szTitle[100];
00376     LPCSTR  pszText = szText, pszTitle = szTitle;
00377     LPSTR   pszTemp;
00378     va_list args;
00379     int    ret;
00380 
00381     va_start(args, uType);
00382     /* wvsprintfA(buf,fmt, args); */
00383 
00384     TRACE("(%p,%p,%p,%p,%08x)\n",
00385         hInstance,hWnd,lpText,lpCaption,uType);
00386 
00387     if (IS_INTRESOURCE(lpCaption))
00388       LoadStringA(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle));
00389     else
00390       pszTitle = lpCaption;
00391 
00392     if (IS_INTRESOURCE(lpText))
00393       LoadStringA(hInstance, LOWORD(lpText), szText, sizeof(szText));
00394     else
00395       pszText = lpText;
00396 
00397     FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
00398                pszText, 0, 0, (LPSTR)&pszTemp, 0, &args);
00399 
00400     va_end(args);
00401 
00402     ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType);
00403     LocalFree(pszTemp);
00404     return ret;
00405 }
00406 
00407 /*************************************************************************
00408  * SHRegisterDragDrop                [SHELL32.86]
00409  *
00410  * Probably equivalent to RegisterDragDrop but under Windows 95 it could use the
00411  * shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE
00412  * for details. Under Windows 98 this function initializes the true OLE when called
00413  * the first time, on XP always returns E_OUTOFMEMORY and it got removed from Vista.
00414  *
00415  *
00416  * NOTES
00417  *     exported by ordinal
00418  *
00419  * SEE ALSO
00420  *     RegisterDragDrop, SHLoadOLE
00421  */
00422 HRESULT WINAPI SHRegisterDragDrop(
00423     HWND hWnd,
00424     LPDROPTARGET pDropTarget)
00425 {
00426     FIXME("(%p,%p):stub.\n", hWnd, pDropTarget);
00427     return RegisterDragDrop(hWnd, pDropTarget);
00428 }
00429 
00430 /*************************************************************************
00431  * SHRevokeDragDrop                [SHELL32.87]
00432  *
00433  * Probably equivalent to RevokeDragDrop but under Windows 9x it could use the
00434  * shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE
00435  * for details. Function removed from Windows Vista.
00436  *
00437  * NOTES
00438  *     exported by ordinal
00439  *
00440  * SEE ALSO
00441  *     RevokeDragDrop, SHLoadOLE
00442  */
00443 HRESULT WINAPI SHRevokeDragDrop(HWND hWnd)
00444 {
00445     FIXME("(%p):stub.\n",hWnd);
00446     return RevokeDragDrop(hWnd);
00447 }
00448 
00449 /*************************************************************************
00450  * SHDoDragDrop                    [SHELL32.88]
00451  *
00452  * Probably equivalent to DoDragDrop but under Windows 9x it could use the
00453  * shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE
00454  * for details
00455  *
00456  * NOTES
00457  *     exported by ordinal
00458  *
00459  * SEE ALSO
00460  *     DoDragDrop, SHLoadOLE
00461  */
00462 HRESULT WINAPI SHDoDragDrop(
00463     HWND hWnd,
00464     LPDATAOBJECT lpDataObject,
00465     LPDROPSOURCE lpDropSource,
00466     DWORD dwOKEffect,
00467     LPDWORD pdwEffect)
00468 {
00469     FIXME("(%p %p %p 0x%08x %p):stub.\n",
00470     hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect);
00471     return DoDragDrop(lpDataObject, lpDropSource, dwOKEffect, pdwEffect);
00472 }
00473 
00474 /*************************************************************************
00475  * ArrangeWindows                [SHELL32.184]
00476  *
00477  */
00478 WORD WINAPI ArrangeWindows(
00479     HWND hwndParent,
00480     DWORD dwReserved,
00481     LPCRECT lpRect,
00482     WORD cKids,
00483     CONST HWND * lpKids)
00484 {
00485     /* Unimplemented in WinXP SP3 */
00486     TRACE("(%p 0x%08x %p 0x%04x %p):stub.\n",
00487        hwndParent, dwReserved, lpRect, cKids, lpKids);
00488     return 0;
00489 }
00490 
00491 /*************************************************************************
00492  * SignalFileOpen                [SHELL32.103]
00493  *
00494  * NOTES
00495  *     exported by ordinal
00496  */
00497 EXTERN_C BOOL WINAPI
00498 SignalFileOpen (LPCITEMIDLIST pidl)
00499 {
00500     FIXME("(0x%08x):stub.\n", pidl);
00501 
00502     return 0;
00503 }
00504 
00505 /*************************************************************************
00506  * SHADD_get_policy - helper function for SHAddToRecentDocs
00507  *
00508  * PARAMETERS
00509  *   policy    [IN]  policy name (null termed string) to find
00510  *   type      [OUT] ptr to DWORD to receive type
00511  *   buffer    [OUT] ptr to area to hold data retrieved
00512  *   len       [IN/OUT] ptr to DWORD holding size of buffer and getting
00513  *                      length filled
00514  *
00515  * RETURNS
00516  *   result of the SHQueryValueEx call
00517  */
00518 static INT SHADD_get_policy(LPCSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len)
00519 {
00520     HKEY Policy_basekey;
00521     INT ret;
00522 
00523     /* Get the key for the policies location in the registry
00524      */
00525     if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
00526               "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
00527               0, KEY_READ, &Policy_basekey)) {
00528 
00529     if (RegOpenKeyExA(HKEY_CURRENT_USER,
00530               "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
00531               0, KEY_READ, &Policy_basekey)) {
00532         TRACE("No Explorer Policies location exists. Policy wanted=%s\n",
00533           policy);
00534         *len = 0;
00535         return ERROR_FILE_NOT_FOUND;
00536     }
00537     }
00538 
00539     /* Retrieve the data if it exists
00540      */
00541     ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len);
00542     RegCloseKey(Policy_basekey);
00543     return ret;
00544 }
00545 
00546 
00547 /*************************************************************************
00548  * SHADD_compare_mru - helper function for SHAddToRecentDocs
00549  *
00550  * PARAMETERS
00551  *   data1     [IN] data being looked for
00552  *   data2     [IN] data in MRU
00553  *   cbdata    [IN] length from FindMRUData call (not used)
00554  *
00555  * RETURNS
00556  *   position within MRU list that data was added.
00557  */
00558 static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData)
00559 {
00560     return lstrcmpiA((LPCSTR)data1, (LPCSTR)data2);
00561 }
00562 
00563 /*************************************************************************
00564  * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs
00565  *
00566  * PARAMETERS
00567  *   mruhandle    [IN] handle for created MRU list
00568  *   doc_name     [IN] null termed pure doc name
00569  *   new_lnk_name [IN] null termed path and file name for .lnk file
00570  *   buffer       [IN/OUT] 2048 byte area to construct MRU data
00571  *   len          [OUT] ptr to int to receive space used in buffer
00572  *
00573  * RETURNS
00574  *   position within MRU list that data was added.
00575  */
00576 static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPCSTR doc_name, LPCSTR new_lnk_name,
00577                                      LPSTR buffer, INT *len)
00578 {
00579     LPSTR ptr;
00580     INT wlen;
00581 
00582     /*FIXME: Document:
00583      *  RecentDocs MRU data structure seems to be:
00584      *    +0h   document file name w/ terminating 0h
00585      *    +nh   short int w/ size of remaining
00586      *    +n+2h 02h 30h, or 01h 30h, or 00h 30h  -  unknown
00587      *    +n+4h 10 bytes zeros  -   unknown
00588      *    +n+eh shortcut file name w/ terminating 0h
00589      *    +n+e+nh 3 zero bytes  -  unknown
00590      */
00591 
00592     /* Create the MRU data structure for "RecentDocs"
00593      */
00594     ptr = buffer;
00595     lstrcpyA(ptr, doc_name);
00596     ptr += (lstrlenA(buffer) + 1);
00597     wlen= lstrlenA(new_lnk_name) + 1 + 12;
00598     *((short int*)ptr) = wlen;
00599     ptr += 2;   /* step past the length */
00600     *(ptr++) = 0x30;  /* unknown reason */
00601     *(ptr++) = 0;     /* unknown, but can be 0x00, 0x01, 0x02 */
00602     memset(ptr, 0, 10);
00603     ptr += 10;
00604     lstrcpyA(ptr, new_lnk_name);
00605     ptr += (lstrlenA(new_lnk_name) + 1);
00606     memset(ptr, 0, 3);
00607     ptr += 3;
00608     *len = ptr - buffer;
00609 
00610     /* Add the new entry into the MRU list
00611      */
00612     return AddMRUData(mruhandle, buffer, *len);
00613 }
00614 
00615 /*************************************************************************
00616  * SHAddToRecentDocs                [SHELL32.@]
00617  *
00618  * Modify (add/clear) Shell's list of recently used documents.
00619  *
00620  * PARAMETERS
00621  *   uFlags  [IN] SHARD_PATHA, SHARD_PATHW or SHARD_PIDL
00622  *   pv      [IN] string or pidl, NULL clears the list
00623  *
00624  * NOTES
00625  *     exported by name
00626  *
00627  * FIXME
00628  *  convert to unicode
00629  */
00630 void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
00631 {
00632 /* If list is a string list lpfnCompare has the following prototype
00633  * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
00634  * for binary lists the prototype is
00635  * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
00636  * where cbData is the no. of bytes to compare.
00637  * Need to check what return value means identical - 0?
00638  */
00639 
00640 
00641     UINT olderrormode;
00642     HKEY HCUbasekey;
00643     CHAR doc_name[MAX_PATH];
00644     CHAR link_dir[MAX_PATH];
00645     CHAR new_lnk_filepath[MAX_PATH];
00646     CHAR new_lnk_name[MAX_PATH];
00647     CHAR * ext;
00648     CComPtr<IMalloc>        ppM;
00649     LPITEMIDLIST pidl;
00650     HWND hwnd = 0;       /* FIXME:  get real window handle */
00651     INT ret;
00652     DWORD data[64], datalen, type;
00653 
00654     TRACE("%04x %p\n", uFlags, pv);
00655 
00656     /*FIXME: Document:
00657      *  RecentDocs MRU data structure seems to be:
00658      *    +0h   document file name w/ terminating 0h
00659      *    +nh   short int w/ size of remaining
00660      *    +n+2h 02h 30h, or 01h 30h, or 00h 30h  -  unknown
00661      *    +n+4h 10 bytes zeros  -   unknown
00662      *    +n+eh shortcut file name w/ terminating 0h
00663      *    +n+e+nh 3 zero bytes  -  unknown
00664      */
00665 
00666     /* See if we need to do anything.
00667      */
00668     datalen = 64;
00669     ret=SHADD_get_policy( "NoRecentDocsHistory", &type, data, &datalen);
00670     if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) {
00671     ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret);
00672     return;
00673     }
00674     if (ret == ERROR_SUCCESS) {
00675     if (!( (type == REG_DWORD) ||
00676            ((type == REG_BINARY) && (datalen == 4)) )) {
00677         ERR("Error policy data for \"NoRecentDocsHistory\" not formatted correctly, type=%d, len=%d\n",
00678         type, datalen);
00679         return;
00680     }
00681 
00682     TRACE("policy value for NoRecentDocsHistory = %08x\n", data[0]);
00683     /* now test the actual policy value */
00684     if ( data[0] != 0)
00685         return;
00686     }
00687 
00688     /* Open key to where the necessary info is
00689      */
00690     /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH)
00691      *        and the close should be done during the _DETACH. The resulting
00692      *        key is stored in the DLL global data.
00693      */
00694     if (RegCreateKeyExA(HKEY_CURRENT_USER,
00695             "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
00696             0, 0, 0, KEY_READ, 0, &HCUbasekey, 0)) {
00697     ERR("Failed to create 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'\n");
00698     return;
00699     }
00700 
00701     /* Get path to user's "Recent" directory
00702      */
00703     if(SUCCEEDED(SHGetMalloc(&ppM))) {
00704     if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT,
00705                          &pidl))) {
00706         SHGetPathFromIDListA(pidl, link_dir);
00707         ppM->Free(pidl);
00708     }
00709     else {
00710         /* serious issues */
00711         link_dir[0] = 0;
00712         ERR("serious issues 1\n");
00713     }
00714     }
00715     else {
00716     /* serious issues */
00717     link_dir[0] = 0;
00718     ERR("serious issues 2\n");
00719     }
00720     TRACE("Users Recent dir %s\n", link_dir);
00721 
00722     /* If no input, then go clear the lists */
00723     if (!pv) {
00724     /* clear user's Recent dir
00725      */
00726 
00727     /* FIXME: delete all files in "link_dir"
00728      *
00729      * while( more files ) {
00730      *    lstrcpyA(old_lnk_name, link_dir);
00731      *    PathAppendA(old_lnk_name, filenam);
00732      *    DeleteFileA(old_lnk_name);
00733      * }
00734      */
00735     FIXME("should delete all files in %s\\\n", link_dir);
00736 
00737     /* clear MRU list
00738      */
00739     /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against
00740      *  HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer
00741      *  and naturally it fails w/ rc=2. It should do it against
00742      *  HKEY_CURRENT_USER which is where it is stored, and where
00743      *  the MRU routines expect it!!!!
00744      */
00745     RegDeleteKeyA(HCUbasekey, "RecentDocs");
00746     RegCloseKey(HCUbasekey);
00747     return;
00748     }
00749 
00750     /* Have data to add, the jobs to be done:
00751      *   1. Add document to MRU list in registry "HKCU\Software\
00752      *      Microsoft\Windows\CurrentVersion\Explorer\RecentDocs".
00753      *   2. Add shortcut to document in the user's Recent directory
00754      *      (CSIDL_RECENT).
00755      *   3. Add shortcut to Start menu's Documents submenu.
00756      */
00757 
00758     /* Get the pure document name from the input
00759      */
00760     switch (uFlags)
00761     {
00762     case SHARD_PIDL:
00763     SHGetPathFromIDListA((LPCITEMIDLIST)pv, doc_name);
00764         break;
00765 
00766     case SHARD_PATHA:
00767         lstrcpynA(doc_name, (LPCSTR)pv, MAX_PATH);
00768         break;
00769 
00770     case SHARD_PATHW:
00771         WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pv, -1, doc_name, MAX_PATH, NULL, NULL);
00772         break;
00773 
00774     default:
00775         FIXME("Unsupported flags: %u\n", uFlags);
00776         return;
00777     }
00778 
00779     TRACE("full document name %s\n", debugstr_a(doc_name));
00780 
00781     /* check if file is a shortcut */
00782     ext = strrchr(doc_name, '.');
00783     if (!lstrcmpiA(ext, ".lnk"))
00784     {
00785         CComPtr<IShellLinkA> ShellLink;
00786         IShellLink_ConstructFromFile(NULL, IID_IShellLinkA, (LPCITEMIDLIST)SHSimpleIDListFromPathA(doc_name), (LPVOID*)&ShellLink);
00787         ShellLink->GetPath(doc_name, MAX_PATH, NULL, 0);
00788     }
00789 
00790     ext = strrchr(doc_name, '.');
00791     if (!lstrcmpiA(ext, ".exe"))
00792     {
00793         /* executables are not added */
00794         return;
00795     }
00796 
00797     PathStripPathA(doc_name);
00798     TRACE("stripped document name %s\n", debugstr_a(doc_name));
00799 
00800 
00801     /* ***  JOB 1: Update registry for ...\Explorer\RecentDocs list  *** */
00802 
00803     {  /* on input needs:
00804     *      doc_name    -  pure file-spec, no path
00805     *      link_dir    -  path to the user's Recent directory
00806     *      HCUbasekey  -  key of ...Windows\CurrentVersion\Explorer" node
00807     * creates:
00808     *      new_lnk_name-  pure file-spec, no path for new .lnk file
00809     *      new_lnk_filepath
00810     *                  -  path and file name of new .lnk file
00811     */
00812     CREATEMRULISTA mymru;
00813     HANDLE mruhandle;
00814     INT len, pos, bufused, err;
00815     INT i;
00816     DWORD attr;
00817     CHAR buffer[2048];
00818     CHAR *ptr;
00819     CHAR old_lnk_name[MAX_PATH];
00820     short int slen;
00821 
00822     mymru.cbSize = sizeof(CREATEMRULISTA);
00823     mymru.nMaxItems = 15;
00824     mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE;
00825     mymru.hKey = HCUbasekey;
00826     mymru.lpszSubKey = "RecentDocs";
00827     mymru.lpfnCompare = (PROC)SHADD_compare_mru;
00828     mruhandle = CreateMRUListA(&mymru);
00829     if (!mruhandle) {
00830         /* MRU failed */
00831         ERR("MRU processing failed, handle zero\n");
00832         RegCloseKey(HCUbasekey);
00833         return;
00834     }
00835     len = lstrlenA(doc_name);
00836     pos = FindMRUData(mruhandle, doc_name, len, 0);
00837 
00838     /* Now get the MRU entry that will be replaced
00839      * and delete the .lnk file for it
00840      */
00841     if ((bufused = EnumMRUListA(mruhandle, (pos == -1) ? 14 : pos,
00842                                     buffer, 2048)) != -1) {
00843         ptr = buffer;
00844         ptr += (lstrlenA(buffer) + 1);
00845         slen = *((short int*)ptr);
00846         ptr += 2;  /* skip the length area */
00847         if (bufused >= slen + (ptr-buffer)) {
00848         /* buffer size looks good */
00849         ptr += 12; /* get to string */
00850         len = bufused - (ptr-buffer);  /* get length of buf remaining */
00851         if ((lstrlenA(ptr) > 0) && (lstrlenA(ptr) <= len-1)) {
00852             /* appears to be good string */
00853             lstrcpyA(old_lnk_name, link_dir);
00854             PathAppendA(old_lnk_name, ptr);
00855             if (!DeleteFileA(old_lnk_name)) {
00856             if ((attr = GetFileAttributesA(old_lnk_name)) == INVALID_FILE_ATTRIBUTES) {
00857                 if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) {
00858                 ERR("Delete for %s failed, err=%d, attr=%08x\n",
00859                     old_lnk_name, err, attr);
00860                 }
00861                 else {
00862                 TRACE("old .lnk file %s did not exist\n",
00863                       old_lnk_name);
00864                 }
00865             }
00866             else {
00867                 ERR("Delete for %s failed, attr=%08x\n",
00868                 old_lnk_name, attr);
00869             }
00870             }
00871             else {
00872             TRACE("deleted old .lnk file %s\n", old_lnk_name);
00873             }
00874         }
00875         }
00876     }
00877 
00878     /* Create usable .lnk file name for the "Recent" directory
00879      */
00880     wsprintfA(new_lnk_name, "%s.lnk", doc_name);
00881     lstrcpyA(new_lnk_filepath, link_dir);
00882     PathAppendA(new_lnk_filepath, new_lnk_name);
00883     i = 1;
00884     olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS);
00885     while (GetFileAttributesA(new_lnk_filepath) != INVALID_FILE_ATTRIBUTES) {
00886         i++;
00887         wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i);
00888         lstrcpyA(new_lnk_filepath, link_dir);
00889         PathAppendA(new_lnk_filepath, new_lnk_name);
00890     }
00891     SetErrorMode(olderrormode);
00892     TRACE("new shortcut will be %s\n", new_lnk_filepath);
00893 
00894     /* Now add the new MRU entry and data
00895      */
00896     pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name,
00897                     buffer, &len);
00898     FreeMRUList(mruhandle);
00899     TRACE("Updated MRU list, new doc is position %d\n", pos);
00900     }
00901 
00902     /* ***  JOB 2: Create shortcut in user's "Recent" directory  *** */
00903 
00904     {  /* on input needs:
00905     *      doc_name    -  pure file-spec, no path
00906     *      new_lnk_filepath
00907     *                  -  path and file name of new .lnk file
00908      *      uFlags[in]  -  flags on call to SHAddToRecentDocs
00909     *      pv[in]      -  document path/pidl on call to SHAddToRecentDocs
00910     */
00911     CComPtr<IShellLinkA>        psl;
00912     CComPtr<IPersistFile>        pPf;
00913     HRESULT hres;
00914     CHAR desc[MAX_PATH];
00915     WCHAR widelink[MAX_PATH];
00916 
00917     CoInitialize(0);
00918 
00919     hres = CoCreateInstance(CLSID_ShellLink,
00920                  NULL,
00921                  CLSCTX_INPROC_SERVER,
00922                  IID_IShellLinkA,
00923                  (void **)&psl);
00924     if(SUCCEEDED(hres)) {
00925 
00926         hres = psl->QueryInterface(IID_IPersistFile,
00927                          (LPVOID *)&pPf);
00928         if(FAILED(hres)) {
00929         /* bombed */
00930         ERR("failed QueryInterface for IPersistFile %08x\n", hres);
00931         goto fail;
00932         }
00933 
00934         /* Set the document path or pidl */
00935         if (uFlags == SHARD_PIDL) {
00936         hres = psl->SetIDList((LPCITEMIDLIST) pv);
00937         } else {
00938         hres = psl->SetPath((LPCSTR) pv);
00939         }
00940         if(FAILED(hres)) {
00941         /* bombed */
00942         ERR("failed Set{IDList|Path} %08x\n", hres);
00943         goto fail;
00944         }
00945 
00946         lstrcpyA(desc, "Shortcut to ");
00947         lstrcatA(desc, doc_name);
00948         hres = psl->SetDescription(desc);
00949         if(FAILED(hres)) {
00950         /* bombed */
00951         ERR("failed SetDescription %08x\n", hres);
00952         goto fail;
00953         }
00954 
00955         MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1,
00956                 widelink, MAX_PATH);
00957         /* create the short cut */
00958         hres = pPf->Save(widelink, TRUE);
00959         if(FAILED(hres)) {
00960         /* bombed */
00961         ERR("failed IPersistFile::Save %08x\n", hres);
00962         goto fail;
00963         }
00964         hres = pPf->SaveCompleted(widelink);
00965         TRACE("shortcut %s has been created, result=%08x\n",
00966           new_lnk_filepath, hres);
00967     }
00968     else {
00969         ERR("CoCreateInstance failed, hres=%08x\n", hres);
00970     }
00971     }
00972 
00973  fail:
00974     CoUninitialize();
00975 
00976     /* all done */
00977     RegCloseKey(HCUbasekey);
00978     return;
00979 }
00980 
00981 /*************************************************************************
00982  * SHCreateShellFolderViewEx            [SHELL32.174]
00983  *
00984  * Create a new instance of the default Shell folder view object.
00985  *
00986  * RETURNS
00987  *  Success: S_OK
00988  *  Failure: error value
00989  *
00990  * NOTES
00991  *  see IShellFolder::CreateViewObject
00992  */
00993 HRESULT WINAPI SHCreateShellFolderViewEx(
00994     LPCSFV psvcbi,    /* [in] shelltemplate struct */
00995     IShellView **ppv) /* [out] IShellView pointer */
00996 {
00997     IShellView * psf;
00998     HRESULT hRes;
00999 
01000     TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
01001       psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback,
01002       psvcbi->fvm, psvcbi->psvOuter);
01003 
01004     hRes = IShellView_Constructor(psvcbi->pshf, &psf);
01005     if (FAILED(hRes))
01006         return hRes;
01007 
01008     if (!psf)
01009       return E_OUTOFMEMORY;
01010 
01011     psf->AddRef();
01012     hRes = psf->QueryInterface(IID_IShellView, (LPVOID *)ppv);
01013     psf->Release();
01014 
01015     return hRes;
01016 }
01017 /*************************************************************************
01018  *  SHWinHelp                    [SHELL32.127]
01019  *
01020  */
01021 EXTERN_C HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z)
01022 {    FIXME("0x%08x 0x%08x 0x%08x 0x%08x stub\n",v,w,x,z);
01023     return 0;
01024 }
01025 /*************************************************************************
01026  *  SHRunControlPanel [SHELL32.161]
01027  *
01028  */
01029 EXTERN_C BOOL WINAPI SHRunControlPanel (LPCWSTR lpcszCmdLine, HWND hwndMsgParent)
01030 {
01031     FIXME("0x%08x 0x%08x stub\n",lpcszCmdLine,hwndMsgParent);
01032     return 0;
01033 }
01034 
01035 static LPUNKNOWN SHELL32_IExplorerInterface=0;
01036 /*************************************************************************
01037  * SHSetInstanceExplorer            [SHELL32.176]
01038  *
01039  * NOTES
01040  *  Sets the interface
01041  */
01042 VOID WINAPI SHSetInstanceExplorer (LPUNKNOWN lpUnknown)
01043 {    TRACE("%p\n", lpUnknown);
01044     SHELL32_IExplorerInterface = lpUnknown;
01045 }
01046 /*************************************************************************
01047  * SHGetInstanceExplorer            [SHELL32.@]
01048  *
01049  * NOTES
01050  *  gets the interface pointer of the explorer and a reference
01051  */
01052 HRESULT WINAPI SHGetInstanceExplorer (IUnknown **lpUnknown)
01053 {    TRACE("%p\n", lpUnknown);
01054 
01055     *lpUnknown = SHELL32_IExplorerInterface;
01056 
01057     if (!SHELL32_IExplorerInterface)
01058       return E_FAIL;
01059 
01060     SHELL32_IExplorerInterface->AddRef();
01061     return NOERROR;
01062 }
01063 /*************************************************************************
01064  * SHFreeUnusedLibraries            [SHELL32.123]
01065  *
01066  * Probably equivalent to CoFreeUnusedLibraries but under Windows 9x it could use
01067  * the shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE
01068  * for details
01069  *
01070  * NOTES
01071  *     exported by ordinal
01072  *
01073  * SEE ALSO
01074  *     CoFreeUnusedLibraries, SHLoadOLE
01075  */
01076 void WINAPI SHFreeUnusedLibraries (void)
01077 {
01078     FIXME("stub\n");
01079     CoFreeUnusedLibraries();
01080 }
01081 /*************************************************************************
01082  * DAD_AutoScroll                [SHELL32.129]
01083  *
01084  */
01085 BOOL WINAPI DAD_AutoScroll(HWND hwnd, AUTO_SCROLL_DATA *samples, const POINT * pt)
01086 {
01087     FIXME("hwnd = %p %p %p\n",hwnd,samples,pt);
01088     return 0;
01089 }
01090 /*************************************************************************
01091  * DAD_DragEnter                [SHELL32.130]
01092  *
01093  */
01094 BOOL WINAPI DAD_DragEnter(HWND hwnd)
01095 {
01096     FIXME("hwnd = %p\n",hwnd);
01097     return FALSE;
01098 }
01099 /*************************************************************************
01100  * DAD_DragEnterEx                [SHELL32.131]
01101  *
01102  */
01103 BOOL WINAPI DAD_DragEnterEx(HWND hwnd, POINT p)
01104 {
01105     FIXME("hwnd = %p (%d,%d)\n",hwnd,p.x,p.y);
01106     return FALSE;
01107 }
01108 /*************************************************************************
01109  * DAD_DragMove                [SHELL32.134]
01110  *
01111  */
01112 BOOL WINAPI DAD_DragMove(POINT p)
01113 {
01114     FIXME("(%d,%d)\n",p.x,p.y);
01115     return FALSE;
01116 }
01117 /*************************************************************************
01118  * DAD_DragLeave                [SHELL32.132]
01119  *
01120  */
01121 BOOL WINAPI DAD_DragLeave(VOID)
01122 {
01123     FIXME("\n");
01124     return FALSE;
01125 }
01126 /*************************************************************************
01127  * DAD_SetDragImage                [SHELL32.136]
01128  *
01129  * NOTES
01130  *  exported by name
01131  */
01132 BOOL WINAPI DAD_SetDragImage(
01133     HIMAGELIST himlTrack,
01134     LPPOINT lppt)
01135 {
01136     FIXME("%p %p stub\n",himlTrack, lppt);
01137   return 0;
01138 }
01139 /*************************************************************************
01140  * DAD_ShowDragImage                [SHELL32.137]
01141  *
01142  * NOTES
01143  *  exported by name
01144  */
01145 BOOL WINAPI DAD_ShowDragImage(BOOL bShow)
01146 {
01147     FIXME("0x%08x stub\n",bShow);
01148     return 0;
01149 }
01150 
01151 static const WCHAR szwCabLocation[] = {
01152   'S','o','f','t','w','a','r','e','\\',
01153   'M','i','c','r','o','s','o','f','t','\\',
01154   'W','i','n','d','o','w','s','\\',
01155   'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
01156   'E','x','p','l','o','r','e','r','\\',
01157   'C','a','b','i','n','e','t','S','t','a','t','e',0
01158 };
01159 
01160 static const WCHAR szwSettings[] = { 'S','e','t','t','i','n','g','s',0 };
01161 
01162 /*************************************************************************
01163  * ReadCabinetState                [SHELL32.651] NT 4.0
01164  *
01165  */
01166 BOOL WINAPI ReadCabinetState(CABINETSTATE *cs, int length)
01167 {
01168     HKEY hkey = 0;
01169     DWORD type, r;
01170 
01171     TRACE("%p %d\n", cs, length);
01172 
01173     if( (cs == NULL) || (length < (int)sizeof(*cs))  )
01174         return FALSE;
01175 
01176     r = RegOpenKeyW( HKEY_CURRENT_USER, szwCabLocation, &hkey );
01177     if( r == ERROR_SUCCESS )
01178     {
01179         type = REG_BINARY;
01180         r = RegQueryValueExW( hkey, szwSettings,
01181             NULL, &type, (LPBYTE)cs, (LPDWORD)&length );
01182         RegCloseKey( hkey );
01183 
01184     }
01185 
01186     /* if we can't read from the registry, create default values */
01187     if ( (r != ERROR_SUCCESS) || (cs->cLength < sizeof(*cs)) ||
01188         (cs->cLength != length) )
01189     {
01190         ERR("Initializing shell cabinet settings\n");
01191         memset(cs, 0, sizeof(*cs));
01192         cs->cLength          = sizeof(*cs);
01193         cs->nVersion         = 2;
01194         cs->fFullPathTitle   = FALSE;
01195         cs->fSaveLocalView   = TRUE;
01196         cs->fNotShell        = FALSE;
01197         cs->fSimpleDefault   = TRUE;
01198         cs->fDontShowDescBar = FALSE;
01199         cs->fNewWindowMode   = FALSE;
01200         cs->fShowCompColor   = FALSE;
01201         cs->fDontPrettyNames = FALSE;
01202         cs->fAdminsCreateCommonGroups = TRUE;
01203         cs->fMenuEnumFilter  = 96;
01204     }
01205 
01206     return TRUE;
01207 }
01208 
01209 /*************************************************************************
01210  * WriteCabinetState                [SHELL32.652] NT 4.0
01211  *
01212  */
01213 BOOL WINAPI WriteCabinetState(CABINETSTATE *cs)
01214 {
01215     DWORD r;
01216     HKEY hkey = 0;
01217 
01218     TRACE("%p\n",cs);
01219 
01220     if( cs == NULL )
01221         return FALSE;
01222 
01223     r = RegCreateKeyExW( HKEY_CURRENT_USER, szwCabLocation, 0,
01224          NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
01225     if( r == ERROR_SUCCESS )
01226     {
01227         r = RegSetValueExW( hkey, szwSettings, 0,
01228             REG_BINARY, (LPBYTE) cs, cs->cLength);
01229 
01230         RegCloseKey( hkey );
01231     }
01232 
01233     return (r==ERROR_SUCCESS);
01234 }
01235 
01236 /*************************************************************************
01237  * FileIconInit                 [SHELL32.660]
01238  *
01239  */
01240 BOOL WINAPI FileIconInit(BOOL bFullInit)
01241 {    FIXME("(%s)\n", bFullInit ? "true" : "false");
01242     return 0;
01243 }
01244 
01245 /*************************************************************************
01246  * IsUserAnAdmin    [SHELL32.680] NT 4.0
01247  *
01248  * Checks whether the current user is a member of the Administrators group.
01249  *
01250  * PARAMS
01251  *     None
01252  *
01253  * RETURNS
01254  *     Success: TRUE
01255  *     Failure: FALSE
01256  */
01257 BOOL WINAPI IsUserAnAdmin(VOID)
01258 {
01259     SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY};
01260     HANDLE hToken;
01261     DWORD dwSize;
01262     PTOKEN_GROUPS lpGroups;
01263     PSID lpSid;
01264     DWORD i;
01265     BOOL bResult = FALSE;
01266 
01267     TRACE("\n");
01268 
01269     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
01270     {
01271         return FALSE;
01272     }
01273 
01274     if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
01275     {
01276         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
01277         {
01278             CloseHandle(hToken);
01279             return FALSE;
01280         }
01281     }
01282 
01283     lpGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), 0, dwSize);
01284     if (lpGroups == NULL)
01285     {
01286         CloseHandle(hToken);
01287         return FALSE;
01288     }
01289 
01290     if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize))
01291     {
01292         HeapFree(GetProcessHeap(), 0, lpGroups);
01293         CloseHandle(hToken);
01294         return FALSE;
01295     }
01296 
01297     CloseHandle(hToken);
01298 
01299     if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
01300                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
01301                                   &lpSid))
01302     {
01303         HeapFree(GetProcessHeap(), 0, lpGroups);
01304         return FALSE;
01305     }
01306 
01307     for (i = 0; i < lpGroups->GroupCount; i++)
01308     {
01309         if (EqualSid(lpSid, lpGroups->Groups[i].Sid))
01310         {
01311             bResult = TRUE;
01312             break;
01313         }
01314     }
01315 
01316     FreeSid(lpSid);
01317     HeapFree(GetProcessHeap(), 0, lpGroups);
01318     return bResult;
01319 }
01320 
01321 /*************************************************************************
01322  * SHAllocShared                [SHELL32.520]
01323  *
01324  * See shlwapi.SHAllocShared
01325  */
01326 HANDLE WINAPI SHAllocShared(LPVOID lpvData, DWORD dwSize, DWORD dwProcId)
01327 {
01328     typedef HANDLE (WINAPI *SHAllocSharedProc)(LPCVOID, DWORD, DWORD);
01329     static SHAllocSharedProc        pSHAllocShared;
01330 
01331     GET_FUNC(pSHAllocShared, SHAllocSharedProc, shlwapi, (char*)7, NULL);
01332     return pSHAllocShared(lpvData, dwSize, dwProcId);
01333 }
01334 
01335 /*************************************************************************
01336  * SHLockShared                    [SHELL32.521]
01337  *
01338  * See shlwapi.SHLockShared
01339  */
01340 LPVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
01341 {
01342     typedef HANDLE (WINAPI *SHLockSharedProc)(HANDLE, DWORD);
01343     static SHLockSharedProc            pSHLockShared;
01344 
01345     GET_FUNC(pSHLockShared, SHLockSharedProc, shlwapi, (char*)8, NULL);
01346     return pSHLockShared(hShared, dwProcId);
01347 }
01348 
01349 /*************************************************************************
01350  * SHUnlockShared                [SHELL32.522]
01351  *
01352  * See shlwapi.SHUnlockShared
01353  */
01354 BOOL WINAPI SHUnlockShared(LPVOID lpView)
01355 {
01356     typedef HANDLE (WINAPI *SHUnlockSharedProc)(LPCVOID);
01357     static SHUnlockSharedProc        pSHUnlockShared;
01358 
01359     GET_FUNC(pSHUnlockShared, SHUnlockSharedProc, shlwapi, (char*)9, FALSE);
01360     return pSHUnlockShared(lpView) != NULL;
01361 }
01362 
01363 /*************************************************************************
01364  * SHFreeShared                    [SHELL32.523]
01365  *
01366  * See shlwapi.SHFreeShared
01367  */
01368 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
01369 {
01370     typedef HANDLE (WINAPI *SHFreeSharedProc)(HANDLE, DWORD);
01371     static SHFreeSharedProc            pSHFreeShared;
01372 
01373     GET_FUNC(pSHFreeShared, SHFreeSharedProc, shlwapi, (char*)10, FALSE);
01374     return pSHFreeShared(hShared, dwProcId) != NULL;
01375 }
01376 
01377 /*************************************************************************
01378  * SetAppStartingCursor                [SHELL32.99]
01379  */
01380 EXTERN_C HRESULT WINAPI SetAppStartingCursor(HWND u, DWORD v)
01381 {    FIXME("hwnd=%p 0x%04x stub\n",u,v );
01382     return 0;
01383 }
01384 
01385 /*************************************************************************
01386  * SHLoadOLE                    [SHELL32.151]
01387  *
01388  * To reduce the memory usage of Windows 95, its shell32 contained an
01389  * internal implementation of a part of COM (see e.g. SHGetMalloc, SHCoCreateInstance,
01390  * SHRegisterDragDrop etc.) that allowed to use in-process STA objects without
01391  * the need to load OLE32.DLL. If OLE32.DLL was already loaded, the SH* function
01392  * would just call the Co* functions.
01393  *
01394  * The SHLoadOLE was called when OLE32.DLL was being loaded to transfer all the
01395  * information from the shell32 "mini-COM" to ole32.dll.
01396  *
01397  * See http://blogs.msdn.com/oldnewthing/archive/2004/07/05/173226.aspx for a
01398  * detailed description.
01399  *
01400  * Under wine ole32.dll is always loaded as it is imported by shlwapi.dll which is
01401  * imported by shell32 and no "mini-COM" is used (except for the "LoadWithoutCOM"
01402  * hack in SHCoCreateInstance)
01403  */
01404 HRESULT WINAPI SHLoadOLE(LPARAM lParam)
01405 {    FIXME("0x%08lx stub\n",lParam);
01406     return S_OK;
01407 }
01408 /*************************************************************************
01409  * DriveType                    [SHELL32.64]
01410  *
01411  */
01412 EXTERN_C int WINAPI DriveType(int DriveType)
01413 {
01414     WCHAR root[] = L"A:\\";
01415     root[0] = L'A' + DriveType;
01416     return GetDriveTypeW(root);
01417 }
01418 
01419 /*************************************************************************
01420  * InvalidateDriveType            [SHELL32.65]
01421  * Unimplemented in XP SP3
01422  */
01423 EXTERN_C int WINAPI InvalidateDriveType(int u)
01424 {
01425     TRACE("0x%08x stub\n",u);
01426     return 0;
01427 }
01428 
01429 /*************************************************************************
01430  * SHAbortInvokeCommand                [SHELL32.198]
01431  *
01432  */
01433 EXTERN_C HRESULT WINAPI SHAbortInvokeCommand(void)
01434 {    FIXME("stub\n");
01435     return 1;
01436 }
01437 
01438 /*************************************************************************
01439  * SHOutOfMemoryMessageBox            [SHELL32.126]
01440  *
01441  */
01442 int WINAPI SHOutOfMemoryMessageBox(
01443     HWND hwndOwner,
01444     LPCSTR lpCaption,
01445     UINT uType)
01446 {
01447     FIXME("%p %s 0x%08x stub\n",hwndOwner, lpCaption, uType);
01448     return 0;
01449 }
01450 
01451 /*************************************************************************
01452  * SHFlushClipboard                [SHELL32.121]
01453  *
01454  */
01455 EXTERN_C HRESULT WINAPI SHFlushClipboard(void)
01456 {
01457     return OleFlushClipboard();
01458 }
01459 
01460 /*************************************************************************
01461  * SHWaitForFileToOpen                [SHELL32.97]
01462  *
01463  */
01464 BOOL WINAPI SHWaitForFileToOpen(
01465     LPCITEMIDLIST pidl,
01466     DWORD dwFlags,
01467     DWORD dwTimeout)
01468 {
01469     FIXME("%p 0x%08x 0x%08x stub\n", pidl, dwFlags, dwTimeout);
01470     return 0;
01471 }
01472 
01473 /************************************************************************
01474  *    RLBuildListOfPaths            [SHELL32.146]
01475  *
01476  * NOTES
01477  *   builds a DPA
01478  */
01479 EXTERN_C DWORD WINAPI RLBuildListOfPaths (void)
01480 {    FIXME("stub\n");
01481     return 0;
01482 }
01483 
01484 /************************************************************************
01485  *    SHValidateUNC                [SHELL32.173]
01486  *
01487  */
01488 EXTERN_C BOOL WINAPI SHValidateUNC (HWND hwndOwner, LPWSTR pszFile, UINT fConnect)
01489 {
01490     FIXME("0x%08x 0x%08x 0x%08x stub\n",hwndOwner,pszFile,fConnect);
01491     return 0;
01492 }
01493 
01494 /************************************************************************
01495  *    DoEnvironmentSubstA            [SHELL32.@]
01496  *
01497  * Replace %KEYWORD% in the str with the value of variable KEYWORD
01498  * from environment. If it is not found the %KEYWORD% is left
01499  * intact. If the buffer is too small, str is not modified.
01500  *
01501  * PARAMS
01502  *  pszString  [I] '\0' terminated string with %keyword%.
01503  *             [O] '\0' terminated string with %keyword% substituted.
01504  *  cchString  [I] size of str.
01505  *
01506  * RETURNS
01507  *     cchString length in the HIWORD;
01508  *     TRUE in LOWORD if subst was successful and FALSE in other case
01509  */
01510 EXTERN_C DWORD WINAPI DoEnvironmentSubstA(LPSTR pszString, UINT cchString)
01511 {
01512     LPSTR dst;
01513     BOOL res = FALSE;
01514     FIXME("(%s, %d) stub\n", debugstr_a(pszString), cchString);
01515     if (pszString == NULL) /* Really return 0? */
01516         return 0;
01517     if ((dst = (LPSTR)HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(CHAR))))
01518     {
01519         DWORD num = ExpandEnvironmentStringsA(pszString, dst, cchString);
01520         if (num && num < cchString) /* dest buffer is too small */
01521         {
01522             res = TRUE;
01523             memcpy(pszString, dst, num);
01524         }
01525         HeapFree(GetProcessHeap(), 0, dst);
01526     }
01527     return MAKELONG(res,cchString); /* Always cchString? */
01528 }
01529 
01530 /************************************************************************
01531  *    DoEnvironmentSubstW            [SHELL32.@]
01532  *
01533  * See DoEnvironmentSubstA.
01534  */
01535 EXTERN_C DWORD WINAPI DoEnvironmentSubstW(LPWSTR pszString, UINT cchString)
01536 {
01537     LPWSTR dst;
01538     BOOL res = FALSE;
01539     FIXME("(%s, %d): stub\n", debugstr_w(pszString), cchString);
01540     if ((dst = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(WCHAR))))
01541     {
01542         DWORD num = ExpandEnvironmentStringsW(pszString, dst, cchString);
01543         if (num)
01544         {
01545             res = TRUE;
01546             wcscpy(pszString, dst);
01547         }
01548         HeapFree(GetProcessHeap(), 0, dst);
01549     }
01550 
01551     return MAKELONG(res,cchString);
01552 }
01553 
01554 /************************************************************************
01555  *    DoEnvironmentSubst            [SHELL32.53]
01556  *
01557  * See DoEnvironmentSubstA.
01558  */
01559 DWORD WINAPI DoEnvironmentSubstAW(LPVOID x, UINT y)
01560 {
01561     if (SHELL_OsIsUnicode())
01562         return DoEnvironmentSubstW((LPWSTR)x, y);
01563     return DoEnvironmentSubstA((LPSTR)x, y);
01564 }
01565 
01566 /*************************************************************************
01567  *      GUIDFromStringA   [SHELL32.703]
01568  */
01569 BOOL WINAPI GUIDFromStringA(LPCSTR str, LPGUID guid)
01570 {
01571     TRACE("GUIDFromStringA() stub\n");
01572     return FALSE;
01573 }
01574 
01575 /*************************************************************************
01576  *      GUIDFromStringW   [SHELL32.704]
01577  */
01578 BOOL WINAPI GUIDFromStringW(LPCWSTR str, LPGUID guid)
01579 {
01580     UNICODE_STRING guid_str;
01581 
01582     RtlInitUnicodeString(&guid_str, str);
01583     return !RtlGUIDFromString(&guid_str, guid);
01584 }
01585 
01586 /*************************************************************************
01587  *      PathIsTemporaryW    [SHELL32.714]
01588  */
01589 EXTERN_C BOOL WINAPI PathIsTemporaryW(LPWSTR Str)
01590 {
01591      FIXME("(%s)stub\n", debugstr_w(Str));
01592     return FALSE;
01593 }
01594 
01595 /*************************************************************************
01596  *      PathIsTemporaryA    [SHELL32.713]
01597  */
01598 EXTERN_C BOOL WINAPI PathIsTemporaryA(LPSTR Str)
01599 {
01600      FIXME("(%s)stub\n", debugstr_a(Str));
01601     return FALSE;
01602 }
01603 
01604 typedef struct _PSXA
01605 {
01606     UINT uiCount;
01607     UINT uiAllocated;
01608     IShellPropSheetExt *pspsx[0];
01609 } PSXA, *PPSXA;
01610 
01611 typedef struct _PSXA_CALL
01612 {
01613     LPFNADDPROPSHEETPAGE lpfnAddReplaceWith;
01614     LPARAM lParam;
01615     BOOL bCalled;
01616     BOOL bMultiple;
01617     UINT uiCount;
01618 } PSXA_CALL, *PPSXA_CALL;
01619 
01620 static BOOL CALLBACK PsxaCall(HPROPSHEETPAGE hpage, LPARAM lParam)
01621 {
01622     PPSXA_CALL Call = (PPSXA_CALL)lParam;
01623 
01624     if (Call != NULL)
01625     {
01626         if ((Call->bMultiple || !Call->bCalled) &&
01627             Call->lpfnAddReplaceWith(hpage, Call->lParam))
01628         {
01629             Call->bCalled = TRUE;
01630             Call->uiCount++;
01631             return TRUE;
01632         }
01633     }
01634 
01635     return FALSE;
01636 }
01637 
01638 /*************************************************************************
01639  *      SHAddFromPropSheetExtArray    [SHELL32.167]
01640  */
01641 UINT WINAPI SHAddFromPropSheetExtArray(HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
01642 {
01643     PSXA_CALL Call;
01644     UINT i;
01645     PPSXA psxa = (PPSXA)hpsxa;
01646 
01647     TRACE("(%p,%p,%08lx)\n", hpsxa, lpfnAddPage, lParam);
01648 
01649     if (psxa)
01650     {
01651         ZeroMemory(&Call, sizeof(Call));
01652         Call.lpfnAddReplaceWith = lpfnAddPage;
01653         Call.lParam = lParam;
01654         Call.bMultiple = TRUE;
01655 
01656         /* Call the AddPage method of all registered IShellPropSheetExt interfaces */
01657         for (i = 0; i != psxa->uiCount; i++)
01658         {
01659             psxa->pspsx[i]->AddPages(PsxaCall, (LPARAM)&Call);
01660         }
01661 
01662         return Call.uiCount;
01663     }
01664 
01665     return 0;
01666 }
01667 
01668 /*************************************************************************
01669  *      SHCreatePropSheetExtArray    [SHELL32.168]
01670  */
01671 HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface)
01672 {
01673     return SHCreatePropSheetExtArrayEx(hKey, pszSubKey, max_iface, NULL);
01674 }
01675 
01676 
01677 /*************************************************************************
01678  *      SHCreatePropSheetExtArrayEx    [SHELL32.194]
01679  */
01680 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj)
01681 {
01682     static const WCHAR szPropSheetSubKey[] = {'s','h','e','l','l','e','x','\\','P','r','o','p','e','r','t','y','S','h','e','e','t','H','a','n','d','l','e','r','s',0};
01683     WCHAR szHandler[64];
01684     DWORD dwHandlerLen;
01685     WCHAR szClsidHandler[39];
01686     DWORD dwClsidSize;
01687     CLSID clsid;
01688     LONG lRet;
01689     DWORD dwIndex;
01690     HKEY hkBase, hkPropSheetHandlers;
01691     PPSXA psxa = NULL;
01692     HRESULT hr;
01693 
01694     TRACE("(%p,%s,%u)\n", hKey, debugstr_w(pszSubKey), max_iface);
01695 
01696     if (max_iface == 0)
01697         return NULL;
01698 
01699     /* Open the registry key */
01700     lRet = RegOpenKeyW(hKey, pszSubKey, &hkBase);
01701     if (lRet != ERROR_SUCCESS)
01702         return NULL;
01703 
01704     lRet = RegOpenKeyExW(hkBase, szPropSheetSubKey, 0, KEY_ENUMERATE_SUB_KEYS, &hkPropSheetHandlers);
01705     RegCloseKey(hkBase);
01706     if (lRet == ERROR_SUCCESS)
01707     {
01708         /* Create and initialize the Property Sheet Extensions Array */
01709         psxa = (PPSXA)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(PSXA) + max_iface * sizeof(IShellPropSheetExt *));
01710         if (psxa)
01711         {
01712             psxa->uiAllocated = max_iface;
01713 
01714             /* Enumerate all subkeys and attempt to load the shell extensions */
01715             dwIndex = 0;
01716             do
01717             {
01718                 dwHandlerLen = sizeof(szHandler) / sizeof(szHandler[0]);
01719                 lRet = RegEnumKeyExW(hkPropSheetHandlers, dwIndex++, szHandler, &dwHandlerLen, NULL, NULL, NULL, NULL);
01720                 if (lRet != ERROR_SUCCESS)
01721                 {
01722                     if (lRet == ERROR_MORE_DATA)
01723                         continue;
01724 
01725                     if (lRet == ERROR_NO_MORE_ITEMS)
01726                         lRet = ERROR_SUCCESS;
01727                     break;
01728                 }
01729                 szHandler[(sizeof(szHandler) / sizeof(szHandler[0])) - 1] = 0;
01730                 hr = CLSIDFromString(szHandler, &clsid);
01731                 if (FAILED(hr))
01732                 {
01733                     dwClsidSize = sizeof(szClsidHandler);
01734                     if (SHGetValueW(hkPropSheetHandlers, szHandler, NULL, NULL, szClsidHandler, &dwClsidSize) == ERROR_SUCCESS)
01735                     {
01736                         szClsidHandler[(sizeof(szClsidHandler) / sizeof(szClsidHandler[0])) - 1] = 0;
01737                         hr = CLSIDFromString(szClsidHandler, &clsid);
01738                     }
01739                 }
01740                 if (SUCCEEDED(hr))
01741                 {
01742                     CComPtr<IShellExtInit>            psxi;
01743                     CComPtr<IShellPropSheetExt>        pspsx;
01744 
01745                    /* Attempt to get an IShellPropSheetExt and an IShellExtInit instance.
01746                        Only if both interfaces are supported it's a real shell extension.
01747                        Then call IShellExtInit's Initialize method. */
01748                     if (SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER/* | CLSCTX_NO_CODE_DOWNLOAD */, IID_IShellPropSheetExt, (LPVOID *)&pspsx)))
01749                     {
01750                         if (SUCCEEDED(pspsx->QueryInterface(IID_IShellExtInit, (PVOID *)&psxi)))
01751                         {
01752                             if (SUCCEEDED(psxi->Initialize(NULL, pDataObj, hKey)))
01753                             {
01754                                 /* Add the IShellPropSheetExt instance to the array */
01755                                 psxa->pspsx[psxa->uiCount++] = pspsx.Detach();
01756                             }
01757                         }
01758                     }
01759                 }
01760             } while (psxa->uiCount != psxa->uiAllocated);
01761         }
01762         else
01763             lRet = ERROR_NOT_ENOUGH_MEMORY;
01764 
01765         RegCloseKey(hkPropSheetHandlers);
01766     }
01767 
01768     if (lRet != ERROR_SUCCESS && psxa)
01769     {
01770         SHDestroyPropSheetExtArray((HPSXA)psxa);
01771         psxa = NULL;
01772     }
01773 
01774     return (HPSXA)psxa;
01775 }
01776 
01777 /*************************************************************************
01778  *      SHReplaceFromPropSheetExtArray    [SHELL32.170]
01779  */
01780 UINT WINAPI SHReplaceFromPropSheetExtArray(HPSXA hpsxa, UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
01781 {
01782     PSXA_CALL Call;
01783     UINT i;
01784     PPSXA psxa = (PPSXA)hpsxa;
01785 
01786     TRACE("(%p,%u,%p,%08lx)\n", hpsxa, uPageID, lpfnReplaceWith, lParam);
01787 
01788     if (psxa)
01789     {
01790         ZeroMemory(&Call, sizeof(Call));
01791         Call.lpfnAddReplaceWith = lpfnReplaceWith;
01792         Call.lParam = lParam;
01793 
01794         /* Call the ReplacePage method of all registered IShellPropSheetExt interfaces.
01795            Each shell extension is only allowed to call the callback once during the callback. */
01796         for (i = 0; i != psxa->uiCount; i++)
01797         {
01798             Call.bCalled = FALSE;
01799             psxa->pspsx[i]->ReplacePage(uPageID, PsxaCall, (LPARAM)&Call);
01800         }
01801 
01802         return Call.uiCount;
01803     }
01804 
01805     return 0;
01806 }
01807 
01808 /*************************************************************************
01809  *      SHDestroyPropSheetExtArray    [SHELL32.169]
01810  */
01811 void WINAPI SHDestroyPropSheetExtArray(HPSXA hpsxa)
01812 {
01813     UINT i;
01814     PPSXA psxa = (PPSXA)hpsxa;
01815 
01816     TRACE("(%p)\n", hpsxa);
01817 
01818     if (psxa)
01819     {
01820         for (i = 0; i != psxa->uiCount; i++)
01821         {
01822             psxa->pspsx[i]->Release();
01823         }
01824 
01825         LocalFree((HLOCAL)psxa);
01826     }
01827 }
01828 
01829 /*************************************************************************
01830  *      CIDLData_CreateFromIDArray    [SHELL32.83]
01831  *
01832  *  Create IDataObject from PIDLs??
01833  */
01834 HRESULT WINAPI CIDLData_CreateFromIDArray(
01835     LPCITEMIDLIST pidlFolder,
01836     UINT cpidlFiles,
01837     LPCITEMIDLIST *lppidlFiles,
01838     IDataObject **ppdataObject)
01839 {
01840     UINT i;
01841     HWND hwnd = 0;   /*FIXME: who should be hwnd of owner? set to desktop */
01842     HRESULT hResult;
01843 
01844     TRACE("(%p, %d, %p, %p)\n", pidlFolder, cpidlFiles, lppidlFiles, ppdataObject);
01845     if (TRACE_ON(pidl))
01846     {
01847         pdump (pidlFolder);
01848         for (i = 0; i < cpidlFiles; i++)
01849             pdump(lppidlFiles[i]);
01850     }
01851     hResult = IDataObject_Constructor(hwnd, pidlFolder, lppidlFiles, cpidlFiles, ppdataObject);
01852     return hResult;
01853 }
01854 
01855 /*************************************************************************
01856  * SHCreateStdEnumFmtEtc            [SHELL32.74]
01857  *
01858  * NOTES
01859  *
01860  */
01861 HRESULT WINAPI SHCreateStdEnumFmtEtc(
01862     UINT cFormats,
01863     const FORMATETC *lpFormats,
01864     LPENUMFORMATETC *ppenumFormatetc)
01865 {
01866     IEnumFORMATETC *pef;
01867     HRESULT hRes;
01868     TRACE("cf=%d fe=%p pef=%p\n", cFormats, lpFormats, ppenumFormatetc);
01869 
01870     hRes = IEnumFORMATETC_Constructor(cFormats, lpFormats, &pef);
01871     if (FAILED(hRes))
01872         return hRes;
01873 
01874     pef->AddRef();
01875     hRes = pef->QueryInterface(IID_IEnumFORMATETC, (LPVOID*)ppenumFormatetc);
01876     pef->Release();
01877 
01878     return hRes;
01879 }
01880 
01881 
01882 /*************************************************************************
01883  *        SHCreateShellFolderView (SHELL32.256)
01884  */
01885 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv, IShellView **ppsv)
01886 {
01887     HRESULT ret = S_OK;
01888 
01889     FIXME("SHCreateShellFolderView() stub\n");
01890 
01891     if (!pcsfv || sizeof(*pcsfv) != pcsfv->cbSize)
01892         ret = E_INVALIDARG;
01893     else
01894     {
01895         LPVOID lpdata = 0;/*LocalAlloc(LMEM_ZEROINIT, 0x4E4);*/
01896 
01897     if (!lpdata)
01898             ret = E_OUTOFMEMORY;
01899     else
01900     {
01901             /* Initialize and return unknown lpdata structure */
01902     }
01903     }
01904 
01905     return ret;
01906 }
01907 
01908 /*************************************************************************
01909  *        SHFindFiles (SHELL32.90)
01910  */
01911 BOOL WINAPI SHFindFiles( LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlSaveFile )
01912 {
01913     FIXME("%p %p\n", pidlFolder, pidlSaveFile );
01914     return FALSE;
01915 }
01916 
01917 /*************************************************************************
01918  *        SHUpdateImageW (SHELL32.192)
01919  *
01920  * Notifies the shell that an icon in the system image list has been changed.
01921  *
01922  * PARAMS
01923  *  pszHashItem [I] Path to file that contains the icon.
01924  *  iIndex      [I] Zero-based index of the icon in the file.
01925  *  uFlags      [I] Flags determining the icon attributes. See notes.
01926  *  iImageIndex [I] Index of the icon in the system image list.
01927  *
01928  * RETURNS
01929  *  Nothing
01930  *
01931  * NOTES
01932  *  uFlags can be one or more of the following flags:
01933  *  GIL_NOTFILENAME - pszHashItem is not a file name.
01934  *  GIL_SIMULATEDOC - Create a document icon using the specified icon.
01935  */
01936 void WINAPI SHUpdateImageW(LPCWSTR pszHashItem, int iIndex, UINT uFlags, int iImageIndex)
01937 {
01938     FIXME("%s, %d, 0x%x, %d - stub\n", debugstr_w(pszHashItem), iIndex, uFlags, iImageIndex);
01939 }
01940 
01941 /*************************************************************************
01942  *        SHUpdateImageA (SHELL32.191)
01943  *
01944  * See SHUpdateImageW.
01945  */
01946 VOID WINAPI SHUpdateImageA(LPCSTR pszHashItem, INT iIndex, UINT uFlags, INT iImageIndex)
01947 {
01948     FIXME("%s, %d, 0x%x, %d - stub\n", debugstr_a(pszHashItem), iIndex, uFlags, iImageIndex);
01949 }
01950 
01951 INT WINAPI SHHandleUpdateImage(LPCITEMIDLIST pidlExtra)
01952 {
01953     FIXME("%p - stub\n", pidlExtra);
01954 
01955     return -1;
01956 }
01957 
01958 BOOL WINAPI SHObjectProperties(HWND hwnd, DWORD dwType, LPCWSTR szObject, LPCWSTR szPage)
01959 {
01960     FIXME("%p, 0x%08x, %s, %s - stub\n", hwnd, dwType, debugstr_w(szObject), debugstr_w(szPage));
01961 
01962     return TRUE;
01963 }
01964 
01965 BOOL WINAPI SHGetNewLinkInfoA(LPCSTR pszLinkTo, LPCSTR pszDir, LPSTR pszName, BOOL *pfMustCopy,
01966                               UINT uFlags)
01967 {
01968     WCHAR wszLinkTo[MAX_PATH];
01969     WCHAR wszDir[MAX_PATH];
01970     WCHAR wszName[MAX_PATH];
01971     BOOL res;
01972 
01973     MultiByteToWideChar(CP_ACP, 0, pszLinkTo, -1, wszLinkTo, MAX_PATH);
01974     MultiByteToWideChar(CP_ACP, 0, pszDir, -1, wszDir, MAX_PATH);
01975 
01976     res = SHGetNewLinkInfoW(wszLinkTo, wszDir, wszName, pfMustCopy, uFlags);
01977 
01978     if (res)
01979         WideCharToMultiByte(CP_ACP, 0, wszName, -1, pszName, MAX_PATH, NULL, NULL);
01980 
01981     return res;
01982 }
01983 
01984 BOOL WINAPI SHGetNewLinkInfoW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName, BOOL *pfMustCopy,
01985                               UINT uFlags)
01986 {
01987     const WCHAR *basename;
01988     WCHAR *dst_basename;
01989     int i=2;
01990     static const WCHAR lnkformat[] = {'%','s','.','l','n','k',0};
01991     static const WCHAR lnkformatnum[] = {'%','s',' ','(','%','d',')','.','l','n','k',0};
01992 
01993     TRACE("(%s, %s, %p, %p, 0x%08x)\n", debugstr_w(pszLinkTo), debugstr_w(pszDir),
01994           pszName, pfMustCopy, uFlags);
01995 
01996     *pfMustCopy = FALSE;
01997 
01998     if (uFlags & SHGNLI_PIDL)
01999     {
02000         FIXME("SHGNLI_PIDL flag unsupported\n");
02001         return FALSE;
02002     }
02003 
02004     if (uFlags)
02005         FIXME("ignoring flags: 0x%08x\n", uFlags);
02006 
02007     /* FIXME: should test if the file is a shortcut or DOS program */
02008     if (GetFileAttributesW(pszLinkTo) == INVALID_FILE_ATTRIBUTES)
02009         return FALSE;
02010 
02011     basename = strrchrW(pszLinkTo, '\\');
02012     if (basename)
02013         basename = basename+1;
02014     else
02015         basename = pszLinkTo;
02016 
02017     lstrcpynW(pszName, pszDir, MAX_PATH);
02018     if (!PathAddBackslashW(pszName))
02019         return FALSE;
02020 
02021     dst_basename = pszName + strlenW(pszName);
02022 
02023     snprintfW(dst_basename, pszName + MAX_PATH - dst_basename, lnkformat, basename);
02024 
02025     while (GetFileAttributesW(pszName) != INVALID_FILE_ATTRIBUTES)
02026     {
02027         snprintfW(dst_basename, pszName + MAX_PATH - dst_basename, lnkformatnum, basename, i);
02028         i++;
02029     }
02030 
02031     return TRUE;
02032 }
02033 
02034 /*************************************************************************
02035  *              SHStartNetConnectionDialog (SHELL32.@)
02036  */
02037 HRESULT WINAPI SHStartNetConnectionDialog(HWND hwnd, LPCSTR pszRemoteName, DWORD dwType)
02038 {
02039     FIXME("%p, %s, 0x%08x - stub\n", hwnd, debugstr_a(pszRemoteName), dwType);
02040 
02041     return S_OK;
02042 }
02043 /*************************************************************************
02044  *              SHEmptyRecycleBinA (SHELL32.@)
02045  */
02046 HRESULT WINAPI SHEmptyRecycleBinA(HWND hwnd, LPCSTR pszRootPath, DWORD dwFlags)
02047 {
02048     LPWSTR szRootPathW = NULL;
02049     int len;
02050     HRESULT hr;
02051 
02052     TRACE("%p, %s, 0x%08x\n", hwnd, debugstr_a(pszRootPath), dwFlags);
02053 
02054     if (pszRootPath)
02055     {
02056         len = MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, NULL, 0);
02057         if (len == 0)
02058             return HRESULT_FROM_WIN32(GetLastError());
02059         szRootPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
02060         if (!szRootPathW)
02061             return E_OUTOFMEMORY;
02062         if (MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, szRootPathW, len) == 0)
02063         {
02064             HeapFree(GetProcessHeap(), 0, szRootPathW);
02065             return HRESULT_FROM_WIN32(GetLastError());
02066         }
02067     }
02068 
02069     hr = SHEmptyRecycleBinW(hwnd, szRootPathW, dwFlags);
02070     HeapFree(GetProcessHeap(), 0, szRootPathW);
02071 
02072     return hr;
02073 }
02074 
02075 HRESULT WINAPI SHEmptyRecycleBinW(HWND hwnd, LPCWSTR pszRootPath, DWORD dwFlags)
02076 {
02077     WCHAR szPath[MAX_PATH] = {0};
02078     DWORD dwSize, dwType;
02079     LONG ret;
02080 
02081     TRACE("%p, %s, 0x%08x\n", hwnd, debugstr_w(pszRootPath), dwFlags);
02082 
02083     if (!(dwFlags & SHERB_NOCONFIRMATION))
02084     {
02085         /* FIXME
02086          * enumerate available files 
02087          * show confirmation dialog 
02088          */
02089         FIXME("show confirmation dialog\n");
02090     }
02091 
02092     if (dwFlags & SHERB_NOPROGRESSUI)
02093     {
02094         ret = EmptyRecycleBinW(pszRootPath);
02095     }
02096     else
02097     {
02098        /* FIXME
02099         * show a progress dialog
02100         */
02101         ret = EmptyRecycleBinW(pszRootPath);
02102     }
02103 
02104     if (!ret)
02105         return HRESULT_FROM_WIN32(GetLastError());
02106 
02107     if (!(dwFlags & SHERB_NOSOUND))
02108     {
02109         dwSize = sizeof(szPath);
02110         ret = RegGetValueW(HKEY_CURRENT_USER, 
02111                            L"AppEvents\\Schemes\\Apps\\Explorer\\EmptyRecycleBin\\.Current",
02112                            NULL,
02113                            RRF_RT_REG_EXPAND_SZ,
02114                            &dwType,
02115                            (PVOID)szPath,
02116                            &dwSize);
02117         if (ret != ERROR_SUCCESS)
02118             return S_OK;
02119 
02120         if (dwType != REG_EXPAND_SZ) /* type dismatch */
02121             return S_OK;
02122 
02123         szPath[(sizeof(szPath)/sizeof(WCHAR))-1] = L'\0';
02124         PlaySoundW(szPath, NULL, SND_FILENAME);
02125     }
02126     return S_OK;
02127 }
02128 
02129 HRESULT WINAPI SHQueryRecycleBinA(LPCSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo)
02130 {
02131     LPWSTR szRootPathW = NULL;
02132     int len;
02133     HRESULT hr;
02134 
02135     TRACE("%s, %p\n", debugstr_a(pszRootPath), pSHQueryRBInfo);
02136 
02137     if (pszRootPath)
02138     {
02139         len = MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, NULL, 0);
02140         if (len == 0)
02141             return HRESULT_FROM_WIN32(GetLastError());
02142         szRootPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
02143         if (!szRootPathW)
02144             return E_OUTOFMEMORY;
02145         if (MultiByteToWideChar(CP_ACP, 0, pszRootPath, -1, szRootPathW, len) == 0)
02146         {
02147             HeapFree(GetProcessHeap(), 0, szRootPathW);
02148             return HRESULT_FROM_WIN32(GetLastError());
02149         }
02150     }
02151 
02152     hr = SHQueryRecycleBinW(szRootPathW, pSHQueryRBInfo);
02153     HeapFree(GetProcessHeap(), 0, szRootPathW);
02154 
02155     return hr;
02156 }
02157 
02158 HRESULT WINAPI SHQueryRecycleBinW(LPCWSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo)
02159 {
02160     FIXME("%s, %p - stub\n", debugstr_w(pszRootPath), pSHQueryRBInfo);
02161 
02162     if (!(pszRootPath) || (pszRootPath[0] == 0) ||
02163         !(pSHQueryRBInfo) || (pSHQueryRBInfo->cbSize < sizeof(SHQUERYRBINFO)))
02164     {
02165         return E_INVALIDARG;
02166     }
02167 
02168     pSHQueryRBInfo->i64Size = 0;
02169     pSHQueryRBInfo->i64NumItems = 0;
02170 
02171     return S_OK;
02172 }
02173 
02174 /*************************************************************************
02175  *              SHSetLocalizedName (SHELL32.@)
02176  */
02177 EXTERN_C HRESULT WINAPI SHSetLocalizedName(LPCWSTR pszPath, LPCWSTR pszResModule, int idsRes)
02178 {
02179     FIXME("%p, %s, %d - stub\n", pszPath, debugstr_w(pszResModule), idsRes);
02180 
02181     return S_OK;
02182 }
02183 
02184 /*************************************************************************
02185  *              LinkWindow_RegisterClass (SHELL32.258)
02186  */
02187 EXTERN_C BOOL WINAPI LinkWindow_RegisterClass(void)
02188 {
02189     FIXME("()\n");
02190     return TRUE;
02191 }
02192 
02193 /*************************************************************************
02194  *              LinkWindow_UnregisterClass (SHELL32.259)
02195  */
02196 EXTERN_C BOOL WINAPI LinkWindow_UnregisterClass(void)
02197 {
02198     FIXME("()\n");
02199     return TRUE;
02200 
02201 }
02202 
02203 /*************************************************************************
02204  *              SHFlushSFCache (SHELL32.526)
02205  *
02206  * Notifies the shell that a user-specified special folder location has changed.
02207  *
02208  * NOTES
02209  *   In Wine, the shell folder registry values are not cached, so this function
02210  *   has no effect.
02211  */
02212 EXTERN_C void WINAPI SHFlushSFCache(void)
02213 {
02214 }
02215 
02216 /*************************************************************************
02217  *              SHGetImageList (SHELL32.727)
02218  *
02219  * Returns a copy of a shell image list.
02220  *
02221  * NOTES
02222  *   Windows XP features 4 sizes of image list, and Vista 5. Wine currently
02223  *   only supports the traditional small and large image lists, so requests
02224  *   for the others will currently fail.
02225  */
02226 EXTERN_C HRESULT WINAPI SHGetImageList(int iImageList, REFIID riid, void **ppv)
02227 {
02228     HIMAGELIST hLarge, hSmall;
02229     HIMAGELIST hNew;
02230     HRESULT ret = E_FAIL;
02231 
02232     /* Wine currently only maintains large and small image lists */
02233     if ((iImageList != SHIL_LARGE) && (iImageList != SHIL_SMALL) && (iImageList != SHIL_SYSSMALL))
02234     {
02235         FIXME("Unsupported image list %i requested\n", iImageList);
02236         return E_FAIL;
02237     }
02238 
02239     Shell_GetImageLists(&hLarge, &hSmall);
02240     hNew = ImageList_Duplicate(iImageList == SHIL_LARGE ? hLarge : hSmall);
02241 
02242     /* Get the interface for the new image list */
02243     if (hNew)
02244     {
02245         ret = HIMAGELIST_QueryInterface(hNew, riid, ppv);
02246         ImageList_Destroy(hNew);
02247     }
02248 
02249     return ret;
02250 }
02251 
02252 /*************************************************************************
02253  *    SHParseDisplayName        [shell version 6.0]
02254  */
02255 EXTERN_C HRESULT WINAPI SHParseDisplayName(LPCWSTR pszName, IBindCtx *pbc,
02256     LPITEMIDLIST *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut)
02257 {
02258     CComPtr<IShellFolder>        psfDesktop;
02259     HRESULT         hr=E_FAIL;
02260     ULONG           dwAttr=sfgaoIn;
02261 
02262     if(!ppidl)
02263         return E_INVALIDARG;
02264 
02265     if (!pszName || !psfgaoOut)
02266     {
02267         *ppidl = NULL;
02268         return E_INVALIDARG;
02269     }
02270 
02271     hr = SHGetDesktopFolder(&psfDesktop);
02272     if (FAILED(hr))
02273     {
02274         *ppidl = NULL;
02275         return hr;
02276     }
02277 
02278     hr = psfDesktop->ParseDisplayName((HWND)NULL, pbc, (LPOLESTR)pszName, (ULONG *)NULL, ppidl, &dwAttr);
02279 
02280     psfDesktop->Release();
02281 
02282     if (SUCCEEDED(hr))
02283         *psfgaoOut = dwAttr;
02284     else
02285         *ppidl = NULL;
02286 
02287     return hr;
02288 }

Generated on Sat May 26 2012 04:25:03 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.