[BROWSEUI]

- CShellBrowser: Add some checks for failures that we re missing.
- CAddressEditBox: Add some checks for failures that we re missing.
- SHCreateFromDesktop: Actually create the proxy desktop window when needed and keep its handle and prefer it when we try to find the proxy desktop window.
- Wake the message queue of the proxy desktop after a browser thread exits so the proxy desktop can exit when the last browser thread exits.
- Add a hack to prefer to show my documents if we ended up trying to open a browser window with a NULL pidl. This is a hack that is needed because SHExplorerParseCmdLine is broken.
- Finally this fixes using "explorer /separate" and also fixes the separate process to exit when the last browser gets closed (this fix also applies to filebrowser.exe which no longer lives forever).
CORE-12168

svn path=/trunk/; revision=73132
This commit is contained in:
Giannis Adamopoulos 2016-11-05 14:40:55 +00:00
parent 7731fea285
commit 86fb59915f
3 changed files with 51 additions and 24 deletions

View file

@ -348,13 +348,22 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID ri
hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
isb->GetPidl(&absolutePIDL);
SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
hr = isb->GetPidl(&absolutePIDL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR | SHGDN_FORPARSING, &ret);
hr = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
StrRetToBufW(&ret, pidlChild, buf, 4095);
hr = sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR | SHGDN_FORPARSING, &ret);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = StrRetToBufW(&ret, pidlChild, buf, 4095);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
indexClosed = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);

View file

@ -5,6 +5,7 @@
#define PROXY_DESKTOP_CLASS L"Proxy Desktop"
BOOL g_SeparateFolders = FALSE;
HWND g_hwndProxyDesktop = NULL;
// fields indented more are unknown ;P
struct HNFBlock
@ -70,13 +71,13 @@ public:
END_MSG_MAP()
};
static CProxyDesktop * CreateProxyDesktop(IEThreadParamBlock * parameters)
{
return new CProxyDesktop(parameters);
}
HWND FindShellProxy(LPITEMIDLIST pidl)
{
/* If there is a proxy desktop in the current process use it */
if (g_hwndProxyDesktop)
return g_hwndProxyDesktop;
/* Try to find the desktop of the main explorer process */
if (!g_SeparateFolders)
{
HWND shell = GetShellWindow();
@ -92,6 +93,7 @@ HWND FindShellProxy(LPITEMIDLIST pidl)
TRACE("Separate folders setting enabled. Ignoring main desktop.\n");
}
/* The main desktop can't be find so try to see if another process has a proxy desktop */
HWND proxy = FindWindow(PROXY_DESKTOP_CLASS, NULL);
if (proxy)
{
@ -355,6 +357,12 @@ static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters)
if (parameters && parameters->offsetF8)
parameters->offsetF8->AddRef();
// HACK! This shouldn't happen! SHExplorerParseCmdLine needs fixing.
if (!parameters->directoryPIDL)
{
SHGetFolderLocation(NULL, CSIDL_PERSONAL, NULL, NULL, &parameters->directoryPIDL);
}
hResult = CShellBrowser_CreateInstance(parameters->directoryPIDL, parameters->dwFlags, IID_PPV_ARG(IBrowserService2, &browser));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
@ -402,6 +410,10 @@ static DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter)
/* Destroying the parameters releases the thread reference */
SHDestroyIETHREADPARAM(parameters);
/* Wake up the proxy desktop thread so it can check whether the last browser thread exited */
/* Use PostMessage in order to force GetMessage to return and check if all browser windows have exited */
PostMessageW(FindShellProxy(NULL), WM_EXPLORER_1037, 0, 0);
OleUninitialize();
return 0;
@ -630,9 +642,11 @@ BOOL WINAPI SHCreateFromDesktop(ExplorerCommandLineParseResults * parseResults)
// Else, start our own message loop!
HRESULT hr = CoInitialize(NULL);
CProxyDesktop * proxy = CreateProxyDesktop(parameters);
CProxyDesktop * proxy = new CProxyDesktop(parameters);
if (proxy)
{
g_hwndProxyDesktop = proxy->Create(0);
LONG refCount;
CComPtr<IUnknown> thread;
if (SHCreateThreadRef(&refCount, &thread) >= 0)
@ -652,6 +666,8 @@ BOOL WINAPI SHCreateFromDesktop(ExplorerCommandLineParseResults * parseResults)
DispatchMessageW(&Msg);
}
DestroyWindow(g_hwndProxyDesktop);
delete proxy;
}

View file

@ -1040,25 +1040,27 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
HIMAGELIST himlSmall, himlLarge;
CComPtr<IShellFolder> sf;
SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
hResult = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
if (SUCCEEDED(hResult))
{
index = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
index = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
Shell_GetImageLists(&himlLarge, &himlSmall);
Shell_GetImageLists(&himlLarge, &himlSmall);
HICON icSmall = ImageList_GetIcon(himlSmall, indexOpen, 0);
HICON icLarge = ImageList_GetIcon(himlLarge, indexOpen, 0);
HICON icSmall = ImageList_GetIcon(himlSmall, indexOpen, 0);
HICON icLarge = ImageList_GetIcon(himlLarge, indexOpen, 0);
/* Hack to make it possible to release the old icons */
/* Something seems to go wrong with WM_SETICON */
HICON oldSmall = (HICON)SendMessage(WM_GETICON, ICON_SMALL, 0);
HICON oldLarge = (HICON)SendMessage(WM_GETICON, ICON_BIG, 0);
/* Hack to make it possible to release the old icons */
/* Something seems to go wrong with WM_SETICON */
HICON oldSmall = (HICON)SendMessage(WM_GETICON, ICON_SMALL, 0);
HICON oldLarge = (HICON)SendMessage(WM_GETICON, ICON_BIG, 0);
SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icSmall));
SendMessage(WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(icLarge));
SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icSmall));
SendMessage(WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(icLarge));
DestroyIcon(oldSmall);
DestroyIcon(oldLarge);
DestroyIcon(oldSmall);
DestroyIcon(oldLarge);
}
}
FireCommandStateChangeAll();