| /* |
| * 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; |
| } |