Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendesktop.cpp
Go to the documentation of this file.
00001 /* 00002 * Virtual Desktop Folder 00003 * 00004 * Copyright 1997 Marcus Meissner 00005 * Copyright 1998, 1999, 2002 Juergen Schmied 00006 * Copyright 2009 Andrew Hill 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 00027 /* 00028 CDesktopFolder should create two file system folders internally, one representing the 00029 user's desktop folder, and the other representing the common desktop folder. It should 00030 also create a CRegFolder to represent the virtual items that exist only in the registry. 00031 The CRegFolder is aggregated by the CDesktopFolder, and queries for the CLSID_IShellFolder, 00032 CLSID_IShellFolder2, or CLSID_IShellIconOverlay interfaces prefer the CRegFolder 00033 implementation. 00034 The CDesktopFolderEnum class should create two enumerators, one for each of the file 00035 system folders, and enumerate the contents of each folder. Since the CRegFolder 00036 implementation of IShellFolder::EnumObjects enumerates the virtual items, the 00037 CDesktopFolderEnum is only responsible for returning the physical items. 00038 CDesktopFolderEnum is incorrect where it filters My Computer from the enumeration 00039 if the new start menu is used. The CDesktopViewCallback is responsible for filtering 00040 it from the view by handling the IncludeObject query to return S_FALSE. The enumerator 00041 always shows My Computer. 00042 */ 00043 00044 /* Undocumented functions from shdocvw */ 00045 extern "C" HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl); 00046 00047 /*********************************************************************** 00048 * Desktopfolder implementation 00049 */ 00050 00051 class CDesktopFolder; 00052 00053 class CDesktopFolderEnum : 00054 public IEnumIDListImpl 00055 { 00056 private: 00057 // CComPtr fDesktopEnumerator; 00058 // CComPtr fCommonDesktopEnumerator; 00059 public: 00060 CDesktopFolderEnum(); 00061 ~CDesktopFolderEnum(); 00062 HRESULT WINAPI Initialize(CDesktopFolder *desktopFolder, HWND hwndOwner, DWORD dwFlags); 00063 00064 BEGIN_COM_MAP(CDesktopFolderEnum) 00065 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList) 00066 END_COM_MAP() 00067 }; 00068 00069 int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll); 00070 00071 static const shvheader DesktopSFHeader[] = { 00072 {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, 00073 {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, 00074 {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, 00075 {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}, 00076 {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5} 00077 }; 00078 00079 #define DESKTOPSHELLVIEWCOLUMNS 5 00080 00081 CDesktopFolderEnum::CDesktopFolderEnum() 00082 { 00083 } 00084 00085 CDesktopFolderEnum::~CDesktopFolderEnum() 00086 { 00087 } 00088 00089 static const WCHAR ClassicStartMenuW[] = L"SOFTWARE\\Microsoft\\Windows\\" 00090 L"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu"; 00091 00092 static INT 00093 IsNamespaceExtensionHidden(const WCHAR *iid) 00094 { 00095 DWORD Result, dwResult; 00096 dwResult = sizeof(DWORD); 00097 00098 if (RegGetValueW(HKEY_CURRENT_USER, /* FIXME use NewStartPanel when activated */ 00099 ClassicStartMenuW, 00100 iid, 00101 RRF_RT_DWORD, 00102 NULL, 00103 &Result, 00104 &dwResult) != ERROR_SUCCESS) 00105 { 00106 return -1; 00107 } 00108 00109 return Result; 00110 } 00111 00112 static VOID 00113 SetNamespaceExtensionVisibleStatus(const WCHAR * iid, DWORD dwStatus) 00114 { 00115 HKEY hKey; 00116 00117 if (RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) 00118 { 00119 RegSetValueExW(hKey, iid, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(DWORD)); 00120 RegCloseKey(hKey); 00121 } 00122 } 00123 00124 /************************************************************************** 00125 * CreateDesktopEnumList() 00126 */ 00127 00128 HRESULT WINAPI CDesktopFolderEnum::Initialize(CDesktopFolder *desktopFolder, HWND hwndOwner, DWORD dwFlags) 00129 { 00130 BOOL ret = TRUE; 00131 WCHAR szPath[MAX_PATH]; 00132 00133 static const WCHAR MyDocumentsClassString[] = L"{450D8FBA-AD25-11D0-98A8-0800361B1103}"; 00134 static const WCHAR Desktop_NameSpaceW[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace"; 00135 00136 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags); 00137 00138 /* enumerate the root folders */ 00139 if (dwFlags & SHCONTF_FOLDERS) 00140 { 00141 HKEY hkey; 00142 UINT i; 00143 DWORD dwResult; 00144 00145 /* create the pidl for This item */ 00146 if (IsNamespaceExtensionHidden(MyDocumentsClassString) < 1) 00147 { 00148 ret = AddToEnumList(_ILCreateMyDocuments()); 00149 } 00150 ret = AddToEnumList(_ILCreateMyComputer()); 00151 00152 for (i = 0; i < 2; i++) 00153 { 00154 if (i == 0) 00155 dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Desktop_NameSpaceW, 0, KEY_READ, &hkey); 00156 else 00157 dwResult = RegOpenKeyExW(HKEY_CURRENT_USER, Desktop_NameSpaceW, 0, KEY_READ, &hkey); 00158 00159 if (dwResult == ERROR_SUCCESS) 00160 { 00161 WCHAR iid[50]; 00162 LPITEMIDLIST pidl; 00163 int i = 0; 00164 00165 while (ret) 00166 { 00167 DWORD size; 00168 LONG r; 00169 00170 size = sizeof (iid) / sizeof (iid[0]); 00171 r = RegEnumKeyExW(hkey, i, iid, &size, 0, NULL, NULL, NULL); 00172 if (ERROR_SUCCESS == r) 00173 { 00174 if (IsNamespaceExtensionHidden(iid) < 1) 00175 { 00176 pidl = _ILCreateGuidFromStrW(iid); 00177 if (pidl != NULL) 00178 { 00179 if (!HasItemWithCLSID(pidl)) 00180 { 00181 ret = AddToEnumList(pidl); 00182 } 00183 else 00184 { 00185 SHFree(pidl); 00186 } 00187 } 00188 } 00189 } 00190 else if (ERROR_NO_MORE_ITEMS == r) 00191 break; 00192 else 00193 ret = FALSE; 00194 i++; 00195 } 00196 RegCloseKey(hkey); 00197 } 00198 } 00199 for (i = 0; i < 2; i++) 00200 { 00201 if (i == 0) 00202 dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, ClassicStartMenuW, 0, KEY_READ, &hkey); 00203 else 00204 dwResult = RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_READ, &hkey); 00205 00206 if (dwResult == ERROR_SUCCESS) 00207 { 00208 DWORD j = 0, dwVal, Val, dwType, dwIID; 00209 LONG r; 00210 WCHAR iid[50]; 00211 00212 while(ret) 00213 { 00214 dwVal = sizeof(Val); 00215 dwIID = sizeof(iid) / sizeof(WCHAR); 00216 00217 r = RegEnumValueW(hkey, j++, iid, &dwIID, NULL, &dwType, (LPBYTE)&Val, &dwVal); 00218 if (r == ERROR_SUCCESS) 00219 { 00220 if (Val == 0 && dwType == REG_DWORD) 00221 { 00222 LPITEMIDLIST pidl = _ILCreateGuidFromStrW(iid); 00223 if (pidl != NULL) 00224 { 00225 if (!HasItemWithCLSID(pidl)) 00226 { 00227 AddToEnumList(pidl); 00228 } 00229 else 00230 { 00231 SHFree(pidl); 00232 } 00233 } 00234 } 00235 } 00236 else if (ERROR_NO_MORE_ITEMS == r) 00237 break; 00238 else 00239 ret = FALSE; 00240 } 00241 RegCloseKey(hkey); 00242 } 00243 00244 } 00245 } 00246 00247 /* enumerate the elements in %windir%\desktop */ 00248 ret = ret && SHGetSpecialFolderPathW(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE); 00249 ret = ret && CreateFolderEnumList(szPath, dwFlags); 00250 00251 ret = ret && SHGetSpecialFolderPathW(0, szPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE); 00252 ret = ret && CreateFolderEnumList(szPath, dwFlags); 00253 00254 return ret ? S_OK : E_FAIL; 00255 } 00256 00257 CDesktopFolder::CDesktopFolder() 00258 { 00259 pidlRoot = NULL; 00260 sPathTarget = NULL; 00261 } 00262 00263 CDesktopFolder::~CDesktopFolder() 00264 { 00265 } 00266 00267 HRESULT WINAPI CDesktopFolder::FinalConstruct() 00268 { 00269 WCHAR szMyPath[MAX_PATH]; 00270 00271 if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE )) 00272 return E_UNEXPECTED; 00273 00274 pidlRoot = _ILCreateDesktop(); /* my qualified pidl */ 00275 sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR)); 00276 wcscpy(sPathTarget, szMyPath); 00277 return S_OK; 00278 } 00279 00280 /************************************************************************** 00281 * CDesktopFolder::ParseDisplayName 00282 * 00283 * NOTES 00284 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds 00285 * to MyComputer 00286 */ 00287 HRESULT WINAPI CDesktopFolder::ParseDisplayName( 00288 HWND hwndOwner, 00289 LPBC pbc, 00290 LPOLESTR lpszDisplayName, 00291 DWORD *pchEaten, 00292 LPITEMIDLIST *ppidl, 00293 DWORD *pdwAttributes) 00294 { 00295 WCHAR szElement[MAX_PATH]; 00296 LPCWSTR szNext = NULL; 00297 LPITEMIDLIST pidlTemp = NULL; 00298 PARSEDURLW urldata; 00299 HRESULT hr = S_OK; 00300 CLSID clsid; 00301 00302 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", 00303 this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName), 00304 pchEaten, ppidl, pdwAttributes); 00305 00306 if (!ppidl) 00307 return E_INVALIDARG; 00308 00309 if (!lpszDisplayName) 00310 { 00311 *ppidl = NULL; 00312 return E_INVALIDARG; 00313 } 00314 00315 *ppidl = NULL; 00316 00317 if (pchEaten) 00318 *pchEaten = 0; /* strange but like the original */ 00319 00320 urldata.cbSize = sizeof(urldata); 00321 00322 if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') 00323 { 00324 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); 00325 TRACE ("-- element: %s\n", debugstr_w (szElement)); 00326 CLSIDFromString (szElement + 2, &clsid); 00327 pidlTemp = _ILCreateGuid (PT_GUID, clsid); 00328 } 00329 else if (PathGetDriveNumberW (lpszDisplayName) >= 0) 00330 { 00331 /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */ 00332 pidlTemp = _ILCreateMyComputer (); 00333 szNext = lpszDisplayName; 00334 } 00335 else if (PathIsUNCW(lpszDisplayName)) 00336 { 00337 pidlTemp = _ILCreateNetwork(); 00338 szNext = lpszDisplayName; 00339 } 00340 else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) ) 00341 { 00342 *ppidl = pidlTemp; 00343 return S_OK; 00344 } 00345 else if (SUCCEEDED(ParseURLW(lpszDisplayName, &urldata))) 00346 { 00347 if (urldata.nScheme == URL_SCHEME_SHELL) /* handle shell: urls */ 00348 { 00349 TRACE ("-- shell url: %s\n", debugstr_w(urldata.pszSuffix)); 00350 SHCLSIDFromStringW (urldata.pszSuffix + 2, &clsid); 00351 pidlTemp = _ILCreateGuid (PT_GUID, clsid); 00352 } 00353 else 00354 return IEParseDisplayNameWithBCW(CP_ACP, lpszDisplayName, pbc, ppidl); 00355 } 00356 else 00357 { 00358 /* it's a filesystem path on the desktop. Let a FSFolder parse it */ 00359 00360 if (*lpszDisplayName) 00361 { 00362 WCHAR szPath[MAX_PATH]; 00363 LPWSTR pathPtr; 00364 00365 /* build a complete path to create a simple pidl */ 00366 lstrcpynW(szPath, sPathTarget, MAX_PATH); 00367 pathPtr = PathAddBackslashW(szPath); 00368 if (pathPtr) 00369 { 00370 lstrcpynW(pathPtr, lpszDisplayName, MAX_PATH - (pathPtr - szPath)); 00371 hr = _ILCreateFromPathW(szPath, &pidlTemp); 00372 } 00373 else 00374 { 00375 /* should never reach here, but for completeness */ 00376 hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); 00377 } 00378 } 00379 else 00380 pidlTemp = _ILCreateMyComputer(); 00381 00382 szNext = NULL; 00383 } 00384 00385 if (SUCCEEDED(hr) && pidlTemp) 00386 { 00387 if (szNext && *szNext) 00388 { 00389 hr = SHELL32_ParseNextElement(this, hwndOwner, pbc, 00390 &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); 00391 } 00392 else 00393 { 00394 if (pdwAttributes && *pdwAttributes) 00395 hr = SHELL32_GetItemAttributes((IShellFolder *)this, 00396 pidlTemp, pdwAttributes); 00397 } 00398 } 00399 00400 if (SUCCEEDED(hr)) 00401 *ppidl = pidlTemp; 00402 else 00403 *ppidl = NULL; 00404 00405 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr); 00406 00407 return hr; 00408 } 00409 00410 /************************************************************************** 00411 * CDesktopFolder::EnumObjects 00412 */ 00413 HRESULT WINAPI CDesktopFolder::EnumObjects( 00414 HWND hwndOwner, 00415 DWORD dwFlags, 00416 LPENUMIDLIST *ppEnumIDList) 00417 { 00418 CComObject<CDesktopFolderEnum> *theEnumerator; 00419 CComPtr<IEnumIDList> result; 00420 HRESULT hResult; 00421 00422 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList); 00423 00424 if (ppEnumIDList == NULL) 00425 return E_POINTER; 00426 *ppEnumIDList = NULL; 00427 00428 ATLTRY (theEnumerator = new CComObject<CDesktopFolderEnum>); 00429 00430 if (theEnumerator == NULL) 00431 return E_OUTOFMEMORY; 00432 00433 hResult = theEnumerator->QueryInterface (IID_IEnumIDList, (void **)&result); 00434 if (FAILED (hResult)) 00435 { 00436 delete theEnumerator; 00437 return hResult; 00438 } 00439 00440 hResult = theEnumerator->Initialize (this, hwndOwner, dwFlags); 00441 if (FAILED (hResult)) 00442 return hResult; 00443 *ppEnumIDList = result.Detach (); 00444 00445 TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList); 00446 00447 return S_OK; 00448 } 00449 00450 /************************************************************************** 00451 * CDesktopFolder::BindToObject 00452 */ 00453 HRESULT WINAPI CDesktopFolder::BindToObject( 00454 LPCITEMIDLIST pidl, 00455 LPBC pbcReserved, 00456 REFIID riid, 00457 LPVOID *ppvOut) 00458 { 00459 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", 00460 this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut); 00461 00462 return SHELL32_BindToChild( pidlRoot, sPathTarget, pidl, riid, ppvOut ); 00463 } 00464 00465 /************************************************************************** 00466 * CDesktopFolder::BindToStorage 00467 */ 00468 HRESULT WINAPI CDesktopFolder::BindToStorage( 00469 LPCITEMIDLIST pidl, 00470 LPBC pbcReserved, 00471 REFIID riid, 00472 LPVOID *ppvOut) 00473 { 00474 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", 00475 this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut); 00476 00477 *ppvOut = NULL; 00478 return E_NOTIMPL; 00479 } 00480 00481 /************************************************************************** 00482 * CDesktopFolder::CompareIDs 00483 */ 00484 HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) 00485 { 00486 int nReturn; 00487 00488 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2); 00489 nReturn = SHELL32_CompareIDs ((IShellFolder *)this, lParam, pidl1, pidl2); 00490 TRACE ("-- %i\n", nReturn); 00491 return nReturn; 00492 } 00493 00494 /************************************************************************** 00495 * CDesktopFolder::CreateViewObject 00496 */ 00497 HRESULT WINAPI CDesktopFolder::CreateViewObject( 00498 HWND hwndOwner, 00499 REFIID riid, 00500 LPVOID *ppvOut) 00501 { 00502 CComPtr<IShellView> pShellView; 00503 HRESULT hr = E_INVALIDARG; 00504 00505 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", 00506 this, hwndOwner, shdebugstr_guid (&riid), ppvOut); 00507 00508 if (!ppvOut) 00509 return hr; 00510 00511 *ppvOut = NULL; 00512 00513 if (IsEqualIID (riid, IID_IDropTarget)) 00514 { 00515 WARN ("IDropTarget not implemented\n"); 00516 hr = E_NOTIMPL; 00517 } 00518 else if (IsEqualIID (riid, IID_IContextMenu)) 00519 { 00520 WARN ("IContextMenu not implemented\n"); 00521 hr = E_NOTIMPL; 00522 } 00523 else if (IsEqualIID (riid, IID_IShellView)) 00524 { 00525 hr = IShellView_Constructor((IShellFolder *)this, &pShellView); 00526 if (pShellView) 00527 hr = pShellView->QueryInterface(riid, ppvOut); 00528 } 00529 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut); 00530 return hr; 00531 } 00532 00533 /************************************************************************** 00534 * CDesktopFolder::GetAttributesOf 00535 */ 00536 HRESULT WINAPI CDesktopFolder::GetAttributesOf( 00537 UINT cidl, 00538 LPCITEMIDLIST *apidl, 00539 DWORD *rgfInOut) 00540 { 00541 HRESULT hr = S_OK; 00542 static const DWORD dwDesktopAttributes = 00543 SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | 00544 SFGAO_STORAGEANCESTOR | SFGAO_HASPROPSHEET | SFGAO_STORAGE | SFGAO_CANLINK; 00545 static const DWORD dwMyComputerAttributes = 00546 SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | 00547 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK; 00548 static DWORD dwMyNetPlacesAttributes = 00549 SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | 00550 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK; 00551 00552 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", 00553 this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); 00554 00555 if (cidl && !apidl) 00556 return E_INVALIDARG; 00557 00558 if (*rgfInOut == 0) 00559 *rgfInOut = ~0; 00560 00561 if(cidl == 0) 00562 *rgfInOut &= dwDesktopAttributes; 00563 else 00564 { 00565 /* TODO: always add SFGAO_CANLINK */ 00566 for (UINT i = 0; i < cidl; ++i) 00567 { 00568 pdump(*apidl); 00569 if (_ILIsDesktop(*apidl)) 00570 *rgfInOut &= dwDesktopAttributes; 00571 else if (_ILIsMyComputer(apidl[i])) 00572 *rgfInOut &= dwMyComputerAttributes; 00573 else if (_ILIsNetHood(apidl[i])) 00574 *rgfInOut &= dwMyNetPlacesAttributes; 00575 else 00576 SHELL32_GetItemAttributes((IShellFolder *)this, apidl[i], rgfInOut); 00577 } 00578 } 00579 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ 00580 *rgfInOut &= ~SFGAO_VALIDATE; 00581 00582 TRACE("-- result=0x%08x\n", *rgfInOut); 00583 00584 return hr; 00585 } 00586 00587 /************************************************************************** 00588 * CDesktopFolder::GetUIObjectOf 00589 * 00590 * PARAMETERS 00591 * HWND hwndOwner, //[in ] Parent window for any output 00592 * UINT cidl, //[in ] array size 00593 * LPCITEMIDLIST* apidl, //[in ] simple pidl array 00594 * REFIID riid, //[in ] Requested Interface 00595 * UINT* prgfInOut, //[ ] reserved 00596 * LPVOID* ppvObject) //[out] Resulting Interface 00597 * 00598 */ 00599 HRESULT WINAPI CDesktopFolder::GetUIObjectOf( 00600 HWND hwndOwner, 00601 UINT cidl, 00602 LPCITEMIDLIST *apidl, 00603 REFIID riid, 00604 UINT *prgfInOut, 00605 LPVOID *ppvOut) 00606 { 00607 LPITEMIDLIST pidl; 00608 IUnknown *pObj = NULL; 00609 HRESULT hr = E_INVALIDARG; 00610 00611 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", 00612 this, hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut); 00613 00614 if (!ppvOut) 00615 return hr; 00616 00617 *ppvOut = NULL; 00618 00619 if (IsEqualIID (riid, IID_IContextMenu)) 00620 { 00621 hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder *)this, NULL, 0, NULL, (IContextMenu **)&pObj); 00622 } 00623 else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1)) 00624 { 00625 hr = IDataObject_Constructor( hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj); 00626 } 00627 else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1)) 00628 { 00629 pidl = ILCombine (pidlRoot, apidl[0]); 00630 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); 00631 SHFree (pidl); 00632 hr = S_OK; 00633 } 00634 else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1)) 00635 { 00636 pidl = ILCombine (pidlRoot, apidl[0]); 00637 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); 00638 SHFree (pidl); 00639 hr = S_OK; 00640 } 00641 else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1)) 00642 { 00643 hr = this->QueryInterface (IID_IDropTarget, (LPVOID *)&pObj); 00644 } 00645 else if ((IsEqualIID(riid, IID_IShellLinkW) || 00646 IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1)) 00647 { 00648 pidl = ILCombine (pidlRoot, apidl[0]); 00649 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); 00650 SHFree (pidl); 00651 } 00652 else 00653 hr = E_NOINTERFACE; 00654 00655 if (SUCCEEDED(hr) && !pObj) 00656 hr = E_OUTOFMEMORY; 00657 00658 *ppvOut = pObj; 00659 TRACE ("(%p)->hr=0x%08x\n", this, hr); 00660 return hr; 00661 } 00662 00663 /************************************************************************** 00664 * CDesktopFolder::GetDisplayNameOf 00665 * 00666 * NOTES 00667 * special case: pidl = null gives desktop-name back 00668 */ 00669 HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) 00670 { 00671 HRESULT hr = S_OK; 00672 LPWSTR pszPath; 00673 00674 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet); 00675 pdump (pidl); 00676 00677 if (!strRet) 00678 return E_INVALIDARG; 00679 00680 pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR)); 00681 if (!pszPath) 00682 return E_OUTOFMEMORY; 00683 00684 if (_ILIsDesktop (pidl)) 00685 { 00686 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && 00687 (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING)) 00688 wcscpy(pszPath, sPathTarget); 00689 else 00690 HCR_GetClassNameW(CLSID_ShellDesktop, pszPath, MAX_PATH); 00691 } 00692 else if (_ILIsPidlSimple (pidl)) 00693 { 00694 GUID const *clsid; 00695 00696 if ((clsid = _ILGetGUIDPointer (pidl))) 00697 { 00698 if (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING) 00699 { 00700 int bWantsForParsing; 00701 00702 /* 00703 * We can only get a filesystem path from a shellfolder if the 00704 * value WantsFORPARSING in CLSID\\{...}\\shellfolder exists. 00705 * 00706 * Exception: The MyComputer folder doesn't have this key, 00707 * but any other filesystem backed folder it needs it. 00708 */ 00709 if (IsEqualIID (*clsid, CLSID_MyComputer)) 00710 { 00711 bWantsForParsing = TRUE; 00712 } 00713 else 00714 { 00715 /* get the "WantsFORPARSING" flag from the registry */ 00716 static const WCHAR clsidW[] = 00717 { 'C', 'L', 'S', 'I', 'D', '\\', 0 }; 00718 static const WCHAR shellfolderW[] = 00719 { '\\', 's', 'h', 'e', 'l', 'l', 'f', 'o', 'l', 'd', 'e', 'r', 0 }; 00720 static const WCHAR wantsForParsingW[] = 00721 { 'W', 'a', 'n', 't', 's', 'F', 'o', 'r', 'P', 'a', 'r', 's', 'i', 'n', 00722 'g', 0 00723 }; 00724 WCHAR szRegPath[100]; 00725 LONG r; 00726 00727 wcscpy (szRegPath, clsidW); 00728 SHELL32_GUIDToStringW (*clsid, &szRegPath[6]); 00729 wcscat (szRegPath, shellfolderW); 00730 r = SHGetValueW(HKEY_CLASSES_ROOT, szRegPath, 00731 wantsForParsingW, NULL, NULL, NULL); 00732 if (r == ERROR_SUCCESS) 00733 bWantsForParsing = TRUE; 00734 else 00735 bWantsForParsing = FALSE; 00736 } 00737 00738 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && 00739 bWantsForParsing) 00740 { 00741 /* 00742 * we need the filesystem path to the destination folder. 00743 * Only the folder itself can know it 00744 */ 00745 hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags, 00746 pszPath, 00747 MAX_PATH); 00748 } 00749 else 00750 { 00751 /* parsing name like ::{...} */ 00752 pszPath[0] = ':'; 00753 pszPath[1] = ':'; 00754 SHELL32_GUIDToStringW (*clsid, &pszPath[2]); 00755 } 00756 } 00757 else 00758 { 00759 /* user friendly name */ 00760 HCR_GetClassNameW (*clsid, pszPath, MAX_PATH); 00761 } 00762 } 00763 else 00764 { 00765 int cLen = 0; 00766 00767 /* file system folder or file rooted at the desktop */ 00768 if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) && 00769 (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER)) 00770 { 00771 lstrcpynW(pszPath, sPathTarget, MAX_PATH - 1); 00772 PathAddBackslashW(pszPath); 00773 cLen = wcslen(pszPath); 00774 } 00775 00776 _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen); 00777 if (!_ILIsFolder(pidl)) 00778 SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags); 00779 00780 if (GetFileAttributes(pszPath) == INVALID_FILE_ATTRIBUTES) 00781 { 00782 /* file system folder or file rooted at the AllUsers desktop */ 00783 if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) && 00784 (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER)) 00785 { 00786 SHGetSpecialFolderPathW(0, pszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE); 00787 PathAddBackslashW(pszPath); 00788 cLen = wcslen(pszPath); 00789 } 00790 00791 _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen); 00792 if (!_ILIsFolder(pidl)) 00793 SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags); 00794 } 00795 } 00796 } 00797 else 00798 { 00799 /* a complex pidl, let the subfolder do the work */ 00800 hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags, 00801 pszPath, MAX_PATH); 00802 } 00803 00804 if (SUCCEEDED(hr)) 00805 { 00806 /* Win9x always returns ANSI strings, NT always returns Unicode strings */ 00807 if (GetVersion() & 0x80000000) 00808 { 00809 strRet->uType = STRRET_CSTR; 00810 if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->cStr, MAX_PATH, 00811 NULL, NULL)) 00812 strRet->cStr[0] = '\0'; 00813 CoTaskMemFree(pszPath); 00814 } 00815 else 00816 { 00817 strRet->uType = STRRET_WSTR; 00818 strRet->pOleStr = pszPath; 00819 } 00820 } 00821 else 00822 CoTaskMemFree(pszPath); 00823 00824 TRACE ("-- (%p)->(%s,0x%08x)\n", this, 00825 strRet->uType == STRRET_CSTR ? strRet->cStr : 00826 debugstr_w(strRet->pOleStr), hr); 00827 return hr; 00828 } 00829 00830 /************************************************************************** 00831 * CDesktopFolder::SetNameOf 00832 * Changes the name of a file object or subfolder, possibly changing its item 00833 * identifier in the process. 00834 * 00835 * PARAMETERS 00836 * HWND hwndOwner, //[in ] Owner window for output 00837 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change 00838 * LPCOLESTR lpszName, //[in ] the items new display name 00839 * DWORD dwFlags, //[in ] SHGNO formatting flags 00840 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned 00841 */ 00842 HRESULT WINAPI CDesktopFolder::SetNameOf( 00843 HWND hwndOwner, 00844 LPCITEMIDLIST pidl, /* simple pidl */ 00845 LPCOLESTR lpName, 00846 DWORD dwFlags, 00847 LPITEMIDLIST *pPidlOut) 00848 { 00849 CComPtr<IShellFolder2> psf; 00850 HRESULT hr; 00851 WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1]; 00852 LPWSTR ptr; 00853 BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl)); 00854 00855 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, 00856 debugstr_w (lpName), dwFlags, pPidlOut); 00857 00858 if (_ILGetGUIDPointer(pidl)) 00859 { 00860 if (SUCCEEDED(BindToObject(pidl, NULL, IID_IShellFolder2, (LPVOID *)&psf))) 00861 { 00862 hr = psf->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut); 00863 return hr; 00864 } 00865 } 00866 00867 /* build source path */ 00868 lstrcpynW(szSrc, sPathTarget, MAX_PATH); 00869 ptr = PathAddBackslashW (szSrc); 00870 if (ptr) 00871 _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc)); 00872 00873 /* build destination path */ 00874 if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) { 00875 lstrcpynW(szDest, sPathTarget, MAX_PATH); 00876 ptr = PathAddBackslashW (szDest); 00877 if (ptr) 00878 lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest)); 00879 } else 00880 lstrcpynW(szDest, lpName, MAX_PATH); 00881 00882 if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) { 00883 WCHAR *ext = PathFindExtensionW(szSrc); 00884 if(*ext != '\0') { 00885 INT len = wcslen(szDest); 00886 lstrcpynW(szDest + len, ext, MAX_PATH - len); 00887 } 00888 } 00889 00890 if (!memcmp(szSrc, szDest, (wcslen(szDest) + 1) * sizeof(WCHAR))) 00891 { 00892 /* src and destination is the same */ 00893 hr = S_OK; 00894 if (pPidlOut) 00895 hr = _ILCreateFromPathW(szDest, pPidlOut); 00896 00897 return hr; 00898 } 00899 00900 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest)); 00901 if (MoveFileW (szSrc, szDest)) 00902 { 00903 hr = S_OK; 00904 00905 if (pPidlOut) 00906 hr = _ILCreateFromPathW(szDest, pPidlOut); 00907 00908 SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, 00909 SHCNF_PATHW, szSrc, szDest); 00910 00911 return hr; 00912 } 00913 return E_FAIL; 00914 } 00915 00916 HRESULT WINAPI CDesktopFolder::GetDefaultSearchGUID(GUID *pguid) 00917 { 00918 FIXME ("(%p)\n", this); 00919 return E_NOTIMPL; 00920 } 00921 00922 HRESULT WINAPI CDesktopFolder::EnumSearches(IEnumExtraSearch **ppenum) 00923 { 00924 FIXME ("(%p)\n", this); 00925 return E_NOTIMPL; 00926 } 00927 00928 HRESULT WINAPI CDesktopFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay) 00929 { 00930 TRACE ("(%p)\n", this); 00931 00932 if (pSort) 00933 *pSort = 0; 00934 if (pDisplay) 00935 *pDisplay = 0; 00936 00937 return S_OK; 00938 } 00939 00940 HRESULT WINAPI CDesktopFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags) 00941 { 00942 TRACE ("(%p)\n", this); 00943 00944 if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS) 00945 return E_INVALIDARG; 00946 00947 *pcsFlags = DesktopSFHeader[iColumn].pcsFlags; 00948 00949 return S_OK; 00950 } 00951 00952 HRESULT WINAPI CDesktopFolder::GetDetailsEx( 00953 LPCITEMIDLIST pidl, 00954 const SHCOLUMNID *pscid, 00955 VARIANT *pv) 00956 { 00957 FIXME ("(%p)\n", this); 00958 00959 return E_NOTIMPL; 00960 } 00961 00962 HRESULT WINAPI CDesktopFolder::GetDetailsOf( 00963 LPCITEMIDLIST pidl, 00964 UINT iColumn, 00965 SHELLDETAILS *psd) 00966 { 00967 HRESULT hr = S_OK; 00968 00969 TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd); 00970 00971 if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS) 00972 return E_INVALIDARG; 00973 00974 if (!pidl) 00975 { 00976 psd->fmt = DesktopSFHeader[iColumn].fmt; 00977 psd->cxChar = DesktopSFHeader[iColumn].cxChar; 00978 psd->str.uType = STRRET_CSTR; 00979 LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid, 00980 psd->str.cStr, MAX_PATH); 00981 return S_OK; 00982 } 00983 00984 /* the data from the pidl */ 00985 psd->str.uType = STRRET_CSTR; 00986 switch (iColumn) 00987 { 00988 case 0: /* name */ 00989 hr = GetDisplayNameOf(pidl, 00990 SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); 00991 break; 00992 case 1: /* size */ 00993 _ILGetFileSize (pidl, psd->str.cStr, MAX_PATH); 00994 break; 00995 case 2: /* type */ 00996 _ILGetFileType (pidl, psd->str.cStr, MAX_PATH); 00997 break; 00998 case 3: /* date */ 00999 _ILGetFileDate (pidl, psd->str.cStr, MAX_PATH); 01000 break; 01001 case 4: /* attributes */ 01002 _ILGetFileAttributes (pidl, psd->str.cStr, MAX_PATH); 01003 break; 01004 } 01005 01006 return hr; 01007 } 01008 01009 HRESULT WINAPI CDesktopFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid) 01010 { 01011 FIXME ("(%p)\n", this); 01012 return E_NOTIMPL; 01013 } 01014 01015 HRESULT WINAPI CDesktopFolder::GetClassID(CLSID *lpClassId) 01016 { 01017 TRACE ("(%p)\n", this); 01018 01019 if (!lpClassId) 01020 return E_POINTER; 01021 01022 *lpClassId = CLSID_ShellDesktop; 01023 01024 return S_OK; 01025 } 01026 01027 HRESULT WINAPI CDesktopFolder::Initialize(LPCITEMIDLIST pidl) 01028 { 01029 TRACE ("(%p)->(%p)\n", this, pidl); 01030 01031 return E_NOTIMPL; 01032 } 01033 01034 HRESULT WINAPI CDesktopFolder::GetCurFolder(LPITEMIDLIST * pidl) 01035 { 01036 TRACE ("(%p)->(%p)\n", this, pidl); 01037 01038 if (!pidl) return E_POINTER; 01039 *pidl = ILClone (pidlRoot); 01040 return S_OK; 01041 } 01042 01043 HRESULT WINAPI CDesktopFolder::GetUniqueName(LPWSTR pwszName, UINT uLen) 01044 { 01045 CComPtr<IEnumIDList> penum; 01046 HRESULT hr; 01047 WCHAR wszText[MAX_PATH]; 01048 WCHAR wszNewFolder[25]; 01049 const WCHAR wszFormat[] = {'%', 's', ' ', '%', 'd', 0 }; 01050 01051 LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, sizeof(wszNewFolder) / sizeof(WCHAR)); 01052 01053 TRACE ("(%p)(%p %u)\n", this, pwszName, uLen); 01054 01055 if (uLen < sizeof(wszNewFolder) / sizeof(WCHAR) + 3) 01056 return E_POINTER; 01057 01058 lstrcpynW (pwszName, wszNewFolder, uLen); 01059 01060 hr = EnumObjects(0, 01061 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum); 01062 if (penum) { 01063 LPITEMIDLIST pidl; 01064 DWORD dwFetched; 01065 int i = 1; 01066 01067 next: 01068 penum->Reset (); 01069 while (S_OK == penum->Next(1, &pidl, &dwFetched) && 01070 dwFetched) { 01071 _ILSimpleGetTextW (pidl, wszText, MAX_PATH); 01072 if (0 == lstrcmpiW (wszText, pwszName)) { 01073 _snwprintf (pwszName, uLen, wszFormat, wszNewFolder, i++); 01074 if (i > 99) { 01075 hr = E_FAIL; 01076 break; 01077 } 01078 goto next; 01079 } 01080 } 01081 01082 } 01083 return hr; 01084 } 01085 01086 HRESULT WINAPI CDesktopFolder::AddFolder(HWND hwnd, LPCWSTR pwszName, LPITEMIDLIST *ppidlOut) 01087 { 01088 WCHAR wszNewDir[MAX_PATH]; 01089 DWORD bRes; 01090 HRESULT hres = E_FAIL; 01091 01092 TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName), ppidlOut); 01093 01094 wszNewDir[0] = 0; 01095 if (sPathTarget) 01096 lstrcpynW(wszNewDir, sPathTarget, MAX_PATH); 01097 PathAppendW(wszNewDir, pwszName); 01098 bRes = CreateDirectoryW (wszNewDir, NULL); 01099 if (bRes) 01100 { 01101 SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL); 01102 hres = S_OK; 01103 if (ppidlOut) 01104 hres = _ILCreateFromPathW(wszNewDir, ppidlOut); 01105 } 01106 01107 return hres; 01108 } 01109 01110 HRESULT WINAPI CDesktopFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl) 01111 { 01112 UINT i; 01113 SHFILEOPSTRUCTW op; 01114 WCHAR wszPath[MAX_PATH]; 01115 WCHAR wszCaption[50]; 01116 WCHAR *wszPathsList; 01117 HRESULT ret; 01118 WCHAR *wszCurrentPath; 01119 UINT bRestoreWithDeskCpl = FALSE; 01120 int res; 01121 01122 TRACE ("(%p)(%u %p)\n", this, cidl, apidl); 01123 if (cidl == 0) return S_OK; 01124 01125 for(i = 0; i < cidl; i++) 01126 { 01127 if (_ILIsMyComputer(apidl[i])) 01128 bRestoreWithDeskCpl++; 01129 else if (_ILIsNetHood(apidl[i])) 01130 bRestoreWithDeskCpl++; 01131 else if (_ILIsMyDocuments(apidl[i])) 01132 bRestoreWithDeskCpl++; 01133 } 01134 01135 if (bRestoreWithDeskCpl) 01136 { 01137 /* FIXME use FormatMessage 01138 * use a similar message resource as in windows 01139 */ 01140 LoadStringW(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, wszPath, sizeof(wszPath) / sizeof(WCHAR)); 01141 wszPath[(sizeof(wszPath)/sizeof(WCHAR))-1] = 0; 01142 01143 LoadStringW(shell32_hInstance, IDS_DELETEITEM_CAPTION, wszCaption, sizeof(wszCaption) / sizeof(WCHAR)); 01144 wszCaption[(sizeof(wszCaption)/sizeof(WCHAR))-1] = 0; 01145 01146 res = SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath, wszCaption, NULL, cidl > 1); 01147 if (res == IDC_YESTOALL || res == IDYES) 01148 { 01149 for(i = 0; i < cidl; i++) 01150 { 01151 if (_ILIsMyComputer(apidl[i])) 01152 SetNamespaceExtensionVisibleStatus(L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1); 01153 else if (_ILIsNetHood(apidl[i])) 01154 SetNamespaceExtensionVisibleStatus(L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1); 01155 else if (_ILIsMyDocuments(apidl[i])) 01156 SetNamespaceExtensionVisibleStatus(L"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1); 01157 } 01158 } 01159 } 01160 if (sPathTarget) 01161 lstrcpynW(wszPath, sPathTarget, MAX_PATH); 01162 else 01163 wszPath[0] = '\0'; 01164 01165 PathAddBackslashW(wszPath); 01166 wszPathsList = BuildPathsList(wszPath, cidl, apidl); 01167 01168 ZeroMemory(&op, sizeof(op)); 01169 op.hwnd = GetActiveWindow(); 01170 op.wFunc = FO_DELETE; 01171 op.pFrom = wszPathsList; 01172 op.fFlags = FOF_ALLOWUNDO; 01173 if (SHFileOperationW(&op)) 01174 { 01175 WARN("SHFileOperation failed\n"); 01176 ret = E_FAIL; 01177 } 01178 else 01179 ret = S_OK; 01180 01181 /* we currently need to manually send the notifies */ 01182 wszCurrentPath = wszPathsList; 01183 for (i = 0; i < cidl; i++) 01184 { 01185 LONG wEventId; 01186 01187 if (_ILIsFolder(apidl[i])) 01188 wEventId = SHCNE_RMDIR; 01189 else if (_ILIsValue(apidl[i])) 01190 wEventId = SHCNE_DELETE; 01191 else 01192 continue; 01193 01194 /* check if file exists */ 01195 if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES) 01196 { 01197 LPITEMIDLIST pidl = ILCombine(pidlRoot, apidl[i]); 01198 SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL); 01199 SHFree(pidl); 01200 } 01201 01202 wszCurrentPath += wcslen(wszCurrentPath) + 1; 01203 } 01204 HeapFree(GetProcessHeap(), 0, wszPathsList); 01205 return ret; 01206 } 01207 01208 HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl) 01209 { 01210 CComPtr<IPersistFolder2> ppf2; 01211 WCHAR szSrcPath[MAX_PATH]; 01212 WCHAR szTargetPath[MAX_PATH]; 01213 SHFILEOPSTRUCTW op; 01214 LPITEMIDLIST pidl; 01215 LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName; 01216 int res, length; 01217 STRRET strRet; 01218 01219 TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl); 01220 01221 pSFFrom->QueryInterface(IID_IPersistFolder2, (LPVOID *)&ppf2); 01222 if (ppf2) 01223 { 01224 if (FAILED(ppf2->GetCurFolder(&pidl))) 01225 return E_FAIL; 01226 01227 if (FAILED(pSFFrom->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strRet))) 01228 { 01229 SHFree (pidl); 01230 return E_FAIL; 01231 } 01232 01233 if (FAILED(StrRetToBufW(&strRet, pidl, szSrcPath, MAX_PATH))) 01234 { 01235 SHFree (pidl); 01236 return E_FAIL; 01237 } 01238 SHFree (pidl); 01239 01240 pszSrc = PathAddBackslashW (szSrcPath); 01241 01242 wcscpy(szTargetPath, sPathTarget); 01243 pszTarget = PathAddBackslashW (szTargetPath); 01244 01245 pszSrcList = BuildPathsList(szSrcPath, cidl, apidl); 01246 pszTargetList = BuildPathsList(szTargetPath, cidl, apidl); 01247 01248 if (!pszSrcList || !pszTargetList) 01249 { 01250 if (pszSrcList) 01251 HeapFree(GetProcessHeap(), 0, pszSrcList); 01252 01253 if (pszTargetList) 01254 HeapFree(GetProcessHeap(), 0, pszTargetList); 01255 01256 SHFree (pidl); 01257 return E_OUTOFMEMORY; 01258 } 01259 ZeroMemory(&op, sizeof(op)); 01260 if (!pszSrcList[0]) 01261 { 01262 /* remove trailing backslash */ 01263 pszSrc--; 01264 pszSrc[0] = L'\0'; 01265 op.pFrom = szSrcPath; 01266 } 01267 else 01268 { 01269 op.pFrom = pszSrcList; 01270 } 01271 01272 if (!pszTargetList[0]) 01273 { 01274 /* remove trailing backslash */ 01275 if (pszTarget - szTargetPath > 3) 01276 { 01277 pszTarget--; 01278 pszTarget[0] = L'\0'; 01279 } 01280 else 01281 { 01282 pszTarget[1] = L'\0'; 01283 } 01284 01285 op.pTo = szTargetPath; 01286 } 01287 else 01288 { 01289 op.pTo = pszTargetList; 01290 } 01291 op.hwnd = GetActiveWindow(); 01292 op.wFunc = FO_COPY; 01293 op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR; 01294 01295 res = SHFileOperationW(&op); 01296 01297 if (res == DE_SAMEFILE) 01298 { 01299 length = wcslen(szTargetPath); 01300 01301 01302 pszFileName = wcsrchr(pszSrcList, '\\'); 01303 pszFileName++; 01304 01305 if (LoadStringW(shell32_hInstance, IDS_COPY_OF, pszTarget, MAX_PATH - length)) 01306 { 01307 wcscat(szTargetPath, L" "); 01308 } 01309 01310 wcscat(szTargetPath, pszFileName); 01311 op.pTo = szTargetPath; 01312 01313 res = SHFileOperationW(&op); 01314 } 01315 01316 01317 HeapFree(GetProcessHeap(), 0, pszSrcList); 01318 HeapFree(GetProcessHeap(), 0, pszTargetList); 01319 01320 if (res) 01321 return E_FAIL; 01322 else 01323 return S_OK; 01324 } 01325 return E_FAIL; 01326 } Generated on Sat May 26 2012 04:17:27 for ReactOS by
1.7.6.1
|