From 1a7b4fb9c15ddd3d107af73a68fd312ea9c52e40 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 17 May 2020 23:29:44 -0500 Subject: [PATCH] explorer: Look for an existing window browsing the given path first. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- programs/explorer/explorer.c | 164 +++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 54 deletions(-) diff --git a/programs/explorer/explorer.c b/programs/explorer/explorer.c index 763fca381b7..43bd4ef13a8 100644 --- a/programs/explorer/explorer.c +++ b/programs/explorer/explorer.c @@ -70,6 +70,9 @@ typedef struct LPITEMIDLIST pidl; IImageList *icon_list; DWORD advise_cookie; + + IShellWindows *sw; + LONG sw_cookie; } explorer_info; enum @@ -77,6 +80,13 @@ enum BACK_BUTTON,FORWARD_BUTTON,UP_BUTTON }; +static void variant_from_pidl(VARIANT *var, const ITEMIDLIST *pidl) +{ + V_VT(var) = VT_ARRAY | VT_UI1; + V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 0, ILGetSize(pidl)); + memcpy(V_ARRAY(var)->pvData, pidl, ILGetSize(pidl)); +} + typedef struct { IExplorerBrowserEvents IExplorerBrowserEvents_iface; @@ -265,6 +275,15 @@ static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplore STRRET strret; WCHAR *name; + if (This->info->sw) + { + VARIANT var; + + variant_from_pidl(&var, pidl); + IShellWindows_OnNavigate(This->info->sw, This->info->sw_cookie, &var); + VariantClear(&var); + } + ILFree(This->info->pidl); This->info->pidl = ILClone(pidl); update_path_box(This->info); @@ -325,7 +344,35 @@ static IExplorerBrowserEvents *make_explorer_events(explorer_info *info) return &ret->IExplorerBrowserEvents_iface; } -static void make_explorer_window(IShellFolder* startFolder) +static IShellFolder *get_starting_shell_folder(WCHAR *path) +{ + IShellFolder* desktop,*folder; + LPITEMIDLIST root_pidl; + HRESULT hres; + + SHGetDesktopFolder(&desktop); + + if (!path) + return desktop; + + hres = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &root_pidl, NULL); + if(FAILED(hres)) + { + return desktop; + } + hres = IShellFolder_BindToObject(desktop,root_pidl,NULL, + &IID_IShellFolder, + (void**)&folder); + ILFree(root_pidl); + if(FAILED(hres)) + { + return desktop; + } + IShellFolder_Release(desktop); + return folder; +} + +static void make_explorer_window(parameters_struct *params) { RECT rect; HWND rebar,nav_toolbar; @@ -339,8 +386,49 @@ static void make_explorer_window(IShellFolder* startFolder) TBBUTTON nav_buttons[3]; int hist_offset,view_offset; REBARBANDINFOW band_info; + VARIANT var, empty_var; + IShellFolder *folder; + IDispatch *dispatch; + WCHAR *path = NULL; + IShellWindows *sw; + ITEMIDLIST *pidl; UINT dpix, dpiy; + DWORD size; + LONG hwnd; HDC hdc; + MSG msg; + + CoCreateInstance(&CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, + &IID_IShellWindows, (void **)&sw); + + if (params->root[0]) + { + size = GetFullPathNameW(params->root, 0, NULL, NULL); + path = malloc(size); + GetFullPathNameW(params->root, size, path, NULL); + } + + if (sw && path) + { + if (!(pidl = ILCreateFromPathW(path))) + { + ERR("Failed to create PIDL for %s.\n", debugstr_w(path)); + IShellWindows_Release(sw); + return; + } + + variant_from_pidl(&var, pidl); + V_VT(&empty_var) = VT_EMPTY; + if (IShellWindows_FindWindowSW(sw, &var, &empty_var, SWC_EXPLORER, &hwnd, 0, &dispatch) == S_OK) + { + TRACE("Found window %#x already browsing path %s.\n", hwnd, debugstr_w(path)); + SetForegroundWindow((HWND)(LONG_PTR)hwnd); + IShellWindows_Release(sw); + return; + } + ILFree(pidl); + VariantClear(&var); + } memset(nav_buttons,0,sizeof(nav_buttons)); @@ -376,6 +464,12 @@ static void make_explorer_window(IShellFolder* startFolder) CW_USEDEFAULT,CW_USEDEFAULT,default_width, default_height,NULL,NULL,explorer_hInstance,NULL); + if (sw) + { + IShellWindows_Register(sw, NULL, (LONG_PTR)info->main_window, SWC_EXPLORER, &info->sw_cookie); + info->sw = sw; + } + fs.ViewMode = FVM_DETAILS; fs.fFlags = FWF_AUTOARRANGE; @@ -439,11 +533,20 @@ static void make_explorer_window(IShellFolder* startFolder) SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info); events = make_explorer_events(info); IExplorerBrowser_Advise(info->browser,events,&info->advise_cookie); - IExplorerBrowser_BrowseToObject(info->browser,(IUnknown*)startFolder, - SBSP_ABSOLUTE); + + folder = get_starting_shell_folder(path); + IExplorerBrowser_BrowseToObject(info->browser, (IUnknown *)folder, SBSP_ABSOLUTE); + IShellFolder_Release(folder); + ShowWindow(info->main_window,SW_SHOWDEFAULT); UpdateWindow(info->main_window); IExplorerBrowserEvents_Release(events); + + while (GetMessageW(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } } static void update_window_size(explorer_info *info, int height, int width) @@ -568,6 +671,9 @@ static LRESULT CALLBACK explorer_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, L switch(uMsg) { case WM_DESTROY: + IShellWindows_Revoke(info->sw, info->sw_cookie); + IShellWindows_Release(info->sw); + IExplorerBrowser_Unadvise(browser,info->advise_cookie); IExplorerBrowser_Destroy(browser); IExplorerBrowser_Release(browser); @@ -625,47 +731,6 @@ static void register_explorer_window_class(void) RegisterClassExW(&window_class); } -static IShellFolder* get_starting_shell_folder(parameters_struct* params) -{ - IShellFolder* desktop,*folder; - LPITEMIDLIST root_pidl; - WCHAR *fullpath = NULL; - HRESULT hres; - DWORD size; - - SHGetDesktopFolder(&desktop); - if (!params->root[0]) - { - return desktop; - } - - size = GetFullPathNameW(params->root, 0, fullpath, NULL); - if (!size) - return desktop; - fullpath = heap_alloc(size * sizeof(WCHAR)); - GetFullPathNameW(params->root, size, fullpath, NULL); - - hres = IShellFolder_ParseDisplayName(desktop,NULL,NULL, - fullpath,NULL, - &root_pidl,NULL); - heap_free(fullpath); - - if(FAILED(hres)) - { - return desktop; - } - hres = IShellFolder_BindToObject(desktop,root_pidl,NULL, - &IID_IShellFolder, - (void**)&folder); - ILFree(root_pidl); - if(FAILED(hres)) - { - return desktop; - } - IShellFolder_Release(desktop); - return folder; -} - static WCHAR *copy_path_string(WCHAR *target, WCHAR *source) { INT i = 0; @@ -793,8 +858,6 @@ int WINAPI wWinMain(HINSTANCE hinstance, parameters_struct parameters; HRESULT hres; - MSG msg; - IShellFolder *folder; INITCOMMONCONTROLSEX init_info; memset(¶meters,0,sizeof(parameters)); @@ -817,13 +880,6 @@ int WINAPI wWinMain(HINSTANCE hinstance, ExitProcess(EXIT_FAILURE); } register_explorer_window_class(); - folder = get_starting_shell_folder(¶meters); - make_explorer_window(folder); - IShellFolder_Release(folder); - while(GetMessageW( &msg, NULL, 0, 0 ) != 0) - { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } + make_explorer_window(¶meters); return 0; }