| /* | |
| * ExplorerBrowser Control implementation. | |
| * | |
| * Copyright 2010 David Hedberg | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include <stdarg.h> | |
| #define COBJMACROS | |
| #define NONAMELESSUNION | |
| #include "winerror.h" | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "wine/list.h" | |
| #include "wine/debug.h" | |
| #include "debughlp.h" | |
| #include "shell32_main.h" | |
| #include "pidl.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(shell); | |
| #define SPLITTER_WIDTH 2 | |
| #define NP_MIN_WIDTH 60 | |
| #define SV_MIN_WIDTH 150 | |
| typedef struct _event_client { | |
| struct list entry; | |
| IExplorerBrowserEvents *pebe; | |
| DWORD cookie; | |
| } event_client; | |
| typedef struct _travellog_entry { | |
| struct list entry; | |
| LPITEMIDLIST pidl; | |
| } travellog_entry; | |
| typedef struct _ExplorerBrowserImpl { | |
| IExplorerBrowser IExplorerBrowser_iface; | |
| IShellBrowser IShellBrowser_iface; | |
| ICommDlgBrowser3 ICommDlgBrowser3_iface; | |
| IObjectWithSite IObjectWithSite_iface; | |
| INameSpaceTreeControlEvents INameSpaceTreeControlEvents_iface; | |
| IInputObject IInputObject_iface; | |
| LONG ref; | |
| BOOL destroyed; | |
| HWND hwnd_main; | |
| HWND hwnd_sv; | |
| RECT splitter_rc; | |
| struct { | |
| INameSpaceTreeControl2 *pnstc2; | |
| HWND hwnd_splitter, hwnd_nstc; | |
| DWORD nstc_cookie; | |
| UINT width; | |
| BOOL show; | |
| RECT rc; | |
| } navpane; | |
| EXPLORER_BROWSER_OPTIONS eb_options; | |
| FOLDERSETTINGS fs; | |
| struct list event_clients; | |
| DWORD events_next_cookie; | |
| struct list travellog; | |
| travellog_entry *travellog_cursor; | |
| int travellog_count; | |
| IShellView *psv; | |
| RECT sv_rc; | |
| LPITEMIDLIST current_pidl; | |
| IUnknown *punk_site; | |
| ICommDlgBrowser *pcdb_site; | |
| ICommDlgBrowser2 *pcdb2_site; | |
| ICommDlgBrowser3 *pcdb3_site; | |
| IExplorerPaneVisibility *pepv_site; | |
| } ExplorerBrowserImpl; | |
| static void initialize_navpane(ExplorerBrowserImpl *This, HWND hwnd_parent, RECT *rc); | |
| /************************************************************************** | |
| * Event functions. | |
| */ | |
| static void events_unadvise_all(ExplorerBrowserImpl *This) | |
| { | |
| event_client *client, *curs; | |
| TRACE("%p\n", This); | |
| LIST_FOR_EACH_ENTRY_SAFE(client, curs, &This->event_clients, event_client, entry) | |
| { | |
| TRACE("Removing %p\n", client); | |
| list_remove(&client->entry); | |
| IExplorerBrowserEvents_Release(client->pebe); | |
| HeapFree(GetProcessHeap(), 0, client); | |
| } | |
| } | |
| static HRESULT events_NavigationPending(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl) | |
| { | |
| event_client *cursor; | |
| HRESULT hres = S_OK; | |
| TRACE("%p\n", This); | |
| LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry) | |
| { | |
| TRACE("Notifying %p\n", cursor); | |
| hres = IExplorerBrowserEvents_OnNavigationPending(cursor->pebe, pidl); | |
| /* If this failed for any reason, the browsing is supposed to be aborted. */ | |
| if(FAILED(hres)) | |
| break; | |
| } | |
| return hres; | |
| } | |
| static void events_NavigationComplete(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl) | |
| { | |
| event_client *cursor; | |
| TRACE("%p\n", This); | |
| LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry) | |
| { | |
| TRACE("Notifying %p\n", cursor); | |
| IExplorerBrowserEvents_OnNavigationComplete(cursor->pebe, pidl); | |
| } | |
| } | |
| static void events_NavigationFailed(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl) | |
| { | |
| event_client *cursor; | |
| TRACE("%p\n", This); | |
| LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry) | |
| { | |
| TRACE("Notifying %p\n", cursor); | |
| IExplorerBrowserEvents_OnNavigationFailed(cursor->pebe, pidl); | |
| } | |
| } | |
| static void events_ViewCreated(ExplorerBrowserImpl *This, IShellView *psv) | |
| { | |
| event_client *cursor; | |
| TRACE("%p\n", This); | |
| LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry) | |
| { | |
| TRACE("Notifying %p\n", cursor); | |
| IExplorerBrowserEvents_OnViewCreated(cursor->pebe, psv); | |
| } | |
| } | |
| /************************************************************************** | |
| * Travellog functions. | |
| */ | |
| static void travellog_remove_entry(ExplorerBrowserImpl *This, travellog_entry *entry) | |
| { | |
| TRACE("Removing %p\n", entry); | |
| list_remove(&entry->entry); | |
| ILFree(entry->pidl); | |
| HeapFree(GetProcessHeap(), 0, entry); | |
| This->travellog_count--; | |
| } | |
| static void travellog_remove_all_entries(ExplorerBrowserImpl *This) | |
| { | |
| travellog_entry *cursor, *cursor2; | |
| TRACE("%p\n", This); | |
| LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry) | |
| travellog_remove_entry(This, cursor); | |
| This->travellog_cursor = NULL; | |
| } | |
| static void travellog_add_entry(ExplorerBrowserImpl *This, LPITEMIDLIST pidl) | |
| { | |
| travellog_entry *new, *cursor, *cursor2; | |
| TRACE("%p (old count %d)\n", pidl, This->travellog_count); | |
| /* Replace the old tail, if any, with the new entry */ | |
| if(This->travellog_cursor) | |
| { | |
| LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, &This->travellog, travellog_entry, entry) | |
| { | |
| if(cursor == This->travellog_cursor) | |
| break; | |
| travellog_remove_entry(This, cursor); | |
| } | |
| } | |
| /* Create and add the new entry */ | |
| new = HeapAlloc(GetProcessHeap(), 0, sizeof(travellog_entry)); | |
| new->pidl = ILClone(pidl); | |
| list_add_tail(&This->travellog, &new->entry); | |
| This->travellog_cursor = new; | |
| This->travellog_count++; | |
| /* Remove the first few entries if the size limit is reached. */ | |
| if(This->travellog_count > 200) | |
| { | |
| UINT i = 0; | |
| LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry) | |
| { | |
| if(i++ > 10) | |
| break; | |
| travellog_remove_entry(This, cursor); | |
| } | |
| } | |
| } | |
| static LPCITEMIDLIST travellog_go_back(ExplorerBrowserImpl *This) | |
| { | |
| travellog_entry *prev; | |
| TRACE("%p, %p\n", This, This->travellog_cursor); | |
| if(!This->travellog_cursor) | |
| return NULL; | |
| prev = LIST_ENTRY(list_prev(&This->travellog, &This->travellog_cursor->entry), | |
| travellog_entry, entry); | |
| if(!prev) | |
| return NULL; | |
| This->travellog_cursor = prev; | |
| return prev->pidl; | |
| } | |
| static LPCITEMIDLIST travellog_go_forward(ExplorerBrowserImpl *This) | |
| { | |
| travellog_entry *next; | |
| TRACE("%p, %p\n", This, This->travellog_cursor); | |
| if(!This->travellog_cursor) | |
| return NULL; | |
| next = LIST_ENTRY(list_next(&This->travellog, &This->travellog_cursor->entry), | |
| travellog_entry, entry); | |
| if(!next) | |
| return NULL; | |
| This->travellog_cursor = next; | |
| return next->pidl; | |
| } | |
| /************************************************************************** | |
| * Helper functions | |
| */ | |
| static void update_layout(ExplorerBrowserImpl *This) | |
| { | |
| RECT rc; | |
| INT navpane_width_actual; | |
| INT shellview_width_actual; | |
| TRACE("%p (navpane: %d, EBO_SHOWFRAMES: %d)\n", | |
| This, This->navpane.show, This->eb_options & EBO_SHOWFRAMES); | |
| GetClientRect(This->hwnd_main, &rc); | |
| if((This->eb_options & EBO_SHOWFRAMES) && This->navpane.show) | |
| navpane_width_actual = This->navpane.width; | |
| else | |
| navpane_width_actual = 0; | |
| shellview_width_actual = rc.right - navpane_width_actual; | |
| if(shellview_width_actual < SV_MIN_WIDTH && navpane_width_actual) | |
| { | |
| INT missing_width = SV_MIN_WIDTH - shellview_width_actual; | |
| if(missing_width < (navpane_width_actual - NP_MIN_WIDTH)) | |
| { | |
| /* Shrink the navpane */ | |
| navpane_width_actual -= missing_width; | |
| shellview_width_actual += missing_width; | |
| } | |
| else | |
| { | |
| /* Hide the navpane */ | |
| shellview_width_actual += navpane_width_actual; | |
| navpane_width_actual = 0; | |
| } | |
| } | |
| /************************************************************** | |
| * Calculate rectangles for the panes. All rectangles contain | |
| * the position of the panes relative to hwnd_main. | |
| */ | |
| if(navpane_width_actual) | |
| { | |
| This->navpane.rc.left = This->navpane.rc.top = 0; | |
| This->navpane.rc.right = navpane_width_actual; | |
| This->navpane.rc.bottom = rc.bottom; | |
| if(!This->navpane.hwnd_splitter) | |
| initialize_navpane(This, This->hwnd_main, &This->navpane.rc); | |
| } | |
| else | |
| ZeroMemory(&This->navpane.rc, sizeof(RECT)); | |
| This->sv_rc.left = navpane_width_actual; | |
| This->sv_rc.top = 0; | |
| This->sv_rc.right = This->sv_rc.left + shellview_width_actual; | |
| This->sv_rc.bottom = rc.bottom; | |
| } | |
| static void size_panes(ExplorerBrowserImpl *This) | |
| { | |
| MoveWindow(This->navpane.hwnd_splitter, | |
| This->navpane.rc.right - SPLITTER_WIDTH, This->navpane.rc.top, | |
| SPLITTER_WIDTH, This->navpane.rc.bottom - This->navpane.rc.top, | |
| TRUE); | |
| MoveWindow(This->hwnd_sv, | |
| This->sv_rc.left, This->sv_rc.top, | |
| This->sv_rc.right - This->sv_rc.left, This->sv_rc.bottom - This->sv_rc.top, | |
| TRUE); | |
| } | |
| static HRESULT change_viewmode(ExplorerBrowserImpl *This, UINT viewmode) | |
| { | |
| IFolderView *pfv; | |
| HRESULT hr; | |
| if(!This->psv) | |
| return E_FAIL; | |
| hr = IShellView_QueryInterface(This->psv, &IID_IFolderView, (void*)&pfv); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = IFolderView_SetCurrentViewMode(pfv, This->fs.ViewMode); | |
| IFolderView_Release(pfv); | |
| } | |
| return hr; | |
| } | |
| static HRESULT create_new_shellview(ExplorerBrowserImpl *This, IShellItem *psi) | |
| { | |
| IShellBrowser *psb = &This->IShellBrowser_iface; | |
| IShellFolder *psf; | |
| IShellView *psv; | |
| HWND hwnd_new; | |
| HRESULT hr; | |
| TRACE("%p, %p\n", This, psi); | |
| hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IShellFolder, (void**)&psf); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = IShellFolder_CreateViewObject(psf, This->hwnd_main, &IID_IShellView, (void**)&psv); | |
| if(SUCCEEDED(hr)) | |
| { | |
| if(This->hwnd_sv) | |
| { | |
| IShellView_DestroyViewWindow(This->psv); | |
| This->hwnd_sv = NULL; | |
| } | |
| hr = IShellView_CreateViewWindow(psv, This->psv, &This->fs, psb, &This->sv_rc, &hwnd_new); | |
| if(SUCCEEDED(hr)) | |
| { | |
| /* Replace the old shellview */ | |
| if(This->psv) IShellView_Release(This->psv); | |
| This->psv = psv; | |
| This->hwnd_sv = hwnd_new; | |
| events_ViewCreated(This, psv); | |
| } | |
| else | |
| { | |
| ERR("CreateViewWindow failed (0x%x)\n", hr); | |
| IShellView_Release(psv); | |
| } | |
| } | |
| else | |
| ERR("CreateViewObject failed (0x%x)\n", hr); | |
| IShellFolder_Release(psf); | |
| } | |
| else | |
| ERR("SI::BindToHandler failed (0x%x)\n", hr); | |
| return hr; | |
| } | |
| static void get_interfaces_from_site(ExplorerBrowserImpl *This) | |
| { | |
| IServiceProvider *psp; | |
| HRESULT hr; | |
| /* Calling this with This->punk_site set to NULL should properly | |
| * release any previously fetched interfaces. | |
| */ | |
| if(This->pcdb_site) | |
| { | |
| ICommDlgBrowser_Release(This->pcdb_site); | |
| if(This->pcdb2_site) ICommDlgBrowser2_Release(This->pcdb2_site); | |
| if(This->pcdb3_site) ICommDlgBrowser3_Release(This->pcdb3_site); | |
| This->pcdb_site = NULL; | |
| This->pcdb2_site = NULL; | |
| This->pcdb3_site = NULL; | |
| } | |
| if(This->pepv_site) | |
| { | |
| IExplorerPaneVisibility_Release(This->pepv_site); | |
| This->pepv_site = NULL; | |
| } | |
| if(!This->punk_site) | |
| return; | |
| hr = IUnknown_QueryInterface(This->punk_site, &IID_IServiceProvider, (void**)&psp); | |
| if(FAILED(hr)) | |
| { | |
| ERR("Failed to get IServiceProvider from site.\n"); | |
| return; | |
| } | |
| /* ICommDlgBrowser */ | |
| IServiceProvider_QueryService(psp, &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser, | |
| (void**)&This->pcdb_site); | |
| IServiceProvider_QueryService(psp, &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser2, | |
| (void**)&This->pcdb2_site); | |
| IServiceProvider_QueryService(psp, &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser3, | |
| (void**)&This->pcdb3_site); | |
| /* IExplorerPaneVisibility */ | |
| IServiceProvider_QueryService(psp, &SID_ExplorerPaneVisibility, &IID_IExplorerPaneVisibility, | |
| (void**)&This->pepv_site); | |
| IServiceProvider_Release(psp); | |
| } | |
| /************************************************************************** | |
| * General pane functionality. | |
| */ | |
| static void update_panestate(ExplorerBrowserImpl *This) | |
| { | |
| EXPLORERPANESTATE eps = EPS_DONTCARE; | |
| BOOL show_navpane; | |
| TRACE("%p\n", This); | |
| if(!This->pepv_site) return; | |
| IExplorerPaneVisibility_GetPaneState(This->pepv_site, (REFEXPLORERPANE) &EP_NavPane, &eps); | |
| if( !(eps & EPS_DEFAULT_OFF) ) | |
| show_navpane = TRUE; | |
| else | |
| show_navpane = FALSE; | |
| if(This->navpane.show != show_navpane) | |
| { | |
| update_layout(This); | |
| size_panes(This); | |
| } | |
| This->navpane.show = show_navpane; | |
| } | |
| static void splitter_draw(HWND hwnd, RECT *rc) | |
| { | |
| HDC hdc = GetDC(hwnd); | |
| InvertRect(hdc, rc); | |
| ReleaseDC(hwnd, hdc); | |
| } | |
| /************************************************************************** | |
| * The Navigation Pane. | |
| */ | |
| static LRESULT navpane_splitter_beginresize(ExplorerBrowserImpl *This, HWND hwnd, LPARAM lParam) | |
| { | |
| TRACE("\n"); | |
| SetCapture(hwnd); | |
| This->splitter_rc = This->navpane.rc; | |
| This->splitter_rc.left = This->splitter_rc.right - SPLITTER_WIDTH; | |
| splitter_draw(GetParent(hwnd), &This->splitter_rc); | |
| return TRUE; | |
| } | |
| static LRESULT navpane_splitter_resizing(ExplorerBrowserImpl *This, HWND hwnd, LPARAM lParam) | |
| { | |
| int new_width, dx; | |
| RECT rc; | |
| if(GetCapture() != hwnd) return FALSE; | |
| dx = (SHORT)LOWORD(lParam); | |
| TRACE("%d.\n", dx); | |
| rc = This->navpane.rc; | |
| new_width = This->navpane.width + dx; | |
| if(new_width > NP_MIN_WIDTH && This->sv_rc.right - new_width > SV_MIN_WIDTH) | |
| { | |
| rc.right = new_width; | |
| rc.left = rc.right - SPLITTER_WIDTH; | |
| splitter_draw(GetParent(hwnd), &This->splitter_rc); | |
| splitter_draw(GetParent(hwnd), &rc); | |
| This->splitter_rc = rc; | |
| } | |
| return TRUE; | |
| } | |
| static LRESULT navpane_splitter_endresize(ExplorerBrowserImpl *This, HWND hwnd, LPARAM lParam) | |
| { | |
| int new_width, dx; | |
| if(GetCapture() != hwnd) return FALSE; | |
| dx = (SHORT)LOWORD(lParam); | |
| TRACE("%d.\n", dx); | |
| splitter_draw(GetParent(hwnd), &This->splitter_rc); | |
| new_width = This->navpane.width + dx; | |
| if(new_width < NP_MIN_WIDTH) | |
| new_width = NP_MIN_WIDTH; | |
| else if(This->sv_rc.right - new_width < SV_MIN_WIDTH) | |
| new_width = This->sv_rc.right - SV_MIN_WIDTH; | |
| This->navpane.width = new_width; | |
| update_layout(This); | |
| size_panes(This); | |
| ReleaseCapture(); | |
| return TRUE; | |
| } | |
| static LRESULT navpane_on_wm_create(HWND hwnd, CREATESTRUCTW *crs) | |
| { | |
| ExplorerBrowserImpl *This = crs->lpCreateParams; | |
| INameSpaceTreeControl2 *pnstc2; | |
| DWORD style; | |
| HRESULT hr; | |
| TRACE("%p\n", This); | |
| SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This); | |
| This->navpane.hwnd_splitter = hwnd; | |
| hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER, | |
| &IID_INameSpaceTreeControl2, (void**)&pnstc2); | |
| if(SUCCEEDED(hr)) | |
| { | |
| style = NSTCS_HASEXPANDOS | NSTCS_ROOTHASEXPANDO | NSTCS_SHOWSELECTIONALWAYS; | |
| hr = INameSpaceTreeControl2_Initialize(pnstc2, GetParent(hwnd), NULL, style); | |
| if(SUCCEEDED(hr)) | |
| { | |
| INameSpaceTreeControlEvents *pnstce; | |
| IShellFolder *psfdesktop; | |
| IShellItem *psi; | |
| IOleWindow *pow; | |
| LPITEMIDLIST pidl; | |
| DWORD cookie, style2 = NSTCS2_DISPLAYPADDING; | |
| hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFF, style2); | |
| if(FAILED(hr)) | |
| ERR("SetControlStyle2 failed (0x%08x)\n", hr); | |
| hr = INameSpaceTreeControl2_QueryInterface(pnstc2, &IID_IOleWindow, (void**)&pow); | |
| if(SUCCEEDED(hr)) | |
| { | |
| IOleWindow_GetWindow(pow, &This->navpane.hwnd_nstc); | |
| IOleWindow_Release(pow); | |
| } | |
| else | |
| ERR("QueryInterface(IOleWindow) failed (0x%08x)\n", hr); | |
| pnstce = &This->INameSpaceTreeControlEvents_iface; | |
| hr = INameSpaceTreeControl2_TreeAdvise(pnstc2, (IUnknown*)pnstce, &cookie); | |
| if(FAILED(hr)) | |
| ERR("TreeAdvise failed. (0x%08x).\n", hr); | |
| /* | |
| * Add the default roots | |
| */ | |
| /* TODO: This should be FOLDERID_Links */ | |
| hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = SHCreateShellItem(NULL, NULL, pidl, &psi); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = INameSpaceTreeControl2_AppendRoot(pnstc2, psi, SHCONTF_NONFOLDERS, NSTCRS_VISIBLE, NULL); | |
| IShellItem_Release(psi); | |
| } | |
| ILFree(pidl); | |
| } | |
| SHGetDesktopFolder(&psfdesktop); | |
| hr = SHGetItemFromObject((IUnknown*)psfdesktop, &IID_IShellItem, (void**)&psi); | |
| IShellFolder_Release(psfdesktop); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = INameSpaceTreeControl2_AppendRoot(pnstc2, psi, SHCONTF_FOLDERS, NSTCRS_EXPANDED, NULL); | |
| IShellItem_Release(psi); | |
| } | |
| /* TODO: | |
| * We should advertise IID_INameSpaceTreeControl to the site of the | |
| * host through its IProfferService interface, if any. | |
| */ | |
| This->navpane.pnstc2 = pnstc2; | |
| This->navpane.nstc_cookie = cookie; | |
| return TRUE; | |
| } | |
| } | |
| This->navpane.pnstc2 = NULL; | |
| ERR("Failed (0x%08x)\n", hr); | |
| return FALSE; | |
| } | |
| static LRESULT navpane_on_wm_size_move(ExplorerBrowserImpl *This) | |
| { | |
| UINT height, width; | |
| TRACE("%p\n", This); | |
| width = This->navpane.rc.right - This->navpane.rc.left - SPLITTER_WIDTH; | |
| height = This->navpane.rc.bottom - This->navpane.rc.top; | |
| MoveWindow(This->navpane.hwnd_nstc, | |
| This->navpane.rc.left, This->navpane.rc.top, | |
| width, height, | |
| TRUE); | |
| return FALSE; | |
| } | |
| static LRESULT navpane_on_wm_destroy(ExplorerBrowserImpl *This) | |
| { | |
| INameSpaceTreeControl2_TreeUnadvise(This->navpane.pnstc2, This->navpane.nstc_cookie); | |
| INameSpaceTreeControl2_Release(This->navpane.pnstc2); | |
| This->navpane.pnstc2 = NULL; | |
| return TRUE; | |
| } | |
| static LRESULT CALLBACK navpane_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) | |
| { | |
| ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); | |
| switch(uMessage) { | |
| case WM_CREATE: return navpane_on_wm_create(hWnd, (CREATESTRUCTW*)lParam); | |
| case WM_MOVE: /* Fall through */ | |
| case WM_SIZE: return navpane_on_wm_size_move(This); | |
| case WM_DESTROY: return navpane_on_wm_destroy(This); | |
| case WM_LBUTTONDOWN: return navpane_splitter_beginresize(This, hWnd, lParam); | |
| case WM_MOUSEMOVE: return navpane_splitter_resizing(This, hWnd, lParam); | |
| case WM_LBUTTONUP: return navpane_splitter_endresize(This, hWnd, lParam); | |
| default: | |
| return DefWindowProcW(hWnd, uMessage, wParam, lParam); | |
| } | |
| return 0; | |
| } | |
| static void initialize_navpane(ExplorerBrowserImpl *This, HWND hwnd_parent, RECT *rc) | |
| { | |
| WNDCLASSW wc; | |
| HWND splitter; | |
| static const WCHAR navpane_classname[] = {'e','b','_','n','a','v','p','a','n','e',0}; | |
| if( !GetClassInfoW(shell32_hInstance, navpane_classname, &wc) ) | |
| { | |
| wc.style = CS_HREDRAW | CS_VREDRAW; | |
| wc.lpfnWndProc = navpane_wndproc; | |
| wc.cbClsExtra = 0; | |
| wc.cbWndExtra = 0; | |
| wc.hInstance = shell32_hInstance; | |
| wc.hIcon = 0; | |
| wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_SIZEWE); | |
| wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); | |
| wc.lpszMenuName = NULL; | |
| wc.lpszClassName = navpane_classname; | |
| if (!RegisterClassW(&wc)) return; | |
| } | |
| splitter = CreateWindowExW(0, navpane_classname, NULL, | |
| WS_CHILD | WS_TABSTOP | WS_VISIBLE, | |
| rc->right - SPLITTER_WIDTH, rc->top, | |
| SPLITTER_WIDTH, rc->bottom - rc->top, | |
| hwnd_parent, 0, shell32_hInstance, This); | |
| if(!splitter) | |
| ERR("Failed to create navpane : %d.\n", GetLastError()); | |
| } | |
| /************************************************************************** | |
| * Main window related functions. | |
| */ | |
| static LRESULT main_on_wm_create(HWND hWnd, CREATESTRUCTW *crs) | |
| { | |
| ExplorerBrowserImpl *This = crs->lpCreateParams; | |
| TRACE("%p\n", This); | |
| SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LPARAM)This); | |
| This->hwnd_main = hWnd; | |
| return TRUE; | |
| } | |
| static LRESULT main_on_wm_size(ExplorerBrowserImpl *This) | |
| { | |
| update_layout(This); | |
| size_panes(This); | |
| return TRUE; | |
| } | |
| static LRESULT main_on_cwm_getishellbrowser(ExplorerBrowserImpl *This) | |
| { | |
| return (LRESULT)&This->IShellBrowser_iface; | |
| } | |
| static LRESULT CALLBACK main_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) | |
| { | |
| ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); | |
| switch(uMessage) | |
| { | |
| case WM_CREATE: return main_on_wm_create(hWnd, (CREATESTRUCTW*)lParam); | |
| case WM_SIZE: return main_on_wm_size(This); | |
| case CWM_GETISHELLBROWSER: return main_on_cwm_getishellbrowser(This); | |
| default: return DefWindowProcW(hWnd, uMessage, wParam, lParam); | |
| } | |
| return 0; | |
| } | |
| /************************************************************************** | |
| * IExplorerBrowser Implementation | |
| */ | |
| static inline ExplorerBrowserImpl *impl_from_IExplorerBrowser(IExplorerBrowser *iface) | |
| { | |
| return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IExplorerBrowser_iface); | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnQueryInterface(IExplorerBrowser *iface, | |
| REFIID riid, void **ppvObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject); | |
| *ppvObject = NULL; | |
| if(IsEqualIID(riid, &IID_IExplorerBrowser) || | |
| IsEqualIID(riid, &IID_IUnknown)) | |
| { | |
| *ppvObject = &This->IExplorerBrowser_iface; | |
| } | |
| else if(IsEqualIID(riid, &IID_IShellBrowser) || | |
| IsEqualIID(riid, &IID_IOleWindow)) | |
| { | |
| *ppvObject = &This->IShellBrowser_iface; | |
| } | |
| else if(IsEqualIID(riid, &IID_ICommDlgBrowser) || | |
| IsEqualIID(riid, &IID_ICommDlgBrowser2) || | |
| IsEqualIID(riid, &IID_ICommDlgBrowser3)) | |
| { | |
| *ppvObject = &This->ICommDlgBrowser3_iface; | |
| } | |
| else if(IsEqualIID(riid, &IID_IObjectWithSite)) | |
| { | |
| *ppvObject = &This->IObjectWithSite_iface; | |
| } | |
| else if(IsEqualIID(riid, &IID_IInputObject)) | |
| { | |
| *ppvObject = &This->IInputObject_iface; | |
| } | |
| if(*ppvObject) | |
| { | |
| IUnknown_AddRef((IUnknown*)*ppvObject); | |
| return S_OK; | |
| } | |
| return E_NOINTERFACE; | |
| } | |
| static ULONG WINAPI IExplorerBrowser_fnAddRef(IExplorerBrowser *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| LONG ref = InterlockedIncrement(&This->ref); | |
| TRACE("%p - ref %d\n", This, ref); | |
| return ref; | |
| } | |
| static ULONG WINAPI IExplorerBrowser_fnRelease(IExplorerBrowser *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| LONG ref = InterlockedDecrement(&This->ref); | |
| TRACE("%p - ref %d\n", This, ref); | |
| if(!ref) | |
| { | |
| TRACE("Freeing.\n"); | |
| if(!This->destroyed) | |
| IExplorerBrowser_Destroy(iface); | |
| IObjectWithSite_SetSite(&This->IObjectWithSite_iface, NULL); | |
| HeapFree(GetProcessHeap(), 0, This); | |
| return 0; | |
| } | |
| return ref; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnInitialize(IExplorerBrowser *iface, | |
| HWND hwndParent, const RECT *prc, | |
| const FOLDERSETTINGS *pfs) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| WNDCLASSW wc; | |
| LONG style; | |
| static const WCHAR EB_CLASS_NAME[] = | |
| {'E','x','p','l','o','r','e','r','B','r','o','w','s','e','r','C','o','n','t','r','o','l',0}; | |
| TRACE("%p (%p, %p, %p)\n", This, hwndParent, prc, pfs); | |
| if(This->hwnd_main) | |
| return E_UNEXPECTED; | |
| if(!hwndParent) | |
| return E_INVALIDARG; | |
| if( !GetClassInfoW(shell32_hInstance, EB_CLASS_NAME, &wc) ) | |
| { | |
| wc.style = CS_HREDRAW | CS_VREDRAW; | |
| wc.lpfnWndProc = main_wndproc; | |
| wc.cbClsExtra = 0; | |
| wc.cbWndExtra = 0; | |
| wc.hInstance = shell32_hInstance; | |
| wc.hIcon = 0; | |
| wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); | |
| wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); | |
| wc.lpszMenuName = NULL; | |
| wc.lpszClassName = EB_CLASS_NAME; | |
| if (!RegisterClassW(&wc)) return E_FAIL; | |
| } | |
| style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS; | |
| if (!(This->eb_options & EBO_NOBORDER)) | |
| style |= WS_BORDER; | |
| This->hwnd_main = CreateWindowExW(WS_EX_CONTROLPARENT, EB_CLASS_NAME, NULL, style, | |
| prc->left, prc->top, | |
| prc->right - prc->left, prc->bottom - prc->top, | |
| hwndParent, 0, shell32_hInstance, This); | |
| if(!This->hwnd_main) | |
| { | |
| ERR("Failed to create the window.\n"); | |
| return E_FAIL; | |
| } | |
| This->fs.ViewMode = pfs ? pfs->ViewMode : FVM_DETAILS; | |
| This->fs.fFlags = pfs ? (pfs->fFlags | FWF_NOCLIENTEDGE) : FWF_NOCLIENTEDGE; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| TRACE("%p\n", This); | |
| if(This->psv) | |
| { | |
| IShellView_DestroyViewWindow(This->psv); | |
| IShellView_Release(This->psv); | |
| This->psv = NULL; | |
| This->hwnd_sv = NULL; | |
| } | |
| events_unadvise_all(This); | |
| travellog_remove_all_entries(This); | |
| ILFree(This->current_pidl); | |
| This->current_pidl = NULL; | |
| DestroyWindow(This->hwnd_main); | |
| This->destroyed = TRUE; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnSetRect(IExplorerBrowser *iface, | |
| HDWP *phdwp, RECT rcBrowser) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| TRACE("%p (%p, %s)\n", This, phdwp, wine_dbgstr_rect(&rcBrowser)); | |
| if(phdwp && *phdwp) | |
| { | |
| *phdwp = DeferWindowPos(*phdwp, This->hwnd_main, NULL, rcBrowser.left, rcBrowser.top, | |
| rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, | |
| SWP_NOZORDER | SWP_NOACTIVATE); | |
| if(!*phdwp) | |
| return E_FAIL; | |
| } | |
| else | |
| { | |
| MoveWindow(This->hwnd_main, rcBrowser.left, rcBrowser.top, | |
| rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, TRUE); | |
| } | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnSetPropertyBag(IExplorerBrowser *iface, | |
| LPCWSTR pszPropertyBag) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| FIXME("stub, %p (%s)\n", This, debugstr_w(pszPropertyBag)); | |
| if(!pszPropertyBag) | |
| return E_INVALIDARG; | |
| /* FIXME: This method is currently useless as we don't save any | |
| * settings anywhere, but at least one application breaks if we | |
| * return E_NOTIMPL. | |
| */ | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnSetEmptyText(IExplorerBrowser *iface, | |
| LPCWSTR pszEmptyText) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| FIXME("stub, %p (%s)\n", This, debugstr_w(pszEmptyText)); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnSetFolderSettings(IExplorerBrowser *iface, | |
| const FOLDERSETTINGS *pfs) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| TRACE("%p (%p)\n", This, pfs); | |
| if(!pfs) | |
| return E_INVALIDARG; | |
| This->fs.ViewMode = pfs->ViewMode; | |
| This->fs.fFlags = pfs->fFlags | FWF_NOCLIENTEDGE; | |
| /* Change the settings of the current view, if any. */ | |
| return change_viewmode(This, This->fs.ViewMode); | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnAdvise(IExplorerBrowser *iface, | |
| IExplorerBrowserEvents *psbe, | |
| DWORD *pdwCookie) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| event_client *client; | |
| TRACE("%p (%p, %p)\n", This, psbe, pdwCookie); | |
| client = HeapAlloc(GetProcessHeap(), 0, sizeof(event_client)); | |
| client->pebe = psbe; | |
| client->cookie = ++This->events_next_cookie; | |
| IExplorerBrowserEvents_AddRef(psbe); | |
| *pdwCookie = client->cookie; | |
| list_add_tail(&This->event_clients, &client->entry); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface, | |
| DWORD dwCookie) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| event_client *client; | |
| TRACE("%p (0x%x)\n", This, dwCookie); | |
| LIST_FOR_EACH_ENTRY(client, &This->event_clients, event_client, entry) | |
| { | |
| if(client->cookie == dwCookie) | |
| { | |
| list_remove(&client->entry); | |
| IExplorerBrowserEvents_Release(client->pebe); | |
| HeapFree(GetProcessHeap(), 0, client); | |
| return S_OK; | |
| } | |
| } | |
| return E_INVALIDARG; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface, | |
| EXPLORER_BROWSER_OPTIONS dwFlag) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| static const EXPLORER_BROWSER_OPTIONS unsupported_options = | |
| EBO_ALWAYSNAVIGATE | EBO_NOWRAPPERWINDOW | EBO_HTMLSHAREPOINTVIEW | EBO_NOPERSISTVIEWSTATE; | |
| TRACE("%p (0x%x)\n", This, dwFlag); | |
| if(dwFlag & unsupported_options) | |
| FIXME("Flags 0x%08x contains unsupported options.\n", dwFlag); | |
| This->eb_options = dwFlag; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface, | |
| EXPLORER_BROWSER_OPTIONS *pdwFlag) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| TRACE("%p (%p)\n", This, pdwFlag); | |
| *pdwFlag = This->eb_options; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface, | |
| PCUIDLIST_RELATIVE pidl, | |
| UINT uFlags) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| LPITEMIDLIST absolute_pidl = NULL; | |
| HRESULT hr; | |
| static const UINT unsupported_browse_flags = | |
| SBSP_NEWBROWSER | EBF_SELECTFROMDATAOBJECT | EBF_NODROPTARGET; | |
| TRACE("%p (%p, 0x%x)\n", This, pidl, uFlags); | |
| if(!This->hwnd_main) | |
| return E_FAIL; | |
| if(This->destroyed) | |
| return HRESULT_FROM_WIN32(ERROR_BUSY); | |
| if(This->current_pidl && (This->eb_options & EBO_NAVIGATEONCE)) | |
| return E_FAIL; | |
| if(uFlags & SBSP_EXPLOREMODE) | |
| return E_INVALIDARG; | |
| if(uFlags & unsupported_browse_flags) | |
| FIXME("Argument 0x%x contains unsupported flags.\n", uFlags); | |
| if(uFlags & SBSP_NAVIGATEBACK) | |
| { | |
| TRACE("SBSP_NAVIGATEBACK\n"); | |
| absolute_pidl = ILClone(travellog_go_back(This)); | |
| if(!absolute_pidl && !This->current_pidl) | |
| return E_FAIL; | |
| else if(!absolute_pidl) | |
| return S_OK; | |
| } | |
| else if(uFlags & SBSP_NAVIGATEFORWARD) | |
| { | |
| TRACE("SBSP_NAVIGATEFORWARD\n"); | |
| absolute_pidl = ILClone(travellog_go_forward(This)); | |
| if(!absolute_pidl && !This->current_pidl) | |
| return E_FAIL; | |
| else if(!absolute_pidl) | |
| return S_OK; | |
| } | |
| else if(uFlags & SBSP_PARENT) | |
| { | |
| if(This->current_pidl) | |
| { | |
| if(_ILIsPidlSimple(This->current_pidl)) | |
| { | |
| absolute_pidl = _ILCreateDesktop(); | |
| } | |
| else | |
| { | |
| absolute_pidl = ILClone(This->current_pidl); | |
| ILRemoveLastID(absolute_pidl); | |
| } | |
| } | |
| if(!absolute_pidl) | |
| { | |
| ERR("Failed to get parent pidl.\n"); | |
| return E_FAIL; | |
| } | |
| } | |
| else if(uFlags & SBSP_RELATIVE) | |
| { | |
| /* SBSP_RELATIVE has precedence over SBSP_ABSOLUTE */ | |
| TRACE("SBSP_RELATIVE\n"); | |
| if(This->current_pidl) | |
| { | |
| absolute_pidl = ILCombine(This->current_pidl, pidl); | |
| } | |
| if(!absolute_pidl) | |
| { | |
| ERR("Failed to get absolute pidl.\n"); | |
| return E_FAIL; | |
| } | |
| } | |
| else | |
| { | |
| TRACE("SBSP_ABSOLUTE\n"); | |
| absolute_pidl = ILClone(pidl); | |
| if(!absolute_pidl && !This->current_pidl) | |
| return E_INVALIDARG; | |
| else if(!absolute_pidl) | |
| return S_OK; | |
| } | |
| /* TODO: Asynchronous browsing. Return S_OK here and finish in | |
| * another thread. */ | |
| hr = events_NavigationPending(This, absolute_pidl); | |
| if(FAILED(hr)) | |
| { | |
| TRACE("Browsing aborted.\n"); | |
| ILFree(absolute_pidl); | |
| return E_FAIL; | |
| } | |
| get_interfaces_from_site(This); | |
| update_panestate(This); | |
| /* Only browse if the new pidl differs from the old */ | |
| if(!ILIsEqual(This->current_pidl, absolute_pidl)) | |
| { | |
| IShellItem *psi; | |
| hr = SHCreateItemFromIDList(absolute_pidl, &IID_IShellItem, (void**)&psi); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = create_new_shellview(This, psi); | |
| if(FAILED(hr)) | |
| { | |
| events_NavigationFailed(This, absolute_pidl); | |
| ILFree(absolute_pidl); | |
| IShellItem_Release(psi); | |
| return E_FAIL; | |
| } | |
| /* Add to travellog */ | |
| if( !(This->eb_options & EBO_NOTRAVELLOG) && | |
| !(uFlags & (SBSP_NAVIGATEFORWARD|SBSP_NAVIGATEBACK)) ) | |
| { | |
| travellog_add_entry(This, absolute_pidl); | |
| } | |
| IShellItem_Release(psi); | |
| } | |
| } | |
| events_NavigationComplete(This, absolute_pidl); | |
| ILFree(This->current_pidl); | |
| This->current_pidl = absolute_pidl; | |
| /* Expand the NameSpaceTree to the current location. */ | |
| if(This->navpane.show && This->navpane.pnstc2) | |
| { | |
| IShellItem *psi; | |
| hr = SHCreateItemFromIDList(This->current_pidl, &IID_IShellItem, (void**)&psi); | |
| if(SUCCEEDED(hr)) | |
| { | |
| INameSpaceTreeControl2_EnsureItemVisible(This->navpane.pnstc2, psi); | |
| IShellItem_Release(psi); | |
| } | |
| } | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnBrowseToObject(IExplorerBrowser *iface, | |
| IUnknown *punk, UINT uFlags) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| LPITEMIDLIST pidl; | |
| HRESULT hr; | |
| TRACE("%p (%p, 0x%x)\n", This, punk, uFlags); | |
| if(!punk) | |
| return IExplorerBrowser_BrowseToIDList(iface, NULL, uFlags); | |
| hr = SHGetIDListFromObject(punk, &pidl); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = IExplorerBrowser_BrowseToIDList(iface, pidl, uFlags); | |
| ILFree(pidl); | |
| } | |
| return hr; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnFillFromObject(IExplorerBrowser *iface, | |
| IUnknown *punk, | |
| EXPLORER_BROWSER_FILL_FLAGS dwFlags) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| FIXME("stub, %p (%p, 0x%x)\n", This, punk, dwFlags); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnRemoveAll(IExplorerBrowser *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| FIXME("stub, %p\n", This); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IExplorerBrowser_fnGetCurrentView(IExplorerBrowser *iface, | |
| REFIID riid, void **ppv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface); | |
| TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppv); | |
| if(!This->psv) | |
| return E_FAIL; | |
| return IShellView_QueryInterface(This->psv, riid, ppv); | |
| } | |
| static const IExplorerBrowserVtbl vt_IExplorerBrowser = | |
| { | |
| IExplorerBrowser_fnQueryInterface, | |
| IExplorerBrowser_fnAddRef, | |
| IExplorerBrowser_fnRelease, | |
| IExplorerBrowser_fnInitialize, | |
| IExplorerBrowser_fnDestroy, | |
| IExplorerBrowser_fnSetRect, | |
| IExplorerBrowser_fnSetPropertyBag, | |
| IExplorerBrowser_fnSetEmptyText, | |
| IExplorerBrowser_fnSetFolderSettings, | |
| IExplorerBrowser_fnAdvise, | |
| IExplorerBrowser_fnUnadvise, | |
| IExplorerBrowser_fnSetOptions, | |
| IExplorerBrowser_fnGetOptions, | |
| IExplorerBrowser_fnBrowseToIDList, | |
| IExplorerBrowser_fnBrowseToObject, | |
| IExplorerBrowser_fnFillFromObject, | |
| IExplorerBrowser_fnRemoveAll, | |
| IExplorerBrowser_fnGetCurrentView | |
| }; | |
| /************************************************************************** | |
| * IShellBrowser Implementation | |
| */ | |
| static inline ExplorerBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface) | |
| { | |
| return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IShellBrowser_iface); | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnQueryInterface(IShellBrowser *iface, | |
| REFIID riid, void **ppvObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_QueryInterface(&This->IExplorerBrowser_iface, riid, ppvObject); | |
| } | |
| static ULONG WINAPI IShellBrowser_fnAddRef(IShellBrowser *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_AddRef(&This->IExplorerBrowser_iface); | |
| } | |
| static ULONG WINAPI IShellBrowser_fnRelease(IShellBrowser *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_Release(&This->IExplorerBrowser_iface); | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnGetWindow(IShellBrowser *iface, HWND *phwnd) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p (%p)\n", This, phwnd); | |
| if(!This->hwnd_main) | |
| return E_FAIL; | |
| *phwnd = This->hwnd_main; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnContextSensitiveHelp(IShellBrowser *iface, | |
| BOOL fEnterMode) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%d)\n", This, fEnterMode); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnInsertMenusSB(IShellBrowser *iface, | |
| HMENU hmenuShared, | |
| LPOLEMENUGROUPWIDTHS lpMenuWidths) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p (%p, %p)\n", This, hmenuShared, lpMenuWidths); | |
| /* Not implemented. */ | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnSetMenuSB(IShellBrowser *iface, | |
| HMENU hmenuShared, | |
| HOLEMENU holemenuReserved, | |
| HWND hwndActiveObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p (%p, %p, %p)\n", This, hmenuShared, holemenuReserved, hwndActiveObject); | |
| /* Not implemented. */ | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnRemoveMenusSB(IShellBrowser *iface, | |
| HMENU hmenuShared) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p (%p)\n", This, hmenuShared); | |
| /* Not implemented. */ | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnSetStatusTextSB(IShellBrowser *iface, | |
| LPCOLESTR pszStatusText) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%s)\n", This, debugstr_w(pszStatusText)); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnEnableModelessSB(IShellBrowser *iface, | |
| BOOL fEnable) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%d)\n", This, fEnable); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnTranslateAcceleratorSB(IShellBrowser *iface, | |
| MSG *pmsg, WORD wID) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%p, 0x%x)\n", This, pmsg, wID); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnBrowseObject(IShellBrowser *iface, | |
| LPCITEMIDLIST pidl, UINT wFlags) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p (%p, %x)\n", This, pidl, wFlags); | |
| return IExplorerBrowser_BrowseToIDList(&This->IExplorerBrowser_iface, pidl, wFlags); | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnGetViewStateStream(IShellBrowser *iface, | |
| DWORD grfMode, | |
| IStream **ppStrm) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (0x%x, %p)\n", This, grfMode, ppStrm); | |
| *ppStrm = NULL; | |
| return E_FAIL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnGetControlWindow(IShellBrowser *iface, | |
| UINT id, HWND *phwnd) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("(%p)->(%d, %p)\n", This, id, phwnd); | |
| if (phwnd) *phwnd = NULL; | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnSendControlMsg(IShellBrowser *iface, | |
| UINT id, UINT uMsg, | |
| WPARAM wParam, LPARAM lParam, | |
| LRESULT *pret) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%d, %d, %lx, %lx, %p)\n", This, id, uMsg, wParam, lParam, pret); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnQueryActiveShellView(IShellBrowser *iface, | |
| IShellView **ppshv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| TRACE("%p (%p)\n", This, ppshv); | |
| if(!This->psv) | |
| return E_FAIL; | |
| *ppshv = This->psv; | |
| IShellView_AddRef(This->psv); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnOnViewWindowActive(IShellBrowser *iface, | |
| IShellView *pshv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%p)\n", This, pshv); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IShellBrowser_fnSetToolbarItems(IShellBrowser *iface, | |
| LPTBBUTTONSB lpButtons, | |
| UINT nButtons, UINT uFlags) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface); | |
| FIXME("stub, %p (%p, %d, 0x%x)\n", This, lpButtons, nButtons, uFlags); | |
| return E_NOTIMPL; | |
| } | |
| static const IShellBrowserVtbl vt_IShellBrowser = { | |
| IShellBrowser_fnQueryInterface, | |
| IShellBrowser_fnAddRef, | |
| IShellBrowser_fnRelease, | |
| IShellBrowser_fnGetWindow, | |
| IShellBrowser_fnContextSensitiveHelp, | |
| IShellBrowser_fnInsertMenusSB, | |
| IShellBrowser_fnSetMenuSB, | |
| IShellBrowser_fnRemoveMenusSB, | |
| IShellBrowser_fnSetStatusTextSB, | |
| IShellBrowser_fnEnableModelessSB, | |
| IShellBrowser_fnTranslateAcceleratorSB, | |
| IShellBrowser_fnBrowseObject, | |
| IShellBrowser_fnGetViewStateStream, | |
| IShellBrowser_fnGetControlWindow, | |
| IShellBrowser_fnSendControlMsg, | |
| IShellBrowser_fnQueryActiveShellView, | |
| IShellBrowser_fnOnViewWindowActive, | |
| IShellBrowser_fnSetToolbarItems | |
| }; | |
| /************************************************************************** | |
| * ICommDlgBrowser3 Implementation | |
| */ | |
| static inline ExplorerBrowserImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface) | |
| { | |
| return CONTAINING_RECORD(iface, ExplorerBrowserImpl, ICommDlgBrowser3_iface); | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface, | |
| REFIID riid, | |
| void **ppvObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_QueryInterface(&This->IExplorerBrowser_iface, riid, ppvObject); | |
| } | |
| static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_AddRef(&This->IExplorerBrowser_iface); | |
| } | |
| static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_Release(&This->IExplorerBrowser_iface); | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface, | |
| IShellView *shv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| IDataObject *pdo; | |
| HRESULT hr; | |
| HRESULT ret = S_FALSE; | |
| TRACE("%p (%p)\n", This, shv); | |
| hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&pdo); | |
| if(SUCCEEDED(hr)) | |
| { | |
| FORMATETC fmt; | |
| STGMEDIUM medium; | |
| fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); | |
| fmt.ptd = NULL; | |
| fmt.dwAspect = DVASPECT_CONTENT; | |
| fmt.lindex = -1; | |
| fmt.tymed = TYMED_HGLOBAL; | |
| hr = IDataObject_GetData(pdo, &fmt ,&medium); | |
| IDataObject_Release(pdo); | |
| if(SUCCEEDED(hr)) | |
| { | |
| LPIDA pida = GlobalLock(medium.u.hGlobal); | |
| LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]); | |
| /* Handle folders by browsing to them. */ | |
| if(_ILIsFolder(pidl_child) || _ILIsDrive(pidl_child) || _ILIsSpecialFolder(pidl_child)) | |
| { | |
| IExplorerBrowser_BrowseToIDList(&This->IExplorerBrowser_iface, pidl_child, SBSP_RELATIVE); | |
| ret = S_OK; | |
| } | |
| GlobalUnlock(medium.u.hGlobal); | |
| GlobalFree(medium.u.hGlobal); | |
| } | |
| else | |
| ERR("Failed to get data from IDataObject.\n"); | |
| } else | |
| ERR("Failed to get IDataObject.\n"); | |
| /* If we didn't handle the default command, check if we have a | |
| * client that does */ | |
| if(ret == S_FALSE && This->pcdb_site) | |
| return ICommDlgBrowser_OnDefaultCommand(This->pcdb_site, shv); | |
| return ret; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface, | |
| IShellView *shv, ULONG uChange) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p, %d)\n", This, shv, uChange); | |
| if(This->pcdb_site) | |
| return ICommDlgBrowser_OnStateChange(This->pcdb_site, shv, uChange); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface, | |
| IShellView *pshv, LPCITEMIDLIST pidl) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p, %p)\n", This, pshv, pidl); | |
| if(This->pcdb_site) | |
| return ICommDlgBrowser_IncludeObject(This->pcdb_site, pshv, pidl); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface, | |
| IShellView *pshv, | |
| DWORD dwNotifyType) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p, 0x%x)\n", This, pshv, dwNotifyType); | |
| if(This->pcdb2_site) | |
| return ICommDlgBrowser2_Notify(This->pcdb2_site, pshv, dwNotifyType); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface, | |
| IShellView *pshv, | |
| LPWSTR pszText, int cchMax) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p, %s, %d)\n", This, pshv, debugstr_w(pszText), cchMax); | |
| if(This->pcdb2_site) | |
| return ICommDlgBrowser2_GetDefaultMenuText(This->pcdb2_site, pshv, pszText, cchMax); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface, | |
| DWORD *pdwFlags) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p)\n", This, pdwFlags); | |
| if(This->pcdb2_site) | |
| return ICommDlgBrowser2_GetViewFlags(This->pcdb2_site, pdwFlags); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface, | |
| IShellView *pshv, int iColumn) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p, %d)\n", This, pshv, iColumn); | |
| if(This->pcdb3_site) | |
| return ICommDlgBrowser3_OnColumnClicked(This->pcdb3_site, pshv, iColumn); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface, | |
| LPWSTR pszFileSpec, | |
| int cchFileSpec) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%s, %d)\n", This, debugstr_w(pszFileSpec), cchFileSpec); | |
| if(This->pcdb3_site) | |
| return ICommDlgBrowser3_GetCurrentFilter(This->pcdb3_site, pszFileSpec, cchFileSpec); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface, | |
| IShellView *pshv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface); | |
| TRACE("%p (%p)\n", This, pshv); | |
| if(This->pcdb3_site) | |
| return ICommDlgBrowser3_OnPreviewCreated(This->pcdb3_site, pshv); | |
| return S_OK; | |
| } | |
| static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = { | |
| ICommDlgBrowser3_fnQueryInterface, | |
| ICommDlgBrowser3_fnAddRef, | |
| ICommDlgBrowser3_fnRelease, | |
| ICommDlgBrowser3_fnOnDefaultCommand, | |
| ICommDlgBrowser3_fnOnStateChange, | |
| ICommDlgBrowser3_fnIncludeObject, | |
| ICommDlgBrowser3_fnNotify, | |
| ICommDlgBrowser3_fnGetDefaultMenuText, | |
| ICommDlgBrowser3_fnGetViewFlags, | |
| ICommDlgBrowser3_fnOnColumnClicked, | |
| ICommDlgBrowser3_fnGetCurrentFilter, | |
| ICommDlgBrowser3_fnOnPreviewCreated | |
| }; | |
| /************************************************************************** | |
| * IObjectWithSite Implementation | |
| */ | |
| static inline ExplorerBrowserImpl *impl_from_IObjectWithSite(IObjectWithSite *iface) | |
| { | |
| return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IObjectWithSite_iface); | |
| } | |
| static HRESULT WINAPI IObjectWithSite_fnQueryInterface(IObjectWithSite *iface, | |
| REFIID riid, void **ppvObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_QueryInterface(&This->IExplorerBrowser_iface, riid, ppvObject); | |
| } | |
| static ULONG WINAPI IObjectWithSite_fnAddRef(IObjectWithSite *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_AddRef(&This->IExplorerBrowser_iface); | |
| } | |
| static ULONG WINAPI IObjectWithSite_fnRelease(IObjectWithSite *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_Release(&This->IExplorerBrowser_iface); | |
| } | |
| static HRESULT WINAPI IObjectWithSite_fnSetSite(IObjectWithSite *iface, IUnknown *punk_site) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface); | |
| TRACE("%p (%p)\n", This, punk_site); | |
| if(This->punk_site) | |
| { | |
| IUnknown_Release(This->punk_site); | |
| This->punk_site = NULL; | |
| get_interfaces_from_site(This); | |
| } | |
| This->punk_site = punk_site; | |
| if(This->punk_site) | |
| IUnknown_AddRef(This->punk_site); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI IObjectWithSite_fnGetSite(IObjectWithSite *iface, REFIID riid, void **ppvSite) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface); | |
| TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvSite); | |
| if(!This->punk_site) | |
| return E_FAIL; | |
| return IUnknown_QueryInterface(This->punk_site, riid, ppvSite); | |
| } | |
| static const IObjectWithSiteVtbl vt_IObjectWithSite = { | |
| IObjectWithSite_fnQueryInterface, | |
| IObjectWithSite_fnAddRef, | |
| IObjectWithSite_fnRelease, | |
| IObjectWithSite_fnSetSite, | |
| IObjectWithSite_fnGetSite | |
| }; | |
| /************************************************************************** | |
| * INameSpaceTreeControlEvents Implementation | |
| */ | |
| static inline ExplorerBrowserImpl *impl_from_INameSpaceTreeControlEvents(INameSpaceTreeControlEvents *iface) | |
| { | |
| return CONTAINING_RECORD(iface, ExplorerBrowserImpl, INameSpaceTreeControlEvents_iface); | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnQueryInterface(INameSpaceTreeControlEvents *iface, | |
| REFIID riid, void **ppvObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject); | |
| *ppvObject = NULL; | |
| if(IsEqualIID(riid, &IID_INameSpaceTreeControlEvents) || | |
| IsEqualIID(riid, &IID_IUnknown)) | |
| { | |
| *ppvObject = iface; | |
| } | |
| if(*ppvObject) | |
| { | |
| IUnknown_AddRef((IUnknown*)*ppvObject); | |
| return S_OK; | |
| } | |
| return E_NOINTERFACE; | |
| } | |
| static ULONG WINAPI NSTCEvents_fnAddRef(INameSpaceTreeControlEvents *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_AddRef(&This->IExplorerBrowser_iface); | |
| } | |
| static ULONG WINAPI NSTCEvents_fnRelease(INameSpaceTreeControlEvents *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_Release(&This->IExplorerBrowser_iface); | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnItemClick(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, | |
| NSTCEHITTEST nstceHitTest, | |
| NSTCECLICKTYPE nstceClickType) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstceHitTest, nstceClickType); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnPropertyItemCommit(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnItemStateChanging(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, | |
| NSTCITEMSTATE nstcisMask, | |
| NSTCITEMSTATE nstcisState) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstcisMask, nstcisState); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnItemStateChanged(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, | |
| NSTCITEMSTATE nstcisMask, | |
| NSTCITEMSTATE nstcisState) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstcisMask, nstcisState); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnSelectionChanged(INameSpaceTreeControlEvents *iface, | |
| IShellItemArray *psiaSelection) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| IShellItem *psi; | |
| HRESULT hr; | |
| TRACE("%p (%p)\n", This, psiaSelection); | |
| hr = IShellItemArray_GetItemAt(psiaSelection, 0, &psi); | |
| if(SUCCEEDED(hr)) | |
| { | |
| hr = IExplorerBrowser_BrowseToObject(&This->IExplorerBrowser_iface, | |
| (IUnknown*)psi, SBSP_DEFBROWSER); | |
| IShellItem_Release(psi); | |
| } | |
| return hr; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnKeyboardInput(INameSpaceTreeControlEvents *iface, | |
| UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%d, 0x%lx, 0x%lx)\n", This, uMsg, wParam, lParam); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnBeforeExpand(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnAfterExpand(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnBeginLabelEdit(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnEndLabelEdit(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnGetToolTip(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, LPWSTR pszTip, int cchTip) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, %p, %d)\n", This, psi, pszTip, cchTip); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnBeforeItemDelete(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnItemAdded(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, BOOL fIsRoot) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, %d)\n", This, psi, fIsRoot); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnItemDeleted(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, BOOL fIsRoot) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, %d)\n", This, psi, fIsRoot); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnBeforeContextMenu(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, REFIID riid, void **ppv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, %s, %p)\n", This, psi, shdebugstr_guid(riid), ppv); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnAfterContextMenu(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi, IContextMenu *pcmIn, | |
| REFIID riid, void **ppv) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, %p, %s, %p)\n", This, psi, pcmIn, shdebugstr_guid(riid), ppv); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnBeforeStateImageChange(INameSpaceTreeControlEvents *iface, | |
| IShellItem *psi) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p)\n", This, psi); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI NSTCEvents_fnOnGetDefaultIconIndex(INameSpaceTreeControlEvents* iface, | |
| IShellItem *psi, | |
| int *piDefaultIcon, int *piOpenIcon) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface); | |
| TRACE("%p (%p, %p, %p)\n", This, psi, piDefaultIcon, piOpenIcon); | |
| return E_NOTIMPL; | |
| } | |
| static const INameSpaceTreeControlEventsVtbl vt_INameSpaceTreeControlEvents = { | |
| NSTCEvents_fnQueryInterface, | |
| NSTCEvents_fnAddRef, | |
| NSTCEvents_fnRelease, | |
| NSTCEvents_fnOnItemClick, | |
| NSTCEvents_fnOnPropertyItemCommit, | |
| NSTCEvents_fnOnItemStateChanging, | |
| NSTCEvents_fnOnItemStateChanged, | |
| NSTCEvents_fnOnSelectionChanged, | |
| NSTCEvents_fnOnKeyboardInput, | |
| NSTCEvents_fnOnBeforeExpand, | |
| NSTCEvents_fnOnAfterExpand, | |
| NSTCEvents_fnOnBeginLabelEdit, | |
| NSTCEvents_fnOnEndLabelEdit, | |
| NSTCEvents_fnOnGetToolTip, | |
| NSTCEvents_fnOnBeforeItemDelete, | |
| NSTCEvents_fnOnItemAdded, | |
| NSTCEvents_fnOnItemDeleted, | |
| NSTCEvents_fnOnBeforeContextMenu, | |
| NSTCEvents_fnOnAfterContextMenu, | |
| NSTCEvents_fnOnBeforeStateImageChange, | |
| NSTCEvents_fnOnGetDefaultIconIndex | |
| }; | |
| /************************************************************************** | |
| * IInputObject Implementation | |
| */ | |
| static inline ExplorerBrowserImpl *impl_from_IInputObject(IInputObject *iface) | |
| { | |
| return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IInputObject_iface); | |
| } | |
| static HRESULT WINAPI IInputObject_fnQueryInterface(IInputObject *iface, | |
| REFIID riid, void **ppvObject) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IInputObject(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_QueryInterface(&This->IExplorerBrowser_iface, riid, ppvObject); | |
| } | |
| static ULONG WINAPI IInputObject_fnAddRef(IInputObject *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IInputObject(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_AddRef(&This->IExplorerBrowser_iface); | |
| } | |
| static ULONG WINAPI IInputObject_fnRelease(IInputObject *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IInputObject(iface); | |
| TRACE("%p\n", This); | |
| return IExplorerBrowser_Release(&This->IExplorerBrowser_iface); | |
| } | |
| static HRESULT WINAPI IInputObject_fnUIActivateIO(IInputObject *iface, BOOL fActivate, MSG *pMsg) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IInputObject(iface); | |
| FIXME("stub, %p (%d, %p)\n", This, fActivate, pMsg); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IInputObject_fnHasFocusIO(IInputObject *iface) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IInputObject(iface); | |
| FIXME("stub, %p\n", This); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI IInputObject_fnTranslateAcceleratorIO(IInputObject *iface, MSG *pMsg) | |
| { | |
| ExplorerBrowserImpl *This = impl_from_IInputObject(iface); | |
| FIXME("stub, %p (%p)\n", This, pMsg); | |
| return E_NOTIMPL; | |
| } | |
| static IInputObjectVtbl vt_IInputObject = { | |
| IInputObject_fnQueryInterface, | |
| IInputObject_fnAddRef, | |
| IInputObject_fnRelease, | |
| IInputObject_fnUIActivateIO, | |
| IInputObject_fnHasFocusIO, | |
| IInputObject_fnTranslateAcceleratorIO | |
| }; | |
| HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv) | |
| { | |
| ExplorerBrowserImpl *eb; | |
| HRESULT ret; | |
| TRACE("%p %s %p\n", pUnkOuter, shdebugstr_guid (riid), ppv); | |
| if(!ppv) | |
| return E_POINTER; | |
| if(pUnkOuter) | |
| return CLASS_E_NOAGGREGATION; | |
| eb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExplorerBrowserImpl)); | |
| eb->ref = 1; | |
| eb->IExplorerBrowser_iface.lpVtbl = &vt_IExplorerBrowser; | |
| eb->IShellBrowser_iface.lpVtbl = &vt_IShellBrowser; | |
| eb->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3; | |
| eb->IObjectWithSite_iface.lpVtbl = &vt_IObjectWithSite; | |
| eb->INameSpaceTreeControlEvents_iface.lpVtbl = &vt_INameSpaceTreeControlEvents; | |
| eb->IInputObject_iface.lpVtbl = &vt_IInputObject; | |
| /* Default settings */ | |
| eb->navpane.width = 150; | |
| eb->navpane.show = TRUE; | |
| list_init(&eb->event_clients); | |
| list_init(&eb->travellog); | |
| ret = IExplorerBrowser_QueryInterface(&eb->IExplorerBrowser_iface, riid, ppv); | |
| IExplorerBrowser_Release(&eb->IExplorerBrowser_iface); | |
| TRACE("--(%p)\n", ppv); | |
| return ret; | |
| } |