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