123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885 |
- /*
- * explorer.exe
- *
- * Copyright 2004 CodeWeavers, Mike Hearn
- * Copyright 2005,2006 CodeWeavers, Aric Stewart
- * Copyright 2011 Jay Yang
- *
- * 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
- */
- #define COBJMACROS
- #include "wine/debug.h"
- #include "wine/heap.h"
- #include "explorer_private.h"
- #include "resource.h"
- #include <initguid.h>
- #include <windows.h>
- #include <shellapi.h>
- #include <shobjidl.h>
- #include <shlobj.h>
- #include <shlwapi.h>
- #include <commoncontrols.h>
- #include <commctrl.h>
- WINE_DEFAULT_DEBUG_CHANNEL(explorer);
- #define EXPLORER_INFO_INDEX 0
- #define NAV_TOOLBAR_HEIGHT 30
- #define PATHBOX_HEIGHT 24
- static int nav_toolbar_height;
- static int pathbox_height;
- #define DEFAULT_WIDTH 640
- #define DEFAULT_HEIGHT 480
- static int default_width;
- static int default_height;
- static const WCHAR EXPLORER_CLASS[] = {'E','x','p','l','o','r','e','r','W','C','l','a','s','s',0};
- static const WCHAR PATH_BOX_NAME[] = {'\0'};
- HINSTANCE explorer_hInstance;
- typedef struct parametersTAG {
- BOOL explorer_mode;
- WCHAR root[MAX_PATH];
- WCHAR selection[MAX_PATH];
- } parameters_struct;
- typedef struct
- {
- IExplorerBrowser *browser;
- HWND main_window,path_box;
- INT rebar_height;
- LPITEMIDLIST pidl;
- IImageList *icon_list;
- DWORD advise_cookie;
- IShellWindows *sw;
- LONG sw_cookie;
- } explorer_info;
- enum
- {
- BACK_BUTTON,FORWARD_BUTTON,UP_BUTTON
- };
- static void variant_from_pidl(VARIANT *var, const ITEMIDLIST *pidl)
- {
- V_VT(var) = VT_ARRAY | VT_UI1;
- V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 0, ILGetSize(pidl));
- memcpy(V_ARRAY(var)->pvData, pidl, ILGetSize(pidl));
- }
- typedef struct
- {
- IExplorerBrowserEvents IExplorerBrowserEvents_iface;
- explorer_info* info;
- LONG ref;
- } IExplorerBrowserEventsImpl;
- static IExplorerBrowserEventsImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
- {
- return CONTAINING_RECORD(iface, IExplorerBrowserEventsImpl, IExplorerBrowserEvents_iface);
- }
- static HRESULT WINAPI IExplorerBrowserEventsImpl_fnQueryInterface(IExplorerBrowserEvents *iface, REFIID riid, void **ppvObject)
- {
- return E_NOINTERFACE;
- }
- static ULONG WINAPI IExplorerBrowserEventsImpl_fnAddRef(IExplorerBrowserEvents *iface)
- {
- IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface);
- return InterlockedIncrement(&This->ref);
- }
- static ULONG WINAPI IExplorerBrowserEventsImpl_fnRelease(IExplorerBrowserEvents *iface)
- {
- IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
- if(!ref)
- HeapFree(GetProcessHeap(),0,This);
- return ref;
- }
- static BOOL create_combobox_item(IShellFolder *folder, LPCITEMIDLIST child_pidl, IImageList *icon_list, COMBOBOXEXITEMW *item)
- {
- STRRET strret;
- HRESULT hres;
- PIDLIST_ABSOLUTE parent_pidl, pidl;
- SHFILEINFOW info;
- IImageList *list;
- strret.uType=STRRET_WSTR;
- hres = IShellFolder_GetDisplayNameOf( folder, child_pidl, SHGDN_FORADDRESSBAR, &strret );
- if(SUCCEEDED(hres))
- hres = StrRetToStrW(&strret, child_pidl, &item->pszText);
- if(FAILED(hres))
- {
- WINE_WARN("Could not get name for pidl\n");
- return FALSE;
- }
- item->mask &= ~CBEIF_IMAGE;
- hres = SHGetIDListFromObject( (IUnknown *)folder, &parent_pidl );
- if (FAILED(hres)) return FALSE;
- pidl = ILCombine( parent_pidl, child_pidl );
- if (pidl)
- {
- list = (IImageList *)SHGetFileInfoW( (WCHAR *)pidl, 0, &info, sizeof(info),
- SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_SYSICONINDEX );
- if (list)
- {
- IImageList_Release( list );
- item->iImage = info.iIcon;
- item->mask |= CBEIF_IMAGE;
- }
- ILFree( pidl );
- }
- ILFree( parent_pidl );
- return TRUE;
- }
- static void update_path_box(explorer_info *info)
- {
- COMBOBOXEXITEMW item;
- COMBOBOXEXITEMW main_item;
- IShellFolder *desktop;
- IPersistFolder2 *persist;
- LPITEMIDLIST desktop_pidl;
- IEnumIDList *ids;
- SendMessageW(info->path_box,CB_RESETCONTENT,0,0);
- SHGetDesktopFolder(&desktop);
- IShellFolder_QueryInterface(desktop,&IID_IPersistFolder2,(void**)&persist);
- IPersistFolder2_GetCurFolder(persist,&desktop_pidl);
- IPersistFolder2_Release(persist);
- persist = NULL;
- /*Add Desktop*/
- item.iItem = -1;
- item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_LPARAM;
- item.iIndent = 0;
- create_combobox_item(desktop,desktop_pidl,info->icon_list,&item);
- item.lParam = (LPARAM)desktop_pidl;
- SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
- if(ILIsEqual(info->pidl,desktop_pidl))
- main_item = item;
- else
- CoTaskMemFree(item.pszText);
- /*Add all direct subfolders of Desktop*/
- if(SUCCEEDED(IShellFolder_EnumObjects(desktop,NULL,SHCONTF_FOLDERS,&ids))
- && ids!=NULL)
- {
- LPITEMIDLIST curr_pidl=NULL;
- HRESULT hres;
- item.iIndent = 1;
- while(1)
- {
- ILFree(curr_pidl);
- curr_pidl=NULL;
- hres = IEnumIDList_Next(ids,1,&curr_pidl,NULL);
- if(FAILED(hres) || hres == S_FALSE)
- break;
- if(!create_combobox_item(desktop,curr_pidl,info->icon_list,&item))
- WINE_WARN("Could not create a combobox item\n");
- else
- {
- LPITEMIDLIST full_pidl = ILCombine(desktop_pidl,curr_pidl);
- item.lParam = (LPARAM)full_pidl;
- SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
- if(ILIsEqual(full_pidl,info->pidl))
- main_item = item;
- else if(ILIsParent(full_pidl,info->pidl,FALSE))
- {
- /*add all parents of the pidl passed in*/
- LPITEMIDLIST next_pidl = ILFindChild(full_pidl,info->pidl);
- IShellFolder *curr_folder = NULL, *temp;
- hres = IShellFolder_BindToObject(desktop,curr_pidl,NULL,
- &IID_IShellFolder,
- (void**)&curr_folder);
- if(FAILED(hres))
- WINE_WARN("Could not get an IShellFolder\n");
- while(!ILIsEmpty(next_pidl))
- {
- LPITEMIDLIST first = ILCloneFirst(next_pidl);
- CoTaskMemFree(item.pszText);
- if(!create_combobox_item(curr_folder,first,
- info->icon_list,&item))
- {
- WINE_WARN("Could not create a combobox item\n");
- break;
- }
- ++item.iIndent;
- full_pidl = ILCombine(full_pidl,first);
- item.lParam = (LPARAM)full_pidl;
- SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
- temp=NULL;
- hres = IShellFolder_BindToObject(curr_folder,first,NULL,
- &IID_IShellFolder,
- (void**)&temp);
- if(FAILED(hres))
- {
- WINE_WARN("Could not get an IShellFolder\n");
- break;
- }
- IShellFolder_Release(curr_folder);
- curr_folder = temp;
- ILFree(first);
- next_pidl = ILGetNext(next_pidl);
- }
- memcpy(&main_item,&item,sizeof(item));
- if(curr_folder)
- IShellFolder_Release(curr_folder);
- item.iIndent = 1;
- }
- else
- CoTaskMemFree(item.pszText);
- }
- }
- ILFree(curr_pidl);
- IEnumIDList_Release(ids);
- }
- else
- WINE_WARN("Could not enumerate the desktop\n");
- SendMessageW(info->path_box,CBEM_SETITEMW,0,(LPARAM)&main_item);
- CoTaskMemFree(main_item.pszText);
- }
- static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
- {
- IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface);
- IShellFolder *parent;
- PCUITEMID_CHILD child_pidl;
- HRESULT hres;
- STRRET strret;
- WCHAR *name;
- if (This->info->sw)
- {
- VARIANT var;
- variant_from_pidl(&var, pidl);
- IShellWindows_OnNavigate(This->info->sw, This->info->sw_cookie, &var);
- VariantClear(&var);
- }
- ILFree(This->info->pidl);
- This->info->pidl = ILClone(pidl);
- update_path_box(This->info);
- hres = SHBindToParent(pidl, &IID_IShellFolder, (void **)&parent, &child_pidl);
- if (SUCCEEDED(hres))
- {
- hres = IShellFolder_GetDisplayNameOf(parent, child_pidl, SHGDN_FORADDRESSBAR, &strret);
- if (SUCCEEDED(hres))
- hres = StrRetToStrW(&strret, child_pidl, &name);
- if (SUCCEEDED(hres))
- {
- SetWindowTextW(This->info->main_window, name);
- CoTaskMemFree(name);
- }
- IShellFolder_Release(parent);
- }
- return hres;
- }
- static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationFailed(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
- {
- return S_OK;
- }
- static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationPending(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
- {
- return S_OK;
- }
- static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnViewCreated(IExplorerBrowserEvents *iface, IShellView *psv)
- {
- return S_OK;
- }
- static IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents =
- {
- IExplorerBrowserEventsImpl_fnQueryInterface,
- IExplorerBrowserEventsImpl_fnAddRef,
- IExplorerBrowserEventsImpl_fnRelease,
- IExplorerBrowserEventsImpl_fnOnNavigationPending,
- IExplorerBrowserEventsImpl_fnOnViewCreated,
- IExplorerBrowserEventsImpl_fnOnNavigationComplete,
- IExplorerBrowserEventsImpl_fnOnNavigationFailed
- };
- static IExplorerBrowserEvents *make_explorer_events(explorer_info *info)
- {
- IExplorerBrowserEventsImpl *ret
- = HeapAlloc(GetProcessHeap(), 0, sizeof(IExplorerBrowserEventsImpl));
- ret->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
- ret->info = info;
- ret->ref = 1;
- SHGetImageList(SHIL_SMALL,&IID_IImageList,(void**)&(ret->info->icon_list));
- SendMessageW(info->path_box,CBEM_SETIMAGELIST,0,(LPARAM)ret->info->icon_list);
- return &ret->IExplorerBrowserEvents_iface;
- }
- static IShellFolder *get_starting_shell_folder(WCHAR *path)
- {
- IShellFolder* desktop,*folder;
- LPITEMIDLIST root_pidl;
- HRESULT hres;
- SHGetDesktopFolder(&desktop);
- if (!path)
- return desktop;
- hres = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &root_pidl, NULL);
- if(FAILED(hres))
- {
- return desktop;
- }
- hres = IShellFolder_BindToObject(desktop,root_pidl,NULL,
- &IID_IShellFolder,
- (void**)&folder);
- ILFree(root_pidl);
- if(FAILED(hres))
- {
- return desktop;
- }
- IShellFolder_Release(desktop);
- return folder;
- }
- static void make_explorer_window(parameters_struct *params)
- {
- RECT rect;
- HWND rebar,nav_toolbar;
- FOLDERSETTINGS fs;
- IExplorerBrowserEvents *events;
- explorer_info *info;
- HRESULT hres;
- WCHAR explorer_title[100];
- WCHAR pathbox_label[50];
- TBADDBITMAP bitmap_info;
- TBBUTTON nav_buttons[3];
- int hist_offset,view_offset;
- REBARBANDINFOW band_info;
- VARIANT var, empty_var;
- IShellFolder *folder;
- IDispatch *dispatch;
- WCHAR *path = NULL;
- IShellWindows *sw;
- ITEMIDLIST *pidl;
- UINT dpix, dpiy;
- DWORD size;
- LONG hwnd;
- HDC hdc;
- MSG msg;
- CoCreateInstance(&CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER,
- &IID_IShellWindows, (void **)&sw);
- if (params->root[0])
- {
- size = GetFullPathNameW(params->root, 0, NULL, NULL);
- path = malloc( size * sizeof(WCHAR) );
- GetFullPathNameW(params->root, size, path, NULL);
- }
- if (sw && path)
- {
- if (!(pidl = ILCreateFromPathW(path)))
- {
- ERR("Failed to create PIDL for %s.\n", debugstr_w(path));
- IShellWindows_Release(sw);
- return;
- }
- variant_from_pidl(&var, pidl);
- V_VT(&empty_var) = VT_EMPTY;
- if (IShellWindows_FindWindowSW(sw, &var, &empty_var, SWC_EXPLORER, &hwnd, 0, &dispatch) == S_OK)
- {
- TRACE("Found window %#x already browsing path %s.\n", hwnd, debugstr_w(path));
- SetForegroundWindow((HWND)(LONG_PTR)hwnd);
- IShellWindows_Release(sw);
- return;
- }
- ILFree(pidl);
- VariantClear(&var);
- }
- memset(nav_buttons,0,sizeof(nav_buttons));
- LoadStringW(explorer_hInstance,IDS_EXPLORER_TITLE,explorer_title, ARRAY_SIZE( explorer_title ));
- LoadStringW(explorer_hInstance,IDS_PATHBOX_LABEL,pathbox_label, ARRAY_SIZE( pathbox_label ));
- hdc = GetDC(0);
- dpix = GetDeviceCaps(hdc, LOGPIXELSX);
- dpiy = GetDeviceCaps(hdc, LOGPIXELSY);
- ReleaseDC(0, hdc);
- nav_toolbar_height = MulDiv(NAV_TOOLBAR_HEIGHT, dpiy, USER_DEFAULT_SCREEN_DPI);
- pathbox_height = MulDiv(PATHBOX_HEIGHT, dpiy, USER_DEFAULT_SCREEN_DPI);
- default_width = MulDiv(DEFAULT_WIDTH, dpix, USER_DEFAULT_SCREEN_DPI);
- default_height = MulDiv(DEFAULT_HEIGHT, dpiy, USER_DEFAULT_SCREEN_DPI);
- info = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(explorer_info));
- if(!info)
- {
- WINE_ERR("Could not allocate an explorer_info struct\n");
- return;
- }
- hres = CoCreateInstance(&CLSID_ExplorerBrowser,NULL,CLSCTX_INPROC_SERVER,
- &IID_IExplorerBrowser,(LPVOID*)&info->browser);
- if(FAILED(hres))
- {
- WINE_ERR("Could not obtain an instance of IExplorerBrowser\n");
- HeapFree(GetProcessHeap(),0,info);
- return;
- }
- info->rebar_height=0;
- info->main_window
- = CreateWindowW(EXPLORER_CLASS,explorer_title,WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,CW_USEDEFAULT,default_width,
- default_height,NULL,NULL,explorer_hInstance,NULL);
- if (sw)
- {
- IShellWindows_Register(sw, NULL, (LONG_PTR)info->main_window, SWC_EXPLORER, &info->sw_cookie);
- info->sw = sw;
- }
- fs.ViewMode = FVM_DETAILS;
- fs.fFlags = FWF_AUTOARRANGE;
- SetRect(&rect, 0, 0, default_width, default_height);
- IExplorerBrowser_Initialize(info->browser,info->main_window,&rect,&fs);
- IExplorerBrowser_SetOptions(info->browser,EBO_SHOWFRAMES);
- SetWindowLongPtrW(info->main_window,EXPLORER_INFO_INDEX,(LONG_PTR)info);
- /*setup navbar*/
- rebar = CreateWindowExW(WS_EX_TOOLWINDOW,REBARCLASSNAMEW,NULL,
- WS_CHILD|WS_VISIBLE|RBS_VARHEIGHT|CCS_TOP|CCS_NODIVIDER,
- 0,0,0,0,info->main_window,NULL,explorer_hInstance,NULL);
- nav_toolbar
- = CreateWindowExW(TBSTYLE_EX_MIXEDBUTTONS,TOOLBARCLASSNAMEW,NULL,
- WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT,0,0,0,0,rebar,NULL,
- explorer_hInstance,NULL);
- bitmap_info.hInst = HINST_COMMCTRL;
- bitmap_info.nID = IDB_HIST_LARGE_COLOR;
- hist_offset= SendMessageW(nav_toolbar,TB_ADDBITMAP,0,(LPARAM)&bitmap_info);
- bitmap_info.nID = IDB_VIEW_LARGE_COLOR;
- view_offset= SendMessageW(nav_toolbar,TB_ADDBITMAP,0,(LPARAM)&bitmap_info);
- nav_buttons[0].iBitmap=hist_offset+HIST_BACK;
- nav_buttons[0].idCommand=BACK_BUTTON;
- nav_buttons[0].fsState=TBSTATE_ENABLED;
- nav_buttons[0].fsStyle=BTNS_BUTTON|BTNS_AUTOSIZE;
- nav_buttons[1].iBitmap=hist_offset+HIST_FORWARD;
- nav_buttons[1].idCommand=FORWARD_BUTTON;
- nav_buttons[1].fsState=TBSTATE_ENABLED;
- nav_buttons[1].fsStyle=BTNS_BUTTON|BTNS_AUTOSIZE;
- nav_buttons[2].iBitmap=view_offset+VIEW_PARENTFOLDER;
- nav_buttons[2].idCommand=UP_BUTTON;
- nav_buttons[2].fsState=TBSTATE_ENABLED;
- nav_buttons[2].fsStyle=BTNS_BUTTON|BTNS_AUTOSIZE;
- SendMessageW(nav_toolbar,TB_BUTTONSTRUCTSIZE,sizeof(TBBUTTON),0);
- SendMessageW(nav_toolbar,TB_ADDBUTTONSW,ARRAY_SIZE( nav_buttons ),(LPARAM)nav_buttons);
- band_info.cbSize = sizeof(band_info);
- band_info.fMask = RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
- band_info.hwndChild = nav_toolbar;
- band_info.fStyle=RBBS_GRIPPERALWAYS|RBBS_CHILDEDGE;
- band_info.cyChild=nav_toolbar_height;
- band_info.cx=0;
- band_info.cyMinChild=nav_toolbar_height;
- band_info.cxMinChild=0;
- SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info);
- info->path_box = CreateWindowW(WC_COMBOBOXEXW,PATH_BOX_NAME,
- WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
- 0,0,default_width,pathbox_height,rebar,NULL,
- explorer_hInstance,NULL);
- GetWindowRect(info->path_box, &rect);
- band_info.cyChild = rect.bottom - rect.top;
- band_info.cx=0;
- band_info.cyMinChild = rect.bottom - rect.top;
- band_info.cxMinChild=0;
- band_info.fMask|=RBBIM_TEXT;
- band_info.lpText=pathbox_label;
- band_info.fStyle|=RBBS_BREAK;
- band_info.hwndChild=info->path_box;
- SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info);
- events = make_explorer_events(info);
- IExplorerBrowser_Advise(info->browser,events,&info->advise_cookie);
- folder = get_starting_shell_folder(path);
- IExplorerBrowser_BrowseToObject(info->browser, (IUnknown *)folder, SBSP_ABSOLUTE);
- IShellFolder_Release(folder);
- ShowWindow(info->main_window,SW_SHOWDEFAULT);
- UpdateWindow(info->main_window);
- IExplorerBrowserEvents_Release(events);
- while (GetMessageW(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessageW(&msg);
- }
- }
- static void update_window_size(explorer_info *info, int height, int width)
- {
- RECT new_rect;
- new_rect.left = 0;
- new_rect.top = info->rebar_height;
- new_rect.right = width;
- new_rect.bottom = height;
- IExplorerBrowser_SetRect(info->browser,NULL,new_rect);
- }
- static void do_exit(int code)
- {
- OleUninitialize();
- ExitProcess(code);
- }
- static LRESULT explorer_on_end_edit(explorer_info *info,NMCBEENDEDITW *edit_info)
- {
- LPITEMIDLIST pidl = NULL;
- WINE_TRACE("iWhy=%x\n",edit_info->iWhy);
- switch(edit_info->iWhy)
- {
- case CBENF_DROPDOWN:
- if(edit_info->iNewSelection!=CB_ERR)
- pidl = (LPITEMIDLIST)SendMessageW(edit_info->hdr.hwndFrom,
- CB_GETITEMDATA,
- edit_info->iNewSelection,0);
- break;
- case CBENF_RETURN:
- {
- WCHAR path[MAX_PATH];
- HWND edit_ctrl = (HWND)SendMessageW(edit_info->hdr.hwndFrom,
- CBEM_GETEDITCONTROL,0,0);
- *((WORD*)path)=MAX_PATH;
- SendMessageW(edit_ctrl,EM_GETLINE,0,(LPARAM)path);
- pidl = ILCreateFromPathW(path);
- break;
- }
- case CBENF_ESCAPE:
- /*make sure the that the path box resets*/
- update_path_box(info);
- return 0;
- default:
- return 0;
- }
- if(pidl)
- IExplorerBrowser_BrowseToIDList(info->browser,pidl,SBSP_ABSOLUTE);
- if(edit_info->iWhy==CBENF_RETURN)
- ILFree(pidl);
- return 0;
- }
- static LRESULT update_rebar_size(explorer_info* info,NMRBAUTOSIZE *size_info)
- {
- RECT new_rect;
- RECT window_rect;
- info->rebar_height = size_info->rcTarget.bottom-size_info->rcTarget.top;
- GetWindowRect(info->main_window,&window_rect);
- new_rect.left = 0;
- new_rect.top = info->rebar_height;
- new_rect.right = window_rect.right-window_rect.left;
- new_rect.bottom = window_rect.bottom-window_rect.top;
- IExplorerBrowser_SetRect(info->browser,NULL,new_rect);
- return 0;
- }
- static LRESULT explorer_on_notify(explorer_info* info,NMHDR* notification)
- {
- WINE_TRACE("code=%i\n",notification->code);
- switch(notification->code)
- {
- case CBEN_BEGINEDIT:
- {
- WCHAR path[MAX_PATH];
- HWND edit_ctrl = (HWND)SendMessageW(notification->hwndFrom,
- CBEM_GETEDITCONTROL,0,0);
- SHGetPathFromIDListW(info->pidl,path);
- SetWindowTextW(edit_ctrl,path);
- break;
- }
- case CBEN_ENDEDITA:
- {
- NMCBEENDEDITA *edit_info_a = (NMCBEENDEDITA*)notification;
- NMCBEENDEDITW edit_info_w;
- edit_info_w.hdr = edit_info_a->hdr;
- edit_info_w.fChanged = edit_info_a->fChanged;
- edit_info_w.iNewSelection = edit_info_a->iNewSelection;
- MultiByteToWideChar(CP_ACP,0,edit_info_a->szText,-1,
- edit_info_w.szText,CBEMAXSTRLEN);
- edit_info_w.iWhy = edit_info_a->iWhy;
- return explorer_on_end_edit(info,&edit_info_w);
- }
- case CBEN_ENDEDITW:
- return explorer_on_end_edit(info,(NMCBEENDEDITW*)notification);
- case CBEN_DELETEITEM:
- {
- NMCOMBOBOXEXW *entry = (NMCOMBOBOXEXW*)notification;
- if(entry->ceItem.lParam)
- ILFree((LPITEMIDLIST)entry->ceItem.lParam);
- break;
- }
- case RBN_AUTOSIZE:
- return update_rebar_size(info,(NMRBAUTOSIZE*)notification);
- default:
- break;
- }
- return 0;
- }
- static LRESULT CALLBACK explorer_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- explorer_info *info
- = (explorer_info*)GetWindowLongPtrW(hwnd,EXPLORER_INFO_INDEX);
- IExplorerBrowser *browser = NULL;
- WINE_TRACE("(hwnd=%p,uMsg=%u,wParam=%lx,lParam=%lx)\n",hwnd,uMsg,wParam,lParam);
- if(info)
- browser = info->browser;
- switch(uMsg)
- {
- case WM_DESTROY:
- IShellWindows_Revoke(info->sw, info->sw_cookie);
- IShellWindows_Release(info->sw);
- IExplorerBrowser_Unadvise(browser,info->advise_cookie);
- IExplorerBrowser_Destroy(browser);
- IExplorerBrowser_Release(browser);
- ILFree(info->pidl);
- IImageList_Release(info->icon_list);
- HeapFree(GetProcessHeap(),0,info);
- SetWindowLongPtrW(hwnd,EXPLORER_INFO_INDEX,0);
- PostQuitMessage(0);
- break;
- case WM_QUIT:
- do_exit(wParam);
- case WM_NOTIFY:
- return explorer_on_notify(info,(NMHDR*)lParam);
- case WM_COMMAND:
- if(HIWORD(wParam)==BN_CLICKED)
- {
- switch(LOWORD(wParam))
- {
- case BACK_BUTTON:
- IExplorerBrowser_BrowseToObject(browser,NULL,SBSP_NAVIGATEBACK);
- break;
- case FORWARD_BUTTON:
- IExplorerBrowser_BrowseToObject(browser,NULL,SBSP_NAVIGATEFORWARD);
- break;
- case UP_BUTTON:
- IExplorerBrowser_BrowseToObject(browser,NULL,SBSP_PARENT);
- break;
- }
- }
- break;
- case WM_SIZE:
- update_window_size(info,HIWORD(lParam),LOWORD(lParam));
- break;
- default:
- return DefWindowProcW(hwnd,uMsg,wParam,lParam);
- }
- return 0;
- }
- static void register_explorer_window_class(void)
- {
- WNDCLASSEXW window_class;
- window_class.cbSize = sizeof(WNDCLASSEXW);
- window_class.style = 0;
- window_class.cbClsExtra = 0;
- window_class.cbWndExtra = sizeof(LONG_PTR);
- window_class.lpfnWndProc = explorer_wnd_proc;
- window_class.hInstance = explorer_hInstance;
- window_class.hIcon = NULL;
- window_class.hCursor = NULL;
- window_class.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
- window_class.lpszMenuName = NULL;
- window_class.lpszClassName = EXPLORER_CLASS;
- window_class.hIconSm = NULL;
- RegisterClassExW(&window_class);
- }
- static WCHAR *copy_path_string(WCHAR *target, WCHAR *source)
- {
- INT i = 0;
- while (iswspace(*source)) source++;
- if (*source == '\"')
- {
- source ++;
- while (*source && *source != '\"') target[i++] = *source++;
- target[i] = 0;
- if (*source) source++;
- }
- else
- {
- while (*source && *source != ',') target[i++] = *source++;
- target[i] = 0;
- }
- PathRemoveBackslashW(target);
- return source;
- }
- static void copy_path_root(LPWSTR root, LPWSTR path)
- {
- LPWSTR p,p2;
- INT i = 0;
- p = path;
- while (*p!=0)
- p++;
- while (*p!='\\' && p > path)
- p--;
- if (p == path)
- return;
- p2 = path;
- while (p2 != p)
- {
- root[i] = *p2;
- i++;
- p2++;
- }
- root[i] = 0;
- }
- /*
- * Command Line parameters are:
- * [/n] Opens in single-paned view for each selected items. This is default
- * [/e,] Uses Windows Explorer View
- * [/cd,object] Specifies the root level of the view
- * [/root,object] Specifies the root level of the view
- * [/select,object] parent folder is opened and specified object is selected
- */
- static void parse_command_line(LPWSTR commandline,parameters_struct *parameters)
- {
- static const WCHAR arg_n[] = {'/','n'};
- static const WCHAR arg_e[] = {'/','e',','};
- static const WCHAR arg_cd[] = {'/','c','d',','};
- static const WCHAR arg_root[] = {'/','r','o','o','t',','};
- static const WCHAR arg_select[] = {'/','s','e','l','e','c','t',','};
- static const WCHAR arg_desktop[] = {'/','d','e','s','k','t','o','p'};
- static const WCHAR arg_desktop_quotes[] = {'"','/','d','e','s','k','t','o','p'};
- LPWSTR p = commandline;
- while (*p)
- {
- while (iswspace(*p)) p++;
- if (wcsncmp(p, arg_n, ARRAY_SIZE( arg_n ))==0)
- {
- parameters->explorer_mode = FALSE;
- p += ARRAY_SIZE( arg_n );
- }
- else if (wcsncmp(p, arg_e, ARRAY_SIZE( arg_e ))==0)
- {
- parameters->explorer_mode = TRUE;
- p += ARRAY_SIZE( arg_e );
- }
- else if (wcsncmp(p, arg_cd, ARRAY_SIZE( arg_cd ))==0)
- {
- p += ARRAY_SIZE( arg_cd );
- p = copy_path_string(parameters->root,p);
- }
- else if (wcsncmp(p, arg_root, ARRAY_SIZE( arg_root ))==0)
- {
- p += ARRAY_SIZE( arg_root );
- p = copy_path_string(parameters->root,p);
- }
- else if (wcsncmp(p, arg_select, ARRAY_SIZE( arg_select ))==0)
- {
- p += ARRAY_SIZE( arg_select );
- p = copy_path_string(parameters->selection,p);
- if (!parameters->root[0])
- copy_path_root(parameters->root,
- parameters->selection);
- }
- else if (wcsncmp(p, arg_desktop, ARRAY_SIZE( arg_desktop ))==0)
- {
- p += ARRAY_SIZE( arg_desktop );
- manage_desktop( p ); /* the rest of the command line is handled by desktop mode */
- }
- /* workaround for Worms Armageddon that hardcodes a /desktop option with quotes */
- else if (wcsncmp(p, arg_desktop_quotes, ARRAY_SIZE( arg_desktop_quotes ))==0)
- {
- p += ARRAY_SIZE( arg_desktop_quotes );
- manage_desktop( p ); /* the rest of the command line is handled by desktop mode */
- }
- else
- {
- /* left over command line is generally the path to be opened */
- copy_path_string(parameters->root,p);
- break;
- }
- }
- }
- int WINAPI wWinMain(HINSTANCE hinstance,
- HINSTANCE previnstance,
- LPWSTR cmdline,
- int cmdshow)
- {
- parameters_struct parameters;
- HRESULT hres;
- INITCOMMONCONTROLSEX init_info;
- memset(¶meters,0,sizeof(parameters));
- explorer_hInstance = hinstance;
- parse_command_line(cmdline,¶meters);
- hres = OleInitialize(NULL);
- if(FAILED(hres))
- {
- WINE_ERR("Could not initialize COM\n");
- ExitProcess(EXIT_FAILURE);
- }
- if(parameters.root[0] && !PathIsDirectoryW(parameters.root))
- if(ShellExecuteW(NULL,NULL,parameters.root,NULL,NULL,SW_SHOWDEFAULT) > (HINSTANCE)32)
- ExitProcess(EXIT_SUCCESS);
- init_info.dwSize = sizeof(INITCOMMONCONTROLSEX);
- init_info.dwICC = ICC_USEREX_CLASSES | ICC_BAR_CLASSES | ICC_COOL_CLASSES;
- if(!InitCommonControlsEx(&init_info))
- {
- WINE_ERR("Could not initialize Comctl\n");
- ExitProcess(EXIT_FAILURE);
- }
- register_explorer_window_class();
- make_explorer_window(¶meters);
- return 0;
- }
|