Commit 3c3495ea authored by Michael Jung's avatar Michael Jung Committed by Alexandre Julliard

Add a new CLSID for UnixDosFolder, which is identical to UnixFolder,

but does unix <-> dos path conversion for GetDisplayNameOf and ParseDisplayName.
parent 8eb1a29a
......@@ -264,7 +264,8 @@ static HRESULT WINAPI IExtractIconW_fnGetIconLocation(
*piIndex = -IDI_SHELL_FOLDER;
else if(IsEqualGUID(riid, &CLSID_NetworkPlaces))
*piIndex = -IDI_SHELL_MY_NETWORK_PLACES;
else if(IsEqualGUID(riid, &CLSID_UnixFolder))
else if(IsEqualGUID(riid, &CLSID_UnixFolder) ||
IsEqualGUID(riid, &CLSID_UnixDosFolder))
*piIndex = -IDI_SHELL_DRIVE;
else
*piIndex = -IDI_SHELL_FOLDER;
......
......@@ -526,6 +526,13 @@ static struct regsvr_coclass const coclass_list[] = {
"Apartment",
SHELLFOLDER_WANTSFORPARSING
},
{ &CLSID_UnixDosFolder,
"/",
NULL,
"shell32.dll",
"Apartment",
SHELLFOLDER_WANTSFORPARSING
},
{ NULL } /* list terminator */
};
......
......@@ -93,6 +93,7 @@ HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid,
HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV);
HRESULT WINAPI IControlPanel_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI UnixFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI UnixDosFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppv);
extern HRESULT CPanel_GetIconLocationW(LPITEMIDLIST, LPWSTR, UINT, int*);
HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
......@@ -225,6 +226,7 @@ UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
extern WCHAR swShell32Name[MAX_PATH];
extern const GUID CLSID_UnixFolder;
extern const GUID CLSID_UnixDosFolder;
/* Default shell folder value registration */
HRESULT SHELL_RegisterShellFolders(void);
......
......@@ -72,6 +72,7 @@ struct {
{&CLSID_ControlPanel, &IControlPanel_Constructor},
{&CLSID_AutoComplete, &IAutoComplete_Constructor},
{&CLSID_UnixFolder, &UnixFolder_Constructor},
{&CLSID_UnixDosFolder, &UnixDosFolder_Constructor},
{NULL,NULL}
};
......
......@@ -23,6 +23,7 @@
#include <stdarg.h>
#include <limits.h>
#include <dirent.h>
#include <unistd.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
......@@ -52,6 +53,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell);
const GUID CLSID_UnixFolder = {0xcc702eb2, 0x7dc5, 0x11d9, {0xc6, 0x87, 0x00, 0x04, 0x23, 0x8a, 0x01, 0xcd}};
const GUID CLSID_UnixDosFolder = {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
#define ADJUST_THIS(c,m,p) ((c*)(((long)p)-(long)&(((c*)0)->lp##m##Vtbl)))
#define STATIC_CAST(i,p) ((i*)&p->lp##i##Vtbl)
......@@ -69,6 +71,9 @@ const GUID CLSID_UnixFolder = {0xcc702eb2, 0x7dc5, 0x11d9, {0xc6, 0x87, 0x00, 0x
(((LPSHITEMID)s)->cb-sizeof(USHORT)-sizeof(PIDLTYPE)-sizeof(FileStruct)-sizeof(char)-sizeof(StatStruct))
#define LPSTATSTRUCT_FROM_LPSHITEMID(s) ((StatStruct*)(((LPBYTE)s)+((LPSHITEMID)s)->cb-sizeof(StatStruct)))
#define PATHMODE_UNIX 0
#define PATHMODE_DOS 1
/* This structure is appended to shell32's FileStruct type in IDLs to store unix
* filesystem specific informationen extracted with the stat system call.
*/
......@@ -78,6 +83,19 @@ typedef struct tagStatStruct {
gid_t st_gid;
} StatStruct;
/* UnixFolder object layout and typedef.
*/
typedef struct _UnixFolder {
const IShellFolder2Vtbl *lpIShellFolder2Vtbl;
const IPersistFolder2Vtbl *lpIPersistFolder2Vtbl;
ULONG m_cRef;
CHAR *m_pszPath;
LPITEMIDLIST m_pidlLocation;
LPITEMIDLIST *m_apidlSubDirs;
DWORD m_cSubDirs;
DWORD m_dwPathMode;
} UnixFolder;
/******************************************************************************
* UNIXFS_is_pidl_of_type [INTERNAL]
*
......@@ -128,7 +146,7 @@ static char* UNIXFS_build_shitemid(char *name, struct stat *pStat, void *buffer)
int cNameLen;
char *pSlash;
TRACE("(name=%s, buffer=%p)\n", debugstr_a(name), buffer);
TRACE("(name=%s, pStat=%p, buffer=%p)\n", debugstr_a(name), pStat, buffer);
pSlash = strchr(name, '/');
cNameLen = pSlash ? pSlash - name : strlen(name);
......@@ -157,73 +175,222 @@ static char* UNIXFS_build_shitemid(char *name, struct stat *pStat, void *buffer)
}
/******************************************************************************
* UNIXFS_canonicalize_path [Internal]
*
* Evaluate "/.", "/.." and symbolic links for an absolute unix path.
*
* PARAMS
* pszUnixPath [I] An absolute unix path
* pszCanonicalPath [O] Buffer of length FILENAME_MAX. Will receive the canonical path.
*
* RETURNS
* Success, TRUE
* Failure, FALSE - Path not existent, too long, insufficient rights, to many symlinks
*/
static BOOL UNIXFS_canonicalize_path(const char *pszUnixPath, char *pszCanonicalPath)
{
char *pPathTail, *pElement, *pCanonicalTail, szPath[FILENAME_MAX];
struct stat fileStat;
TRACE("(pszUnixPath=%s, pszCanonicalPath=%p)\n", debugstr_a(pszUnixPath), pszCanonicalPath);
if (!pszUnixPath || *pszUnixPath != '/')
return FALSE;
strcpy(szPath, pszUnixPath);
/* pCanonicalTail always points to the end of the canonical path constructed
* thus far. pPathTail points to the still to be processed part of the input
* path. pElement points to the path element currently investigated.
*/
*pszCanonicalPath = '\0';
pCanonicalTail = pszCanonicalPath;
pPathTail = szPath;
do {
char cTemp;
int cLinks = 0;
pElement = pPathTail;
pPathTail = strchr(pPathTail+1, '/');
if (!pPathTail) /* Last path element may not be terminated by '/'. */
pPathTail = pElement + strlen(pElement);
/* Temporarily terminate the current path element. Will be restored later. */
cTemp = *pPathTail;
*pPathTail = '\0';
/* Skip "/." path elements */
if (!strcmp("/.", pElement)) {
*pPathTail = cTemp;
continue;
}
/* Remove last element in canonical path for "/.." elements, then skip. */
if (!strcmp("/..", pElement)) {
char *pTemp = strrchr(pszCanonicalPath, '/');
if (pTemp)
pCanonicalTail = pTemp;
*pCanonicalTail = '\0';
*pPathTail = cTemp;
continue;
}
/* lstat returns zero on success. */
if (lstat(szPath, &fileStat))
return FALSE;
if (S_ISLNK(fileStat.st_mode)) {
char szSymlink[FILENAME_MAX];
int cLinkLen, cTailLen;
/* Avoid infinite loop for recursive links. */
if (++cLinks > 64)
return FALSE;
cLinkLen = readlink(szPath, szSymlink, FILENAME_MAX);
if (cLinkLen < 0)
return FALSE;
*pPathTail = cTemp;
cTailLen = strlen(pPathTail);
if (szSymlink[0] == '/') {
/* Absolute link. Copy to szPath, concat remaining path and start all over. */
if (cLinkLen + cTailLen + 1 > FILENAME_MAX)
return FALSE;
memcpy(szSymlink + cLinkLen, pPathTail, cTailLen + 1);
memcpy(szPath, szSymlink, cLinkLen + cTailLen + 1);
*pszCanonicalPath = '\0';
pCanonicalTail = pszCanonicalPath;
pPathTail = szPath;
} else {
/* Relative link. Expand into szPath and continue. */
char szTemp[FILENAME_MAX];
int cTailLen = strlen(pPathTail);
if (pElement - szPath + 1 + cLinkLen + cTailLen + 1 > FILENAME_MAX)
return FALSE;
memcpy(szTemp, pPathTail, cTailLen + 1);
memcpy(pElement + 1, szSymlink, cLinkLen);
memcpy(pElement + 1 + cLinkLen, szTemp, cTailLen + 1);
pPathTail = pElement;
}
} else {
/* Regular directory or file. Copy to canonical path */
if (pCanonicalTail - pszCanonicalPath + pPathTail - pElement + 1 > FILENAME_MAX)
return FALSE;
memcpy(pCanonicalTail, pElement, pPathTail - pElement + 1);
pCanonicalTail += pPathTail - pElement;
*pPathTail = cTemp;
}
} while (pPathTail[0] == '/' && pPathTail[1]); /* Also handles paths terminated by '/' */
TRACE("--> %s\n", debugstr_a(pszCanonicalPath));
return TRUE;
}
/******************************************************************************
* UNIXFS_path_to_pidl [Internal]
*
* PARAMS
* base [I] Path prefix. May be NULL if "path" parameter is absolute
* path [I] An absolute unix path or a path relativ to "base"
* ppidl [O] The corresponding ITEMIDLIST. Release with SHFree/ILFree
* pUnixFolder [I] If path is relative, pUnixFolder represents the base path
* path [I] An absolute unix or dos path or a path relativ to pUnixFolder
* ppidl [O] The corresponding ITEMIDLIST. Release with SHFree/ILFree
*
* RETURNS
* Success: TRUE
* Failure: FALSE, invalid params or out of memory
*
* NOTES
* pUnixFolder also carries the information if the path is expected to be unix or dos.
*/
static BOOL UNIXFS_path_to_pidl(const char *base, const char *path, LPITEMIDLIST *ppidl) {
static BOOL UNIXFS_path_to_pidl(UnixFolder *pUnixFolder, const WCHAR *path, LPITEMIDLIST *ppidl) {
LPITEMIDLIST pidl;
struct stat fileStat;
int cSubDirs, cPidlLen, res;
char *pSlash, *pCompletePath, *pNextPathElement;
int cSubDirs, cPidlLen, res, cPathLen;
char *pSlash, szCompletePath[FILENAME_MAX], *pNextPathElement;
TRACE("pUnixFolder=%p, path=%s, ppidl=%p\n", pUnixFolder, debugstr_w(path), ppidl);
if (!ppidl || !path)
return FALSE;
TRACE("path=%s, ppidl=%p\n", debugstr_a(path), ppidl);
cPathLen = lstrlenW(path);
/* Fail, if base + path is not an absolute path */
if (!ppidl || !path || (path[0] != '/' && (!base || base[0] != '/'))) return FALSE;
/* Build an absolute path and let pNextPathElement point to the interesting relativ path. */
if (path[0] != '/') {
pCompletePath = SHAlloc(strlen(base)+strlen(path)+1);
if (!pCompletePath) return FALSE;
sprintf(pCompletePath, "%s%s", base, path);
pNextPathElement = pCompletePath + strlen(base);
} else {
pCompletePath = SHAlloc(strlen(path)+1);
if (!pCompletePath) return FALSE;
memcpy(pCompletePath, path, strlen(path)+1);
pNextPathElement = pCompletePath + 1;
/* Build an absolute path and let pNextPathElement point to the interesting
* relative sub-path. We need the absolute path to call 'stat', but the pidl
* will only contain the relative part.
*/
if ((pUnixFolder->m_dwPathMode == PATHMODE_DOS) && (path[1] == ':'))
{
/* Absolute dos path. Convert to unix */
char *pszUnixPath = wine_get_unix_file_name(path);
if (!UNIXFS_canonicalize_path(pszUnixPath, szCompletePath)) {
HeapFree(GetProcessHeap(), 0, pszUnixPath);
return FALSE;
}
HeapFree(GetProcessHeap(), 0, pszUnixPath);
pNextPathElement = szCompletePath + 1;
}
else if ((pUnixFolder->m_dwPathMode == PATHMODE_UNIX) && (path[0] == '/'))
{
/* Absolute unix path. Just convert to ANSI. */
WideCharToMultiByte(CP_ACP, 0, path, -1, szCompletePath, FILENAME_MAX, NULL, NULL);
pNextPathElement = szCompletePath + 1;
}
else
{
/* Relative dos or unix path. Concat with this folder's path */
int cBasePathLen = strlen(pUnixFolder->m_pszPath);
memcpy(szCompletePath, pUnixFolder->m_pszPath, cBasePathLen);
WideCharToMultiByte(CP_ACP, 0, path, -1, szCompletePath + cBasePathLen,
FILENAME_MAX - cBasePathLen, NULL, NULL);
pNextPathElement = szCompletePath + cBasePathLen;
/* If in dos mode, replace '\' with '/' */
if (pUnixFolder->m_dwPathMode == PATHMODE_DOS) {
char *pBackslash = strchr(pNextPathElement, '\\');
while (pBackslash) {
*pBackslash = '/';
pBackslash = strchr(pBackslash, '\\');
}
}
}
/* At this point, we have an absolute unix path in szCompletePath. */
TRACE("complete path: %s\n", szCompletePath);
/* Count the number of sub-directories in the path */
cSubDirs = 1; /* Path may not be terminated with '/', thus start with 1 */
pSlash = strchr(pNextPathElement, '/');
while (pSlash) {
while (pSlash && pSlash[1]) {
cSubDirs++;
pSlash = strchr(pSlash+1, '/');
}
/* Allocate enough memory to hold the path. The -cSubDirs is for the '/'
* characters, which are not stored in the ITEMIDLIST. */
cPidlLen = strlen(pCompletePath) - cSubDirs + cSubDirs * SHITEMID_LEN_FROM_NAME_LEN(0) + sizeof(USHORT);
cPidlLen = strlen(pNextPathElement) - cSubDirs + 1 + cSubDirs * SHITEMID_LEN_FROM_NAME_LEN(0) + sizeof(USHORT);
*ppidl = pidl = (LPITEMIDLIST)SHAlloc(cPidlLen);
if (!pidl) {
SHFree(pCompletePath);
return FALSE;
}
if (!pidl) return FALSE;
/* Concatenate the SHITEMIDs of the sub-directories. */
while (*pNextPathElement) {
pSlash = strchr(pNextPathElement, '/');
if (pSlash) {
*pSlash = '\0';
res = stat(pCompletePath, &fileStat);
res = stat(szCompletePath, &fileStat);
*pSlash = '/';
if (res) {
SHFree(pCompletePath);
SHFree(pidl);
return FALSE;
}
} else {
if (stat(pCompletePath, &fileStat)) {
SHFree(pCompletePath);
if (stat(szCompletePath, &fileStat)) {
SHFree(pidl);
return FALSE;
}
......@@ -233,8 +400,10 @@ static BOOL UNIXFS_path_to_pidl(const char *base, const char *path, LPITEMIDLIST
pidl = ILGetNext(pidl);
}
pidl->mkid.cb = 0; /* Terminate the ITEMIDLIST */
SHFree(pCompletePath);
if ((int)pidl-(int)*ppidl+sizeof(USHORT) > cPidlLen) /* We've corrupted the heap :( */
ERR("Computed length of pidl to small. Please report.\n");
return TRUE;
}
......@@ -251,20 +420,25 @@ static BOOL UNIXFS_path_to_pidl(const char *base, const char *path, LPITEMIDLIST
* Success: TRUE
* Failure: FALSE, pidl doesn't specify a unix path or out of memory
*/
static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, UnixFolder *pUnixFolder) {
LPCITEMIDLIST current = pidl, root;
DWORD dwPathLen;
char *pNextDir;
TRACE("(pidl=%p, path=%p)\n", pidl, path);
TRACE("(pidl=%p, pUnixFolder=%p)\n", pidl, pUnixFolder);
*path = NULL;
pUnixFolder->m_pszPath = NULL;
/* Find the UnixFolderClass root */
while (current->mkid.cb) {
LPPIDLDATA pData = _ILGetDataPointer(current);
if (!pData) return FALSE;
if (pData->type == PT_GUID && IsEqualIID(&CLSID_UnixFolder, &pData->u.guid.guid)) break;
if (pData->type == PT_GUID &&
(IsEqualIID(&CLSID_UnixFolder, &pData->u.guid.guid) ||
IsEqualIID(&CLSID_UnixDosFolder, &pData->u.guid.guid)))
{
break;
}
current = ILGetNext(current);
}
root = current = ILGetNext(current);
......@@ -277,8 +451,8 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
};
/* Build the path */
*path = pNextDir = SHAlloc(dwPathLen);
if (!path) {
pUnixFolder->m_pszPath = pNextDir = SHAlloc(dwPathLen);
if (!pUnixFolder->m_pszPath) {
WARN("SHAlloc failed!\n");
return FALSE;
}
......@@ -292,7 +466,7 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
}
*pNextDir='\0';
TRACE("resulting path: %s\n", *path);
TRACE("--> %s\n", pUnixFolder->m_pszPath);
return TRUE;
}
......@@ -314,7 +488,7 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
* The array of PIDLs and each PIDL are allocated with SHAlloc. You'll have
* to release each PIDL as well as the array itself with SHFree.
*/
static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl, DWORD *pCount)
static BOOL UNIXFS_build_subfolder_pidls(UnixFolder *pUnixFolder)
{
struct dirent *pDirEntry;
struct stat fileStat;
......@@ -323,19 +497,19 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
USHORT sLen;
char *pszFQPath;
TRACE("(path=%s, apidl=%p, pCount=%p)\n", debugstr_a(path), apidl, pCount);
TRACE("(pUnixFolder=%p)\n", pUnixFolder);
*apidl = NULL;
*pCount = 0;
pUnixFolder->m_apidlSubDirs = NULL;
pUnixFolder->m_cSubDirs = 0;
dir = opendir(path);
dir = opendir(pUnixFolder->m_pszPath);
if (!dir) {
WARN("Failed to open directory '%s'.\n", path);
WARN("Failed to open directory '%s'.\n", pUnixFolder->m_pszPath);
return FALSE;
}
/* Allocate space for fully qualified paths */
pszFQPath = SHAlloc(strlen(path) + PATH_MAX);
pszFQPath = SHAlloc(strlen(pUnixFolder->m_pszPath) + PATH_MAX);
if (!pszFQPath) {
WARN("SHAlloc failed!\n");
return FALSE;
......@@ -344,7 +518,7 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
/* Count number of directory entries. */
for (cDirEntries = 0, pDirEntry = readdir(dir); pDirEntry; pDirEntry = readdir(dir)) {
if (!strcmp(pDirEntry->d_name, ".") || !strcmp(pDirEntry->d_name, "..")) continue;
sprintf(pszFQPath, "%s%s", path, pDirEntry->d_name);
sprintf(pszFQPath, "%s%s", pUnixFolder->m_pszPath, pDirEntry->d_name);
if (!stat(pszFQPath, &fileStat) && (S_ISDIR(fileStat.st_mode) || S_ISREG(fileStat.st_mode))) cDirEntries++;
}
......@@ -356,8 +530,8 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
}
/* Allocate the array of PIDLs */
*apidl = SHAlloc(cDirEntries * sizeof(LPITEMIDLIST));
if (!apidl) {
pUnixFolder->m_apidlSubDirs = SHAlloc(cDirEntries * sizeof(LPITEMIDLIST));
if (!pUnixFolder->m_apidlSubDirs) {
WARN("SHAlloc failed!\n");
return FALSE;
}
......@@ -368,7 +542,7 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
if (!strcmp(pDirEntry->d_name, ".") || !strcmp(pDirEntry->d_name, "..")) continue;
sprintf(pszFQPath, "%s%s", path, pDirEntry->d_name);
sprintf(pszFQPath, "%s%s", pUnixFolder->m_pszPath, pDirEntry->d_name);
if (stat(pszFQPath, &fileStat)) continue;
if (!S_ISDIR(fileStat.st_mode) && !S_ISREG(fileStat.st_mode)) continue;
......@@ -381,10 +555,10 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
UNIXFS_build_shitemid(pDirEntry->d_name, &fileStat, pid);
memset(((PBYTE)pid)+pid->cb, 0, sizeof(USHORT));
(*apidl)[i++] = (LPITEMIDLIST)pid;
pUnixFolder->m_apidlSubDirs[i++] = (LPITEMIDLIST)pid;
}
*pCount = i;
pUnixFolder->m_cSubDirs = i;
closedir(dir);
SHFree(pszFQPath);
......@@ -487,18 +661,6 @@ UnixFolderIcon UnixDocumentIconSingleton = { &UnixFolderIcon_IExtractIconW_Vtbl,
* Class whose heap based instances represent unix filesystem directories.
*/
/* UnixFolder object layout and typedef.
*/
typedef struct _UnixFolder {
const IShellFolder2Vtbl *lpIShellFolder2Vtbl;
const IPersistFolder2Vtbl *lpIPersistFolder2Vtbl;
ULONG m_cRef;
CHAR *m_pszPath;
LPITEMIDLIST m_pidlLocation;
LPITEMIDLIST *m_apidlSubDirs;
DWORD m_cSubDirs;
} UnixFolder;
static void UnixFolder_Destroy(UnixFolder *pUnixFolder) {
DWORD i;
......@@ -566,22 +728,13 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_ParseDisplayName(IShellFolder2* i
ULONG* pdwAttributes)
{
UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
int cPathLen;
char *pszAnsiPath, *pBackslash;
BOOL result;
TRACE("(iface=%p, hwndOwner=%p, pbcReserved=%p, lpszDisplayName=%s, pchEaten=%p, ppidl=%p, "
"pdwAttributes=%p) stub\n", iface, hwndOwner, pbcReserved, debugstr_w(lpszDisplayName),
pchEaten, ppidl, pdwAttributes);
pchEaten = NULL;
cPathLen = lstrlenW(lpszDisplayName);
pszAnsiPath = (char*)SHAlloc(cPathLen+1);
WideCharToMultiByte(CP_ACP, 0, lpszDisplayName, -1, pszAnsiPath, cPathLen+1, NULL, NULL);
for (pBackslash = strchr(pszAnsiPath, '\\'); pBackslash; pBackslash = strchr(pBackslash, '\\'))
*pBackslash = '/';
result = UNIXFS_path_to_pidl(This->m_pszPath, pszAnsiPath, ppidl);
result = UNIXFS_path_to_pidl(This, lpszDisplayName, ppidl);
if (result && pdwAttributes && *pdwAttributes)
{
/* need to traverse to the last element for the attribute */
......@@ -595,10 +748,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_ParseDisplayName(IShellFolder2* i
SHELL32_GetItemAttributes((IShellFolder*)iface, last_pidl, pdwAttributes);
}
SHFree(pszAnsiPath);
if (!result) TRACE("FAILED!\n");
return result ? S_OK : E_FAIL;
}
......@@ -632,7 +782,11 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_BindToObject(IShellFolder2* iface
TRACE("(iface=%p, pidl=%p, pbcReserver=%p, riid=%p, ppvOut=%p)\n",
iface, pidl, pbcReserved, riid, ppvOut);
hr = UnixFolder_Constructor(NULL, &IID_IPersistFolder2, (void**)&persistFolder);
if (This->m_dwPathMode == PATHMODE_DOS)
hr = UnixDosFolder_Constructor(NULL, &IID_IPersistFolder2, (void**)&persistFolder);
else
hr = UnixFolder_Constructor(NULL, &IID_IPersistFolder2, (void**)&persistFolder);
if (!SUCCEEDED(hr)) return hr;
hr = IPersistFolder_QueryInterface(persistFolder, riid, (void**)ppvOut);
......@@ -682,7 +836,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_CompareIDs(IShellFolder2* iface,
_ILGetTextPointer(pidl2), NAME_LEN_FROM_LPSHITEMID(pidl2));
if ((compare == CSTR_LESS_THAN) || (compare == CSTR_GREATER_THAN))
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)(compare == CSTR_LESS_THAN)?-1:1);
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)((compare == CSTR_LESS_THAN)?-1:1));
if (pidl1->mkid.cb < pidl2->mkid.cb)
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)-1);
......@@ -737,7 +891,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetAttributesOf(IShellFolder2* if
for (i=0; i<cidl; i++) {
LPPIDLDATA pData = _ILGetDataPointer(apidl[i]);
if (!pData) continue;
if (pData->type == PT_FOLDER) flags &= (SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
if (pData->type == PT_FOLDER) flags &= (SFGAO_FILESYSTEM|SFGAO_FILESYSANCESTOR|SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
if (pData->type == PT_VALUE) flags &= SFGAO_FILESYSTEM;
}
......@@ -799,6 +953,11 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetDisplayNameOf(IShellFolder2* i
if (!pidl->mkid.cb) {
lpName->uType = STRRET_CSTR;
strcpy(lpName->u.cStr, This->m_pszPath);
if (This->m_dwPathMode == PATHMODE_DOS) {
char path[MAX_PATH];
GetFullPathNameA(lpName->u.cStr, MAX_PATH, path, NULL);
strcpy(lpName->u.cStr, path);
}
} else {
IShellFolder *pSubFolder;
USHORT emptyIDL = 0;
......@@ -815,6 +974,8 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetDisplayNameOf(IShellFolder2* i
strcpy(lpName->u.cStr, pszFileName ? pszFileName : "");
}
TRACE("--> %s\n", lpName->u.cStr);
return hr;
}
......@@ -993,23 +1154,27 @@ static HRESULT WINAPI UnixFolder_IPersistFolder2_Initialize(IPersistFolder2* ifa
TRACE("(iface=%p, pidl=%p)\n", iface, pidl);
This->m_pidlLocation = ILClone(pidl);
UNIXFS_pidl_to_path(pidl, &This->m_pszPath);
UNIXFS_build_subfolder_pidls(This->m_pszPath, &This->m_apidlSubDirs, &This->m_cSubDirs);
pdump(pidl);
UNIXFS_pidl_to_path(pidl, This);
UNIXFS_build_subfolder_pidls(This);
return S_OK;
}
static HRESULT WINAPI UnixFolder_IPersistFolder2_GetCurFolder(IPersistFolder2* iface, LPITEMIDLIST* ppidl)
{
UnixFolder *This = ADJUST_THIS(UnixFolder, IPersistFolder2, iface);
TRACE ("(%p)->(%p)\n", This, ppidl);
TRACE ("(iface=%p, ppidl=%p)\n", iface, ppidl);
if (!ppidl)
return E_POINTER;
*ppidl = ILClone (This->m_pidlLocation);
return S_OK;
}
/* VTable for UnixFolder's IPersistFolder interface.
*/
static const IPersistFolder2Vtbl UnixFolder_IPersistFolder2_Vtbl = {
......@@ -1022,7 +1187,7 @@ static const IPersistFolder2Vtbl UnixFolder_IPersistFolder2_Vtbl = {
};
/******************************************************************************
* UnixFolder_Constructor [Internal]
* Unix[Dos]Folder_Constructor [Internal]
*
* PARAMS
* pUnkOuter [I] Outer class for aggregation. Currently ignored.
......@@ -1030,28 +1195,41 @@ static const IPersistFolder2Vtbl UnixFolder_IPersistFolder2_Vtbl = {
* ppv [O] Pointer to an riid interface to the UnixFolder object.
*
* NOTES
* This is the only function exported from shfldr_unixfs.c. It's called from
* shellole.c's default class factory and thus has to exhibit a LPFNCREATEINSTANCE
* Those are the only functions exported from shfldr_unixfs.c. They are called from
* shellole.c's default class factory and thus have to exhibit a LPFNCREATEINSTANCE
* compatible signature.
*
* The UnixDosFolder_Constructor sets the dwPathMode member to PATHMODE_DOS. This
* means that paths are converted from dos to unix and back at the interfaces.
*/
HRESULT WINAPI UnixFolder_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) {
HRESULT hr;
UnixFolder *pUnixFolder;
static HRESULT CreateUnixFolder(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv, DWORD dwPathMode) {
HRESULT hr = E_FAIL;
UnixFolder *pUnixFolder = SHAlloc((ULONG)sizeof(UnixFolder));
TRACE("(pUnkOuter=%p, riid=%p, ppv=%p)\n", pUnkOuter, riid, ppv);
if(pUnixFolder) {
pUnixFolder->lpIShellFolder2Vtbl = &UnixFolder_IShellFolder2_Vtbl;
pUnixFolder->lpIPersistFolder2Vtbl = &UnixFolder_IPersistFolder2_Vtbl;
pUnixFolder->m_cRef = 0;
pUnixFolder->m_pszPath = NULL;
pUnixFolder->m_apidlSubDirs = NULL;
pUnixFolder->m_cSubDirs = 0;
pUnixFolder->m_dwPathMode = dwPathMode;
UnixFolder_IShellFolder2_AddRef(STATIC_CAST(IShellFolder2, pUnixFolder));
hr = UnixFolder_IShellFolder2_QueryInterface(STATIC_CAST(IShellFolder2, pUnixFolder), riid, ppv);
UnixFolder_IShellFolder2_Release(STATIC_CAST(IShellFolder2, pUnixFolder));
}
return hr;
}
pUnixFolder = SHAlloc((ULONG)sizeof(UnixFolder));
pUnixFolder->lpIShellFolder2Vtbl = &UnixFolder_IShellFolder2_Vtbl;
pUnixFolder->lpIPersistFolder2Vtbl = &UnixFolder_IPersistFolder2_Vtbl;
pUnixFolder->m_cRef = 0;
pUnixFolder->m_pszPath = NULL;
pUnixFolder->m_apidlSubDirs = NULL;
pUnixFolder->m_cSubDirs = 0;
HRESULT WINAPI UnixFolder_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) {
TRACE("(pUnkOuter=%p, riid=%p, ppv=%p)\n", pUnkOuter, riid, ppv);
return CreateUnixFolder(pUnkOuter, riid, ppv, PATHMODE_UNIX);
}
UnixFolder_IShellFolder2_AddRef(STATIC_CAST(IShellFolder2, pUnixFolder));
hr = UnixFolder_IShellFolder2_QueryInterface(STATIC_CAST(IShellFolder2, pUnixFolder), riid, ppv);
UnixFolder_IShellFolder2_Release(STATIC_CAST(IShellFolder2, pUnixFolder));
return hr;
HRESULT WINAPI UnixDosFolder_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) {
TRACE("(pUnkOuter=%p, riid=%p, ppv=%p)\n", pUnkOuter, riid, ppv);
return CreateUnixFolder(pUnkOuter, riid, ppv, PATHMODE_DOS);
}
/******************************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment