📄 winefile.c
字号:
int level = dir->level + 1;
#ifdef UNICODE
char cpath[MAX_PATH];
WideCharToMultiByte(CP_UNIXCP, 0, path, -1, cpath, MAX_PATH, NULL, NULL);
#else
const char* cpath = path;
#endif
pdir = opendir(cpath);
if (pdir) {
struct stat st;
struct dirent* ent;
char buffer[MAX_PATH], *p;
const char* s;
for(p=buffer,s=cpath; *s; )
*p++ = *s++;
if (p==buffer || p[-1]!='/')
*p++ = '/';
while((ent=readdir(pdir))) {
entry = alloc_entry();
if (!first_entry)
first_entry = entry;
if (last)
last->next = entry;
entry->etype = ET_UNIX;
strcpy(p, ent->d_name);
#ifdef UNICODE
MultiByteToWideChar(CP_UNIXCP, 0, p, -1, entry->data.cFileName, MAX_PATH);
#else
lstrcpy(entry->data.cFileName, p);
#endif
if (!stat(buffer, &st)) {
entry->data.dwFileAttributes = p[0]=='.'? FILE_ATTRIBUTE_HIDDEN: 0;
if (S_ISDIR(st.st_mode))
entry->data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
entry->data.nFileSizeLow = st.st_size & 0xFFFFFFFF;
entry->data.nFileSizeHigh = st.st_size >> 32;
memset(&entry->data.ftCreationTime, 0, sizeof(FILETIME));
time_to_filetime(&st.st_atime, &entry->data.ftLastAccessTime);
time_to_filetime(&st.st_mtime, &entry->data.ftLastWriteTime);
entry->bhfi.nFileIndexLow = ent->d_ino;
entry->bhfi.nFileIndexHigh = 0;
entry->bhfi.nNumberOfLinks = st.st_nlink;
entry->bhfi_valid = TRUE;
} else {
entry->data.nFileSizeLow = 0;
entry->data.nFileSizeHigh = 0;
entry->bhfi_valid = FALSE;
}
entry->down = NULL;
entry->up = dir;
entry->expanded = FALSE;
entry->scanned = FALSE;
entry->level = level;
last = entry;
}
if (last)
last->next = NULL;
closedir(pdir);
}
dir->down = first_entry;
dir->scanned = TRUE;
}
static Entry* find_entry_unix(Entry* dir, LPCTSTR name)
{
Entry* entry;
for(entry=dir->down; entry; entry=entry->next) {
LPCTSTR p = name;
LPCTSTR q = entry->data.cFileName;
do {
if (!*p || *p==TEXT('/'))
return entry;
} while(*p++ == *q++);
}
return 0;
}
static Entry* read_tree_unix(Root* root, LPCTSTR path, SORT_ORDER sortOrder, HWND hwnd)
{
TCHAR buffer[MAX_PATH];
Entry* entry = &root->entry;
LPCTSTR s = path;
PTSTR d = buffer;
HCURSOR old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
entry->etype = ET_UNIX;
while(entry) {
while(*s && *s!=TEXT('/'))
*d++ = *s++;
while(*s == TEXT('/'))
s++;
*d++ = TEXT('/');
*d = TEXT('\0');
read_directory(entry, buffer, sortOrder, hwnd);
if (entry->down)
entry->expanded = TRUE;
if (!*s)
break;
entry = find_entry_unix(entry, s);
}
SetCursor(old_cursor);
return entry;
}
#endif /* !defined(_NO_EXTENSIONS) && defined(__WINE__) */
#ifdef _SHELL_FOLDERS
#ifdef UNICODE
#define get_strret get_strretW
#define path_from_pidl path_from_pidlW
#else
#define get_strret get_strretA
#define path_from_pidl path_from_pidlA
#endif
static void free_strret(STRRET* str)
{
if (str->uType == STRRET_WSTR)
IMalloc_Free(Globals.iMalloc, str->UNION_MEMBER(pOleStr));
}
#ifndef UNICODE
static LPSTR strcpyn(LPSTR dest, LPCSTR source, size_t count)
{
LPCSTR s;
LPSTR d = dest;
for(s=source; count&&(*d++=*s++); )
count--;
return dest;
}
static void get_strretA(STRRET* str, const SHITEMID* shiid, LPSTR buffer, int len)
{
switch(str->uType) {
case STRRET_WSTR:
WideCharToMultiByte(CP_ACP, 0, str->UNION_MEMBER(pOleStr), -1, buffer, len, NULL, NULL);
break;
case STRRET_OFFSET:
strcpyn(buffer, (LPCSTR)shiid+str->UNION_MEMBER(uOffset), len);
break;
case STRRET_CSTR:
strcpyn(buffer, str->UNION_MEMBER(cStr), len);
}
}
static HRESULT path_from_pidlA(IShellFolder* folder, LPITEMIDLIST pidl, LPSTR buffer, int len)
{
STRRET str;
/* SHGDN_FORPARSING: get full path of id list */
HRESULT hr = IShellFolder_GetDisplayNameOf(folder, pidl, SHGDN_FORPARSING, &str);
if (SUCCEEDED(hr)) {
get_strretA(&str, &pidl->mkid, buffer, len);
free_strret(&str);
} else
buffer[0] = '\0';
return hr;
}
#endif
static LPWSTR wcscpyn(LPWSTR dest, LPCWSTR source, size_t count)
{
LPCWSTR s;
LPWSTR d = dest;
for(s=source; count&&(*d++=*s++); )
count--;
return dest;
}
static void get_strretW(STRRET* str, const SHITEMID* shiid, LPWSTR buffer, int len)
{
switch(str->uType) {
case STRRET_WSTR:
wcscpyn(buffer, str->UNION_MEMBER(pOleStr), len);
break;
case STRRET_OFFSET:
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)shiid+str->UNION_MEMBER(uOffset), -1, buffer, len);
break;
case STRRET_CSTR:
MultiByteToWideChar(CP_ACP, 0, str->UNION_MEMBER(cStr), -1, buffer, len);
}
}
static HRESULT name_from_pidl(IShellFolder* folder, LPITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags)
{
STRRET str;
HRESULT hr = IShellFolder_GetDisplayNameOf(folder, pidl, flags, &str);
if (SUCCEEDED(hr)) {
get_strret(&str, &pidl->mkid, buffer, len);
free_strret(&str);
} else
buffer[0] = '\0';
return hr;
}
static HRESULT path_from_pidlW(IShellFolder* folder, LPITEMIDLIST pidl, LPWSTR buffer, int len)
{
STRRET str;
/* SHGDN_FORPARSING: get full path of id list */
HRESULT hr = IShellFolder_GetDisplayNameOf(folder, pidl, SHGDN_FORPARSING, &str);
if (SUCCEEDED(hr)) {
get_strretW(&str, &pidl->mkid, buffer, len);
free_strret(&str);
} else
buffer[0] = '\0';
return hr;
}
/* create an item id list from a file system path */
static LPITEMIDLIST get_path_pidl(LPTSTR path, HWND hwnd)
{
LPITEMIDLIST pidl;
HRESULT hr;
ULONG len;
#ifdef UNICODE
LPWSTR buffer = path;
#else
WCHAR buffer[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, path, -1, buffer, MAX_PATH);
#endif
hr = IShellFolder_ParseDisplayName(Globals.iDesktop, hwnd, NULL, buffer, &len, &pidl, NULL);
if (FAILED(hr))
return NULL;
return pidl;
}
/* convert an item id list from relative to absolute (=relative to the desktop) format */
static LPITEMIDLIST get_to_absolute_pidl(Entry* entry, HWND hwnd)
{
if (entry->up && entry->up->etype==ET_SHELL) {
IShellFolder* folder = entry->up->folder;
WCHAR buffer[MAX_PATH];
HRESULT hr = path_from_pidlW(folder, entry->pidl, buffer, MAX_PATH);
if (SUCCEEDED(hr)) {
LPITEMIDLIST pidl;
ULONG len;
hr = IShellFolder_ParseDisplayName(Globals.iDesktop, hwnd, NULL, buffer, &len, &pidl, NULL);
if (SUCCEEDED(hr))
return pidl;
}
} else if (entry->etype == ET_WINDOWS) {
TCHAR path[MAX_PATH];
get_path(entry, path);
return get_path_pidl(path, hwnd);
} else if (entry->pidl)
return ILClone(entry->pidl);
return NULL;
}
static HICON extract_icon(IShellFolder* folder, LPCITEMIDLIST pidl)
{
IExtractIcon* pExtract;
if (SUCCEEDED(IShellFolder_GetUIObjectOf(folder, 0, 1, (LPCITEMIDLIST*)&pidl, &IID_IExtractIcon, 0, (LPVOID*)&pExtract))) {
TCHAR path[_MAX_PATH];
unsigned flags;
HICON hicon;
int idx;
if (SUCCEEDED((*pExtract->lpVtbl->GetIconLocation)(pExtract, GIL_FORSHELL, path, _MAX_PATH, &idx, &flags))) {
if (!(flags & GIL_NOTFILENAME)) {
if (idx == -1)
idx = 0; /* special case for some control panel applications */
if ((int)ExtractIconEx(path, idx, 0, &hicon, 1) > 0)
flags &= ~GIL_DONTCACHE;
} else {
HICON hIconLarge = 0;
HRESULT hr = (*pExtract->lpVtbl->Extract)(pExtract, path, idx, &hIconLarge, &hicon, MAKELONG(0/*GetSystemMetrics(SM_CXICON)*/,GetSystemMetrics(SM_CXSMICON)));
if (SUCCEEDED(hr))
DestroyIcon(hIconLarge);
}
return hicon;
}
}
return 0;
}
static Entry* find_entry_shell(Entry* dir, LPCITEMIDLIST pidl)
{
Entry* entry;
for(entry=dir->down; entry; entry=entry->next) {
if (entry->pidl->mkid.cb == pidl->mkid.cb &&
!memcmp(entry->pidl, pidl, entry->pidl->mkid.cb))
return entry;
}
return 0;
}
static Entry* read_tree_shell(Root* root, LPITEMIDLIST pidl, SORT_ORDER sortOrder, HWND hwnd)
{
Entry* entry = &root->entry;
Entry* next;
LPITEMIDLIST next_pidl = pidl;
IShellFolder* folder;
IShellFolder* child = NULL;
HRESULT hr;
HCURSOR old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
#ifndef _NO_EXTENSIONS
entry->etype = ET_SHELL;
#endif
folder = Globals.iDesktop;
while(entry) {
entry->pidl = next_pidl;
entry->folder = folder;
if (!pidl->mkid.cb)
break;
/* copy first element of item idlist */
next_pidl = IMalloc_Alloc(Globals.iMalloc, pidl->mkid.cb+sizeof(USHORT));
memcpy(next_pidl, pidl, pidl->mkid.cb);
((LPITEMIDLIST)((LPBYTE)next_pidl+pidl->mkid.cb))->mkid.cb = 0;
hr = IShellFolder_BindToObject(folder, next_pidl, 0, &IID_IShellFolder, (void**)&child);
if (!SUCCEEDED(hr))
break;
read_directory(entry, NULL, sortOrder, hwnd);
if (entry->down)
entry->expanded = TRUE;
next = find_entry_shell(entry, next_pidl);
if (!next)
break;
folder = child;
entry = next;
/* go to next element */
pidl = (LPITEMIDLIST) ((LPBYTE)pidl+pidl->mkid.cb);
}
SetCursor(old_cursor);
return entry;
}
static void fill_w32fdata_shell(IShellFolder* folder, LPCITEMIDLIST pidl, SFGAOF attribs, WIN32_FIND_DATA* w32fdata)
{
if (!(attribs & SFGAO_FILESYSTEM) ||
FAILED(SHGetDataFromIDList(folder, pidl, SHGDFIL_FINDDATA, w32fdata, sizeof(WIN32_FIND_DATA)))) {
WIN32_FILE_ATTRIBUTE_DATA fad;
IDataObject* pDataObj;
STGMEDIUM medium = {0, {0}, 0};
FORMATETC fmt = {Globals.cfStrFName, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hr = IShellFolder_GetUIObjectOf(folder, 0, 1, &pidl, &IID_IDataObject, 0, (LPVOID*)&pDataObj);
if (SUCCEEDED(hr)) {
hr = IDataObject_GetData(pDataObj, &fmt, &medium);
IDataObject_Release(pDataObj);
if (SUCCEEDED(hr)) {
LPCTSTR path = (LPCTSTR)GlobalLock(medium.UNION_MEMBER(hGlobal));
UINT sem_org = SetErrorMode(SEM_FAILCRITICALERRORS);
if (GetFileAttributesEx(path, GetFileExInfoStandard, &fad)) {
w32fdata->dwFileAttributes = fad.dwFileAttributes;
w32fdata->ftCreationTime = fad.ftCreationTime;
w32fdata->ftLastAccessTime = fad.ftLastAccessTime;
w32fdata->ftLastWriteTime = fad.ftLastWriteTime;
if (!(fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
w32fdata->nFileSizeLow = fad.nFileSizeLow;
w32fdata->nFileSizeHigh = fad.nFileSizeHigh;
}
}
SetErrorMode(sem_org);
GlobalUnlock(medium.UNION_MEMBER(hGlobal));
GlobalFree(medium.UNION_MEMBER(hGlobal));
}
}
}
if (attribs & (SFGAO_FOLDER|SFGAO_HASSUBFOLDER))
w32fdata->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
if (attribs & SFGAO_READONLY)
w32fdata->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
if (attribs & SFGAO_COMPRESSED)
w32fdata->dwFileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
}
static void read_directory_shell(Entry* dir, HWND hwnd)
{
IShellFolder* folder = dir->folder;
int level = dir->level + 1;
HRESULT hr;
IShellFolder* child;
IEnumIDList* idlist;
Entry* first_entry = NULL;
Entry* last = NULL;
Entry* entry;
if (!folder)
return;
hr = IShellFolder_EnumObjects(folder, hwnd, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN|SHCONTF_SHAREABLE|SHCONTF_STORAGE, &idlist);
if (SUCCEEDED(hr)) {
for(;;) {
#define FETCH_ITEM_COUNT 32
LPITEMIDLIST pidls[FETCH_ITEM_COUNT];
SFGAOF attribs;
ULONG cnt = 0;
ULONG n;
memset(pidls, 0, sizeof(pidls));
hr = IEnumIDList_Next(idlist, FETCH_ITEM_COUNT, pidls, &cnt);
if (!SUCCEEDED(hr))
break;
if (hr == S_FALSE)
break;
for(n=0; n<cnt; ++n) {
entry = alloc_entry();
if (!first_entry)
first_entry = entry;
if (last)
last->next = entry;
memset(&entry->data, 0, sizeof(WIN32_FIND_DATA));
entry->bhfi_valid = FALSE;
attribs = ~SFGAO_FILESYSTEM; /*SFGAO_HASSUBFOLDER|SFGAO_FOLDER; SFGAO_FILESYSTEM sorgt daf黵, da
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -