[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_LEFT, 15},
62 {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 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 static const DWORD dwComputerAttributes =
70 SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
71 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
72 static const DWORD dwControlPanelAttributes =
73 SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
74 static const DWORD dwDriveAttributes =
75 SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
76 SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK;
77
78 CDrivesFolderEnum::CDrivesFolderEnum()
79 {
80 }
81
82 CDrivesFolderEnum::~CDrivesFolderEnum()
83 {
84 }
85
86 HRESULT WINAPI CDrivesFolderEnum::Initialize(HWND hwndOwner, DWORD dwFlags)
87 {
88 if (CreateMyCompEnumList(dwFlags) == FALSE)
89 return E_FAIL;
90
91 return S_OK;
92 }
93
94 /**************************************************************************
95 * CDrivesFolderEnum::CreateMyCompEnumList()
96 */
97
98 BOOL CDrivesFolderEnum::CreateMyCompEnumList(DWORD dwFlags)
99 {
100 BOOL bRet = TRUE;
101 static const WCHAR MyComputer_NameSpaceW[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace";
102
103 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
104
105 /* enumerate the folders */
106 if (dwFlags & SHCONTF_FOLDERS)
107 {
108 WCHAR wszDriveName[] = {'A', ':', '\\', '\0'};
109 DWORD dwDrivemap = GetLogicalDrives();
110 HKEY hKey;
111 UINT i;
112
113 while (bRet && wszDriveName[0] <= 'Z')
114 {
115 if(dwDrivemap & 0x00000001L)
116 bRet = AddToEnumList(_ILCreateDrive(wszDriveName));
117 wszDriveName[0]++;
118 dwDrivemap = dwDrivemap >> 1;
119 }
120
121 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n", this);
122 for (i = 0; i < 2; i++)
123 {
124 if (bRet && ERROR_SUCCESS == RegOpenKeyExW(i == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
125 MyComputer_NameSpaceW, 0, KEY_READ, &hKey))
126 {
127 WCHAR wszBuf[50];
128 DWORD dwSize, j = 0;
129 LONG ErrorCode;
130 LPITEMIDLIST pidl;
131
132 while (bRet)
133 {
134 dwSize = sizeof(wszBuf) / sizeof(wszBuf[0]);
135 ErrorCode = RegEnumKeyExW(hKey, j, wszBuf, &dwSize, 0, NULL, NULL, NULL);
136 if (ERROR_SUCCESS == ErrorCode)
137 {
138 if (wszBuf[0] != L'{')
139 {
140 dwSize = sizeof(wszBuf);
141 RegGetValueW(hKey, wszBuf, NULL, RRF_RT_REG_SZ, NULL, wszBuf, &dwSize);
142 }
143
144 /* FIXME: shell extensions - the type should be PT_SHELLEXT (tested) */
145 pidl = _ILCreateGuidFromStrW(wszBuf);
146 if (pidl != NULL)
147 bRet = AddToEnumList(pidl);
148 else
149 ERR("Invalid MyComputer namespace extesion: %s\n", wszBuf);
150 j++;
151 }
152 else if (ERROR_NO_MORE_ITEMS == ErrorCode)
153 break;
154 else
155 bRet = FALSE;
156 }
157 RegCloseKey(hKey);
158 }
159 }
160 }
161 return bRet;
162 }
163
164 CDrivesFolder::CDrivesFolder()
165 {
166 pidlRoot = NULL;
167 }
168
169 CDrivesFolder::~CDrivesFolder()
170 {
171 TRACE ("-- destroying IShellFolder(%p)\n", this);
172 SHFree(pidlRoot);
173 }
174
175 HRESULT WINAPI CDrivesFolder::FinalConstruct()
176 {
177 pidlRoot = _ILCreateMyComputer(); /* my qualified pidl */
178 if (pidlRoot == NULL)
179 return E_OUTOFMEMORY;
180
181 return S_OK;
182 }
183
184 /**************************************************************************
185 * CDrivesFolder::ParseDisplayName
186 */
187 HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
188 DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes)
189 {
190 HRESULT hr = E_INVALIDARG;
191 LPCWSTR szNext = NULL;
192 LPITEMIDLIST pidlTemp = NULL;
193
194 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
195 hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
196 pchEaten, ppidl, pdwAttributes);
197
198 *ppidl = 0;
199 if (pchEaten)
200 *pchEaten = 0; /* strange but like the original */
201
202 /* handle CLSID paths */
203 if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
204 return SH_ParseGuidDisplayName(this, hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
205
206 if (PathGetDriveNumberW(lpszDisplayName) < 0)
207 return E_INVALIDARG;
208
209 pidlTemp = _ILCreateDrive(lpszDisplayName);
210 if (!pidlTemp)
211 return E_OUTOFMEMORY;
212
213 if (lpszDisplayName[2] == L'\\')
214 {
215 szNext = &lpszDisplayName[3];
216 }
217
218 if (szNext && *szNext)
219 {
220 hr = SHELL32_ParseNextElement (this, hwndOwner, pbc, &pidlTemp,
221 (LPOLESTR) szNext, pchEaten, pdwAttributes);
222 }
223 else
224 {
225 hr = S_OK;
226 if (pdwAttributes && *pdwAttributes)
227 {
228 if (_ILIsDrive(pidlTemp))
229 *pdwAttributes &= dwDriveAttributes;
230 else if (_ILIsSpecialFolder(pidlTemp))
231 SHELL32_GetGuidItemAttributes(this, pidlTemp, pdwAttributes);
232 else
233 ERR("Got an unkown pidl here!\n");
234 }
235 }
236
237 *ppidl = pidlTemp;
238
239 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
240
241 return hr;
242 }
243
244 /**************************************************************************
245 * CDrivesFolder::EnumObjects
246 */
247 HRESULT WINAPI CDrivesFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
248 {
249 return ShellObjectCreatorInit<CDrivesFolderEnum>(hwndOwner, dwFlags, IID_IEnumIDList, ppEnumIDList);
250 }
251
252 /**************************************************************************
253 * CDrivesFolder::BindToObject
254 */
255 HRESULT WINAPI CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
256 {
257 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
258 pidl, pbcReserved, shdebugstr_guid(&riid), ppvOut);
259
260 if (_ILIsSpecialFolder(pidl))
261 return SHELL32_BindToGuidItem(pidlRoot, pidl, pbcReserved, riid, ppvOut);
262
263 return SHELL32_BindToFS(pidlRoot, NULL, pidl, riid, ppvOut);
264 }
265
266 /**************************************************************************
267 * CDrivesFolder::BindToStorage
268 */
269 HRESULT WINAPI CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
270 {
271 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
272 pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
273
274 *ppvOut = NULL;
275 return E_NOTIMPL;
276 }
277
278 /**************************************************************************
279 * CDrivesFolder::CompareIDs
280 */
281
282 HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
283 {
284 if (!pidl1 || !pidl2)
285 {
286 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam, pidl1, pidl2);
287 return E_INVALIDARG;
288 }
289
290 if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
291 return SHELL32_CompareGuidItems(this, lParam, pidl1, pidl2);
292
293 if (!_ILIsDrive(pidl1) || !_ILIsDrive(pidl2) || LOWORD(lParam) >= MYCOMPUTERSHELLVIEWCOLUMNS)
294 return E_INVALIDARG;
295
296 CHAR* pszDrive1 = _ILGetDataPointer(pidl1)->u.drive.szDriveName;
297 CHAR* pszDrive2 = _ILGetDataPointer(pidl2)->u.drive.szDriveName;
298
299 int result;
300 switch(LOWORD(lParam))
301 {
302 case 0: /* name */
303 {
304 result = stricmp(pszDrive1, pszDrive2);
305 return MAKE_COMPARE_HRESULT(result);
306 }
307 case 1: /* Type */
308 {
309 return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
310 }
311 case 2: /* Size */
312 case 3: /* Size Available */
313 {
314 ULARGE_INTEGER Drive1Available, Drive1Total, Drive2Available, Drive2Total;
315
316 if (GetVolumeInformationA(pszDrive1, NULL, 0, NULL, NULL, NULL, NULL, 0))
317 GetDiskFreeSpaceExA(pszDrive1, &Drive1Available, &Drive1Total, NULL);
318 else
319 Drive1Available.QuadPart = Drive1Total.QuadPart = 0;
320
321 if (GetVolumeInformationA(pszDrive2, NULL, 0, NULL, NULL, NULL, NULL, 0))
322 GetDiskFreeSpaceExA(pszDrive2, &Drive2Available, &Drive2Total, NULL);
323 else
324 Drive2Available.QuadPart = Drive2Total.QuadPart = 0;
325
326 LARGE_INTEGER Diff;
327 if (lParam == 2) /* Size */
328 Diff.QuadPart = Drive1Total.QuadPart - Drive2Total.QuadPart;
329 else /* Size available */
330 Diff.QuadPart = Drive1Available.QuadPart - Drive2Available.QuadPart;
331
332 return MAKE_COMPARE_HRESULT(Diff.QuadPart);
333 }
334 }
335 return E_INVALIDARG;
336 }
337
338 /**************************************************************************
339 * CDrivesFolder::CreateViewObject
340 */
341 HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
342 {
343 CComPtr<IShellView> pShellView;
344 HRESULT hr = E_INVALIDARG;
345
346 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
347 hwndOwner, shdebugstr_guid (&riid), ppvOut);
348
349 if (!ppvOut)
350 return hr;
351
352 *ppvOut = NULL;
353
354 if (IsEqualIID(riid, IID_IDropTarget))
355 {
356 WARN("IDropTarget not implemented\n");
357 hr = E_NOTIMPL;
358 }
359 else if (IsEqualIID(riid, IID_IContextMenu))
360 {
361 WARN("IContextMenu not implemented\n");
362 hr = E_NOTIMPL;
363 }
364 else if (IsEqualIID(riid, IID_IShellView))
365 {
366 hr = CDefView_Constructor(this, riid, ppvOut);
367 }
368 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
369 return hr;
370 }
371
372 static BOOL _ILIsControlPanel(LPCITEMIDLIST pidl)
373 {
374 GUID *guid = _ILGetGUIDPointer(pidl);
375
376 TRACE("(%p)\n", pidl);
377
378 if (guid)
379 return IsEqualIID(*guid, CLSID_ControlPanel);
380 return FALSE;
381 }
382
383 /**************************************************************************
384 * CDrivesFolder::GetAttributesOf
385 */
386 HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
387 {
388 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
389 this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
390
391 if (cidl && !apidl)
392 return E_INVALIDARG;
393
394 if (*rgfInOut == 0)
395 *rgfInOut = ~0;
396
397 /* FIXME: always add SFGAO_CANLINK */
398 if(cidl == 0)
399 *rgfInOut &= dwComputerAttributes;
400 else
401 {
402 for (UINT i = 0; i < cidl; ++i)
403 {
404 if (_ILIsDrive(apidl[i]))
405 *rgfInOut &= dwDriveAttributes;
406 else if (_ILIsControlPanel(apidl[i]))
407 *rgfInOut &= dwControlPanelAttributes;
408 else if (_ILIsSpecialFolder(*apidl))
409 SHELL32_GetGuidItemAttributes(this, apidl[i], rgfInOut);
410 else
411 ERR("Got unknown pidl type!\n");
412 }
413 }
414
415 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
416 *rgfInOut &= ~SFGAO_VALIDATE;
417
418 TRACE ("-- result=0x%08x\n", *rgfInOut);
419 return S_OK;
420 }
421
422 /**************************************************************************
423 * CDrivesFolder::GetUIObjectOf
424 *
425 * PARAMETERS
426 * hwndOwner [in] Parent window for any output
427 * cidl [in] array size
428 * apidl [in] simple pidl array
429 * riid [in] Requested Interface
430 * prgfInOut [ ] reserved
431 * ppvObject [out] Resulting Interface
432 *
433 */
434 HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner,
435 UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
436 REFIID riid, UINT *prgfInOut, LPVOID *ppvOut)
437 {
438 LPITEMIDLIST pidl;
439 LPVOID pObj = NULL;
440 HRESULT hr = E_INVALIDARG;
441
442 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
443 hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
444
445 if (!ppvOut)
446 return hr;
447
448 *ppvOut = NULL;
449
450 if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
451 {
452 hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj);
453 }
454 else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
455 {
456 hr = IDataObject_Constructor (hwndOwner,
457 pidlRoot, apidl, cidl, (IDataObject **)&pObj);
458 }
459 else if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID (riid, IID_IExtractIconW)) && (cidl == 1))
460 {
461 hr = GenericExtractIcon_CreateInstance(this, apidl[0], riid, &pObj);
462 }
463 else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
464 {
465 IDropTarget * pDt = NULL;
466 hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
467 pObj = pDt;
468 }
469 else if ((IsEqualIID(riid, IID_IShellLinkW) ||
470 IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
471 {
472 pidl = ILCombine (pidlRoot, apidl[0]);
473 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*) &pObj);
474 SHFree (pidl);
475 }
476 else
477 hr = E_NOINTERFACE;
478
479 if (SUCCEEDED(hr) && !pObj)
480 hr = E_OUTOFMEMORY;
481
482 *ppvOut = pObj;
483 TRACE ("(%p)->hr=0x%08x\n", this, hr);
484 return hr;
485 }
486
487 /**************************************************************************
488 * CDrivesFolder::GetDisplayNameOf
489 */
490 HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
491 {
492 LPWSTR pszPath;
493 HRESULT hr = S_OK;
494
495 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
496 pdump (pidl);
497
498 if (!strRet)
499 return E_INVALIDARG;
500
501 if (!_ILIsPidlSimple (pidl))
502 {
503 return SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, strRet);
504 }
505 else if (!_ILIsDesktop(pidl) && _ILIsSpecialFolder(pidl))
506 {
507 return SHELL32_GetDisplayNameOfGUIDItem(this, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", pidl, dwFlags, strRet);
508 }
509 else if (pidl->mkid.cb && !_ILIsDrive(pidl))
510 {
511 ERR("Wrong pidl type\n");
512 return E_INVALIDARG;
513 }
514
515 pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
516 if (!pszPath)
517 return E_OUTOFMEMORY;
518
519 pszPath[0] = 0;
520
521 if (!pidl->mkid.cb)
522 {
523 /* parsing name like ::{...} */
524 pszPath[0] = ':';
525 pszPath[1] = ':';
526 SHELL32_GUIDToStringW(CLSID_MyComputer, &pszPath[2]);
527 }
528 else
529 {
530 _ILSimpleGetTextW(pidl, pszPath, MAX_PATH); /* append my own path */
531 /* long view "lw_name (C:)" */
532 if (!(dwFlags & SHGDN_FORPARSING))
533 {
534 WCHAR wszDrive[18] = {0};
535 DWORD dwVolumeSerialNumber, dwMaximumComponentLength, dwFileSystemFlags;
536 static const WCHAR wszOpenBracket[] = {' ', '(', 0};
537 static const WCHAR wszCloseBracket[] = {')', 0};
538
539 lstrcpynW(wszDrive, pszPath, 4);
540 pszPath[0] = L'\0';
541 GetVolumeInformationW(wszDrive, pszPath,
542 MAX_PATH - 7,
543 &dwVolumeSerialNumber,
544 &dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0);
545 pszPath[MAX_PATH-1] = L'\0';
546 if (!wcslen(pszPath))
547 {
548 UINT DriveType, ResourceId;
549 DriveType = GetDriveTypeW(wszDrive);
550 switch(DriveType)
551 {
552 case DRIVE_FIXED:
553 ResourceId = IDS_DRIVE_FIXED;
554 break;
555 case DRIVE_REMOTE:
556 ResourceId = IDS_DRIVE_NETWORK;
557 break;
558 case DRIVE_CDROM:
559 ResourceId = IDS_DRIVE_CDROM;
560 break;
561 default:
562 ResourceId = 0;
563 }
564 if (ResourceId)
565 {
566 dwFileSystemFlags = LoadStringW(shell32_hInstance, ResourceId, pszPath, MAX_PATH);
567 if (dwFileSystemFlags > MAX_PATH - 7)
568 pszPath[MAX_PATH-7] = L'\0';
569 }
570 }
571 wcscat (pszPath, wszOpenBracket);
572 wszDrive[2] = L'\0';
573 wcscat (pszPath, wszDrive);
574 wcscat (pszPath, wszCloseBracket);
575 }
576 }
577
578 if (SUCCEEDED(hr))
579 {
580 strRet->uType = STRRET_WSTR;
581 strRet->pOleStr = pszPath;
582 }
583 else
584 CoTaskMemFree(pszPath);
585
586 TRACE("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
587 return hr;
588 }
589
590 /**************************************************************************
591 * CDrivesFolder::SetNameOf
592 * Changes the name of a file object or subfolder, possibly changing its item
593 * identifier in the process.
594 *
595 * PARAMETERS
596 * hwndOwner [in] Owner window for output
597 * pidl [in] simple pidl of item to change
598 * lpszName [in] the items new display name
599 * dwFlags [in] SHGNO formatting flags
600 * ppidlOut [out] simple pidl returned
601 */
602 HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,
603 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
604 {
605 WCHAR szName[30];
606
607 if (_ILIsDrive(pidl))
608 {
609 if (_ILSimpleGetTextW(pidl, szName, _countof(szName)))
610 SetVolumeLabelW(szName, lpName);
611 if (pPidlOut)
612 *pPidlOut = _ILCreateDrive(szName);
613 return S_OK;
614 }
615
616 return SHELL32_SetNameOfGuidItem(pidl, lpName, dwFlags, pPidlOut);
617 }
618
619 HRESULT WINAPI CDrivesFolder::GetDefaultSearchGUID(GUID * pguid)
620 {
621 FIXME ("(%p)\n", this);
622 return E_NOTIMPL;
623 }
624
625 HRESULT WINAPI CDrivesFolder::EnumSearches(IEnumExtraSearch ** ppenum)
626 {
627 FIXME ("(%p)\n", this);
628 return E_NOTIMPL;
629 }
630
631 HRESULT WINAPI CDrivesFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
632 {
633 TRACE ("(%p)\n", this);
634
635 if (pSort)
636 *pSort = 0;
637 if (pDisplay)
638 *pDisplay = 0;
639 return S_OK;
640 }
641
642 HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
643 {
644 TRACE ("(%p)\n", this);
645
646 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
647 return E_INVALIDARG;
648 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
649 return S_OK;
650 }
651
652 HRESULT WINAPI CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
653 {
654 FIXME ("(%p)\n", this);
655 return E_NOTIMPL;
656 }
657
658 /* FIXME: drive size >4GB is rolling over */
659 HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
660 {
661 HRESULT hr;
662
663 TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
664
665 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
666 return E_INVALIDARG;
667
668 if (!pidl)
669 {
670 psd->fmt = MyComputerSFHeader[iColumn].fmt;
671 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
672 return SHSetStrRet(&psd->str, MyComputerSFHeader[iColumn].colnameid);
673 }
674 else if (_ILIsSpecialFolder(pidl))
675 {
676 return SHELL32_GetDetailsOfGuidItem(this, pidl, iColumn, psd);
677 }
678 else
679 {
680 char szPath[MAX_PATH];
681 ULARGE_INTEGER ulBytes;
682
683 psd->str.cStr[0] = 0x00;
684 psd->str.uType = STRRET_CSTR;
685 switch (iColumn)
686 {
687 case 0: /* name */
688 hr = GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
689 break;
690 case 1: /* type */
691 _ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
692 break;
693 case 2: /* total size */
694 _ILSimpleGetText (pidl, szPath, MAX_PATH);
695 if (GetVolumeInformationA(szPath, NULL, 0, NULL, NULL, NULL, NULL, 0))
696 {
697 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
698 StrFormatByteSize64A(ulBytes.QuadPart, psd->str.cStr, MAX_PATH);
699 }
700 break;
701 case 3: /* free size */
702 _ILSimpleGetText (pidl, szPath, MAX_PATH);
703 if (GetVolumeInformationA(szPath, NULL, 0, NULL, NULL, NULL, NULL, 0))
704 {
705 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
706 StrFormatByteSize64A(ulBytes.QuadPart, psd->str.cStr, MAX_PATH);
707 }
708 break;
709 }
710 hr = S_OK;
711 }
712
713 return hr;
714 }
715
716 HRESULT WINAPI CDrivesFolder::MapColumnToSCID(UINT column, SHCOLUMNID * pscid)
717 {
718 FIXME("(%p)\n", this);
719 return E_NOTIMPL;
720 }
721
722 /************************************************************************
723 * CDrivesFolder::GetClassID
724 */
725 HRESULT WINAPI CDrivesFolder::GetClassID(CLSID *lpClassId)
726 {
727 TRACE ("(%p)\n", this);
728
729 if (!lpClassId)
730 return E_POINTER;
731
732 *lpClassId = CLSID_MyComputer;
733 return S_OK;
734 }
735
736 /************************************************************************
737 * CDrivesFolder::Initialize
738 *
739 * NOTES: it makes no sense to change the pidl
740 */
741 HRESULT WINAPI CDrivesFolder::Initialize(LPCITEMIDLIST pidl)
742 {
743 TRACE ("(%p)->(%p)\n", this, pidl);
744
745 if (pidlRoot)
746 SHFree((LPVOID)pidlRoot);
747
748 pidlRoot = ILClone(pidl);
749 return S_OK;
750 }
751
752 /**************************************************************************
753 * CDrivesFolder::GetCurFolder
754 */
755 HRESULT WINAPI CDrivesFolder::GetCurFolder(LPITEMIDLIST *pidl)
756 {
757 TRACE("(%p)->(%p)\n", this, pidl);
758
759 if (!pidl)
760 return E_POINTER;
761
762 *pidl = ILClone(pidlRoot);
763 return S_OK;
764 }