summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/Windows/Shell.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/Windows/Shell.cpp')
-rw-r--r--3rdparty/lzma/CPP/Windows/Shell.cpp569
1 files changed, 525 insertions, 44 deletions
diff --git a/3rdparty/lzma/CPP/Windows/Shell.cpp b/3rdparty/lzma/CPP/Windows/Shell.cpp
index 8e82c14a726..b2a3489870d 100644
--- a/3rdparty/lzma/CPP/Windows/Shell.cpp
+++ b/3rdparty/lzma/CPP/Windows/Shell.cpp
@@ -3,17 +3,49 @@
#include "StdAfx.h"
#include "../Common/MyCom.h"
-#ifndef _UNICODE
#include "../Common/StringConvert.h"
-#endif
#include "COM.h"
+#include "FileName.h"
+#include "MemoryGlobal.h"
#include "Shell.h"
#ifndef _UNICODE
extern bool g_IsNT;
#endif
+// MSVC6 and old SDK don't support this function:
+// #define LWSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
+// LWSTDAPI StrRetToStrW(STRRET *pstr, LPCITEMIDLIST pidl, LPWSTR *ppsz);
+
+// #define SHOW_DEBUG_SHELL
+
+#ifdef SHOW_DEBUG_SHELL
+
+#include "../Common/IntToString.h"
+
+static void Print_Number(UInt32 number, const char *s)
+{
+ AString s2;
+ s2.Add_UInt32(number);
+ s2.Add_Space();
+ s2 += s;
+ OutputDebugStringA(s2);
+}
+
+#define ODS(sz) { OutputDebugStringA(sz); }
+#define ODS_U(s) { OutputDebugStringW(s); }
+#define ODS_(op) { op; }
+
+#else
+
+#define ODS(sz)
+#define ODS_U(s)
+#define ODS_(op)
+
+#endif
+
+
namespace NWindows {
namespace NShell {
@@ -23,12 +55,24 @@ namespace NShell {
void CItemIDList::Free()
{
- if (m_Object == NULL)
+ if (!m_Object)
return;
+ /* DOCs:
+ SHGetMalloc was introduced in Windows 95 and Microsoft Windows NT 4.0,
+ but as of Windows 2000 it is no longer necessary.
+ In its place, programs can call the equivalent (and easier to use) CoTaskMemAlloc and CoTaskMemFree.
+ Description from oldnewthings:
+ shell functions could work without COM (if OLE32.DLL is not loaded),
+ but now if OLE32.DLL is loaded, then shell functions and com functions do same things.
+ 22.02: so we use OLE32.DLL function to free memory:
+ */
+ /*
CMyComPtr<IMalloc> shellMalloc;
if (::SHGetMalloc(&shellMalloc) != NOERROR)
throw 41099;
shellMalloc->Free(m_Object);
+ */
+ CoTaskMemFree(m_Object);
m_Object = NULL;
}
@@ -65,9 +109,354 @@ CItemIDList& CItemIDList::operator=(const CItemIDList &object)
}
*/
+
+static HRESULT ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names)
+{
+ names.Clear();
+ const wchar_t *lim = p + size;
+ UString s;
+ /*
+ if (size == 0 || p[size - 1] != 0)
+ return E_INVALIDARG;
+ if (size == 1)
+ return S_OK;
+ if (p[size - 2] != 0)
+ return E_INVALIDARG;
+ */
+ for (;;)
+ {
+ const wchar_t *start = p;
+ for (;;)
+ {
+ if (p == lim) return E_INVALIDARG; // S_FALSE
+ if (*p++ == 0)
+ break;
+ }
+ const size_t num = (size_t)(p - start);
+ if (num == 1)
+ {
+ if (p != lim) return E_INVALIDARG; // S_FALSE
+ return S_OK;
+ }
+ s.SetFrom(start, (unsigned)(num - 1));
+ ODS_U(s)
+ names.Add(s);
+ // names.ReserveOnePosition();
+ // names.AddInReserved_Ptr_of_new(new UString((unsigned)num - 1, start));
+ }
+}
+
+
+static HRESULT ReadAnsiStrings(const char *p, size_t size, UStringVector &names)
+{
+ names.Clear();
+ AString name;
+ for (; size != 0; size--)
+ {
+ const char c = *p++;
+ if (c == 0)
+ {
+ if (name.IsEmpty())
+ return S_OK;
+ names.Add(GetUnicodeString(name));
+ name.Empty();
+ }
+ else
+ name += c;
+ }
+ return E_INVALIDARG;
+}
+
+
+#define INIT_FORMATETC_HGLOBAL(type) { (type), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }
+
+static HRESULT DataObject_GetData_HGLOBAL(IDataObject *dataObject, CLIPFORMAT cf, NCOM::CStgMedium &medium)
+{
+ FORMATETC etc = INIT_FORMATETC_HGLOBAL(cf);
+ RINOK(dataObject->GetData(&etc, &medium))
+ if (medium.tymed != TYMED_HGLOBAL)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+static HRESULT DataObject_GetData_HDROP_Names(IDataObject *dataObject, UStringVector &names)
+{
+ names.Clear();
+ NCOM::CStgMedium medium;
+
+ /* Win10 : if (dataObject) is from IContextMenu::Initialize() and
+ if (len_of_path >= MAX_PATH (260) for some file in data object)
+ {
+ GetData() returns HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
+ "The data area passed to a system call is too small",
+ Is there a way to fix this code for long paths?
+ } */
+
+ RINOK(DataObject_GetData_HGLOBAL(dataObject, CF_HDROP, medium))
+ const size_t blockSize = GlobalSize(medium.hGlobal);
+ if (blockSize < sizeof(DROPFILES))
+ return E_INVALIDARG;
+ NMemory::CGlobalLock dropLock(medium.hGlobal);
+ const DROPFILES *dropFiles = (const DROPFILES *)dropLock.GetPointer();
+ if (!dropFiles)
+ return E_INVALIDARG;
+ if (blockSize < dropFiles->pFiles
+ || dropFiles->pFiles < sizeof(DROPFILES)
+ // || dropFiles->pFiles != sizeof(DROPFILES)
+ )
+ return E_INVALIDARG;
+ const size_t size = blockSize - dropFiles->pFiles;
+ const void *namesData = (const Byte *)(const void *)dropFiles + dropFiles->pFiles;
+ HRESULT hres;
+ if (dropFiles->fWide)
+ {
+ if (size % sizeof(wchar_t) != 0)
+ return E_INVALIDARG;
+ hres = ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names);
+ }
+ else
+ hres = ReadAnsiStrings((const char *)namesData, size, names);
+
+ ODS_(Print_Number(names.Size(), "DataObject_GetData_HDROP_Names"))
+ return hres;
+}
+
+
+
+// CF_IDLIST:
+#define MYWIN_CFSTR_SHELLIDLIST TEXT("Shell IDList Array")
+
+typedef struct
+{
+ UINT cidl;
+ UINT aoffset[1];
+} MYWIN_CIDA;
+/*
+ cidl : number of PIDLs that are being transferred, not including the parent folder.
+ aoffset : An array of offsets, relative to the beginning of this structure.
+ aoffset[0] - fully qualified PIDL of a parent folder.
+ If this PIDL is empty, the parent folder is the desktop.
+ aoffset[1] ... aoffset[cidl] : offset to one of the PIDLs to be transferred.
+ All of these PIDLs are relative to the PIDL of the parent folder.
+*/
+
+static HRESULT DataObject_GetData_IDLIST(IDataObject *dataObject, UStringVector &names)
+{
+ names.Clear();
+ NCOM::CStgMedium medium;
+ RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT)
+ RegisterClipboardFormat(MYWIN_CFSTR_SHELLIDLIST), medium))
+ const size_t blockSize = GlobalSize(medium.hGlobal);
+ if (blockSize < sizeof(MYWIN_CIDA) || blockSize >= (UInt32)((UInt32)0 - 1))
+ return E_INVALIDARG;
+ NMemory::CGlobalLock dropLock(medium.hGlobal);
+ const MYWIN_CIDA *cida = (const MYWIN_CIDA *)dropLock.GetPointer();
+ if (!cida)
+ return E_INVALIDARG;
+ if (cida->cidl == 0)
+ {
+ // is it posssible to have no selected items?
+ // it's unexpected case.
+ return E_INVALIDARG;
+ }
+ if (cida->cidl >= (blockSize - (UInt32)sizeof(MYWIN_CIDA)) / sizeof(UINT))
+ return E_INVALIDARG;
+ const UInt32 start = cida->cidl * (UInt32)sizeof(UINT) + (UInt32)sizeof(MYWIN_CIDA);
+
+ STRRET strret;
+ CMyComPtr<IShellFolder> parentFolder;
+ {
+ const UINT offset = cida->aoffset[0];
+ if (offset < start || offset >= blockSize
+ // || offset != start
+ )
+ return E_INVALIDARG;
+
+ CMyComPtr<IShellFolder> desktopFolder;
+ RINOK(::SHGetDesktopFolder(&desktopFolder))
+ if (!desktopFolder)
+ return E_FAIL;
+
+ LPCITEMIDLIST const lpcItem = (LPCITEMIDLIST)(const void *)((const Byte *)cida + offset);
+
+ #ifdef SHOW_DEBUG_SHELL
+ {
+ const HRESULT res = desktopFolder->GetDisplayNameOf(
+ lpcItem, SHGDN_FORPARSING, &strret);
+ if (res == S_OK && strret.uType == STRRET_WSTR)
+ {
+ ODS_U(strret.pOleStr)
+ /* if lpcItem is empty, the path will be
+ "C:\Users\user_name\Desktop"
+ if lpcItem is "My Computer" folder, the path will be
+ "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" */
+ CoTaskMemFree(strret.pOleStr);
+ }
+ }
+ #endif
+
+ RINOK(desktopFolder->BindToObject(lpcItem,
+ NULL, IID_IShellFolder, (void **)&parentFolder))
+ if (!parentFolder)
+ return E_FAIL;
+ }
+
+ names.ClearAndReserve(cida->cidl);
+ UString path;
+
+ // for (int y = 0; y < 1; y++) // for debug
+ for (unsigned i = 1; i <= cida->cidl; i++)
+ {
+ const UINT offset = cida->aoffset[i];
+ if (offset < start || offset >= blockSize)
+ return E_INVALIDARG;
+ const void *p = (const Byte *)(const void *)cida + offset;
+ /* ITEMIDLIST of file can contain more than one SHITEMID item.
+ In win10 only SHGDN_FORPARSING returns path that contains
+ all path parts related to parts of ITEMIDLIST.
+ So we can use only SHGDN_FORPARSING here.
+ Don't use (SHGDN_INFOLDER)
+ Don't use (SHGDN_INFOLDER | SHGDN_FORPARSING)
+ */
+ RINOK(parentFolder->GetDisplayNameOf((LPCITEMIDLIST)p, SHGDN_FORPARSING, &strret))
+
+ /*
+ // MSVC6 and old SDK do not support StrRetToStrW().
+ LPWSTR lpstr;
+ RINOK (StrRetToStrW(&strret, NULL, &lpstr))
+ ODS_U(lpstr)
+ path = lpstr;
+ CoTaskMemFree(lpstr);
+ */
+ if (strret.uType != STRRET_WSTR)
+ return E_INVALIDARG;
+ ODS_U(strret.pOleStr)
+ path = strret.pOleStr;
+ // the path could have super path prefix "\\\\?\\"
+ // we can remove super path prefix here, if we don't need that prefix
+ #ifdef Z7_LONG_PATH
+ // we remove super prefix, if we can work without that prefix
+ NFile::NName::If_IsSuperPath_RemoveSuperPrefix(path);
+ #endif
+ names.AddInReserved(path);
+ CoTaskMemFree(strret.pOleStr);
+ }
+
+ ODS_(Print_Number(cida->cidl, "CFSTR_SHELLIDLIST END"))
+ return S_OK;
+}
+
+
+HRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &paths)
+{
+ ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names START")
+ HRESULT hres = NShell::DataObject_GetData_HDROP_Names(dataObject, paths);
+ // if (hres == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
+ if (hres != S_OK)
+ {
+ ODS("-- DataObject_GetData_IDLIST START")
+ // for (int y = 0; y < 10000; y++) // for debug
+ hres = NShell::DataObject_GetData_IDLIST(dataObject, paths);
+ }
+ ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names END")
+ return hres;
+}
+
+
+
+// #if (NTDDI_VERSION >= NTDDI_VISTA)
+typedef struct
+{
+ UINT cItems; // number of items in rgdwFileAttributes array
+ DWORD dwSumFileAttributes; // all of the attributes ORed together
+ DWORD dwProductFileAttributes; // all of the attributes ANDed together
+ DWORD rgdwFileAttributes[1]; // array
+} MYWIN_FILE_ATTRIBUTES_ARRAY;
+
+#define MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY TEXT("File Attributes Array")
+
+HRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs)
+{
+ attribs.Clear();
+ NCOM::CStgMedium medium;
+ RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT)
+ RegisterClipboardFormat(MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY), medium))
+ const size_t blockSize = GlobalSize(medium.hGlobal);
+ if (blockSize < sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY))
+ return E_INVALIDARG;
+ NMemory::CGlobalLock dropLock(medium.hGlobal);
+ const MYWIN_FILE_ATTRIBUTES_ARRAY *faa = (const MYWIN_FILE_ATTRIBUTES_ARRAY *)dropLock.GetPointer();
+ if (!faa)
+ return E_INVALIDARG;
+ const unsigned numFiles = faa->cItems;
+ if (numFiles == 0)
+ {
+ // is it posssible to have empty array here?
+ return E_INVALIDARG;
+ }
+ if ((blockSize - (sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY) - sizeof(DWORD)))
+ / sizeof(DWORD) != numFiles)
+ return E_INVALIDARG;
+ // attribs.Sum = faa->dwSumFileAttributes;
+ // attribs.Product = faa->dwProductFileAttributes;
+ // attribs.Vals.SetFromArray(faa->rgdwFileAttributes, numFiles);
+ // attribs.IsDirVector.ClearAndSetSize(numFiles);
+
+ if ((faa->dwSumFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ {
+ /* in win10: if selected items are volumes (c:\, d:\ ..) in My Compter,
+ all items have FILE_ATTRIBUTE_DIRECTORY attribute
+ ntfs volume also have FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM
+ udf volume: FILE_ATTRIBUTE_READONLY
+ dvd-rom device: (-1) : all bits are set
+ */
+ const DWORD *attr = faa->rgdwFileAttributes;
+ // DWORD product = (UInt32)0 - 1, sum = 0;
+ for (unsigned i = 0; i < numFiles; i++)
+ {
+ if (attr[i] & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ // attribs.ThereAreDirs = true;
+ attribs.FirstDirIndex = (int)i;
+ break;
+ }
+ // attribs.IsDirVector[i] = (attr[i] & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ // product &= v;
+ // sum |= v;
+ }
+ // ODS_(Print_Number(product, "Product calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
+ // ODS_(Print_Number(sum, "Sum calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
+ }
+ // ODS_(Print_Number(attribs.Product, "Product FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
+ // ODS_(Print_Number(attribs.Sum, "Sum FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
+ ODS_(Print_Number(numFiles, "FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
+ return S_OK;
+}
+
+
/////////////////////////////
// CDrop
+/*
+ win10:
+ DragQueryFile() implementation code is not effective because
+ there is no pointer inside DROP internal file list, so
+ DragQueryFile(fileIndex) runs all names in range [0, fileIndex].
+ DragQueryFile(,, buf, bufSize)
+ if (buf == NULL) by spec
+ {
+ returns value is the required size
+ in characters, of the buffer, not including the terminating null character
+ tests show that if (bufSize == 0), then it also returns required size.
+ }
+ if (bufSize != NULL)
+ {
+ returns: the count of the characters copied, not including null character.
+ win10: null character is also copied at position buf[ret_count];
+ }
+*/
+
+/*
void CDrop::Attach(HDROP object)
{
Free();
@@ -87,43 +476,133 @@ UINT CDrop::QueryCountOfFiles()
return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);
}
-UString CDrop::QueryFileName(UINT fileIndex)
+void CDrop::QueryFileName(UINT fileIndex, UString &fileName)
{
- UString fileName;
#ifndef _UNICODE
if (!g_IsNT)
{
AString fileNameA;
- UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);
- const unsigned len = bufferSize + 2;
- QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1);
+ const UINT len = QueryFile(fileIndex, (LPTSTR)NULL, 0);
+ const UINT numCopied = QueryFile(fileIndex, fileNameA.GetBuf(len + 2), len + 2);
fileNameA.ReleaseBuf_CalcLen(len);
+ if (numCopied != len)
+ throw 20221223;
fileName = GetUnicodeString(fileNameA);
}
else
#endif
{
- UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
- const unsigned len = bufferSize + 2;
- QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1);
+ // kReserve must be >= 3 for additional buffer size
+ // safety and for optimal performance
+ const unsigned kReserve = 3;
+ {
+ unsigned len = 0;
+ wchar_t *buf = fileName.GetBuf_GetMaxAvail(len);
+ if (len >= kReserve)
+ {
+ const UINT numCopied = QueryFile(fileIndex, buf, len);
+ if (numCopied < len - 1)
+ {
+ // (numCopied < len - 1) case means that it have copied full string.
+ fileName.ReleaseBuf_CalcLen(numCopied);
+ return;
+ }
+ }
+ }
+ const UINT len = QueryFile(fileIndex, (LPWSTR)NULL, 0);
+ const UINT numCopied = QueryFile(fileIndex,
+ fileName.GetBuf(len + kReserve), len + kReserve);
fileName.ReleaseBuf_CalcLen(len);
+ if (numCopied != len)
+ throw 20221223;
}
- return fileName;
}
+
void CDrop::QueryFileNames(UStringVector &fileNames)
{
UINT numFiles = QueryCountOfFiles();
+
+ Print_Number(numFiles, "\n====== CDrop::QueryFileNames START ===== \n");
+
fileNames.ClearAndReserve(numFiles);
+ UString s;
for (UINT i = 0; i < numFiles; i++)
- fileNames.AddInReserved(QueryFileName(i));
+ {
+ QueryFileName(i, s);
+ if (!s.IsEmpty())
+ fileNames.AddInReserved(s);
+ }
+ Print_Number(numFiles, "\n====== CDrop::QueryFileNames END ===== \n");
}
+*/
-bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
+// #if (NTDDI_VERSION >= NTDDI_VISTA)
+// SHGetPathFromIDListEx returns a win32 file system path for the item in the name space.
+typedef int Z7_WIN_GPFIDL_FLAGS;
+
+extern "C" {
+typedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath);
+typedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts);
+}
+
+#ifndef _UNICODE
+
+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, AString &path)
{
- const unsigned len = MAX_PATH * 2;
+ path.Empty();
+ const unsigned len = MAX_PATH + 16;
+ const bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
+ path.ReleaseBuf_CalcLen(len);
+ return result;
+}
+
+#endif
+
+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
+{
+ path.Empty();
+ unsigned len = MAX_PATH + 16;
+
+#ifdef _UNICODE
bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
+#else
+ const
+ Func_SHGetPathFromIDListW
+ shGetPathFromIDListW = Z7_GET_PROC_ADDRESS(
+ Func_SHGetPathFromIDListW, ::GetModuleHandleW(L"shell32.dll"),
+ "SHGetPathFromIDListW");
+ if (!shGetPathFromIDListW)
+ return false;
+ bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
+#endif
+
+ if (!result)
+ {
+ ODS("==== GetPathFromIDList() SHGetPathFromIDList() returned false")
+ /* for long path we need SHGetPathFromIDListEx().
+ win10: SHGetPathFromIDListEx() for long path returns path with
+ with super path prefix "\\\\?\\". */
+ const
+ Func_SHGetPathFromIDListEx
+ func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS(
+ Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L"shell32.dll"),
+ "SHGetPathFromIDListEx");
+ if (func_SHGetPathFromIDListEx)
+ {
+ ODS("==== GetPathFromIDList() (SHGetPathFromIDListEx)")
+ do
+ {
+ len *= 4;
+ result = BOOLToBool(func_SHGetPathFromIDListEx(itemIDList, path.GetBuf(len), len, 0));
+ if (result)
+ break;
+ }
+ while (len <= (1 << 16));
+ }
+ }
+
path.ReleaseBuf_CalcLen(len);
return result;
}
@@ -153,8 +632,8 @@ bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
MessageBoxW(0, L"yes", L"", 0);
*/
/*
- UString s = L"all files";
- s += L" (*.*)";
+ UString s = "all files";
+ s += " (*.*)";
return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
*/
return false;
@@ -162,11 +641,16 @@ bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
#else
+/* win10: SHBrowseForFolder() doesn't support long paths,
+ even if long path suppport is enabled in registry and in manifest.
+ and SHBrowseForFolder() doesn't support super path prefix "\\\\?\\". */
+
bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
{
+ resultPath.Empty();
NWindows::NCOM::CComInitializer comInitializer;
LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
- if (itemIDList == NULL)
+ if (!itemIDList)
return false;
CItemIDList itemIDListHolder;
itemIDListHolder.Attach(itemIDList);
@@ -174,7 +658,7 @@ bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
}
-int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
+static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
{
#ifndef UNDER_CE
switch (uMsg)
@@ -203,7 +687,7 @@ int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM da
}
-bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
+static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
LPCTSTR initialFolder, CSysString &resultPath)
{
CSysString displayName;
@@ -222,11 +706,18 @@ bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
browseInfo.lpszTitle = title;
// #endif
browseInfo.ulFlags = ulFlags;
- browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
+ browseInfo.lpfn = initialFolder ? BrowseCallbackProc : NULL;
browseInfo.lParam = (LPARAM)initialFolder;
return BrowseForFolder(&browseInfo, resultPath);
}
+#ifdef Z7_OLD_WIN_SDK
+// ShlObj.h:
+#ifndef BIF_NEWDIALOGSTYLE
+#define BIF_NEWDIALOGSTYLE 0x0040
+#endif
+#endif
+
bool BrowseForFolder(HWND owner, LPCTSTR title,
LPCTSTR initialFolder, CSysString &resultPath)
{
@@ -240,39 +731,29 @@ bool BrowseForFolder(HWND owner, LPCTSTR title,
#ifndef _UNICODE
-typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
-
-bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
-{
- path.Empty();
- SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)
- ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
- if (shGetPathFromIDListW == 0)
- return false;
- const unsigned len = MAX_PATH * 2;
- bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
- path.ReleaseBuf_CalcLen(len);
- return result;
+extern "C" {
+typedef LPITEMIDLIST (WINAPI * Func_SHBrowseForFolderW)(LPBROWSEINFOW lpbi);
}
-typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
-
-bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
+static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
{
NWindows::NCOM::CComInitializer comInitializer;
- SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
- ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");
- if (shBrowseForFolderW == 0)
+ const
+ Func_SHBrowseForFolderW
+ f_SHBrowseForFolderW = Z7_GET_PROC_ADDRESS(
+ Func_SHBrowseForFolderW, ::GetModuleHandleW(L"shell32.dll"),
+ "SHBrowseForFolderW");
+ if (!f_SHBrowseForFolderW)
return false;
- LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);
- if (itemIDList == NULL)
+ LPITEMIDLIST itemIDList = f_SHBrowseForFolderW(browseInfo);
+ if (!itemIDList)
return false;
CItemIDList itemIDListHolder;
itemIDListHolder.Attach(itemIDList);
return GetPathFromIDList(itemIDList, resultPath);
}
-
+static
int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
{
switch (uMsg)
@@ -311,7 +792,7 @@ static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
browseInfo.lpszTitle = title;
browseInfo.ulFlags = ulFlags;
- browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
+ browseInfo.lpfn = initialFolder ? BrowseCallbackProc2 : NULL;
browseInfo.lParam = (LPARAM)initialFolder;
return BrowseForFolder(&browseInfo, resultPath);
}