2 * UNIXFS - Shell namespace extension for the unix filesystem
4 * Copyright (C) 2005 Michael Jung
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
35 #include "shell32_main.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41 const GUID CLSID_UnixFolder = {0xcc702eb2, 0x7dc5, 0x11d9, {0xc6, 0x87, 0x00, 0x04, 0x23, 0x8a, 0x01, 0xcd}};
43 #define ADJUST_THIS(c,m,p) ((c*)(((long)p)-(long)&(((c*)0)->lp##m##Vtbl)))
44 #define STATIC_CAST(i,p) ((i*)&p->lp##i##Vtbl)
46 /******************************************************************************
47 * UNIXFS_path_to_pidl [Internal]
50 * path [I] An absolute unix path
51 * ppidl [O] The corresponding ITEMIDLIST. Release with SHFree/ILFree
55 * Failure: FALSE, invalid params, path not absolute or out of memory
58 * 'path' has to be an absolute unix filesystem path starting and
59 * ending with a slash ('/'). Currently, only directories (no files)
62 static BOOL UNIXFS_path_to_pidl(char *path, LPITEMIDLIST *ppidl) {
64 int cSubDirs, cPidlLen;
65 char *pSlash, *pSubDir;
67 TRACE("path=%s, ppidl=%p", debugstr_a(path), ppidl);
69 /* Fail, if no absolute path given */
70 if (!ppidl || !path || path[0] != '/') return FALSE;
72 /* Count the number of sub-directories in the path */
74 pSlash = strchr(path, '/');
77 pSlash = strchr(pSlash+1, '/');
80 /* Allocate enough memory to hold the path */
81 cPidlLen = strlen(path) + cSubDirs * sizeof(USHORT) + sizeof(USHORT);
82 *ppidl = pidl = (LPITEMIDLIST)SHAlloc(cPidlLen);
83 if (!pidl) return FALSE;
85 /* Start with a SHITEMID for the root directory */
87 pidl->mkid.abID[0] = '/';
88 pidl = ILGetNext(pidl);
90 /* Append SHITEMIDs for the sub-directories */
92 pSlash = strchr(pSubDir, '/');
94 pidl->mkid.cb = (USHORT)(pSlash+3-pSubDir);
95 memcpy(pidl->mkid.abID, pSubDir, pidl->mkid.cb);
97 pSlash = strchr(pSubDir, '/');
98 pidl = ILGetNext(pidl);
100 pidl->mkid.cb = 0; /* Terminate the ITEMIDLIST */
102 /* Path doesn't end with a '/' */
104 WARN("Path '%s' not in canonical form.\n", path);
109 /******************************************************************************
110 * UNIXFS_pidl_to_path [Internal]
112 * Construct the unix path that corresponds to a fully qualified ITEMIDLIST
115 * pidl [I] ITEMIDLIST that specifies the absolute location of the folder
116 * path [O] The corresponding unix path as a zero terminated ascii string
120 * Failure: FALSE, pidl doesn't specify a unix path or out of memory
122 static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
123 LPCITEMIDLIST current = pidl, root;
127 TRACE("(pidl=%p, path=%p)\n", pidl, path);
131 /* Find the UnixFolderClass root */
132 while (current->mkid.cb) {
133 if (current->mkid.cb < sizeof(GUID)+4) return FALSE;
134 if (IsEqualIID(&CLSID_UnixFolder, ¤t->mkid.abID[2])) break;
135 current = ILGetNext(current);
137 if (!current->mkid.cb) return FALSE;
138 root = ILGetNext(current);
140 /* Determine the path's length bytes */
141 dwPathLen = 1; /* For the terminating '\0' */
143 while (current->mkid.cb) {
144 dwPathLen += current->mkid.cb - sizeof(USHORT);
145 current = ILGetNext(current);
149 *path = pNextDir = SHAlloc(dwPathLen);
151 WARN("SHAlloc failed!\n");
155 while (current->mkid.cb) {
156 memcpy(pNextDir, current->mkid.abID, current->mkid.cb - sizeof(USHORT));
157 pNextDir += current->mkid.cb - sizeof(USHORT);
158 current = ILGetNext(current);
162 TRACE("resulting path: %s\n", *path);
166 /******************************************************************************
167 * UNIXFS_build_subfolder_pidls [Internal]
169 * Builds an array of subfolder PIDLs relative to a unix directory
172 * path [I] Name of a unix directory as a zero terminated ascii string
173 * apidl [O] The array of PIDLs
174 * pCount [O] Size of apidl
178 * Failure: FALSE, path is not a valid unix directory or out of memory
181 * The array of PIDLs and each PIDL are allocated with SHAlloc. You'll have
182 * to release each PIDL as well as the array itself with SHFree.
184 static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl, DWORD *pCount)
187 struct dirent *pSubDir;
191 TRACE("(path=%s, apidl=%p, pCount=%p)\n", path, apidl, pCount);
196 /* Special case for 'My UNIX Filesystem' shell folder:
197 * The unix root directory is the only child of 'My UNIX Filesystem'.
202 pid = (LPSHITEMID)SHAlloc(1 + 2 * sizeof(USHORT));
205 memset(((PBYTE)pid)+pid->cb, 0, sizeof(USHORT));
207 *apidl = SHAlloc(sizeof(LPITEMIDLIST));
208 (*apidl)[0] = (LPITEMIDLIST)pid;
216 WARN("Failed to open directory '%s'.\n", path);
220 /* Count number of sub directories.
222 for (cSubDirs = 0, pSubDir = readdir(dir); pSubDir; pSubDir = readdir(dir)) {
223 if (strcmp(pSubDir->d_name, ".") &&
224 strcmp(pSubDir->d_name, "..") &&
225 pSubDir->d_type == DT_DIR)
231 /* If there are no subdirectories, we are done. */
237 /* Allocate the array of PIDLs */
238 *apidl = SHAlloc(cSubDirs * sizeof(LPITEMIDLIST));
240 WARN("SHAlloc failed!\n");
244 /* Allocate and initialize one SHITEMID per sub-directory. */
245 for (rewinddir(dir), pSubDir = readdir(dir), i = 0; pSubDir; pSubDir = readdir(dir)) {
248 if (!strcmp(pSubDir->d_name, ".") ||
249 !strcmp(pSubDir->d_name, "..") ||
250 pSubDir->d_type != DT_DIR)
255 sLen = strlen(pSubDir->d_name)+1; /* For the trailing '/' */
256 pid = (LPSHITEMID)SHAlloc(sLen + 2 * sizeof(USHORT));
258 WARN("SHAlloc failed!\n");
262 pid->cb = (USHORT)(sLen + sizeof(USHORT));
263 memcpy(pid->abID, pSubDir->d_name, sLen-1);
264 pid->abID[sLen-1] = '/';
265 memset(((PBYTE)pid)+pid->cb, 0, sizeof(USHORT));
267 (*apidl)[i++] = (LPITEMIDLIST)pid;
276 /******************************************************************************
279 * Singleton class, which is used by the shell to extract icons to represent
280 * folders in tree- and listviews. Currently, all this singleton does is to
281 * provide the shell with the absolute path to "shell32.dll" and with the
282 * indices of the closed and opened folder icons in the resources of this dll.
285 /* UnixFolderIcon object layout and typedef.
287 typedef struct _UnixFolderIcon {
288 const IExtractIconWVtbl *lpIExtractIconWVtbl;
291 static HRESULT WINAPI UnixFolderIcon_IExtractIconW_QueryInterface(IExtractIconW *iface, REFIID riid,
294 TRACE("(iface=%p, riid=%p, ppv=%p)\n", iface, riid, ppv);
296 if (!ppv) return E_INVALIDARG;
298 if (IsEqualIID(&IID_IUnknown, riid) ||
299 IsEqualIID(&IID_IExtractIconW, riid))
304 return E_NOINTERFACE;
307 IExtractIconW_AddRef(iface);
311 static ULONG WINAPI UnixFolderIcon_IExtractIconW_AddRef(IExtractIconW *iface) {
312 TRACE("(iface=%p)\n", iface);
316 static ULONG WINAPI UnixFolderIcon_IExtractIconW_Release(IExtractIconW *iface) {
317 TRACE("(iface=%p)\n", iface);
321 static HRESULT WINAPI UnixFolderIcon_IExtractIconW_GetIconLocation(IExtractIconW *iface,
322 UINT uFlags, LPWSTR szIconFile, UINT cchMax, INT* piIndex, UINT* pwFlags)
324 TRACE("(iface=%p, uFlags=%u, szIconFile=%s, cchMax=%u, piIndex=%p, pwFlags=%p)\n",
325 iface, uFlags, debugstr_w(szIconFile), cchMax, piIndex, pwFlags);
327 lstrcpynW(szIconFile, swShell32Name, cchMax);
328 *piIndex = (uFlags & GIL_OPENICON) ? 4 : 3;
334 static HRESULT WINAPI UnixFolderIcon_IExtractIconW_Extract(
335 IExtractIconW *iface, LPCWSTR pszFile, UINT nIconIndex, HICON* phiconLarge, HICON* phiconSmall,
338 TRACE("(iface=%p, pszFile=%s, nIconIndex=%u, phiconLarge=%p, phiconSmall=%p, nIconSize=%u)"
339 "stub\n", iface, debugstr_w(pszFile), nIconIndex, phiconLarge, phiconSmall, nIconSize);
344 /* VTable for the IExtractIconW interface of the UnixFolderIcon class.
346 static const IExtractIconWVtbl UnixFolderIcon_IExtractIconW_Vtbl = {
347 UnixFolderIcon_IExtractIconW_QueryInterface,
348 UnixFolderIcon_IExtractIconW_AddRef,
349 UnixFolderIcon_IExtractIconW_Release,
350 UnixFolderIcon_IExtractIconW_GetIconLocation,
351 UnixFolderIcon_IExtractIconW_Extract
354 /* The singleton instance
356 UnixFolderIcon UnixFolderIconSingleton = { &UnixFolderIcon_IExtractIconW_Vtbl };
358 /******************************************************************************
361 * Class whose heap based instances represent unix filesystem directories.
364 static shvheader GenericSFHeader[] = {
365 {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
366 {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
367 {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
368 {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
369 {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
372 #define GENERICSHELLVIEWCOLUMNS 5
374 /* UnixFolder object layout and typedef.
376 typedef struct _UnixFolder {
377 const IShellFolder2Vtbl *lpIShellFolder2Vtbl;
378 const IPersistFolderVtbl *lpIPersistFolderVtbl;
381 LPITEMIDLIST m_pidlLocation;
382 LPITEMIDLIST *m_apidlSubDirs;
386 static void UnixFolder_Destroy(UnixFolder *pUnixFolder) {
389 TRACE("(pUnixFolder=%p)\n", pUnixFolder);
391 if (pUnixFolder->m_apidlSubDirs)
392 for (i=0; i < pUnixFolder->m_cSubDirs; i++)
393 SHFree(pUnixFolder->m_apidlSubDirs[i]);
394 SHFree(pUnixFolder->m_apidlSubDirs);
395 SHFree(pUnixFolder->m_pszPath);
396 ILFree(pUnixFolder->m_pidlLocation);
400 static HRESULT WINAPI UnixFolder_IShellFolder2_QueryInterface(IShellFolder2 *iface, REFIID riid,
403 UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
405 TRACE("(iface=%p, riid=%p, ppv=%p)\n", iface, riid, ppv);
407 if (!ppv) return E_INVALIDARG;
409 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IShellFolder, riid) ||
410 IsEqualIID(&IID_IShellFolder2, riid))
412 *ppv = &This->lpIShellFolder2Vtbl;
413 } else if (IsEqualIID(&IID_IPersistFolder, riid) || IsEqualIID(&IID_IPersist, riid)) {
414 *ppv = &This->lpIPersistFolderVtbl;
417 return E_NOINTERFACE;
420 IUnknown_AddRef((IUnknown*)*ppv);
424 static ULONG WINAPI UnixFolder_IShellFolder2_AddRef(IShellFolder2 *iface) {
425 UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
427 TRACE("(iface=%p)\n", iface);
429 return InterlockedIncrement(&This->m_cRef);
432 static ULONG WINAPI UnixFolder_IShellFolder2_Release(IShellFolder2 *iface) {
433 UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
436 TRACE("(iface=%p)\n", iface);
438 cRef = InterlockedDecrement(&This->m_cRef);
441 UnixFolder_Destroy(This);
446 static HRESULT WINAPI UnixFolder_IShellFolder2_ParseDisplayName(IShellFolder2* iface, HWND hwndOwner,
447 LPBC pbcReserved, LPOLESTR lpszDisplayName, ULONG* pchEaten, LPITEMIDLIST* ppidl,
448 ULONG* pdwAttributes)
454 TRACE("(iface=%p, hwndOwner=%p, pbcReserved=%p, lpszDisplayName=%s, pchEaten=%p, ppidl=%p, "
455 "pdwAttributes=%p) stub\n", iface, hwndOwner, pbcReserved, debugstr_w(lpszDisplayName),
456 pchEaten, ppidl, pdwAttributes);
458 cPathLen = lstrlenW(lpszDisplayName);
459 pszAnsiPath = (char*)SHAlloc(cPathLen+1);
460 WideCharToMultiByte(CP_ACP, 0, lpszDisplayName, -1, pszAnsiPath, cPathLen+1, NULL, NULL);
462 result = UNIXFS_path_to_pidl(pszAnsiPath, ppidl);
466 return result ? S_OK : E_FAIL;
469 static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder);
471 static HRESULT WINAPI UnixFolder_IShellFolder2_EnumObjects(IShellFolder2* iface, HWND hwndOwner,
472 SHCONTF grfFlags, IEnumIDList** ppEnumIDList)
474 UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
475 IUnknown *newIterator;
478 TRACE("(iface=%p, hwndOwner=%p, grfFlags=%08lx, ppEnumIDList=%p)\n",
479 iface, hwndOwner, grfFlags, ppEnumIDList);
481 newIterator = UnixSubFolderIterator_Construct(This);
482 hr = IUnknown_QueryInterface(newIterator, &IID_IEnumIDList, (void**)ppEnumIDList);
483 IUnknown_Release(newIterator);
488 static HRESULT WINAPI UnixFolder_IShellFolder2_BindToObject(IShellFolder2* iface, LPCITEMIDLIST pidl,
489 LPBC pbcReserved, REFIID riid, void** ppvOut)
491 UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
492 IPersistFolder *persistFolder;
493 LPITEMIDLIST pidlSubFolder;
496 TRACE("(iface=%p, pidl=%p, pbcReserver=%p, riid=%p, ppvOut=%p)\n",
497 iface, pidl, pbcReserved, riid, ppvOut);
499 hr = UnixFolder_Constructor(NULL, &IID_IPersistFolder, (void**)&persistFolder);
500 if (!SUCCEEDED(hr)) return hr;
501 hr = IPersistFolder_QueryInterface(persistFolder, riid, (void**)ppvOut);
503 pidlSubFolder = ILCombine(This->m_pidlLocation, pidl);
504 IPersistFolder_Initialize(persistFolder, pidlSubFolder);
505 IPersistFolder_Release(persistFolder);
506 ILFree(pidlSubFolder);
511 static HRESULT WINAPI UnixFolder_IShellFolder2_BindToStorage(IShellFolder2* This, LPCITEMIDLIST pidl,
512 LPBC pbcReserved, REFIID riid, void** ppvObj)
518 static HRESULT WINAPI UnixFolder_IShellFolder2_CompareIDs(IShellFolder2* iface, LPARAM lParam,
519 LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
521 BOOL isEmpty1, isEmpty2;
523 LPITEMIDLIST firstpidl;
527 TRACE("(iface=%p, lParam=%ld, pidl1=%p, pidl2=%p)\n", iface, lParam, pidl1, pidl2);
529 isEmpty1 = !pidl1 || !pidl1->mkid.cb;
530 isEmpty2 = !pidl2 || !pidl2->mkid.cb;
532 if (isEmpty1 && isEmpty2)
533 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
535 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)-1);
537 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)1);
539 compare = CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE, pidl1->mkid.abID, pidl1->mkid.cb,
540 pidl2->mkid.abID, pidl2->mkid.cb);
541 if ((compare == CSTR_LESS_THAN) || (compare == CSTR_GREATER_THAN))
542 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)(compare == CSTR_LESS_THAN)?-1:1);
544 if (pidl1->mkid.cb < pidl2->mkid.cb)
545 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)-1);
546 else if (pidl1->mkid.cb > pidl2->mkid.cb)
547 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)1);
549 firstpidl = ILCloneFirst(pidl1);
550 pidl1 = ILGetNext(pidl1);
551 pidl2 = ILGetNext(pidl2);
553 hr = IShellFolder2_BindToObject(iface, firstpidl, NULL, &IID_IShellFolder, (LPVOID*)&psf);
555 hr = IShellFolder_CompareIDs(psf, lParam, pidl1, pidl2);
556 IShellFolder2_Release(psf);
563 static HRESULT WINAPI UnixFolder_IShellFolder2_CreateViewObject(IShellFolder2* iface, HWND hwndOwner,
564 REFIID riid, void** ppv)
566 HRESULT hr = E_INVALIDARG;
568 TRACE("(iface=%p, hwndOwner=%p, riid=%p, ppv=%p) stub\n", iface, hwndOwner, riid, ppv);
570 if (!ppv) return E_INVALIDARG;
573 if (IsEqualIID(&IID_IShellView, riid)) {
574 LPSHELLVIEW pShellView;
576 pShellView = IShellView_Constructor((IShellFolder*)iface);
578 hr = IShellView_QueryInterface(pShellView, riid, ppv);
579 IShellView_Release(pShellView);
586 static HRESULT WINAPI UnixFolder_IShellFolder2_GetAttributesOf(IShellFolder2* iface, UINT cidl,
587 LPCITEMIDLIST* apidl, SFGAOF* rgfInOut)
589 TRACE("(iface=%p, cidl=%u, apidl=%p, rgfInOut=%p) semi-stub\n", iface, cidl, apidl, rgfInOut);
591 *rgfInOut = *rgfInOut & (SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
596 static HRESULT WINAPI UnixFolder_IShellFolder2_GetUIObjectOf(IShellFolder2* iface, HWND hwndOwner,
597 UINT cidl, LPCITEMIDLIST* apidl, REFIID riid, UINT* prgfInOut, void** ppvOut)
599 UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
601 TRACE("(iface=%p, hwndOwner=%p, cidl=%d, apidl=%p, riid=%s, prgfInOut=%p, ppv=%p)\n",
602 iface, hwndOwner, cidl, apidl, debugstr_guid(riid), prgfInOut, ppvOut);
604 if (IsEqualIID(&IID_IContextMenu, riid)) {
605 *ppvOut = ISvItemCm_Constructor((IShellFolder*)iface, This->m_pidlLocation, apidl, cidl);
607 } else if (IsEqualIID(&IID_IDataObject, riid)) {
608 *ppvOut = IDataObject_Constructor(hwndOwner, This->m_pidlLocation, apidl, cidl);
610 } else if (IsEqualIID(&IID_IExtractIconA, riid)) {
611 FIXME("IExtractIconA\n");
613 } else if (IsEqualIID(&IID_IExtractIconW, riid)) {
614 *ppvOut = &UnixFolderIconSingleton;
616 } else if (IsEqualIID(&IID_IDropTarget, riid)) {
617 FIXME("IDropTarget\n");
619 } else if (IsEqualIID(&IID_IShellLinkW, riid)) {
620 FIXME("IShellLinkW\n");
622 } else if (IsEqualIID(&IID_IShellLinkA, riid)) {
623 FIXME("IShellLinkA\n");
626 FIXME("Unknown interface %s in GetUIObjectOf\n", debugstr_guid(riid));
627 return E_NOINTERFACE;
631 static HRESULT WINAPI UnixFolder_IShellFolder2_GetDisplayNameOf(IShellFolder2* iface,
632 LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET* lpName)
634 LPCSHITEMID pSHItem = (LPCSHITEMID)pidl;
635 char szName[MAX_PATH];
637 lpName->uType = STRRET_CSTR;
638 if (!pidl->mkid.cb) {
639 strcpy(lpName->u.cStr, "");
643 memcpy(szName, pSHItem->abID, pSHItem->cb-sizeof(USHORT));
644 szName[pSHItem->cb-sizeof(USHORT)] = '\0';
646 TRACE("(iface=%p, pidl=%p, uFlags=%lx, lpName=%p)\n", iface, pidl, uFlags, lpName);
648 if ((uFlags & SHGDN_FORPARSING) && !(uFlags & SHGDN_INFOLDER)) {
649 STRRET strSubfolderName;
650 IShellFolder *pSubFolder;
652 LPITEMIDLIST pidlFirst;
654 pidlFirst = ILCloneFirst(pidl);
656 WARN("ILCloneFirst failed!\n");
660 hr = IShellFolder_BindToObject(iface, pidlFirst, NULL, &IID_IShellFolder,
661 (void**)&pSubFolder);
662 if (!SUCCEEDED(hr)) {
663 WARN("BindToObject failed!\n");
670 hr = IShellFolder_GetDisplayNameOf(pSubFolder, ILGetNext(pidl), uFlags, &strSubfolderName);
671 if (!SUCCEEDED(hr)) {
672 WARN("GetDisplayNameOf failed!\n");
676 snprintf(lpName->u.cStr, MAX_PATH, "%s%s", szName, strSubfolderName.u.cStr);
678 IShellFolder_Release(pSubFolder);
681 strcpy(lpName->u.cStr, szName);
682 len = strlen(lpName->u.cStr);
683 if (len > 1) lpName->u.cStr[len-1] = '\0';
689 static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* This, HWND hwnd,
690 LPCITEMIDLIST pidl, LPCOLESTR lpszName, SHGDNF uFlags, LPITEMIDLIST* ppidlOut)
696 static HRESULT WINAPI UnixFolder_IShellFolder2_EnumSearches(IShellFolder2* iface,
697 IEnumExtraSearch **ppEnum)
703 static HRESULT WINAPI UnixFolder_IShellFolder2_GetDefaultColumn(IShellFolder2* iface,
704 DWORD dwReserved, ULONG *pSort, ULONG *pDisplay)
710 static HRESULT WINAPI UnixFolder_IShellFolder2_GetDefaultColumnState(IShellFolder2* iface,
711 UINT iColumn, SHCOLSTATEF *pcsFlags)
717 static HRESULT WINAPI UnixFolder_IShellFolder2_GetDefaultSearchGUID(IShellFolder2* iface,
724 static HRESULT WINAPI UnixFolder_IShellFolder2_GetDetailsEx(IShellFolder2* iface,
725 LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
731 static HRESULT WINAPI UnixFolder_IShellFolder2_GetDetailsOf(IShellFolder2* iface,
732 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
736 TRACE("(iface=%p, pidl=%p, iColumn=%d, psd=%p) stub\n", iface, pidl, iColumn, psd);
738 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS)
742 psd->fmt = GenericSFHeader[iColumn].fmt;
743 psd->cxChar = GenericSFHeader[iColumn].cxChar;
744 psd->str.uType = STRRET_CSTR;
745 LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
750 hr = IShellFolder2_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL|SHGDN_INFOLDER, &psd->str);
753 psd->str.uType = STRRET_CSTR;
759 static HRESULT WINAPI UnixFolder_IShellFolder2_MapColumnToSCID(IShellFolder2* iface, UINT iColumn,
766 /* VTable for UnixFolder's IShellFolder2 interface.
768 static const IShellFolder2Vtbl UnixFolder_IShellFolder2_Vtbl = {
769 UnixFolder_IShellFolder2_QueryInterface,
770 UnixFolder_IShellFolder2_AddRef,
771 UnixFolder_IShellFolder2_Release,
772 UnixFolder_IShellFolder2_ParseDisplayName,
773 UnixFolder_IShellFolder2_EnumObjects,
774 UnixFolder_IShellFolder2_BindToObject,
775 UnixFolder_IShellFolder2_BindToStorage,
776 UnixFolder_IShellFolder2_CompareIDs,
777 UnixFolder_IShellFolder2_CreateViewObject,
778 UnixFolder_IShellFolder2_GetAttributesOf,
779 UnixFolder_IShellFolder2_GetUIObjectOf,
780 UnixFolder_IShellFolder2_GetDisplayNameOf,
781 UnixFolder_IShellFolder2_SetNameOf,
782 UnixFolder_IShellFolder2_GetDefaultSearchGUID,
783 UnixFolder_IShellFolder2_EnumSearches,
784 UnixFolder_IShellFolder2_GetDefaultColumn,
785 UnixFolder_IShellFolder2_GetDefaultColumnState,
786 UnixFolder_IShellFolder2_GetDetailsEx,
787 UnixFolder_IShellFolder2_GetDetailsOf,
788 UnixFolder_IShellFolder2_MapColumnToSCID
791 static HRESULT WINAPI UnixFolder_IPersistFolder_QueryInterface(IPersistFolder* This, REFIID riid,
794 return UnixFolder_IShellFolder2_QueryInterface(
795 (IShellFolder2*)ADJUST_THIS(UnixFolder, IPersistFolder, This), riid, ppvObject);
798 static ULONG WINAPI UnixFolder_IPersistFolder_AddRef(IPersistFolder* This)
800 return UnixFolder_IShellFolder2_AddRef(
801 (IShellFolder2*)ADJUST_THIS(UnixFolder, IPersistFolder, This));
804 static ULONG WINAPI UnixFolder_IPersistFolder_Release(IPersistFolder* This)
806 return UnixFolder_IShellFolder2_Release(
807 (IShellFolder2*)ADJUST_THIS(UnixFolder, IPersistFolder, This));
810 static HRESULT WINAPI UnixFolder_IPersistFolder_GetClassID(IPersistFolder* This, CLSID* pClassID)
816 static HRESULT WINAPI UnixFolder_IPersistFolder_Initialize(IPersistFolder* iface, LPCITEMIDLIST pidl)
818 UnixFolder *This = ADJUST_THIS(UnixFolder, IPersistFolder, iface);
820 TRACE("(iface=%p, pidl=%p)\n", iface, pidl);
822 This->m_pidlLocation = ILClone(pidl);
823 UNIXFS_pidl_to_path(pidl, &This->m_pszPath);
824 UNIXFS_build_subfolder_pidls(This->m_pszPath, &This->m_apidlSubDirs, &This->m_cSubDirs);
829 /* VTable for UnixFolder's IPersistFolder interface.
831 static const IPersistFolderVtbl UnixFolder_IPersistFolder_Vtbl = {
832 UnixFolder_IPersistFolder_QueryInterface,
833 UnixFolder_IPersistFolder_AddRef,
834 UnixFolder_IPersistFolder_Release,
835 UnixFolder_IPersistFolder_GetClassID,
836 UnixFolder_IPersistFolder_Initialize
839 /******************************************************************************
840 * UnixFolder_Constructor [Internal]
843 * pUnkOuter [I] Outer class for aggregation. Currently ignored.
844 * riid [I] Interface asked for by the client.
845 * ppv [O] Pointer to an riid interface to the UnixFolder object.
848 * This is the only function exported from shfldr_unixfs.c. It's called from
849 * shellole.c's default class factory and thus has to exhibit a LPFNCREATEINSTANCE
850 * compatible signature.
852 HRESULT WINAPI UnixFolder_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) {
854 UnixFolder *pUnixFolder;
856 TRACE("(pUnkOuter=%p, riid=%p, ppv=%p)\n", pUnkOuter, riid, ppv);
858 pUnixFolder = SHAlloc((ULONG)sizeof(UnixFolder));
859 pUnixFolder->lpIShellFolder2Vtbl = &UnixFolder_IShellFolder2_Vtbl;
860 pUnixFolder->lpIPersistFolderVtbl = &UnixFolder_IPersistFolder_Vtbl;
861 pUnixFolder->m_cRef = 0;
862 pUnixFolder->m_pszPath = NULL;
863 pUnixFolder->m_apidlSubDirs = NULL;
864 pUnixFolder->m_cSubDirs = 0;
866 UnixFolder_IShellFolder2_AddRef(STATIC_CAST(IShellFolder2, pUnixFolder));
867 hr = UnixFolder_IShellFolder2_QueryInterface(STATIC_CAST(IShellFolder2, pUnixFolder), riid, ppv);
868 UnixFolder_IShellFolder2_Release(STATIC_CAST(IShellFolder2, pUnixFolder));
872 /******************************************************************************
873 * UnixSubFolderIterator
875 * Class whose heap based objects represent iterators over the sub-directories
876 * of a given UnixFolder object.
879 /* UnixSubFolderIterator object layout and typedef.
881 typedef struct _UnixSubFolderIterator {
882 const IEnumIDListVtbl *lpIEnumIDListVtbl;
884 UnixFolder *m_pUnixFolder;
886 } UnixSubFolderIterator;
888 static void UnixSubFolderIterator_Destroy(UnixSubFolderIterator *iterator) {
889 TRACE("(iterator=%p)\n", iterator);
891 UnixFolder_IShellFolder2_Release((IShellFolder2*)iterator->m_pUnixFolder);
895 static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_QueryInterface(IEnumIDList* iface,
896 REFIID riid, void** ppv)
898 TRACE("(iface=%p, riid=%p, ppv=%p)\n", iface, riid, ppv);
900 if (!ppv) return E_INVALIDARG;
902 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumIDList, riid)) {
906 return E_NOINTERFACE;
909 IEnumIDList_AddRef(iface);
913 static ULONG WINAPI UnixSubFolderIterator_IEnumIDList_AddRef(IEnumIDList* iface)
915 UnixSubFolderIterator *This = ADJUST_THIS(UnixSubFolderIterator, IEnumIDList, iface);
917 TRACE("(iface=%p)\n", iface);
919 return InterlockedIncrement(&This->m_cRef);
922 static ULONG WINAPI UnixSubFolderIterator_IEnumIDList_Release(IEnumIDList* iface)
924 UnixSubFolderIterator *This = ADJUST_THIS(UnixSubFolderIterator, IEnumIDList, iface);
927 TRACE("(iface=%p)\n", iface);
929 cRef = InterlockedDecrement(&This->m_cRef);
932 UnixSubFolderIterator_Destroy(This);
937 static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Next(IEnumIDList* iface, ULONG celt,
938 LPITEMIDLIST* rgelt, ULONG* pceltFetched)
940 UnixSubFolderIterator *This = ADJUST_THIS(UnixSubFolderIterator, IEnumIDList, iface);
943 TRACE("(iface=%p, celt=%ld, rgelt=%p, pceltFetched=%p)\n", iface, celt, rgelt, pceltFetched);
945 for (i=0; (i < celt) && (This->m_cIdx < This->m_pUnixFolder->m_cSubDirs); i++, This->m_cIdx++) {
946 rgelt[i] = ILClone(This->m_pUnixFolder->m_apidlSubDirs[This->m_cIdx]);
952 return i == celt ? S_OK : S_FALSE;
955 static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Skip(IEnumIDList* iface, ULONG celt)
957 UnixSubFolderIterator *This = ADJUST_THIS(UnixSubFolderIterator, IEnumIDList, iface);
959 TRACE("(iface=%p, celt=%ld)\n", iface, celt);
961 if (This->m_cIdx + celt > This->m_pUnixFolder->m_cSubDirs) {
962 This->m_cIdx = This->m_pUnixFolder->m_cSubDirs;
965 This->m_cIdx += celt;
970 static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Reset(IEnumIDList* iface)
972 UnixSubFolderIterator *This = ADJUST_THIS(UnixSubFolderIterator, IEnumIDList, iface);
974 TRACE("(iface=%p)\n", iface);
981 static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Clone(IEnumIDList* This,
982 IEnumIDList** ppenum)
988 /* VTable for UnixSubFolderIterator's IEnumIDList interface.
990 static const IEnumIDListVtbl UnixSubFolderIterator_IEnumIDList_Vtbl = {
991 UnixSubFolderIterator_IEnumIDList_QueryInterface,
992 UnixSubFolderIterator_IEnumIDList_AddRef,
993 UnixSubFolderIterator_IEnumIDList_Release,
994 UnixSubFolderIterator_IEnumIDList_Next,
995 UnixSubFolderIterator_IEnumIDList_Skip,
996 UnixSubFolderIterator_IEnumIDList_Reset,
997 UnixSubFolderIterator_IEnumIDList_Clone
1000 static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder) {
1001 UnixSubFolderIterator *iterator;
1003 TRACE("(pUnixFolder=%p)\n", pUnixFolder);
1005 iterator = SHAlloc((ULONG)sizeof(UnixSubFolderIterator));
1006 iterator->lpIEnumIDListVtbl = &UnixSubFolderIterator_IEnumIDList_Vtbl;
1007 iterator->m_cRef = 0;
1008 iterator->m_cIdx = 0;
1009 iterator->m_pUnixFolder = pUnixFolder;
1011 UnixSubFolderIterator_IEnumIDList_AddRef((IEnumIDList*)iterator);
1012 UnixFolder_IShellFolder2_AddRef((IShellFolder2*)pUnixFolder);
1014 return (IUnknown*)iterator;