Support for regular files (as opposed to directories).

This commit is contained in:
Michael Jung 2005-04-25 10:56:29 +00:00 committed by Alexandre Julliard
parent e901cc4b53
commit 3abb5bd6bb
4 changed files with 291 additions and 172 deletions

View File

@ -132,43 +132,9 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "&Durchsuchen...", 12288, 170, 63, 50, 14, WS_TABSTOP
}
/*
special folders
*/
STRINGTABLE DISCARDABLE
{
IDS_DESKTOP "Desktop"
IDS_MYCOMPUTER "Arbeitsplatz"
}
/*
context menus
*/
STRINGTABLE DISCARDABLE
{
IDS_VIEW_LARGE "&Große Symbole"
IDS_VIEW_SMALL "&Kleine Symbole"
IDS_VIEW_LIST "&Liste"
IDS_VIEW_DETAILS "&Details"
IDS_SELECT "Auswählen"
IDS_OPEN "Öffnen"
}
STRINGTABLE DISCARDABLE
{
IDS_CREATEFOLDER_DENIED "Es konnte kein neues Verzeichnis erstellt werden: Zugriff verweigert."
IDS_CREATEFOLDER_CAPTION "Es trat ein Fehler beim Erstellen eines neuen Verzeichnisses auf"
IDS_DELETEITEM_CAPTION "Bestätigung: Datei löschen"
IDS_DELETEFOLDER_CAPTION "Bestätigung: Verzeichnis löschen"
IDS_DELETEITEM_TEXT "Sind Sie sich sicher, dass Sie die Datei '%1' löschen möchten ?"
IDS_DELETEMULTIPLE_TEXT "Sind Sie sich sicher, dass Sie diese %1 Dateien löschen möchten ?"
IDS_OVERWRITEFILE_TEXT "Möchten Sie, dass die Datei '%1' überschrieben wird ?"
IDS_OVERWRITEFILE_CAPTION "Bestätigung: Datei überschreiben"
}
/* columns in the shellview */
STRINGTABLE
BEGIN
/* columns in the shellview */
IDS_SHV_COLUMN1 "Datei"
IDS_SHV_COLUMN2 "Größe"
IDS_SHV_COLUMN3 "Typ"
@ -178,20 +144,37 @@ BEGIN
IDS_SHV_COLUMN7 "Freier Speicher"
IDS_SHV_COLUMN8 "Name"
IDS_SHV_COLUMN9 "Kommentar"
END
IDS_SHV_COLUMN10 "Besitzer"
IDS_SHV_COLUMN11 "Gruppe"
/* message box strings */
STRINGTABLE DISCARDABLE
{
IDS_RESTART_TITLE "Neustarten"
IDS_RESTART_PROMPT "Möchten Sie, dass ein simulierter Windows Neustart durchgeführt wird ?"
IDS_SHUTDOWN_TITLE "Anhalten"
IDS_SHUTDOWN_PROMPT "Möchten Sie die aktuelle Wine Sitzung beenden ?"
}
/* special folders */
IDS_DESKTOP "Desktop"
IDS_MYCOMPUTER "Arbeitsplatz"
/* shell folder path default values */
STRINGTABLE DISCARDABLE
{
/* context menus */
IDS_VIEW_LARGE "&Große Symbole"
IDS_VIEW_SMALL "&Kleine Symbole"
IDS_VIEW_LIST "&Liste"
IDS_VIEW_DETAILS "&Details"
IDS_SELECT "Auswählen"
IDS_OPEN "Öffnen"
IDS_CREATEFOLDER_DENIED "Es konnte kein neues Verzeichnis erstellt werden: Zugriff verweigert."
IDS_CREATEFOLDER_CAPTION "Es trat ein Fehler beim Erstellen eines neuen Verzeichnisses auf"
IDS_DELETEITEM_CAPTION "Bestätigung: Datei löschen"
IDS_DELETEFOLDER_CAPTION "Bestätigung: Verzeichnis löschen"
IDS_DELETEITEM_TEXT "Sind Sie sich sicher, dass Sie die Datei '%1' löschen möchten ?"
IDS_DELETEMULTIPLE_TEXT "Sind Sie sich sicher, dass Sie diese %1 Dateien löschen möchten ?"
IDS_OVERWRITEFILE_TEXT "Möchten Sie, dass die Datei '%1' überschrieben wird ?"
IDS_OVERWRITEFILE_CAPTION "Bestätigung: Datei überschreiben"
/* message box strings */
IDS_RESTART_TITLE "Neustarten"
IDS_RESTART_PROMPT "Möchten Sie, dass ein simulierter Windows Neustart durchgeführt wird ?"
IDS_SHUTDOWN_TITLE "Anhalten"
IDS_SHUTDOWN_PROMPT "Möchten Sie die aktuelle Wine Sitzung beenden ?"
/* shell folder path default values */
IDS_PROGRAMS "Startmenü\\Programme"
IDS_PERSONAL "Eigene Dateien"
IDS_FAVORITES "Favoriten"

View File

@ -131,43 +131,9 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP
}
/*
special folders
*/
STRINGTABLE DISCARDABLE
{
IDS_DESKTOP "Desktop"
IDS_MYCOMPUTER "My Computer"
}
/*
context menus
*/
STRINGTABLE DISCARDABLE
{
IDS_VIEW_LARGE "Lar&ge Icons"
IDS_VIEW_SMALL "S&mall Icons"
IDS_VIEW_LIST "&List"
IDS_VIEW_DETAILS "&Details"
IDS_SELECT "Select"
IDS_OPEN "Open"
}
STRINGTABLE DISCARDABLE
{
IDS_CREATEFOLDER_DENIED "Can not create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"
IDS_DELETEITEM_CAPTION "Confirm file delete"
IDS_DELETEFOLDER_CAPTION "Confirm folder delete"
IDS_DELETEITEM_TEXT "Are you sure you want to delete '%1'?"
IDS_DELETEMULTIPLE_TEXT "Are you sure you want to delete these %1 items?"
IDS_OVERWRITEFILE_TEXT "OverWrite File %1?"
IDS_OVERWRITEFILE_CAPTION "Confirm File OverWrite"
}
/* columns in the shellview */
STRINGTABLE
BEGIN
/* columns in the shellview */
IDS_SHV_COLUMN1 "File"
IDS_SHV_COLUMN2 "Size"
IDS_SHV_COLUMN3 "Type"
@ -177,20 +143,37 @@ BEGIN
IDS_SHV_COLUMN7 "Size available"
IDS_SHV_COLUMN8 "Name"
IDS_SHV_COLUMN9 "Comments"
END
IDS_SHV_COLUMN10 "Owner"
IDS_SHV_COLUMN11 "Group"
/* message box strings */
STRINGTABLE DISCARDABLE
{
IDS_RESTART_TITLE "Restart"
IDS_RESTART_PROMPT "Do you want to simulate a Windows reboot?"
IDS_SHUTDOWN_TITLE "Shutdown"
IDS_SHUTDOWN_PROMPT "Do you want to shutdown your Wine session?"
}
/* special folders */
IDS_DESKTOP "Desktop"
IDS_MYCOMPUTER "My Computer"
/* shell folder path default values */
STRINGTABLE DISCARDABLE
{
/* context menus */
IDS_VIEW_LARGE "Lar&ge Icons"
IDS_VIEW_SMALL "S&mall Icons"
IDS_VIEW_LIST "&List"
IDS_VIEW_DETAILS "&Details"
IDS_SELECT "Select"
IDS_OPEN "Open"
IDS_CREATEFOLDER_DENIED "Can not create new Folder: Permission denied."
IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder"
IDS_DELETEITEM_CAPTION "Confirm file delete"
IDS_DELETEFOLDER_CAPTION "Confirm folder delete"
IDS_DELETEITEM_TEXT "Are you sure you want to delete '%1'?"
IDS_DELETEMULTIPLE_TEXT "Are you sure you want to delete these %1 items?"
IDS_OVERWRITEFILE_TEXT "OverWrite File %1?"
IDS_OVERWRITEFILE_CAPTION "Confirm File OverWrite"
/* message box strings */
IDS_RESTART_TITLE "Restart"
IDS_RESTART_PROMPT "Do you want to simulate a Windows reboot?"
IDS_SHUTDOWN_TITLE "Shutdown"
IDS_SHUTDOWN_PROMPT "Do you want to shutdown your Wine session?"
/* shell folder path default values */
IDS_PROGRAMS "Start Menu\\Programs"
IDS_PERSONAL "My Documents"
IDS_FAVORITES "Favorites"

View File

@ -21,6 +21,9 @@
#include <stdio.h>
#include <stdarg.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#define COBJMACROS
#define NONAMELESSUNION
@ -30,6 +33,8 @@
#include "winbase.h"
#include "winuser.h"
#include "objbase.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/debug.h"
#include "shell32_main.h"
@ -44,27 +49,75 @@ const GUID CLSID_UnixFolder = {0xcc702eb2, 0x7dc5, 0x11d9, {0xc6, 0x87, 0x00, 0x
#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)
/* FileStruct reserves one byte for szNames, thus we don't need to
* alloc a byte for the terminating '\0' of 'name'. Two of the four
/* FileStruct reserves one byte for szNames, thus we don't have to
* alloc a byte for the terminating '\0' of 'name'. Two of the
* additional bytes are for SHITEMID's cb field. One is for IDLDATA's
* type field. One is for FileStruct's szNames field, to terminate
* the alternate DOS name, which we don't use here.
* the alternate DOS name, which we don't use here. And then there's
* the additional StatStruct.
*/
#define SHITEMID_LEN_FROM_NAME_LEN(n) (sizeof(USHORT)+sizeof(PIDLTYPE)+sizeof(FileStruct)+(n)+sizeof(char))
#define NAME_LEN_FROM_LPSHITEMID(s) (((LPSHITEMID)s)->cb-sizeof(USHORT)-sizeof(PIDLTYPE)-sizeof(FileStruct)-sizeof(char))
#define SHITEMID_LEN_FROM_NAME_LEN(n) \
(sizeof(USHORT)+sizeof(PIDLTYPE)+sizeof(FileStruct)+(n)+sizeof(char)+sizeof(StatStruct))
#define NAME_LEN_FROM_LPSHITEMID(s) \
(((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)))
/* This structure is appended to shell32's FileStruct type in IDLs to store unix
* filesystem specific informationen extracted with the stat system call.
*/
typedef struct tagStatStruct {
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
} StatStruct;
/******************************************************************************
* UNIXFS_is_pidl_of_type [INTERNAL]
*
* Checks for the first SHITEMID of an ITEMIDLIST if it passes a filter.
*
* PARAMS
* pIDL [I] The ITEMIDLIST to be checked.
* fFilter [I] Shell condition flags, which specify the filter.
*
* RETURNS
* TRUE, if pIDL is accepted by fFilter
* FALSE, otherwise
*/
static inline BOOL UNIXFS_is_pidl_of_type(LPITEMIDLIST pIDL, SHCONTF fFilter) {
LPSTR pszText = _ILGetTextPointer(pIDL);
if (!pszText) return FALSE;
if (pszText[0] == '.' && !(fFilter & SHCONTF_INCLUDEHIDDEN)) return FALSE;
if (_ILIsFolder(pIDL) && (fFilter & SHCONTF_FOLDERS)) return TRUE;
if (_ILIsValue(pIDL) && (fFilter & SHCONTF_NONFOLDERS)) return TRUE;
return FALSE;
}
/******************************************************************************
* UNIXFS_build_shitemid [Internal]
*
* Builds a shell item for the given path. Only the part of the path up to the
* next '/' or to the end of the string is considered. Don't forget do append a
* 0 ushort value, if what you need is a ITEMIDLIST with a single entry.
* Constructs a new SHITEMID for a single path item (up to the next '/' or
* '\0') into a buffer. Decorates the SHITEMID with information from a stat
* system call.
*
* The signature of this function will change in the future. Better documentation
* to follow.
* PARAMS
* name [I] The name of the next path item. Terminated by either '\0' or '/'.
* pStat [I] A stat struct variable obtained by a stat system call on the file.
* buffer [O] SHITEMID will be constructed here.
*
* RETURNS
* A pointer to the next '/' or '\0' character in name.
*
* NOTES
* Minimum size of buffer is SHITEMID_LEN_FROM_NAME_LEN(strlen(name)).
* If what you need is a PIDLLIST with a single SHITEMID, don't forget to append
* a 0 USHORT value.
*/
static const char* UNIXFS_build_shitemid(const char *name, void *buffer) {
static char* UNIXFS_build_shitemid(char *name, struct stat *pStat, void *buffer) {
LARGE_INTEGER time;
FILETIME fileTime;
LPPIDLDATA pIDLData;
StatStruct *pStatStruct;
int cNameLen;
char *pSlash;
@ -76,16 +129,21 @@ static const char* UNIXFS_build_shitemid(const char *name, void *buffer) {
memset(buffer, 0, SHITEMID_LEN_FROM_NAME_LEN(cNameLen));
((LPSHITEMID)buffer)->cb = SHITEMID_LEN_FROM_NAME_LEN(cNameLen) ;
/* Other than the type and the name those are dummy values for now. More to come.
*/
pIDLData = _ILGetDataPointer((LPCITEMIDLIST)buffer);
pIDLData->type = PT_FOLDER;
pIDLData->u.file.dwFileSize = 0;
pIDLData->u.file.uFileDate = 0;
pIDLData->u.file.uFileTime = 0;
pIDLData->type = S_ISDIR(pStat->st_mode) ? PT_FOLDER : PT_VALUE;
pIDLData->u.file.dwFileSize = (DWORD)pStat->st_size;
RtlSecondsSince1970ToTime( pStat->st_mtime, &time );
fileTime.dwLowDateTime = time.u.LowPart;
fileTime.dwHighDateTime = time.u.HighPart;
FileTimeToDosDateTime(&fileTime, &pIDLData->u.file.uFileDate, &pIDLData->u.file.uFileTime);
pIDLData->u.file.uFileAttribs = 0;
memcpy(pIDLData->u.file.szNames, name, cNameLen);
pStatStruct = LPSTATSTRUCT_FROM_LPSHITEMID(buffer);
pStatStruct->st_mode = pStat->st_mode;
pStatStruct->st_uid = pStat->st_uid;
pStatStruct->st_gid = pStat->st_gid;
return pSlash ? pSlash+1 : (name + cNameLen);
}
@ -105,10 +163,11 @@ static const char* UNIXFS_build_shitemid(const char *name, void *buffer) {
* ending with a slash ('/'). Currently, only directories (no files)
* are accepted.
*/
static BOOL UNIXFS_path_to_pidl(const char *path, LPITEMIDLIST *ppidl) {
static BOOL UNIXFS_path_to_pidl(char *path, LPITEMIDLIST *ppidl) {
LPITEMIDLIST pidl;
struct stat fileStat;
int cSubDirs, cPidlLen;
const char *pSlash;
char *pSlash, swap;
TRACE("path=%s, ppidl=%p", debugstr_a(path), ppidl);
@ -130,9 +189,26 @@ static BOOL UNIXFS_path_to_pidl(const char *path, LPITEMIDLIST *ppidl) {
if (!pidl) return FALSE;
/* Concatenate the SHITEMIDs of the sub-directories. */
pSlash = path; /* First character of path is guaranteed to be '/' */
while (*path) {
path = UNIXFS_build_shitemid(path, pidl);
if (pSlash) {
/* For the stat call, we temporarily replace the char
* after the next '/' with a '\0'. */
swap = pSlash[1];
pSlash[1] = '\0';
if (stat(path, &fileStat)) {
pSlash[1] = swap;
return FALSE;
}
pSlash[1] = swap;
} else {
/* We are at the last item in path. */
if (stat(path, &fileStat)) return FALSE;
}
path = UNIXFS_build_shitemid(path, &fileStat, pidl);
pidl = ILGetNext(pidl);
pSlash = strchr(path, '/');
}
pidl->mkid.cb = 0; /* Terminate the ITEMIDLIST */
@ -218,12 +294,14 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
*/
static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl, DWORD *pCount)
{
struct dirent *pDirEntry;
struct stat fileStat;
DIR *dir;
struct dirent *pSubDir;
DWORD cSubDirs, i;
DWORD cDirEntries, i;
USHORT sLen;
char *pszFQPath;
TRACE("(path=%s, apidl=%p, pCount=%p)\n", path, apidl, pCount);
TRACE("(path=%s, apidl=%p, pCount=%p)\n", debugstr_a(path), apidl, pCount);
*apidl = NULL;
*pCount = 0;
@ -234,8 +312,9 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
if (!strlen(path)) {
LPSHITEMID pid;
if (stat("/", &fileStat)) return FALSE;
pid = (LPSHITEMID)SHAlloc(SHITEMID_LEN_FROM_NAME_LEN(0)+sizeof(USHORT));
UNIXFS_build_shitemid("", pid);
UNIXFS_build_shitemid("", &fileStat, pid);
memset(((PBYTE)pid)+pid->cb, 0, sizeof(USHORT));
*apidl = SHAlloc(sizeof(LPITEMIDLIST));
@ -255,48 +334,51 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
return FALSE;
}
/* Count number of sub directories.
*/
for (cSubDirs = 0, pSubDir = readdir(dir); pSubDir; pSubDir = readdir(dir)) {
if (strcmp(pSubDir->d_name, ".") &&
strcmp(pSubDir->d_name, "..") &&
pSubDir->d_type == DT_DIR)
{
cSubDirs++;
}
/* Allocate space for fully qualified paths */
pszFQPath = SHAlloc(strlen(path) + NAME_MAX);
if (!pszFQPath) {
WARN("SHAlloc failed!\n");
return FALSE;
}
/* If there are no subdirectories, we are done. */
if (cSubDirs == 0) {
/* 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);
if (!stat(pszFQPath, &fileStat) && (S_ISDIR(fileStat.st_mode) || S_ISREG(fileStat.st_mode))) cDirEntries++;
}
/* If there are no entries, we are done. */
if (cDirEntries == 0) {
closedir(dir);
SHFree(pszFQPath);
return TRUE;
}
/* Allocate the array of PIDLs */
*apidl = SHAlloc(cSubDirs * sizeof(LPITEMIDLIST));
*apidl = SHAlloc(cDirEntries * sizeof(LPITEMIDLIST));
if (!apidl) {
WARN("SHAlloc failed!\n");
return FALSE;
}
/* Allocate and initialize one SHITEMID per sub-directory. */
for (rewinddir(dir), pSubDir = readdir(dir), i = 0; pSubDir; pSubDir = readdir(dir)) {
for (rewinddir(dir), pDirEntry = readdir(dir), i = 0; pDirEntry; pDirEntry = readdir(dir)) {
LPSHITEMID pid;
if (!strcmp(pSubDir->d_name, ".") ||
!strcmp(pSubDir->d_name, "..") ||
pSubDir->d_type != DT_DIR)
{
continue;
}
if (!strcmp(pDirEntry->d_name, ".") || !strcmp(pDirEntry->d_name, "..")) continue;
sLen = strlen(pSubDir->d_name);
sprintf(pszFQPath, "%s%s", path, pDirEntry->d_name);
if (stat(pszFQPath, &fileStat)) continue;
if (!S_ISDIR(fileStat.st_mode) && !S_ISREG(fileStat.st_mode)) continue;
sLen = strlen(pDirEntry->d_name);
pid = (LPSHITEMID)SHAlloc(SHITEMID_LEN_FROM_NAME_LEN(sLen)+sizeof(USHORT));
if (!pid) {
WARN("SHAlloc failed!\n");
return FALSE;
}
UNIXFS_build_shitemid(pSubDir->d_name, pid);
UNIXFS_build_shitemid(pDirEntry->d_name, &fileStat, pid);
memset(((PBYTE)pid)+pid->cb, 0, sizeof(USHORT));
(*apidl)[i++] = (LPITEMIDLIST)pid;
@ -304,6 +386,7 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
*pCount = i;
closedir(dir);
SHFree(pszFQPath);
return TRUE;
}
@ -321,6 +404,7 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
*/
typedef struct _UnixFolderIcon {
const IExtractIconWVtbl *lpIExtractIconWVtbl;
BOOL bFolder;
} UnixFolderIcon;
static HRESULT WINAPI UnixFolderIcon_IExtractIconW_QueryInterface(IExtractIconW *iface, REFIID riid,
@ -356,11 +440,17 @@ static ULONG WINAPI UnixFolderIcon_IExtractIconW_Release(IExtractIconW *iface) {
static HRESULT WINAPI UnixFolderIcon_IExtractIconW_GetIconLocation(IExtractIconW *iface,
UINT uFlags, LPWSTR szIconFile, UINT cchMax, INT* piIndex, UINT* pwFlags)
{
UnixFolderIcon *This = ADJUST_THIS(UnixFolderIcon, IExtractIconW, iface);
TRACE("(iface=%p, uFlags=%u, szIconFile=%s, cchMax=%u, piIndex=%p, pwFlags=%p)\n",
iface, uFlags, debugstr_w(szIconFile), cchMax, piIndex, pwFlags);
lstrcpynW(szIconFile, swShell32Name, cchMax);
*piIndex = (uFlags & GIL_OPENICON) ? 4 : 3;
if (This->bFolder) {
*piIndex = (uFlags & GIL_OPENICON) ? -IDI_SHELL_FOLDER_OPEN : -IDI_SHELL_FOLDER;
} else {
*piIndex = -IDI_SHELL_DOCUMENT;
}
*pwFlags = 0;
return S_OK;
@ -388,7 +478,8 @@ static const IExtractIconWVtbl UnixFolderIcon_IExtractIconW_Vtbl = {
/* The singleton instance
*/
UnixFolderIcon UnixFolderIconSingleton = { &UnixFolderIcon_IExtractIconW_Vtbl };
UnixFolderIcon UnixFolderIconSingleton = { &UnixFolderIcon_IExtractIconW_Vtbl, TRUE };
UnixFolderIcon UnixDocumentIconSingleton = { &UnixFolderIcon_IExtractIconW_Vtbl, FALSE };
/******************************************************************************
* UnixFolder
@ -396,16 +487,6 @@ UnixFolderIcon UnixFolderIconSingleton = { &UnixFolderIcon_IExtractIconW_Vtbl };
* Class whose heap based instances represent unix filesystem directories.
*/
static shvheader GenericSFHeader[] = {
{IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
{IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
{IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
};
#define GENERICSHELLVIEWCOLUMNS 5
/* UnixFolder object layout and typedef.
*/
typedef struct _UnixFolder {
@ -501,7 +582,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_ParseDisplayName(IShellFolder2* i
return result ? S_OK : E_FAIL;
}
static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder);
static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder, SHCONTF fFilter);
static HRESULT WINAPI UnixFolder_IShellFolder2_EnumObjects(IShellFolder2* iface, HWND hwndOwner,
SHCONTF grfFlags, IEnumIDList** ppEnumIDList)
@ -513,7 +594,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_EnumObjects(IShellFolder2* iface,
TRACE("(iface=%p, hwndOwner=%p, grfFlags=%08lx, ppEnumIDList=%p)\n",
iface, hwndOwner, grfFlags, ppEnumIDList);
newIterator = UnixSubFolderIterator_Construct(This);
newIterator = UnixSubFolderIterator_Construct(This, grfFlags);
hr = IUnknown_QueryInterface(newIterator, &IID_IEnumIDList, (void**)ppEnumIDList);
IUnknown_Release(newIterator);
@ -571,6 +652,11 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_CompareIDs(IShellFolder2* iface,
else if (isEmpty2)
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)1);
if (_ILIsFolder(pidl1) && !_ILIsFolder(pidl2))
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)-1);
if (!_ILIsFolder(pidl1) && _ILIsFolder(pidl2))
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)1);
compare = CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
_ILGetTextPointer(pidl1), NAME_LEN_FROM_LPSHITEMID(pidl1),
_ILGetTextPointer(pidl2), NAME_LEN_FROM_LPSHITEMID(pidl2));
@ -623,9 +709,19 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_CreateViewObject(IShellFolder2* i
static HRESULT WINAPI UnixFolder_IShellFolder2_GetAttributesOf(IShellFolder2* iface, UINT cidl,
LPCITEMIDLIST* apidl, SFGAOF* rgfInOut)
{
UINT i;
SFGAOF flags= ~(SFGAOF)0;
TRACE("(iface=%p, cidl=%u, apidl=%p, rgfInOut=%p) semi-stub\n", iface, cidl, apidl, rgfInOut);
*rgfInOut = *rgfInOut & (SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
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_VALUE) flags &= SFGAO_FILESYSTEM;
}
*rgfInOut = *rgfInOut & flags;
return S_OK;
}
@ -648,7 +744,11 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetUIObjectOf(IShellFolder2* ifac
FIXME("IExtractIconA\n");
return E_FAIL;
} else if (IsEqualIID(&IID_IExtractIconW, riid)) {
*ppvOut = &UnixFolderIconSingleton;
if (cidl != 1) return E_FAIL;
if (_ILIsFolder(apidl[0]))
*ppvOut = &UnixFolderIconSingleton;
else
*ppvOut = &UnixDocumentIconSingleton;
return S_OK;
} else if (IsEqualIID(&IID_IDropTarget, riid)) {
FIXME("IDropTarget\n");
@ -760,34 +860,70 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetDetailsEx(IShellFolder2* iface
return E_NOTIMPL;
}
#define SHELLVIEWCOLUMNS 6
static HRESULT WINAPI UnixFolder_IShellFolder2_GetDetailsOf(IShellFolder2* iface,
LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
{
HRESULT hr = E_FAIL;
struct passwd *pPasswd;
struct group *pGroup;
static const shvheader SFHeader[SHELLVIEWCOLUMNS] = {
{IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
{IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN10, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 7},
{IDS_SHV_COLUMN11, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 7},
{IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 8},
{IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}
};
TRACE("(iface=%p, pidl=%p, iColumn=%d, psd=%p) stub\n", iface, pidl, iColumn, psd);
if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS)
if (!psd || iColumn >= SHELLVIEWCOLUMNS)
return E_INVALIDARG;
if (!pidl) {
psd->fmt = GenericSFHeader[iColumn].fmt;
psd->cxChar = GenericSFHeader[iColumn].cxChar;
psd->fmt = SFHeader[iColumn].fmt;
psd->cxChar = SFHeader[iColumn].cxChar;
psd->str.uType = STRRET_CSTR;
LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
LoadStringA(shell32_hInstance, SFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
return S_OK;
} else {
StatStruct *pStatStruct = LPSTATSTRUCT_FROM_LPSHITEMID(pidl);
psd->str.u.cStr[0] = '\0';
psd->str.uType = STRRET_CSTR;
switch (iColumn) {
case 0:
hr = IShellFolder2_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL|SHGDN_INFOLDER, &psd->str);
break;
case 2:
_ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
case 1:
psd->str.u.cStr[0] = S_ISDIR(pStatStruct->st_mode) ? 'd' : '-';
psd->str.u.cStr[1] = (pStatStruct->st_mode & S_IRUSR) ? 'r' : '-';
psd->str.u.cStr[2] = (pStatStruct->st_mode & S_IWUSR) ? 'w' : '-';
psd->str.u.cStr[3] = (pStatStruct->st_mode & S_IXUSR) ? 'x' : '-';
psd->str.u.cStr[4] = (pStatStruct->st_mode & S_IRGRP) ? 'r' : '-';
psd->str.u.cStr[5] = (pStatStruct->st_mode & S_IWGRP) ? 'w' : '-';
psd->str.u.cStr[6] = (pStatStruct->st_mode & S_IXGRP) ? 'x' : '-';
psd->str.u.cStr[7] = (pStatStruct->st_mode & S_IROTH) ? 'r' : '-';
psd->str.u.cStr[8] = (pStatStruct->st_mode & S_IWOTH) ? 'w' : '-';
psd->str.u.cStr[9] = (pStatStruct->st_mode & S_IXOTH) ? 'x' : '-';
psd->str.u.cStr[10] = '\0';
break;
case 2:
pPasswd = getpwuid(pStatStruct->st_uid);
if (pPasswd) strcpy(psd->str.u.cStr, pPasswd->pw_name);
break;
case 3:
pGroup = getgrgid(pStatStruct->st_gid);
if (pGroup) strcpy(psd->str.u.cStr, pGroup->gr_name);
break;
case 4:
_ILGetFileSize(pidl, psd->str.u.cStr, MAX_PATH);
break;
case 5:
_ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
break;
default:
psd->str.u.cStr[0] = '\0';
}
psd->str.uType = STRRET_CSTR;
}
return hr;
@ -920,6 +1056,7 @@ typedef struct _UnixSubFolderIterator {
ULONG m_cRef;
UnixFolder *m_pUnixFolder;
ULONG m_cIdx;
SHCONTF m_fFilter;
} UnixSubFolderIterator;
static void UnixSubFolderIterator_Destroy(UnixSubFolderIterator *iterator) {
@ -979,8 +1116,12 @@ static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Next(IEnumIDList* iface,
TRACE("(iface=%p, celt=%ld, rgelt=%p, pceltFetched=%p)\n", iface, celt, rgelt, pceltFetched);
for (i=0; (i < celt) && (This->m_cIdx < This->m_pUnixFolder->m_cSubDirs); i++, This->m_cIdx++) {
rgelt[i] = ILClone(This->m_pUnixFolder->m_apidlSubDirs[This->m_cIdx]);
for (i=0; (i < celt) && (This->m_cIdx < This->m_pUnixFolder->m_cSubDirs); This->m_cIdx++) {
LPITEMIDLIST pCurrent = This->m_pUnixFolder->m_apidlSubDirs[This->m_cIdx];
if (UNIXFS_is_pidl_of_type(pCurrent, This->m_fFilter)) {
rgelt[i] = ILClone(pCurrent);
i++;
}
}
if (pceltFetched)
@ -992,14 +1133,23 @@ static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Next(IEnumIDList* iface,
static HRESULT WINAPI UnixSubFolderIterator_IEnumIDList_Skip(IEnumIDList* iface, ULONG celt)
{
UnixSubFolderIterator *This = ADJUST_THIS(UnixSubFolderIterator, IEnumIDList, iface);
ULONG i;
TRACE("(iface=%p, celt=%ld)\n", iface, celt);
if (This->m_cIdx + celt > This->m_pUnixFolder->m_cSubDirs) {
for (i=0; i < celt; i++) {
while (This->m_cIdx < This->m_pUnixFolder->m_cSubDirs &&
!UNIXFS_is_pidl_of_type(This->m_pUnixFolder->m_apidlSubDirs[This->m_cIdx], This->m_fFilter))
{
This->m_cIdx++;
}
This->m_cIdx++;
}
if (This->m_cIdx > This->m_pUnixFolder->m_cSubDirs) {
This->m_cIdx = This->m_pUnixFolder->m_cSubDirs;
return S_FALSE;
} else {
This->m_cIdx += celt;
return S_OK;
}
}
@ -1034,7 +1184,7 @@ static const IEnumIDListVtbl UnixSubFolderIterator_IEnumIDList_Vtbl = {
UnixSubFolderIterator_IEnumIDList_Clone
};
static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder) {
static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder, SHCONTF fFilter) {
UnixSubFolderIterator *iterator;
TRACE("(pUnixFolder=%p)\n", pUnixFolder);
@ -1044,6 +1194,7 @@ static IUnknown *UnixSubFolderIterator_Construct(UnixFolder *pUnixFolder) {
iterator->m_cRef = 0;
iterator->m_cIdx = 0;
iterator->m_pUnixFolder = pUnixFolder;
iterator->m_fFilter = fFilter;
UnixSubFolderIterator_IEnumIDList_AddRef((IEnumIDList*)iterator);
UnixFolder_IShellFolder2_AddRef((IShellFolder2*)pUnixFolder);

View File

@ -31,6 +31,8 @@
#define IDS_SHV_COLUMN7 13
#define IDS_SHV_COLUMN8 14
#define IDS_SHV_COLUMN9 15
#define IDS_SHV_COLUMN10 16
#define IDS_SHV_COLUMN11 17
#define IDS_DESKTOP 20
#define IDS_MYCOMPUTER 21