From 1e44d47830014b5d67160a815d74f8f19a7ecebc Mon Sep 17 00:00:00 2001 From: David Quintana Date: Fri, 26 Sep 2014 14:47:07 +0000 Subject: [PATCH] [BROWSEUI] * Implement SHCreateFromDesktop and supporting functions, and move those implementations to their own file. [SHELL32] * Handle message 1035 from the desktop window. [SHLWAPI] * Fix a bug in SHAllocShared, where source and destination parameters were reversed. [EXPLORER-NEW] * Use SHCreateFromDesktop to open the new window. NOTE: There appears to be some more problems with the SH*Shared implementation, beyond the swapped parameters, which prevent the opening of the new windows. These functions will have to be revised and the corrected implementation sent to WINE. svn path=/branches/shell-experiments/; revision=64314 --- base/shell/explorer-new/explorer.c | 96 ++--- base/shell/explorer-new/traywnd.c | 6 +- base/shell/filebrowser/CMakeLists.txt | 2 +- base/shell/filebrowser/filebrowser.c | 111 +---- dll/win32/browseui/CMakeLists.txt | 1 + dll/win32/browseui/browseuiord.cpp | 134 ------ dll/win32/browseui/desktopipc.cpp | 591 ++++++++++++++++++++++++++ dll/win32/browseui/shellbrowser.cpp | 6 - dll/win32/shell32/desktop.cpp | 5 + dll/win32/shell32/undocshell.h | 24 -- dll/win32/shlwapi/ordinal.c | 32 +- include/psdk/shlwapi.h | 10 + include/psdk/shlwapi_undoc.h | 87 ++-- 13 files changed, 733 insertions(+), 372 deletions(-) create mode 100644 dll/win32/browseui/desktopipc.cpp diff --git a/base/shell/explorer-new/explorer.c b/base/shell/explorer-new/explorer.c index 28d7c9e11d3..36980e6ed23 100644 --- a/base/shell/explorer-new/explorer.c +++ b/base/shell/explorer-new/explorer.c @@ -383,6 +383,25 @@ _tWinMain(IN HINSTANCE hInstance, DbgPrint("Explorer starting... Commandline: %S\n", lpCmdLine); + /* + * Set our shutdown parameters: we want to shutdown the very last, + * but before any TaskMgr instance (which has a shutdown level of 1). + */ + SetProcessShutdownParameters(2, 0); + + if (GetShellWindow() == NULL) + CreateShellDesktop = TRUE; + + /* FIXME - initialize SSO Thread */ + + if (!CreateShellDesktop) + { + EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 }; + + if (SHExplorerParseCmdLine(&parseResults)) + return SHCreateFromDesktop(&parseResults); + } + if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkExplorer) != ERROR_SUCCESS) @@ -407,72 +426,33 @@ _tWinMain(IN HINSTANCE hInstance, InitCommonControls(); OleInitialize(NULL); - /* - * Set our shutdown parameters: we want to shutdown the very last, - * but before any TaskMgr instance (which has a shutdown level of 1). - */ - SetProcessShutdownParameters(2, 0); - ProcessStartupItems(); - if (GetShellWindow() == NULL) - CreateShellDesktop = TRUE; + /* Initialize shell dde support */ + ShellDDEInit(TRUE); - /* FIXME - initialize SSO Thread */ + /* Initialize shell icons */ + FileIconInit(TRUE); - if (CreateShellDesktop) + /* Initialize CLSID_ShellWindows class */ + WinList_Init(); + + if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass()) { - /* Initialize shell dde support */ - ShellDDEInit(TRUE); + Tray = CreateTrayWindow(); + /* This not only hides the minimized window captions in the bottom + left screen corner, but is also needed in order to receive + HSHELL_* notification messages (which are required for taskbar + buttons to work right) */ + HideMinimizedWindows(TRUE); - /* Initialize shell icons */ - FileIconInit(TRUE); - - /* Initialize CLSID_ShellWindows class */ - WinList_Init(); - - if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass()) - { - Tray = CreateTrayWindow(); - /* This not only hides the minimized window captions in the bottom - left screen corner, but is also needed in order to receive - HSHELL_* notification messages (which are required for taskbar - buttons to work right) */ - HideMinimizedWindows(TRUE); - - if (Tray != NULL) - hShellDesktop = DesktopCreateWindow(Tray); - } - - /* WinXP: Notify msgina to hide the welcome screen */ - if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent"))) - SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent")); + if (Tray != NULL) + hShellDesktop = DesktopCreateWindow(Tray); } - else - { - HRESULT hr; - EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 }; - if (!SHExplorerParseCmdLine(&parseResults)) - return 0; - - // TODO: Handle the case where .strPath was assigned instead of .pidlPath - - if (parseResults.dwFlags & SH_EXPLORER_CMDLINE_FLAG_IDLIST) - { - TRACE("Trying to open browser window... \n"); - - hr = SHOpenNewFrame(parseResults.pidlPath, NULL, 0, 0); - if (FAILED(hr)) - return 0; - - /* FIXME: we should wait a bit here and see if a window was created. If not we should exit this process. */ - Sleep(1000); - ExitThread(0); - - return 0; - } - } + /* WinXP: Notify msgina to hide the welcome screen */ + if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent"))) + SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent")); if (Tray != NULL) { diff --git a/base/shell/explorer-new/traywnd.c b/base/shell/explorer-new/traywnd.c index 086ca5c793b..3e04bf42ee6 100644 --- a/base/shell/explorer-new/traywnd.c +++ b/base/shell/explorer-new/traywnd.c @@ -2199,7 +2199,8 @@ static void PopupStartMenu(IN ITrayWindowImpl *This) } } -static void ProcessMouseTracking(ITrayWindowImpl * This) +static void +ProcessMouseTracking(ITrayWindowImpl * This) { RECT rcCurrent; POINT pt; @@ -2249,7 +2250,8 @@ static void ProcessMouseTracking(ITrayWindowImpl * This) } } -static void ProcessAutoHide(ITrayWindowImpl * This) +static void +ProcessAutoHide(ITrayWindowImpl * This) { RECT rc = This->rcTrayWnd[This->Position]; INT w = This->TraySize.cx - GetSystemMetrics(SM_CXBORDER) * 2 - 1; diff --git a/base/shell/filebrowser/CMakeLists.txt b/base/shell/filebrowser/CMakeLists.txt index aaee7bde933..bc2b50ccc7c 100644 --- a/base/shell/filebrowser/CMakeLists.txt +++ b/base/shell/filebrowser/CMakeLists.txt @@ -12,4 +12,4 @@ add_importlibs(filebrowser msvcrt kernel32) -add_cd_file(TARGET explorer DESTINATION reactos FOR all) +add_cd_file(TARGET filebrowser DESTINATION reactos FOR all) diff --git a/base/shell/filebrowser/filebrowser.c b/base/shell/filebrowser/filebrowser.c index d7e22d95bac..c8a822812f4 100644 --- a/base/shell/filebrowser/filebrowser.c +++ b/base/shell/filebrowser/filebrowser.c @@ -23,115 +23,18 @@ #include #include #include +#include +#include +#include typedef HRESULT (WINAPI *SH_OPEN_NEW_FRAME)(LPITEMIDLIST pidl, IUnknown *paramC, long param10, long param14); int _tmain(int argc, _TCHAR* argv[]) { - WCHAR root[MAX_PATH]; - HRESULT hr; - LPSHELLFOLDER pDesktopFolder = NULL; - LPITEMIDLIST pidlRoot = NULL; - typedef HRESULT(WINAPI *SH_OPEN_NEW_FRAME)(LPITEMIDLIST pidl, IUnknown *paramC, long param10, long param14); - SH_OPEN_NEW_FRAME SHOpenNewFrame; + EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 }; - HMODULE hBrowseui = LoadLibraryW(L"browseui.dll"); + if (SHExplorerParseCmdLine(&parseResults)) + return SHCreateFromDesktop(&parseResults); - if (!hBrowseui) - return 1; - - - if (argc < 2) - { - SH_OPEN_NEW_FRAME SHOpenNewFrame = (SH_OPEN_NEW_FRAME) GetProcAddress(hBrowseui, (LPCSTR) 103); - LPITEMIDLIST pidlDrives; - SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlDrives); - SHOpenNewFrame((LPITEMIDLIST) pidlDrives, NULL, 0, 0); - } - else - { - /* A shell is already loaded. Parse the command line arguments - and unless we need to do something specific simply display - the desktop in a separate explorer window */ - /* FIXME */ - - /* Commandline switches: - * - * /n Open a new window, even if an existing one still exists. - * /e Start with the explorer sidebar shown. - * /root, Open a window for the given object path. - * /select, Open a window with the given object selected. - */ - - /* FIXME: Do it right */ - WCHAR* tmp = wcsstr(argv[1], L"/root,"); - if (tmp) - { - WCHAR* tmp2; - - tmp += 6; // skip to beginning of path - tmp2 = wcschr(tmp, L','); - - if (tmp2) - { - wcsncpy(root, tmp, tmp2 - tmp); - } - else - { - wcscpy(root, tmp); - } - } - else - { - wcscpy(root, argv[1]); - } - - if (root[0] == L'"') - { - int len = wcslen(root) - 2; - wcsncpy(root, root + 1, len); - root[len] = 0; - } - - if (wcslen(root) > 0) - { - LPITEMIDLIST pidl; - ULONG chEaten; - ULONG dwAttributes; - - if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder))) - { - hr = pDesktopFolder->lpVtbl->ParseDisplayName(pDesktopFolder, - NULL, - NULL, - root, - &chEaten, - &pidl, - &dwAttributes); - if (SUCCEEDED(hr)) - { - pidlRoot = pidl; - } - } - } - - if (!pidlRoot) - { - hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlRoot); - if (FAILED(hr)) - return 0; - } - - SHOpenNewFrame = (SH_OPEN_NEW_FRAME) GetProcAddress(hBrowseui, (LPCSTR) 103); - - hr = SHOpenNewFrame(pidlRoot, (IUnknown*) pDesktopFolder, 0, 0); - if (FAILED(hr)) - return 0; - } - - /* FIXME: we should wait a bit here and see if a window was created. If not we should exit this process. */ - Sleep(1000); - - ExitThread(0); + return 0; } - diff --git a/dll/win32/browseui/CMakeLists.txt b/dll/win32/browseui/CMakeLists.txt index 7c9877f5fbf..0d92a03b543 100644 --- a/dll/win32/browseui/CMakeLists.txt +++ b/dll/win32/browseui/CMakeLists.txt @@ -22,6 +22,7 @@ list(APPEND SOURCE browseui.cpp browseuiord.cpp commonbrowser.cpp + desktopipc.cpp globalfoldersettings.cpp internettoolbar.cpp parsecmdline.cpp diff --git a/dll/win32/browseui/browseuiord.cpp b/dll/win32/browseui/browseuiord.cpp index 6f4d869b3e5..e198f06462b 100644 --- a/dll/win32/browseui/browseuiord.cpp +++ b/dll/win32/browseui/browseuiord.cpp @@ -20,8 +20,6 @@ #include "precomp.h" -extern DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter); - /************************************************************************* * InitOCHostClass [BROWSEUI.101] */ @@ -30,14 +28,6 @@ extern "C" void WINAPI InitOCHostClass(long param8) // forwards to shdocvw } -/************************************************************************* - * SHOpenFolderWindow [BROWSEUI.102] - */ -extern "C" long WINAPI SHOpenFolderWindow(IEThreadParamBlock *param8) -{ - return 0; -} - /************************************************************************* * SHCreateSavedWindows [BROWSEUI.105] * Called to recreate explorer windows from previous session @@ -46,15 +36,6 @@ extern "C" void WINAPI SHCreateSavedWindows() { } -/************************************************************************* - * SHCreateFromDesktop [BROWSEUI.106] - * parameter is a FolderInfo - */ -extern "C" long WINAPI SHCreateFromDesktop(long param8) -{ - return -1; -} - /************************************************************************* * SHExplorerParseCmdLine [BROWSEUI.107] */ @@ -91,54 +72,6 @@ extern "C" long WINAPI IDataObject_GetDeskBandState(long param8) return -1; } -/************************************************************************* - * SHCreateIETHREADPARAM [BROWSEUI.123] - */ -extern "C" IEThreadParamBlock *WINAPI SHCreateIETHREADPARAM( - long param8, long paramC, IUnknown *param10, IUnknown *param14) -{ - IEThreadParamBlock *result; - - result = (IEThreadParamBlock *)LocalAlloc(LMEM_ZEROINIT, 256); - if (result == NULL) - return NULL; - result->offset0 = param8; - result->offset8 = paramC; - result->offsetC = param10; - if (param10 != NULL) - param10->AddRef(); - result->offset14 = param14; - if (param14 != NULL) - param14->AddRef(); - return result; -} - -/************************************************************************* - * SHCloneIETHREADPARAM [BROWSEUI.124] - */ -extern "C" IEThreadParamBlock *WINAPI SHCloneIETHREADPARAM(IEThreadParamBlock *param) -{ - IEThreadParamBlock *result; - - result = (IEThreadParamBlock *)LocalAlloc(LMEM_FIXED, 256); - if (result == NULL) - return NULL; - memcpy(result, param, 0x40 * 4); - if (result->directoryPIDL != NULL) - result->directoryPIDL = ILClone(result->directoryPIDL); - if (result->offset7C != NULL) - result->offset7C = ILClone(result->offset7C); - if (result->offset80 != NULL) - result->offset80 = ILClone(result->offset80); - if (result->offset70 != NULL) - result->offset70->AddRef(); -#if 0 - if (result->offsetC != NULL) - result->offsetC->Method2C(); -#endif - return result; -} - /************************************************************************* * SHParseIECommandLine [BROWSEUI.125] */ @@ -147,40 +80,6 @@ extern "C" long WINAPI SHParseIECommandLine(long param8, long paramC) return -1; } -/************************************************************************* - * SHDestroyIETHREADPARAM [BROWSEUI.126] - */ -extern "C" void WINAPI SHDestroyIETHREADPARAM(IEThreadParamBlock *param) -{ - if (param == NULL) - return; - if (param->directoryPIDL != NULL) - ILFree(param->directoryPIDL); - if (param->offset7C != NULL) - ILFree(param->offset7C); - if ((param->offset4 & 0x80000) == 0 && param->offset80 != NULL) - ILFree(param->offset80); - if (param->offset14 != NULL) - param->offset14->Release(); - if (param->offset70 != NULL) - param->offset70->Release(); - if (param->offset78 != NULL) - param->offset78->Release(); - if (param->offsetC != NULL) - param->offsetC->Release(); - if (param->offsetF8 != NULL) - param->offsetF8->Release(); - LocalFree(param); -} - -/************************************************************************* - * SHOnCWMCommandLine [BROWSEUI.127] - */ -extern "C" HRESULT WINAPI SHOnCWMCommandLine(long param8) -{ - return E_NOTIMPL; -} - /************************************************************************* * Channel_GetFolderPidl [BROWSEUI.128] */ @@ -261,36 +160,3 @@ extern "C" BOOL WINAPI SHIsExplorerBrowser() { return TRUE; } - -// 75FA56C1h -// (pidl, 0, -1, 1) -// this function should handle creating a new process if needed, but I'm leaving that out for now -// this function always opens a new window - it does NOT check for duplicates -/************************************************************************* - * SHOpenNewFrame [BROWSEUI.103] - */ -extern "C" HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, long param14) -{ - IEThreadParamBlock *parameters; - HANDLE threadHandle; - DWORD threadID; - - parameters = SHCreateIETHREADPARAM(0, 1, paramC, NULL); - if (parameters == NULL) - { - ILFree(pidl); - return E_OUTOFMEMORY; - } - if (paramC != NULL) - parameters->offset10 = param10; - parameters->directoryPIDL = pidl; - parameters->offset4 = param14; - threadHandle = CreateThread(NULL, 0x10000, BrowserThreadProc, parameters, 0, &threadID); - if (threadHandle != NULL) - { - CloseHandle(threadHandle); - return S_OK; - } - SHDestroyIETHREADPARAM(parameters); - return E_FAIL; -} diff --git a/dll/win32/browseui/desktopipc.cpp b/dll/win32/browseui/desktopipc.cpp new file mode 100644 index 00000000000..6d405b3a727 --- /dev/null +++ b/dll/win32/browseui/desktopipc.cpp @@ -0,0 +1,591 @@ +#include "precomp.h" +#include +#include + +#define PROXY_DESKTOP_CLASS L"Proxy Desktop" + +BOOL g_SeparateFolders = FALSE; + +// fields indented more are unknown ;P +struct HNFBlock +{ + UINT cbSize; + DWORD offset4; + DWORD offset8; + DWORD offsetC; + DWORD offset10; + DWORD offset14; + DWORD offset18; + DWORD offset1C; + DWORD offset20; + DWORD offset24; + DWORD offset28; + DWORD offset2C; + DWORD offset30; + UINT directoryPidlLength; + UINT pidlSize7C; + UINT pidlSize80; + UINT pathLength; +}; + +extern DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter); + +class CProxyDesktop : + public CComObjectRootEx, + public CWindowImpl < CProxyDesktop, CWindow, CFrameWinTraits > +{ + IEThreadParamBlock * m_Parameters; + + LPITEMIDLIST m_rootPidl; + +public: + CProxyDesktop(IEThreadParamBlock * parameters) : + m_Parameters(parameters) + { + + } + + virtual ~CProxyDesktop() + { + } + + LRESULT OnMessage1037(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + DbgPrint("Proxy Desktop message 1037.\n"); + bHandled = TRUE; + return TRUE; + } + + LRESULT OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + DbgPrint("Proxy Desktop message 1035 received.\n"); + bHandled = TRUE; + SHOnCWMCommandLine((HANDLE) lParam); + return 0; + } + + DECLARE_WND_CLASS_EX(PROXY_DESKTOP_CLASS, CS_SAVEBITS | CS_DROPSHADOW, COLOR_3DFACE) + + BEGIN_MSG_MAP(CProxyDesktop) + MESSAGE_HANDLER(WM_EXPLORER_1037, OnMessage1037) + MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW, OnOpenNewWindow) + END_MSG_MAP() +}; + +static CProxyDesktop * CreateProxyDesktop(IEThreadParamBlock * parameters) +{ + return new CProxyDesktop(parameters); +} + +HWND FindShellProxy(LPITEMIDLIST pidl) +{ + if (!g_SeparateFolders) + { + HWND shell = GetShellWindow(); + + if (shell) + { + DbgPrint("Found main desktop.\n"); + return shell; + } + } + else + { + DbgPrint("Separate folders setting enabled. Ignoring main desktop.\n"); + } + + HWND proxy = FindWindow(PROXY_DESKTOP_CLASS, NULL); + if (proxy) + { + DbgPrint("Found proxy desktop.\n"); + return proxy; + } + + return NULL; +} + +HANDLE MakeSharedPacket(IEThreadParamBlock * threadParams, LPCWSTR strPath, int dwProcessId) +{ + HNFBlock* hnfData; + UINT sharedBlockSize = sizeof(*hnfData); + UINT directoryPidlLength = 0; + UINT pidlSize7C = 0; + UINT pidlSize80 = 0; + UINT pathLength = 0; + LPITEMIDLIST pidl80 = threadParams->offset80; + + // Count the total length of the message packet + + // directory PIDL + if (threadParams->directoryPIDL) + { + directoryPidlLength = ILGetSize(threadParams->directoryPIDL); + sharedBlockSize += directoryPidlLength; + DbgPrint("directoryPidlLength=%d\n", directoryPidlLength); + } + + // another PIDL + if (threadParams->offset7C) + { + pidlSize7C = ILGetSize(threadParams->offset7C); + sharedBlockSize += pidlSize7C; + DbgPrint("pidlSize7C=%d\n", pidlSize7C); + } + + // This flag indicates the presence of another pidl? + if (!(threadParams->offset84 & 0x8000)) + { + if (pidl80) + { + pidlSize80 = ILGetSize(pidl80); + sharedBlockSize += pidlSize80; + DbgPrint("pidlSize80=%d\n", pidlSize7C); + } + } + else + { + DbgPrint("pidl80 sent by value = %p\n", pidl80); + pidlSize80 = 4; + sharedBlockSize += pidlSize80; + } + + // The path string + if (strPath) + { + pathLength = 2 * lstrlenW(strPath) + 2; + sharedBlockSize += pathLength; + DbgPrint("pathLength=%d\n", pidlSize7C); + } + + DbgPrint("sharedBlockSize=%d\n", sharedBlockSize); + + // Allocate and fill the shared section + HANDLE hShared = SHAllocShared(0, sharedBlockSize, dwProcessId); + if (!hShared) + { + DbgPrint("Shared section alloc error.\n"); + return 0; + } + + PBYTE target = (PBYTE) SHLockShared(hShared, dwProcessId); + if (!target) + { + DbgPrint("Shared section lock error. %d\n", GetLastError()); + SHFreeShared(hShared, dwProcessId); + return 0; + } + + // Basic information + hnfData = (HNFBlock*) target; + hnfData->cbSize = sharedBlockSize; + hnfData->offset4 = (DWORD) (threadParams->dwFlags); + hnfData->offset8 = (DWORD) (threadParams->offset8); + hnfData->offsetC = (DWORD) (threadParams->offset74); + hnfData->offset10 = (DWORD) (threadParams->offsetD8); + hnfData->offset14 = (DWORD) (threadParams->offset84); + hnfData->offset18 = (DWORD) (threadParams->offset88); + hnfData->offset1C = (DWORD) (threadParams->offset8C); + hnfData->offset20 = (DWORD) (threadParams->offset90); + hnfData->offset24 = (DWORD) (threadParams->offset94); + hnfData->offset28 = (DWORD) (threadParams->offset98); + hnfData->offset2C = (DWORD) (threadParams->offset9C); + hnfData->offset30 = (DWORD) (threadParams->offsetA0); + hnfData->directoryPidlLength = 0; + hnfData->pidlSize7C = 0; + hnfData->pidlSize80 = 0; + hnfData->pathLength = 0; + target += sizeof(*hnfData); + + // Copy the directory pidl contents + if (threadParams->directoryPIDL) + { + memcpy(target, threadParams->directoryPIDL, directoryPidlLength); + target += directoryPidlLength; + hnfData->directoryPidlLength = directoryPidlLength; + } + + // Copy the other pidl contents + if (threadParams->offset7C) + { + memcpy(target, threadParams->offset7C, pidlSize7C); + target += pidlSize7C; + hnfData->pidlSize7C = pidlSize7C; + } + + // copy the third pidl + if (threadParams->offset84 & 0x8000) + { + *(LPITEMIDLIST*) target = pidl80; + target += pidlSize80; + hnfData->pidlSize80 = pidlSize80; + } + else if (pidl80) + { + memcpy(target, pidl80, pidlSize80); + target += pidlSize80; + hnfData->pidlSize80 = pidlSize80; + } + + // and finally the path string + if (strPath) + { + memcpy(target, strPath, pathLength); + hnfData->pathLength = pathLength; + } + + SHUnlockShared(hnfData); + + return hShared; +} + +PIE_THREAD_PARAM_BLOCK ParseSharedPacket(HANDLE hData) +{ + HNFBlock * hnfData; + PBYTE block; + int pid; + PIE_THREAD_PARAM_BLOCK params = NULL; + + if (!hData) + goto cleanup0; + + pid = GetCurrentProcessId(); + block = (PBYTE) SHLockShared(hData, pid); + + hnfData = (HNFBlock *) block; + if (!block) + goto cleanup2; + + if (hnfData->cbSize < sizeof(HNFBlock)) + goto cleanup2; + + params = SHCreateIETHREADPARAM(0, hnfData->offset8, 0, 0); + if (!params) + goto cleanup2; + + params->dwFlags = hnfData->offset4; + params->offset8 = hnfData->offset8; + params->offset74 = hnfData->offsetC; + params->offsetD8 = hnfData->offset10; + params->offset84 = hnfData->offset14; + params->offset88 = hnfData->offset18; + params->offset8C = hnfData->offset1C; + params->offset90 = hnfData->offset20; + params->offset94 = hnfData->offset24; + params->offset98 = hnfData->offset28; + params->offset9C = hnfData->offset2C; + params->offsetA0 = hnfData->offset30; + + block += sizeof(*hnfData); + if (hnfData->directoryPidlLength) + { + LPITEMIDLIST pidl = NULL; + if (*block) + pidl = ILClone((LPITEMIDLIST) block); + params->directoryPIDL = pidl; + + block += hnfData->directoryPidlLength; + } + + if (hnfData->pidlSize7C) + { + LPITEMIDLIST pidl = NULL; + if (*block) + pidl = ILClone((LPITEMIDLIST) block); + params->offset7C = pidl; + + block += hnfData->pidlSize80; + } + + if (hnfData->pidlSize80) + { + if (!(params->offset84 & 0x8000)) + { + params->offset80 = *(LPITEMIDLIST *) block; + } + else + { + LPITEMIDLIST pidl = NULL; + if (*block) + pidl = ILClone((LPITEMIDLIST) block); + params->offset80 = pidl; + } + + block += hnfData->pidlSize80; + } + + if (hnfData->pathLength) + { + CComPtr psfDesktop; + PWSTR strPath = (PWSTR) block; + + if (FAILED(SHGetDesktopFolder(&psfDesktop))) + { + params->directoryPIDL = NULL; + goto cleanup0; + } + + if (FAILED(psfDesktop->ParseDisplayName(NULL, NULL, strPath, NULL, ¶ms->directoryPIDL, NULL))) + { + params->directoryPIDL = NULL; + goto cleanup0; + } + } + +cleanup2: + SHUnlockShared(hnfData); + SHFreeShared(hData, pid); + +cleanup0: + if (!params->directoryPIDL) + { + SHDestroyIETHREADPARAM(params); + return NULL; + } + + return params; +} + + +/************************************************************************* +* SHOnCWMCommandLine [BROWSEUI.127] +*/ +extern "C" BOOL WINAPI SHOnCWMCommandLine(HANDLE hSharedInfo) +{ + DbgPrint("SHOnCWMCommandLine\n"); + + PIE_THREAD_PARAM_BLOCK params = ParseSharedPacket(hSharedInfo); + + if (params) + return SHOpenFolderWindow(params); + + return FALSE; +} + +/************************************************************************* +* SHCreateIETHREADPARAM [BROWSEUI.123] +*/ +extern "C" IEThreadParamBlock *WINAPI SHCreateIETHREADPARAM( + long param8, long paramC, IUnknown *param10, IUnknown *param14) +{ + IEThreadParamBlock *result; + + DbgPrint("SHCreateIETHREADPARAM\n"); + + result = (IEThreadParamBlock *) LocalAlloc(LMEM_ZEROINIT, 256); + if (result == NULL) + return NULL; + result->offset0 = param8; + result->offset8 = paramC; + result->offsetC = param10; + if (param10 != NULL) + param10->AddRef(); + result->offset14 = param14; + if (param14 != NULL) + param14->AddRef(); + return result; +} + +/************************************************************************* +* SHCloneIETHREADPARAM [BROWSEUI.124] +*/ +extern "C" IEThreadParamBlock *WINAPI SHCloneIETHREADPARAM(IEThreadParamBlock *param) +{ + IEThreadParamBlock *result; + + DbgPrint("SHCloneIETHREADPARAM\n"); + + result = (IEThreadParamBlock *) LocalAlloc(LMEM_FIXED, 256); + if (result == NULL) + return NULL; + memcpy(result, param, 0x40 * 4); + if (result->directoryPIDL != NULL) + result->directoryPIDL = ILClone(result->directoryPIDL); + if (result->offset7C != NULL) + result->offset7C = ILClone(result->offset7C); + if (result->offset80 != NULL) + result->offset80 = ILClone(result->offset80); + if (result->offset70 != NULL) + result->offset70->AddRef(); +#if 0 + if (result->offsetC != NULL) + result->offsetC->Method2C(); +#endif + return result; +} + +/************************************************************************* +* SHDestroyIETHREADPARAM [BROWSEUI.126] +*/ +extern "C" void WINAPI SHDestroyIETHREADPARAM(IEThreadParamBlock *param) +{ + DbgPrint("SHDestroyIETHREADPARAM\n"); + + if (param == NULL) + return; + if (param->directoryPIDL != NULL) + ILFree(param->directoryPIDL); + if (param->offset7C != NULL) + ILFree(param->offset7C); + if ((param->dwFlags & 0x80000) == 0 && param->offset80 != NULL) + ILFree(param->offset80); + if (param->offset14 != NULL) + param->offset14->Release(); + if (param->offset70 != NULL) + param->offset70->Release(); + if (param->offset78 != NULL) + param->offset78->Release(); + if (param->offsetC != NULL) + param->offsetC->Release(); + if (param->offsetF8 != NULL) + param->offsetF8->Release(); + LocalFree(param); +} + +/************************************************************************* +* SHOpenFolderWindow [BROWSEUI.102] +* see SHOpenNewFrame below for remarks +*/ +extern "C" HRESULT WINAPI SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters) +{ + HANDLE threadHandle; + DWORD threadID; + + DbgPrint("SHOpenFolderWindow\n"); + + threadHandle = CreateThread(NULL, 0x10000, BrowserThreadProc, parameters, 0, &threadID); + if (threadHandle != NULL) + { + CloseHandle(threadHandle); + return S_OK; + } + SHDestroyIETHREADPARAM(parameters); + return E_FAIL; +} + +// 75FA56C1h +// (pidl, 0, -1, 1) +// this function should handle creating a new process if needed, but I'm leaving that out for now +// this function always opens a new window - it does NOT check for duplicates +/************************************************************************* +* SHOpenNewFrame [BROWSEUI.103] +*/ +extern "C" HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags) +{ + IEThreadParamBlock *parameters; + + DbgPrint("SHOpenNewFrame\n"); + + parameters = SHCreateIETHREADPARAM(0, 1, paramC, NULL); + if (parameters == NULL) + { + ILFree(pidl); + return E_OUTOFMEMORY; + } + if (paramC != NULL) + parameters->offset10 = param10; + parameters->directoryPIDL = pidl; + parameters->dwFlags = dwFlags; + + return SHOpenFolderWindow(parameters); +} + +/************************************************************************* +* SHCreateFromDesktop [BROWSEUI.106] +* parameter is a FolderInfo +*/ +BOOL WINAPI SHCreateFromDesktop(ExplorerCommandLineParseResults * parseResults) +{ + DbgPrint("SHCreateFromDesktop\n"); + + IEThreadParamBlock * parameters = SHCreateIETHREADPARAM(0, 0, 0, 0); + if (!parameters) + return FALSE; + + PCWSTR strPath = NULL; + if (parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_STRING) + { + if (parseResults->pidlPath) + { + WARN("strPath and pidlPath are both assigned. This shouldn't happen.\n"); + } + + strPath = parseResults->strPath; + } + + parameters->dwFlags = parseResults->dwFlags; + parameters->offset8 = parseResults->offsetC; + + LPITEMIDLIST pidl = parseResults->pidlPath ? ILClone(parseResults->pidlPath) : NULL; + if (!pidl && parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_STRING) + { + if (parseResults->strPath && parseResults->strPath[0]) + { + pidl = ILCreateFromPathW(parseResults->strPath); + } + } + + parameters->directoryPIDL = pidl; + + // Try to find the owner of the idlist, if we aren't running /SEPARATE + HWND desktop = NULL; + if (!(parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_SEPARATE)) + desktop = FindShellProxy(parameters->directoryPIDL); + + // If found, ask it to open the new window + if (desktop) + { + DbgPrint("Found desktop hwnd=%p\n", desktop); + + DWORD dwProcessId; + + GetWindowThreadProcessId(desktop, &dwProcessId); + AllowSetForegroundWindow(dwProcessId); + + HANDLE hShared = MakeSharedPacket(parameters, strPath, dwProcessId); + if (hShared) + { + DbgPrint("Sending open message...\n"); + + PostMessageW(desktop, WM_EXPLORER_OPEN_NEW_WINDOW, 0, (LPARAM) hShared); + } + + SHDestroyIETHREADPARAM(parameters); + return TRUE; + } + + DbgPrint("Desktop not found or separate flag requested.\n"); + + // Else, start our own message loop! + HRESULT hr = CoInitialize(NULL); + CProxyDesktop * proxy = CreateProxyDesktop(parameters); + if (proxy) + { + LONG refCount; + CComPtr thread; + if (SHCreateThreadRef(&refCount, &thread) >= 0) + { + SHSetInstanceExplorer(thread); + if (strPath) + parameters->directoryPIDL = ILCreateFromPath(strPath); + SHOpenFolderWindow(parameters); + parameters = NULL; + thread.Release(); + } + + MSG Msg; + while (GetMessageW(&Msg, 0, 0, 0) && refCount) + { + TranslateMessage(&Msg); + DispatchMessageW(&Msg); + } + + delete proxy; + } + + if (SUCCEEDED(hr)) + CoUninitialize(); + + SHDestroyIETHREADPARAM(parameters); + + return TRUE; +} diff --git a/dll/win32/browseui/shellbrowser.cpp b/dll/win32/browseui/shellbrowser.cpp index 39353d5120d..347e0baeb81 100644 --- a/dll/win32/browseui/shellbrowser.cpp +++ b/dll/win32/browseui/shellbrowser.cpp @@ -3447,14 +3447,8 @@ DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter) { HRESULT hr; IEThreadParamBlock * parameters = (IEThreadParamBlock *) lpThreadParameter; - INITCOMMONCONTROLSEX iccex = - { - sizeof(iccex), - 0xFFFF /* everything! */ - }; OleInitialize(NULL); - InitCommonControlsEx(&iccex); ATLTRY(hr = ExplorerMessageLoop(parameters)); diff --git a/dll/win32/shell32/desktop.cpp b/dll/win32/shell32/desktop.cpp index 5e7b903f71f..51dbfa8d1fa 100644 --- a/dll/win32/shell32/desktop.cpp +++ b/dll/win32/shell32/desktop.cpp @@ -475,6 +475,11 @@ LRESULT CALLBACK CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd, IN UINT uMsg, break; } + case WM_EXPLORER_OPEN_NEW_WINDOW: + DbgPrint("Proxy Desktop message 1035 received.\n"); + SHOnCWMCommandLine((HANDLE)lParam); + break; + default: DefMsgHandler: Ret = DefWindowProcW(hwnd, uMsg, wParam, lParam); diff --git a/dll/win32/shell32/undocshell.h b/dll/win32/shell32/undocshell.h index 043b8f49cd9..dad99e0a616 100644 --- a/dll/win32/shell32/undocshell.h +++ b/dll/win32/shell32/undocshell.h @@ -126,30 +126,6 @@ DWORD WINAPI SHNetConnectionDialog( LPCWSTR lpstrRemoteName, DWORD dwType); -/**************************************************************************** - * Memory Routines - */ - -/* The Platform SDK's shlobj.h header defines similar functions with a - * leading underscore. However those are unusable because of the leading - * underscore, because they have an incorrect calling convention, and - * because these functions are not exported by name anyway. - */ -HANDLE WINAPI SHAllocShared( - LPVOID pv, - ULONG cb, - DWORD pid); - -BOOL WINAPI SHFreeShared( - HANDLE hMem, - DWORD pid); - -LPVOID WINAPI SHLockShared( - HANDLE hMem, - DWORD pid); - -BOOL WINAPI SHUnlockShared(LPVOID pv); - /**************************************************************************** * Cabinet Window Messages */ diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index c8c3055ded8..83f683879ee 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -71,7 +71,7 @@ static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId, if (dwDstProcId == dwMyProcId) hDst = GetCurrentProcess(); else - hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId); + hDst = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwDstProcId); if (hDst) { @@ -79,12 +79,12 @@ static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId, if (dwSrcProcId == dwMyProcId) hSrc = GetCurrentProcess(); else - hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId); + hSrc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwSrcProcId); if (hSrc) { /* Make handle available to dest process */ - if (!DuplicateHandle(hDst, hShared, hSrc, &hRet, + if (!DuplicateHandle(hSrc, hShared, hDst, &hRet, dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS)) hRet = NULL; @@ -175,18 +175,32 @@ PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId) { HANDLE hDup; LPVOID pMapped; + DWORD thisProcessId = GetCurrentProcessId(); TRACE("(%p %d)\n", hShared, dwProcId); - /* Get handle to shared memory for current process */ - hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(), - FILE_MAP_ALL_ACCESS, 0); + if (dwProcId != thisProcessId) + { + /* Get handle to shared memory for current process */ + hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(), + FILE_MAP_ALL_ACCESS, 0); + } + else + { + hDup = hShared; + } + /* Get View */ pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - CloseHandle(hDup); + + if (dwProcId != thisProcessId) + { + CloseHandle(hDup); + } if (pMapped) - return (char *) pMapped + sizeof(DWORD); /* Hide size */ + return (char *) pMapped + sizeof(DWORD); /* Hide size */ + return NULL; } @@ -231,7 +245,7 @@ BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId) /* Get a copy of the handle for our process, closing the source handle */ hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(), - FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE); + FILE_MAP_ALL_ACCESS, DUPLICATE_CLOSE_SOURCE); /* Close local copy */ return CloseHandle(hClose); } diff --git a/include/psdk/shlwapi.h b/include/psdk/shlwapi.h index ed9ee364cea..785c2cd19a7 100644 --- a/include/psdk/shlwapi.h +++ b/include/psdk/shlwapi.h @@ -1864,6 +1864,16 @@ HRESULT WINAPI SHCreateStreamWrapper(LPBYTE,DWORD,DWORD,struct IStream**); #ifndef NO_SHLWAPI_SHARED +// These functions are only included in this file starting with the Windows 7 platform SDK + +HANDLE +WINAPI +SHAllocShared( + _In_opt_ const void *pvData, + _In_ DWORD dwSize, + _In_ DWORD dwDestinationProcessId + ); + PVOID WINAPI SHLockShared( diff --git a/include/psdk/shlwapi_undoc.h b/include/psdk/shlwapi_undoc.h index 38d79bb036a..07862364141 100644 --- a/include/psdk/shlwapi_undoc.h +++ b/include/psdk/shlwapi_undoc.h @@ -27,40 +27,50 @@ extern "C" { typedef struct IEThreadParamBlock { - long offset0; - long offset4; - long offset8; - IUnknown *offsetC; - long offset10; - IUnknown *offset14; - LPITEMIDLIST directoryPIDL; - char filler1[84]; // unknown contents - IUnknown *offset70; - long filler2; // unknown contents - IUnknown *offset78; - LPITEMIDLIST offset7C; - LPITEMIDLIST offset80; - char filler3[116]; // unknown contents - IUnknown *offsetF8; // instance explorer - long filler4; // unknown contents + long offset0; + DWORD dwFlags; + long offset8; + IUnknown * offsetC; + long offset10; + IUnknown * offset14; + LPITEMIDLIST directoryPIDL; // 0x18 + char offset1C[0x70-0x1C]; // unknown contents -- 0x1C..0x6c + IUnknown * offset70; + long offset74; // unknown contents + IUnknown * offset78; + LPITEMIDLIST offset7C; + LPITEMIDLIST offset80; + LONG offset84; + LONG offset88; + LONG offset8C; + LONG offset90; + LONG offset94; + LONG offset98; + LONG offset9C; + LONG offsetA0; + char offsetA4[0xD8-0xA4]; // unknown contents -- 0xA4..0xD8 + LONG offsetD8; + char offsetDC[0xF8-0xDC]; // unknown contents -- 0xDC..0xF8 + IUnknown * offsetF8; // instance explorer + LONG offsetFC; // unknown contents } IE_THREAD_PARAM_BLOCK, *PIE_THREAD_PARAM_BLOCK; typedef struct ExplorerCommandLineParseResults { - LPWSTR strPath; - LPITEMIDLIST pidlPath; - DWORD dwFlags; - DWORD unk_12; - DWORD unk_16; - DWORD unk_20; - DWORD unk_24; - DWORD unk_28; - LPITEMIDLIST pidlRoot; - DWORD unk_36; - DWORD unk_40; - DWORD unk_44; - DWORD unk_48; - GUID guidInproc; + LPWSTR strPath; + LPITEMIDLIST pidlPath; + DWORD dwFlags; + DWORD offsetC; + DWORD offset10; + DWORD offset14; + DWORD offset18; + DWORD offset1C; + LPITEMIDLIST pidlRoot; + DWORD offset24; + DWORD offset28; + DWORD offset2C; + DWORD offset30; + GUID guidInproc; } EXPLORER_CMDLINE_PARSE_RESULTS, *PEXPLORER_CMDLINE_PARSE_RESULTS; #define SH_EXPLORER_CMDLINE_FLAG_ONE 0x00000001 @@ -81,8 +91,17 @@ typedef struct ExplorerCommandLineParseResults // unknown/unused 0x00008000 // unknown/unused 0x00010000 #define SH_EXPLORER_CMDLINE_FLAG_SEPARATE 0x00020000 +// unknown/unused 0x00040000 +// unknown/unused 0x00080000 +// unknown/unused 0x00100000 +// unknown/unused 0x00200000 +// unknown/unused 0x00400000 +// unknown/unused 0x00800000 +// unknown/unused 0x01000000 #define SH_EXPLORER_CMDLINE_FLAG_STRING 0x02000000 +#define WM_EXPLORER_OPEN_NEW_WINDOW (WM_USER+11) +#define WM_EXPLORER_1037 (WM_USER+13) BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen); BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen); @@ -122,9 +141,9 @@ HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds); BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild); void WINAPI InitOCHostClass(long param8); -long WINAPI SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK param8); +long WINAPI SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters); void WINAPI SHCreateSavedWindows(void); -long WINAPI SHCreateFromDesktop(long param8); +BOOL WINAPI SHCreateFromDesktop(PEXPLORER_CMDLINE_PARSE_RESULTS parseResults); UINT WINAPI SHExplorerParseCmdLine(PEXPLORER_CMDLINE_PARSE_RESULTS pParseResults); void WINAPI UEMRegisterNotify(long param8, long paramC); HRESULT WINAPI SHCreateBandForPidl(LPCITEMIDLIST param8, IUnknown *paramC, BOOL param10); @@ -134,7 +153,7 @@ PIE_THREAD_PARAM_BLOCK WINAPI SHCreateIETHREADPARAM(long param8, long paramC, IU PIE_THREAD_PARAM_BLOCK WINAPI SHCloneIETHREADPARAM(PIE_THREAD_PARAM_BLOCK param); long WINAPI SHParseIECommandLine(long param8, long paramC); void WINAPI SHDestroyIETHREADPARAM(PIE_THREAD_PARAM_BLOCK param); -HRESULT WINAPI SHOnCWMCommandLine(long param8); +BOOL WINAPI SHOnCWMCommandLine(HANDLE hSharedInfo); LPITEMIDLIST WINAPI Channel_GetFolderPidl(void); IUnknown *WINAPI ChannelBand_Create(LPITEMIDLIST pidl); HRESULT WINAPI Channels_SetBandInfoSFB(IUnknown *param8); @@ -145,7 +164,7 @@ HRESULT WINAPI GetInfoTip(IUnknown *param8, long paramC, LPTSTR *param10, long c HRESULT WINAPI SHEnumClassesOfCategories(long param8, long paramC, long param10, long param14, long param18); HRESULT WINAPI SHWriteClassesOfCategories(long param8, long paramC, long param10, long param14, long param18, long param1C, long param20); BOOL WINAPI SHIsExplorerBrowser(); -HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, long param14); +HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags); #ifdef __cplusplus } /* extern "C" */