[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / folders / CDrivesFolder.cpp
1 /*
2 * Virtual Workplace folder
3 *
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2009 Andrew Hill
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include <precomp.h>
24
25 WINE_DEFAULT_DEBUG_CHANNEL (shell);
26
27 /*
28 CDrivesFolder should create a CRegFolder to represent the virtual items that exist only in
29 the registry. The CRegFolder is aggregated by the CDrivesFolder.
30 The CDrivesFolderEnum class should enumerate only drives on the system. Since the CRegFolder
31 implementation of IShellFolder::EnumObjects enumerates the virtual items, the
32 CDrivesFolderEnum is only responsible for returning the physical items.
33
34 2. At least on my XP system, the drive pidls returned are of type PT_DRIVE1, not PT_DRIVE
35 3. The parsing name returned for my computer is incorrect. It should be "My Computer"
36 */
37
38 /***********************************************************************
39 * IShellFolder implementation
40 */
41
42 class CDrivesFolderEnum :
43 public CEnumIDListBase
44 {
45 public:
46 CDrivesFolderEnum();
47 ~CDrivesFolderEnum();
48 HRESULT WINAPI Initialize(HWND hwndOwner, DWORD dwFlags);
49 BOOL CreateMyCompEnumList(DWORD dwFlags);
50
51 BEGIN_COM_MAP(CDrivesFolderEnum)
52 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
53 END_COM_MAP()
54 };
55
56 /***********************************************************************
57 * IShellFolder [MyComputer] implementation
58 */
59
60 static const shvheader MyComputerSFHeader[] = {
61 {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
62 {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
63 {IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
64 {IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
65 };
66
67 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
68
69 CDrivesFolderEnum::CDrivesFolderEnum()
70 {
71 }
72
73 CDrivesFolderEnum::~CDrivesFolderEnum()
74 {
75 }
76
77 HRESULT WINAPI CDrivesFolderEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
78 {
79 if (CreateMyCompEnumList(dwFlags) == FALSE)
80 return E_FAIL;
81
82 return S_OK;
83 }
84
85 /**************************************************************************
86 * CDrivesFolderEnum::CreateMyCompEnumList()
87 */
88
89 BOOL CDrivesFolderEnum::CreateMyCompEnumList(DWORD dwFlags)
90 {
91 BOOL bRet = TRUE;
92 static const WCHAR MyComputer_NameSpaceW[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace";
93
94 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
95
96 /* enumerate the folders */
97 if (dwFlags & SHCONTF_FOLDERS)
98 {
99 WCHAR wszDriveName[] = {'A', ':', '\\', '\0'};
100 DWORD dwDrivemap = GetLogicalDrives();
101 HKEY hKey;
102 UINT i;
103
104 while (bRet && wszDriveName[0] <= 'Z')
105 {
106 if(dwDrivemap & 0x00000001L)
107 bRet = AddToEnumList(_ILCreateDrive(wszDriveName));
108 wszDriveName[0]++;
109 dwDrivemap = dwDrivemap >> 1;
110 }
111
112 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n", this);
113 for (i = 0; i < 2; i++)
114 {
115 if (bRet && ERROR_SUCCESS == RegOpenKeyExW(i == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
116 MyComputer_NameSpaceW, 0, KEY_READ, &hKey))
117 {
118 WCHAR wszBuf[50];
119 DWORD dwSize, j = 0;
120 LONG ErrorCode;
121 LPITEMIDLIST pidl;
122
123 while (bRet)
124 {
125 dwSize = sizeof(wszBuf) / sizeof(wszBuf[0]);
126 ErrorCode = RegEnumKeyExW(hKey, j, wszBuf, &dwSize, 0, NULL, NULL, NULL);
127 if (ERROR_SUCCESS == ErrorCode)
128 {
129 if (wszBuf[0] != L'{')
130 {
131 dwSize = sizeof(wszBuf);
132 RegGetValueW(hKey, wszBuf, NULL, RRF_RT_REG_SZ, NULL, wszBuf, &dwSize);
133 }
134
135 /* FIXME: shell extensions - the type should be PT_SHELLEXT (tested) */
136 pidl = _ILCreateGuidFromStrW(wszBuf);
137 if (pidl != NULL)
138 bRet = AddToEnumList(pidl);
139 else
140 ERR("Invalid MyComputer namespace extesion: %s\n", wszBuf);
141 j++;
142 }
143 else if (ERROR_NO_MORE_ITEMS == ErrorCode)
144 break;
145 else
146 bRet = FALSE;
147 }
148 RegCloseKey(hKey);
149 }
150 }
151 }
152 return bRet;
153 }
154
155 CDrivesFolder::CDrivesFolder()
156 {
157 pidlRoot = NULL;
158 sName = NULL;
159 }
160
161 CDrivesFolder::~CDrivesFolder()
162 {
163 TRACE ("-- destroying IShellFolder(%p)\n", this);
164 SHFree(pidlRoot);
165 }
166
167 HRESULT WINAPI CDrivesFolder::FinalConstruct()
168 {
169 DWORD dwSize;
170 WCHAR szName[MAX_PATH];
171 WCHAR wszMyCompKey[256];
172 INT i;
173
174 pidlRoot = _ILCreateMyComputer(); /* my qualified pidl */
175 if (pidlRoot == NULL)
176 return E_OUTOFMEMORY;
177
178 i = swprintf(wszMyCompKey, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\");
179 StringFromGUID2(CLSID_MyComputer, wszMyCompKey + i, sizeof(wszMyCompKey) / sizeof(wszMyCompKey[0]) - i);
180 dwSize = sizeof(szName);
181 if (RegGetValueW(HKEY_CURRENT_USER, wszMyCompKey,
182 NULL, RRF_RT_REG_SZ, NULL, szName, &dwSize) == ERROR_SUCCESS)
183 {
184 sName = (LPWSTR)SHAlloc((wcslen(szName) + 1) * sizeof(WCHAR));
185 if (sName)
186 wcscpy(sName, szName);
187 TRACE("sName %s\n", debugstr_w(sName));
188 }
189 return S_OK;
190 }
191
192 /**************************************************************************
193 * CDrivesFolder::ParseDisplayName
194 */
195 HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
196 DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes)
197 {
198 HRESULT hr = E_INVALIDARG;
199 LPCWSTR szNext = NULL;
200 WCHAR szElement[MAX_PATH];
201 LPITEMIDLIST pidlTemp = NULL;
202 CLSID clsid;
203
204 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
205 hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
206 pchEaten, ppidl, pdwAttributes);
207
208 *ppidl = 0;
209 if (pchEaten)
210 *pchEaten = 0; /* strange but like the original */
211
212 /* handle CLSID paths */
213 if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
214 {
215 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
216 TRACE ("-- element: %s\n", debugstr_w (szElement));
217 CLSIDFromString (szElement + 2, &clsid);
218 pidlTemp = _ILCreateGuid (PT_GUID, clsid);
219 }
220 /* do we have an absolute path name ? */
221 else if (PathGetDriveNumberW (lpszDisplayName) >= 0 &&
222 lpszDisplayName[2] == (WCHAR) '\\')
223 {
224 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
225 /* make drive letter uppercase to enable PIDL comparison */
226 szElement[0] = toupper(szElement[0]);
227 pidlTemp = _ILCreateDrive (szElement);
228 }
229
230 if (szNext && *szNext)
231 {
232 hr = SHELL32_ParseNextElement (this, hwndOwner, pbc, &pidlTemp,
233 (LPOLESTR) szNext, pchEaten, pdwAttributes);
234 }
235 else
236 {
237 hr = S_OK;
238 if (pdwAttributes && *pdwAttributes)
239 {
240 if (_ILIsCPanelStruct(pidlTemp))
241 *pdwAttributes &= SFGAO_CANLINK;
242 else if (_ILIsSpecialFolder(pidlTemp))
243 SHELL32_GetGuidItemAttributes(this, pidlTemp, pdwAttributes);
244 else
245 ERR("Got an unkown pidl here!\n");
246 }
247 }
248
249 *ppidl = pidlTemp;
250
251 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
252
253 return hr;
254 }
255
256 /**************************************************************************
257 * CDrivesFolder::EnumObjects
258 */
259 HRESULT WINAPI CDrivesFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
260 {
261 return ShellObjectCreatorInit<CDrivesFolderEnum>(hwndOwner, dwFlags, IID_IEnumIDList, ppEnumIDList);
262 }
263
264 /**************************************************************************
265 * CDrivesFolder::BindToObject
266 */
267 HRESULT WINAPI CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
268 {
269 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
270 pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
271
272 if (_ILIsSpecialFolder(pidl))
273 return SHELL32_BindToGuidItem(pidlRoot, pidl, pbcReserved, riid, ppvOut);
274
275 return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut);
276 }
277
278 /**************************************************************************
279 * CDrivesFolder::BindToStorage
280 */
281 HRESULT WINAPI CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
282 {
283 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
284 pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
285
286 *ppvOut = NULL;
287 return E_NOTIMPL;
288 }
289
290 /**************************************************************************
291 * CDrivesFolder::CompareIDs
292 */
293
294 HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
295 {
296 int nReturn;
297
298 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
299 nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
300 TRACE("-- %i\n", nReturn);
301 return nReturn;
302 }
303
304 /**************************************************************************
305 * CDrivesFolder::CreateViewObject
306 */
307 HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
308 {
309 CComPtr<IShellView> pShellView;
310 HRESULT hr = E_INVALIDARG;
311
312 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
313 hwndOwner, shdebugstr_guid (&riid), ppvOut);
314
315 if (!ppvOut)
316 return hr;
317
318 *ppvOut = NULL;
319
320 if (IsEqualIID(riid, IID_IDropTarget))
321 {
322 WARN("IDropTarget not implemented\n");
323 hr = E_NOTIMPL;
324 }
325 else if (IsEqualIID(riid, IID_IContextMenu))
326 {
327 WARN("IContextMenu not implemented\n");
328 hr = E_NOTIMPL;
329 }
330 else if (IsEqualIID(riid, IID_IShellView))
331 {
332 hr = CDefView_Constructor(this, riid, ppvOut);
333 }
334 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
335 return hr;
336 }
337
338 static BOOL _ILIsControlPanel(LPCITEMIDLIST pidl)
339 {
340 GUID *guid = _ILGetGUIDPointer(pidl);
341
342 TRACE("(%p)\n", pidl);
343
344 if (guid)
345 return IsEqualIID(*guid, CLSID_ControlPanel);
346 return FALSE;
347 }
348
349 /**************************************************************************
350 * CDrivesFolder::GetAttributesOf
351 */
352 HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
353 {
354 static const DWORD dwComputerAttributes =
355 SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
356 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
357 static const DWORD dwControlPanelAttributes =
358 SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
359 static const DWORD dwDriveAttributes =
360 SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
361 SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK;
362
363 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
364 this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
365
366 if (cidl && !apidl)
367 return E_INVALIDARG;
368
369 if (*rgfInOut == 0)
370 *rgfInOut = ~0;
371
372 /* FIXME: always add SFGAO_CANLINK */
373 if(cidl == 0)
374 *rgfInOut &= dwComputerAttributes;
375 else
376 {
377 for (UINT i = 0; i < cidl; ++i)
378 {
379 if (_ILIsDrive(apidl[i]))
380 *rgfInOut &= dwDriveAttributes;
381 else if (_ILIsControlPanel(apidl[i]))
382 *rgfInOut &= dwControlPanelAttributes;
383 else if (_ILIsSpecialFolder(*apidl))
384 SHELL32_GetGuidItemAttributes(this, apidl[i], rgfInOut);
385 else
386 ERR("Got unknown pidl type!\n");
387 }
388 }
389
390 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
391 *rgfInOut &= ~SFGAO_VALIDATE;
392
393 TRACE ("-- result=0x%08x\n", *rgfInOut);
394 return S_OK;
395 }
396
397 /**************************************************************************
398 * CDrivesFolder::GetUIObjectOf
399 *
400 * PARAMETERS
401 * hwndOwner [in] Parent window for any output
402 * cidl [in] array size
403 * apidl [in] simple pidl array
404 * riid [in] Requested Interface
405 * prgfInOut [ ] reserved
406 * ppvObject [out] Resulting Interface
407 *
408 */
409 HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner,
410 UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
411 REFIID riid, UINT *prgfInOut, LPVOID *ppvOut)
412 {
413 LPITEMIDLIST pidl;
414 IUnknown *pObj = NULL;
415 HRESULT hr = E_INVALIDARG;
416
417 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
418 hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
419
420 if (!ppvOut)
421 return hr;
422
423 *ppvOut = NULL;
424
425 if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
426 {
427 hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj);
428 }
429 else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
430 {
431 hr = IDataObject_Constructor (hwndOwner,
432 pidlRoot, apidl, cidl, (IDataObject **)&pObj);
433 }
434 else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
435 {
436 pidl = ILCombine (pidlRoot, apidl[0]);
437 pObj = IExtractIconA_Constructor (pidl);
438 SHFree (pidl);
439 hr = S_OK;
440 }
441 else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
442 {
443 pidl = ILCombine (pidlRoot, apidl[0]);
444 pObj = IExtractIconW_Constructor (pidl);
445 SHFree (pidl);
446 hr = S_OK;
447 }
448 else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
449 {
450 IDropTarget * pDt = NULL;
451 hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
452 pObj = pDt;
453 }
454 else if ((IsEqualIID(riid, IID_IShellLinkW) ||
455 IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
456 {
457 pidl = ILCombine (pidlRoot, apidl[0]);
458 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*) &pObj);
459 SHFree (pidl);
460 }
461 else
462 hr = E_NOINTERFACE;
463
464 if (SUCCEEDED(hr) && !pObj)
465 hr = E_OUTOFMEMORY;
466
467 *ppvOut = pObj;
468 TRACE ("(%p)->hr=0x%08x\n", this, hr);
469 return hr;
470 }
471
472 /**************************************************************************
473 * CDrivesFolder::GetDisplayNameOf
474 */
475 HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
476 {
477 LPWSTR pszPath;
478 HRESULT hr = S_OK;
479
480 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
481 pdump (pidl);
482
483 if (!strRet)
484 return E_INVALIDARG;
485
486 pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
487 if (!pszPath)
488 return E_OUTOFMEMORY;
489
490 pszPath[0] = 0;
491
492 if (!pidl->mkid.cb)
493 {
494 /* parsing name like ::{...} */
495 pszPath[0] = ':';
496 pszPath[1] = ':';
497 SHELL32_GUIDToStringW(CLSID_MyComputer, &pszPath[2]);
498 }
499 else if (_ILIsPidlSimple(pidl))
500 {
501 if (_ILIsSpecialFolder(pidl))
502 return SHELL32_GetDisplayNameOfGUIDItem(this, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", pidl, dwFlags, strRet);
503 else if (_ILIsDrive(pidl))
504 {
505 _ILSimpleGetTextW(pidl, pszPath, MAX_PATH); /* append my own path */
506 /* long view "lw_name (C:)" */
507 if (!(dwFlags & SHGDN_FORPARSING))
508 {
509 WCHAR wszDrive[18] = {0};
510 DWORD dwVolumeSerialNumber, dwMaximumComponentLength, dwFileSystemFlags;
511 static const WCHAR wszOpenBracket[] = {' ', '(', 0};
512 static const WCHAR wszCloseBracket[] = {')', 0};
513
514 lstrcpynW(wszDrive, pszPath, 4);
515 pszPath[0] = L'\0';
516 GetVolumeInformationW(wszDrive, pszPath,
517 MAX_PATH - 7,
518 &dwVolumeSerialNumber,
519 &dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0);
520 pszPath[MAX_PATH-1] = L'\0';
521 if (!wcslen(pszPath))
522 {
523 UINT DriveType, ResourceId;
524 DriveType = GetDriveTypeW(wszDrive);
525 switch(DriveType)
526 {
527 case DRIVE_FIXED:
528 ResourceId = IDS_DRIVE_FIXED;
529 break;
530 case DRIVE_REMOTE:
531 ResourceId = IDS_DRIVE_NETWORK;
532 break;
533 case DRIVE_CDROM:
534 ResourceId = IDS_DRIVE_CDROM;
535 break;
536 default:
537 ResourceId = 0;
538 }
539 if (ResourceId)
540 {
541 dwFileSystemFlags = LoadStringW(shell32_hInstance, ResourceId, pszPath, MAX_PATH);
542 if (dwFileSystemFlags > MAX_PATH - 7)
543 pszPath[MAX_PATH-7] = L'\0';
544 }
545 }
546 wcscat (pszPath, wszOpenBracket);
547 wszDrive[2] = L'\0';
548 wcscat (pszPath, wszDrive);
549 wcscat (pszPath, wszCloseBracket);
550 }
551 }
552 else
553 {
554 /* Neither a shell namespace extension nor a drive letter. */
555 ERR("Wrong pidl type\n");
556 CoTaskMemFree(pszPath);
557 return E_INVALIDARG;
558 }
559 }
560 else
561 {
562 /* Complex pidl. Let the child folder do the work */
563 hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, pszPath, MAX_PATH);
564 }
565
566 if (SUCCEEDED(hr))
567 {
568 strRet->uType = STRRET_WSTR;
569 strRet->pOleStr = pszPath;
570 }
571 else
572 CoTaskMemFree(pszPath);
573
574 TRACE("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
575 return hr;
576 }
577
578 /**************************************************************************
579 * CDrivesFolder::SetNameOf
580 * Changes the name of a file object or subfolder, possibly changing its item
581 * identifier in the process.
582 *
583 * PARAMETERS
584 * hwndOwner [in] Owner window for output
585 * pidl [in] simple pidl of item to change
586 * lpszName [in] the items new display name
587 * dwFlags [in] SHGNO formatting flags
588 * ppidlOut [out] simple pidl returned
589 */
590 HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,
591 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
592 {
593 LPWSTR sName;
594 HKEY hKey;
595 UINT length;
596 WCHAR szName[30];
597
598 TRACE("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this,
599 hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
600
601 if (_ILIsDrive(pidl))
602 {
603 if (_ILSimpleGetTextW(pidl, szName, _countof(szName)))
604 SetVolumeLabelW(szName, lpName);
605 if (pPidlOut)
606 *pPidlOut = _ILCreateDrive(szName);
607 return S_OK;
608 }
609
610
611 if (pPidlOut != NULL)
612 *pPidlOut = _ILCreateMyComputer();
613
614 length = (wcslen(lpName) + 1) * sizeof(WCHAR);
615 sName = (LPWSTR)SHAlloc(length);
616
617 if (!sName)
618 return E_OUTOFMEMORY;
619
620 if (RegOpenKeyExW(HKEY_CURRENT_USER,
621 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
622 0,
623 KEY_WRITE,
624 &hKey) != ERROR_SUCCESS)
625 {
626 WARN("Error: failed to open registry key\n");
627 }
628 else
629 {
630 RegSetValueExW(hKey, NULL, 0, REG_SZ, (const LPBYTE)lpName, length);
631 RegCloseKey(hKey);
632 }
633
634 wcscpy(sName, lpName);
635 SHFree(this->sName);
636 this->sName = sName;
637 TRACE("result %s\n", debugstr_w(sName));
638 return S_OK;
639 }
640
641 HRESULT WINAPI CDrivesFolder::GetDefaultSearchGUID(GUID * pguid)
642 {
643 FIXME ("(%p)\n", this);
644 return E_NOTIMPL;
645 }
646
647 HRESULT WINAPI CDrivesFolder::EnumSearches(IEnumExtraSearch ** ppenum)
648 {
649 FIXME ("(%p)\n", this);
650 return E_NOTIMPL;
651 }
652
653 HRESULT WINAPI CDrivesFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
654 {
655 TRACE ("(%p)\n", this);
656
657 if (pSort)
658 *pSort = 0;
659 if (pDisplay)
660 *pDisplay = 0;
661 return S_OK;
662 }
663
664 HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
665 {
666 TRACE ("(%p)\n", this);
667
668 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
669 return E_INVALIDARG;
670 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
671 return S_OK;
672 }
673
674 HRESULT WINAPI CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
675 {
676 FIXME ("(%p)\n", this);
677 return E_NOTIMPL;
678 }
679
680 /* FIXME: drive size >4GB is rolling over */
681 HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
682 {
683 HRESULT hr;
684
685 TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
686
687 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
688 return E_INVALIDARG;
689
690 if (!pidl)
691 {
692 psd->fmt = MyComputerSFHeader[iColumn].fmt;
693 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
694 psd->str.uType = STRRET_CSTR;
695 LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid,
696 psd->str.cStr, MAX_PATH);
697 return S_OK;
698 }
699 else
700 {
701 char szPath[MAX_PATH];
702 ULARGE_INTEGER ulBytes;
703
704 psd->str.cStr[0] = 0x00;
705 psd->str.uType = STRRET_CSTR;
706 switch (iColumn)
707 {
708 case 0: /* name */
709 hr = GetDisplayNameOf(pidl,
710 SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
711 break;
712 case 1: /* type */
713 _ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
714 break;
715 case 2: /* total size */
716 if (_ILIsDrive(pidl))
717 {
718 _ILSimpleGetText (pidl, szPath, MAX_PATH);
719 GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL);
720 StrFormatByteSize64A (ulBytes.QuadPart, psd->str.cStr, MAX_PATH);
721 }
722 break;
723 case 3: /* free size */
724 if (_ILIsDrive(pidl))
725 {
726 _ILSimpleGetText (pidl, szPath, MAX_PATH);
727 GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL);
728 StrFormatByteSize64A (ulBytes.QuadPart, psd->str.cStr, MAX_PATH);
729 }
730 break;
731 }
732 hr = S_OK;
733 }
734
735 return hr;
736 }
737
738 HRESULT WINAPI CDrivesFolder::MapColumnToSCID(UINT column, SHCOLUMNID * pscid)
739 {
740 FIXME("(%p)\n", this);
741 return E_NOTIMPL;
742 }
743
744 /************************************************************************
745 * CDrivesFolder::GetClassID
746 */
747 HRESULT WINAPI CDrivesFolder::GetClassID(CLSID *lpClassId)
748 {
749 TRACE ("(%p)\n", this);
750
751 if (!lpClassId)
752 return E_POINTER;
753
754 *lpClassId = CLSID_MyComputer;
755 return S_OK;
756 }
757
758 /************************************************************************
759 * CDrivesFolder::Initialize
760 *
761 * NOTES: it makes no sense to change the pidl
762 */
763 HRESULT WINAPI CDrivesFolder::Initialize(LPCITEMIDLIST pidl)
764 {
765 TRACE ("(%p)->(%p)\n", this, pidl);
766
767 if (pidlRoot)
768 SHFree((LPVOID)pidlRoot);
769
770 pidlRoot = ILClone(pidl);
771 return S_OK;
772 }
773
774 /**************************************************************************
775 * CDrivesFolder::GetCurFolder
776 */
777 HRESULT WINAPI CDrivesFolder::GetCurFolder(LPITEMIDLIST *pidl)
778 {
779 TRACE("(%p)->(%p)\n", this, pidl);
780
781 if (!pidl)
782 return E_POINTER;
783
784 *pidl = ILClone(pidlRoot);
785 return S_OK;
786 }