4 * Copyright 2004 CodeWeavers, Mike Hearn
5 * Copyright 2005,2006 CodeWeavers, Aric Stewart
6 * Copyright 2011 Jay Yang
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
26 #include "wine/heap.h"
27 #include "explorer_private.h"
36 #include <commoncontrols.h>
39 WINE_DEFAULT_DEBUG_CHANNEL(explorer
);
41 #define EXPLORER_INFO_INDEX 0
43 #define NAV_TOOLBAR_HEIGHT 30
44 #define PATHBOX_HEIGHT 24
45 static int nav_toolbar_height
;
46 static int pathbox_height
;
48 #define DEFAULT_WIDTH 640
49 #define DEFAULT_HEIGHT 480
50 static int default_width
;
51 static int default_height
;
54 static const WCHAR EXPLORER_CLASS
[] = {'E','x','p','l','o','r','e','r','W','C','l','a','s','s',0};
55 static const WCHAR PATH_BOX_NAME
[] = {'\0'};
57 HINSTANCE explorer_hInstance
;
59 typedef struct parametersTAG
{
62 WCHAR selection
[MAX_PATH
];
67 IExplorerBrowser
*browser
;
68 HWND main_window
,path_box
;
71 IImageList
*icon_list
;
80 BACK_BUTTON
,FORWARD_BUTTON
,UP_BUTTON
83 static void variant_from_pidl(VARIANT
*var
, const ITEMIDLIST
*pidl
)
85 V_VT(var
) = VT_ARRAY
| VT_UI1
;
86 V_ARRAY(var
) = SafeArrayCreateVector(VT_UI1
, 0, ILGetSize(pidl
));
87 memcpy(V_ARRAY(var
)->pvData
, pidl
, ILGetSize(pidl
));
92 IExplorerBrowserEvents IExplorerBrowserEvents_iface
;
95 } IExplorerBrowserEventsImpl
;
97 static IExplorerBrowserEventsImpl
*impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents
*iface
)
99 return CONTAINING_RECORD(iface
, IExplorerBrowserEventsImpl
, IExplorerBrowserEvents_iface
);
102 static HRESULT WINAPI
IExplorerBrowserEventsImpl_fnQueryInterface(IExplorerBrowserEvents
*iface
, REFIID riid
, void **ppvObject
)
104 return E_NOINTERFACE
;
107 static ULONG WINAPI
IExplorerBrowserEventsImpl_fnAddRef(IExplorerBrowserEvents
*iface
)
109 IExplorerBrowserEventsImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
110 return InterlockedIncrement(&This
->ref
);
113 static ULONG WINAPI
IExplorerBrowserEventsImpl_fnRelease(IExplorerBrowserEvents
*iface
)
115 IExplorerBrowserEventsImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
116 ULONG ref
= InterlockedDecrement(&This
->ref
);
118 HeapFree(GetProcessHeap(),0,This
);
122 static BOOL
create_combobox_item(IShellFolder
*folder
, LPCITEMIDLIST child_pidl
, IImageList
*icon_list
, COMBOBOXEXITEMW
*item
)
126 PIDLIST_ABSOLUTE parent_pidl
, pidl
;
130 strret
.uType
=STRRET_WSTR
;
131 hres
= IShellFolder_GetDisplayNameOf( folder
, child_pidl
, SHGDN_FORADDRESSBAR
, &strret
);
133 hres
= StrRetToStrW(&strret
, child_pidl
, &item
->pszText
);
136 WINE_WARN("Could not get name for pidl\n");
140 item
->mask
&= ~CBEIF_IMAGE
;
141 hres
= SHGetIDListFromObject( (IUnknown
*)folder
, &parent_pidl
);
142 if (FAILED(hres
)) return FALSE
;
144 pidl
= ILCombine( parent_pidl
, child_pidl
);
147 list
= (IImageList
*)SHGetFileInfoW( (WCHAR
*)pidl
, 0, &info
, sizeof(info
),
148 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_SYSICONINDEX
);
151 IImageList_Release( list
);
152 item
->iImage
= info
.iIcon
;
153 item
->mask
|= CBEIF_IMAGE
;
157 ILFree( parent_pidl
);
162 static void update_path_box(explorer_info
*info
)
164 COMBOBOXEXITEMW item
;
165 COMBOBOXEXITEMW main_item
;
166 IShellFolder
*desktop
;
167 IPersistFolder2
*persist
;
168 LPITEMIDLIST desktop_pidl
;
171 SendMessageW(info
->path_box
,CB_RESETCONTENT
,0,0);
172 SHGetDesktopFolder(&desktop
);
173 IShellFolder_QueryInterface(desktop
,&IID_IPersistFolder2
,(void**)&persist
);
174 IPersistFolder2_GetCurFolder(persist
,&desktop_pidl
);
175 IPersistFolder2_Release(persist
);
179 item
.mask
= CBEIF_TEXT
| CBEIF_INDENT
| CBEIF_LPARAM
;
181 create_combobox_item(desktop
,desktop_pidl
,info
->icon_list
,&item
);
182 item
.lParam
= (LPARAM
)desktop_pidl
;
183 SendMessageW(info
->path_box
,CBEM_INSERTITEMW
,0,(LPARAM
)&item
);
184 if(ILIsEqual(info
->pidl
,desktop_pidl
))
187 CoTaskMemFree(item
.pszText
);
188 /*Add all direct subfolders of Desktop*/
189 if(SUCCEEDED(IShellFolder_EnumObjects(desktop
,NULL
,SHCONTF_FOLDERS
,&ids
))
192 LPITEMIDLIST curr_pidl
=NULL
;
200 hres
= IEnumIDList_Next(ids
,1,&curr_pidl
,NULL
);
201 if(FAILED(hres
) || hres
== S_FALSE
)
203 if(!create_combobox_item(desktop
,curr_pidl
,info
->icon_list
,&item
))
204 WINE_WARN("Could not create a combobox item\n");
207 LPITEMIDLIST full_pidl
= ILCombine(desktop_pidl
,curr_pidl
);
208 item
.lParam
= (LPARAM
)full_pidl
;
209 SendMessageW(info
->path_box
,CBEM_INSERTITEMW
,0,(LPARAM
)&item
);
210 if(ILIsEqual(full_pidl
,info
->pidl
))
212 else if(ILIsParent(full_pidl
,info
->pidl
,FALSE
))
214 /*add all parents of the pidl passed in*/
215 LPITEMIDLIST next_pidl
= ILFindChild(full_pidl
,info
->pidl
);
216 IShellFolder
*curr_folder
= NULL
, *temp
;
217 hres
= IShellFolder_BindToObject(desktop
,curr_pidl
,NULL
,
219 (void**)&curr_folder
);
221 WINE_WARN("Could not get an IShellFolder\n");
222 while(!ILIsEmpty(next_pidl
))
224 LPITEMIDLIST first
= ILCloneFirst(next_pidl
);
225 CoTaskMemFree(item
.pszText
);
226 if(!create_combobox_item(curr_folder
,first
,
227 info
->icon_list
,&item
))
229 WINE_WARN("Could not create a combobox item\n");
233 full_pidl
= ILCombine(full_pidl
,first
);
234 item
.lParam
= (LPARAM
)full_pidl
;
235 SendMessageW(info
->path_box
,CBEM_INSERTITEMW
,0,(LPARAM
)&item
);
237 hres
= IShellFolder_BindToObject(curr_folder
,first
,NULL
,
242 WINE_WARN("Could not get an IShellFolder\n");
245 IShellFolder_Release(curr_folder
);
249 next_pidl
= ILGetNext(next_pidl
);
251 memcpy(&main_item
,&item
,sizeof(item
));
253 IShellFolder_Release(curr_folder
);
257 CoTaskMemFree(item
.pszText
);
261 IEnumIDList_Release(ids
);
264 WINE_WARN("Could not enumerate the desktop\n");
265 SendMessageW(info
->path_box
,CBEM_SETITEMW
,0,(LPARAM
)&main_item
);
266 CoTaskMemFree(main_item
.pszText
);
269 static HRESULT WINAPI
IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplorerBrowserEvents
*iface
, PCIDLIST_ABSOLUTE pidl
)
271 IExplorerBrowserEventsImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
272 IShellFolder
*parent
;
273 PCUITEMID_CHILD child_pidl
;
282 variant_from_pidl(&var
, pidl
);
283 IShellWindows_OnNavigate(This
->info
->sw
, This
->info
->sw_cookie
, &var
);
287 ILFree(This
->info
->pidl
);
288 This
->info
->pidl
= ILClone(pidl
);
289 update_path_box(This
->info
);
291 hres
= SHBindToParent(pidl
, &IID_IShellFolder
, (void **)&parent
, &child_pidl
);
294 hres
= IShellFolder_GetDisplayNameOf(parent
, child_pidl
, SHGDN_FORADDRESSBAR
, &strret
);
296 hres
= StrRetToStrW(&strret
, child_pidl
, &name
);
299 SetWindowTextW(This
->info
->main_window
, name
);
303 IShellFolder_Release(parent
);
309 static HRESULT WINAPI
IExplorerBrowserEventsImpl_fnOnNavigationFailed(IExplorerBrowserEvents
*iface
, PCIDLIST_ABSOLUTE pidl
)
314 static HRESULT WINAPI
IExplorerBrowserEventsImpl_fnOnNavigationPending(IExplorerBrowserEvents
*iface
, PCIDLIST_ABSOLUTE pidl
)
319 static HRESULT WINAPI
IExplorerBrowserEventsImpl_fnOnViewCreated(IExplorerBrowserEvents
*iface
, IShellView
*psv
)
324 static IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents
=
326 IExplorerBrowserEventsImpl_fnQueryInterface
,
327 IExplorerBrowserEventsImpl_fnAddRef
,
328 IExplorerBrowserEventsImpl_fnRelease
,
329 IExplorerBrowserEventsImpl_fnOnNavigationPending
,
330 IExplorerBrowserEventsImpl_fnOnViewCreated
,
331 IExplorerBrowserEventsImpl_fnOnNavigationComplete
,
332 IExplorerBrowserEventsImpl_fnOnNavigationFailed
335 static IExplorerBrowserEvents
*make_explorer_events(explorer_info
*info
)
337 IExplorerBrowserEventsImpl
*ret
338 = HeapAlloc(GetProcessHeap(), 0, sizeof(IExplorerBrowserEventsImpl
));
339 ret
->IExplorerBrowserEvents_iface
.lpVtbl
= &vt_IExplorerBrowserEvents
;
342 SHGetImageList(SHIL_SMALL
,&IID_IImageList
,(void**)&(ret
->info
->icon_list
));
343 SendMessageW(info
->path_box
,CBEM_SETIMAGELIST
,0,(LPARAM
)ret
->info
->icon_list
);
344 return &ret
->IExplorerBrowserEvents_iface
;
347 static IShellFolder
*get_starting_shell_folder(WCHAR
*path
)
349 IShellFolder
* desktop
,*folder
;
350 LPITEMIDLIST root_pidl
;
353 SHGetDesktopFolder(&desktop
);
358 hres
= IShellFolder_ParseDisplayName(desktop
, NULL
, NULL
, path
, NULL
, &root_pidl
, NULL
);
363 hres
= IShellFolder_BindToObject(desktop
,root_pidl
,NULL
,
371 IShellFolder_Release(desktop
);
375 static void make_explorer_window(parameters_struct
*params
)
378 HWND rebar
,nav_toolbar
;
380 IExplorerBrowserEvents
*events
;
383 WCHAR explorer_title
[100];
384 WCHAR pathbox_label
[50];
385 TBADDBITMAP bitmap_info
;
386 TBBUTTON nav_buttons
[3];
387 int hist_offset
,view_offset
;
388 REBARBANDINFOW band_info
;
389 VARIANT var
, empty_var
;
390 IShellFolder
*folder
;
401 CoCreateInstance(&CLSID_ShellWindows
, NULL
, CLSCTX_LOCAL_SERVER
,
402 &IID_IShellWindows
, (void **)&sw
);
406 size
= GetFullPathNameW(params
->root
, 0, NULL
, NULL
);
408 GetFullPathNameW(params
->root
, size
, path
, NULL
);
413 if (!(pidl
= ILCreateFromPathW(path
)))
415 ERR("Failed to create PIDL for %s.\n", debugstr_w(path
));
416 IShellWindows_Release(sw
);
420 variant_from_pidl(&var
, pidl
);
421 V_VT(&empty_var
) = VT_EMPTY
;
422 if (IShellWindows_FindWindowSW(sw
, &var
, &empty_var
, SWC_EXPLORER
, &hwnd
, 0, &dispatch
) == S_OK
)
424 TRACE("Found window %#x already browsing path %s.\n", hwnd
, debugstr_w(path
));
425 SetForegroundWindow((HWND
)(LONG_PTR
)hwnd
);
426 IShellWindows_Release(sw
);
433 memset(nav_buttons
,0,sizeof(nav_buttons
));
435 LoadStringW(explorer_hInstance
,IDS_EXPLORER_TITLE
,explorer_title
, ARRAY_SIZE( explorer_title
));
436 LoadStringW(explorer_hInstance
,IDS_PATHBOX_LABEL
,pathbox_label
, ARRAY_SIZE( pathbox_label
));
439 dpix
= GetDeviceCaps(hdc
, LOGPIXELSX
);
440 dpiy
= GetDeviceCaps(hdc
, LOGPIXELSY
);
442 nav_toolbar_height
= MulDiv(NAV_TOOLBAR_HEIGHT
, dpiy
, USER_DEFAULT_SCREEN_DPI
);
443 pathbox_height
= MulDiv(PATHBOX_HEIGHT
, dpiy
, USER_DEFAULT_SCREEN_DPI
);
444 default_width
= MulDiv(DEFAULT_WIDTH
, dpix
, USER_DEFAULT_SCREEN_DPI
);
445 default_height
= MulDiv(DEFAULT_HEIGHT
, dpiy
, USER_DEFAULT_SCREEN_DPI
);
447 info
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(explorer_info
));
450 WINE_ERR("Could not allocate an explorer_info struct\n");
453 hres
= CoCreateInstance(&CLSID_ExplorerBrowser
,NULL
,CLSCTX_INPROC_SERVER
,
454 &IID_IExplorerBrowser
,(LPVOID
*)&info
->browser
);
457 WINE_ERR("Could not obtain an instance of IExplorerBrowser\n");
458 HeapFree(GetProcessHeap(),0,info
);
461 info
->rebar_height
=0;
463 = CreateWindowW(EXPLORER_CLASS
,explorer_title
,WS_OVERLAPPEDWINDOW
,
464 CW_USEDEFAULT
,CW_USEDEFAULT
,default_width
,
465 default_height
,NULL
,NULL
,explorer_hInstance
,NULL
);
469 IShellWindows_Register(sw
, NULL
, (LONG_PTR
)info
->main_window
, SWC_EXPLORER
, &info
->sw_cookie
);
473 fs
.ViewMode
= FVM_DETAILS
;
474 fs
.fFlags
= FWF_AUTOARRANGE
;
476 SetRect(&rect
, 0, 0, default_width
, default_height
);
477 IExplorerBrowser_Initialize(info
->browser
,info
->main_window
,&rect
,&fs
);
478 IExplorerBrowser_SetOptions(info
->browser
,EBO_SHOWFRAMES
);
479 SetWindowLongPtrW(info
->main_window
,EXPLORER_INFO_INDEX
,(LONG_PTR
)info
);
482 rebar
= CreateWindowExW(WS_EX_TOOLWINDOW
,REBARCLASSNAMEW
,NULL
,
483 WS_CHILD
|WS_VISIBLE
|RBS_VARHEIGHT
|CCS_TOP
|CCS_NODIVIDER
,
484 0,0,0,0,info
->main_window
,NULL
,explorer_hInstance
,NULL
);
486 = CreateWindowExW(TBSTYLE_EX_MIXEDBUTTONS
,TOOLBARCLASSNAMEW
,NULL
,
487 WS_CHILD
|WS_VISIBLE
|TBSTYLE_FLAT
,0,0,0,0,rebar
,NULL
,
488 explorer_hInstance
,NULL
);
490 bitmap_info
.hInst
= HINST_COMMCTRL
;
491 bitmap_info
.nID
= IDB_HIST_LARGE_COLOR
;
492 hist_offset
= SendMessageW(nav_toolbar
,TB_ADDBITMAP
,0,(LPARAM
)&bitmap_info
);
493 bitmap_info
.nID
= IDB_VIEW_LARGE_COLOR
;
494 view_offset
= SendMessageW(nav_toolbar
,TB_ADDBITMAP
,0,(LPARAM
)&bitmap_info
);
496 nav_buttons
[0].iBitmap
=hist_offset
+HIST_BACK
;
497 nav_buttons
[0].idCommand
=BACK_BUTTON
;
498 nav_buttons
[0].fsState
=TBSTATE_ENABLED
;
499 nav_buttons
[0].fsStyle
=BTNS_BUTTON
|BTNS_AUTOSIZE
;
500 nav_buttons
[1].iBitmap
=hist_offset
+HIST_FORWARD
;
501 nav_buttons
[1].idCommand
=FORWARD_BUTTON
;
502 nav_buttons
[1].fsState
=TBSTATE_ENABLED
;
503 nav_buttons
[1].fsStyle
=BTNS_BUTTON
|BTNS_AUTOSIZE
;
504 nav_buttons
[2].iBitmap
=view_offset
+VIEW_PARENTFOLDER
;
505 nav_buttons
[2].idCommand
=UP_BUTTON
;
506 nav_buttons
[2].fsState
=TBSTATE_ENABLED
;
507 nav_buttons
[2].fsStyle
=BTNS_BUTTON
|BTNS_AUTOSIZE
;
508 SendMessageW(nav_toolbar
,TB_BUTTONSTRUCTSIZE
,sizeof(TBBUTTON
),0);
509 SendMessageW(nav_toolbar
,TB_ADDBUTTONSW
,ARRAY_SIZE( nav_buttons
),(LPARAM
)nav_buttons
);
511 band_info
.cbSize
= sizeof(band_info
);
512 band_info
.fMask
= RBBIM_STYLE
|RBBIM_CHILD
|RBBIM_CHILDSIZE
|RBBIM_SIZE
;
513 band_info
.hwndChild
= nav_toolbar
;
514 band_info
.fStyle
=RBBS_GRIPPERALWAYS
|RBBS_CHILDEDGE
;
515 band_info
.cyChild
=nav_toolbar_height
;
517 band_info
.cyMinChild
=nav_toolbar_height
;
518 band_info
.cxMinChild
=0;
519 SendMessageW(rebar
,RB_INSERTBANDW
,-1,(LPARAM
)&band_info
);
520 info
->path_box
= CreateWindowW(WC_COMBOBOXEXW
,PATH_BOX_NAME
,
521 WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
522 0,0,default_width
,pathbox_height
,rebar
,NULL
,
523 explorer_hInstance
,NULL
);
524 GetWindowRect(info
->path_box
, &rect
);
525 band_info
.cyChild
= rect
.bottom
- rect
.top
;
527 band_info
.cyMinChild
= rect
.bottom
- rect
.top
;
528 band_info
.cxMinChild
=0;
529 band_info
.fMask
|=RBBIM_TEXT
;
530 band_info
.lpText
=pathbox_label
;
531 band_info
.fStyle
|=RBBS_BREAK
;
532 band_info
.hwndChild
=info
->path_box
;
533 SendMessageW(rebar
,RB_INSERTBANDW
,-1,(LPARAM
)&band_info
);
534 events
= make_explorer_events(info
);
535 IExplorerBrowser_Advise(info
->browser
,events
,&info
->advise_cookie
);
537 folder
= get_starting_shell_folder(path
);
538 IExplorerBrowser_BrowseToObject(info
->browser
, (IUnknown
*)folder
, SBSP_ABSOLUTE
);
539 IShellFolder_Release(folder
);
541 ShowWindow(info
->main_window
,SW_SHOWDEFAULT
);
542 UpdateWindow(info
->main_window
);
543 IExplorerBrowserEvents_Release(events
);
545 while (GetMessageW(&msg
, NULL
, 0, 0))
547 TranslateMessage(&msg
);
548 DispatchMessageW(&msg
);
552 static void update_window_size(explorer_info
*info
, int height
, int width
)
556 new_rect
.top
= info
->rebar_height
;
557 new_rect
.right
= width
;
558 new_rect
.bottom
= height
;
559 IExplorerBrowser_SetRect(info
->browser
,NULL
,new_rect
);
562 static void do_exit(int code
)
568 static LRESULT
explorer_on_end_edit(explorer_info
*info
,NMCBEENDEDITW
*edit_info
)
570 LPITEMIDLIST pidl
= NULL
;
572 WINE_TRACE("iWhy=%x\n",edit_info
->iWhy
);
573 switch(edit_info
->iWhy
)
576 if(edit_info
->iNewSelection
!=CB_ERR
)
577 pidl
= (LPITEMIDLIST
)SendMessageW(edit_info
->hdr
.hwndFrom
,
579 edit_info
->iNewSelection
,0);
583 WCHAR path
[MAX_PATH
];
584 HWND edit_ctrl
= (HWND
)SendMessageW(edit_info
->hdr
.hwndFrom
,
585 CBEM_GETEDITCONTROL
,0,0);
586 *((WORD
*)path
)=MAX_PATH
;
587 SendMessageW(edit_ctrl
,EM_GETLINE
,0,(LPARAM
)path
);
588 pidl
= ILCreateFromPathW(path
);
592 /*make sure the that the path box resets*/
593 update_path_box(info
);
599 IExplorerBrowser_BrowseToIDList(info
->browser
,pidl
,SBSP_ABSOLUTE
);
600 if(edit_info
->iWhy
==CBENF_RETURN
)
605 static LRESULT
update_rebar_size(explorer_info
* info
,NMRBAUTOSIZE
*size_info
)
609 info
->rebar_height
= size_info
->rcTarget
.bottom
-size_info
->rcTarget
.top
;
610 GetWindowRect(info
->main_window
,&window_rect
);
612 new_rect
.top
= info
->rebar_height
;
613 new_rect
.right
= window_rect
.right
-window_rect
.left
;
614 new_rect
.bottom
= window_rect
.bottom
-window_rect
.top
;
615 IExplorerBrowser_SetRect(info
->browser
,NULL
,new_rect
);
619 static LRESULT
explorer_on_notify(explorer_info
* info
,NMHDR
* notification
)
621 WINE_TRACE("code=%i\n",notification
->code
);
622 switch(notification
->code
)
626 WCHAR path
[MAX_PATH
];
627 HWND edit_ctrl
= (HWND
)SendMessageW(notification
->hwndFrom
,
628 CBEM_GETEDITCONTROL
,0,0);
629 SHGetPathFromIDListW(info
->pidl
,path
);
630 SetWindowTextW(edit_ctrl
,path
);
635 NMCBEENDEDITA
*edit_info_a
= (NMCBEENDEDITA
*)notification
;
636 NMCBEENDEDITW edit_info_w
;
637 edit_info_w
.hdr
= edit_info_a
->hdr
;
638 edit_info_w
.fChanged
= edit_info_a
->fChanged
;
639 edit_info_w
.iNewSelection
= edit_info_a
->iNewSelection
;
640 MultiByteToWideChar(CP_ACP
,0,edit_info_a
->szText
,-1,
641 edit_info_w
.szText
,CBEMAXSTRLEN
);
642 edit_info_w
.iWhy
= edit_info_a
->iWhy
;
643 return explorer_on_end_edit(info
,&edit_info_w
);
646 return explorer_on_end_edit(info
,(NMCBEENDEDITW
*)notification
);
647 case CBEN_DELETEITEM
:
649 NMCOMBOBOXEXW
*entry
= (NMCOMBOBOXEXW
*)notification
;
650 if(entry
->ceItem
.lParam
)
651 ILFree((LPITEMIDLIST
)entry
->ceItem
.lParam
);
655 return update_rebar_size(info
,(NMRBAUTOSIZE
*)notification
);
662 static LRESULT CALLBACK
explorer_wnd_proc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
665 = (explorer_info
*)GetWindowLongPtrW(hwnd
,EXPLORER_INFO_INDEX
);
666 IExplorerBrowser
*browser
= NULL
;
668 WINE_TRACE("(hwnd=%p,uMsg=%u,wParam=%lx,lParam=%lx)\n",hwnd
,uMsg
,wParam
,lParam
);
670 browser
= info
->browser
;
674 IShellWindows_Revoke(info
->sw
, info
->sw_cookie
);
675 IShellWindows_Release(info
->sw
);
677 IExplorerBrowser_Unadvise(browser
,info
->advise_cookie
);
678 IExplorerBrowser_Destroy(browser
);
679 IExplorerBrowser_Release(browser
);
681 IImageList_Release(info
->icon_list
);
682 HeapFree(GetProcessHeap(),0,info
);
683 SetWindowLongPtrW(hwnd
,EXPLORER_INFO_INDEX
,0);
689 return explorer_on_notify(info
,(NMHDR
*)lParam
);
691 if(HIWORD(wParam
)==BN_CLICKED
)
693 switch(LOWORD(wParam
))
696 IExplorerBrowser_BrowseToObject(browser
,NULL
,SBSP_NAVIGATEBACK
);
699 IExplorerBrowser_BrowseToObject(browser
,NULL
,SBSP_NAVIGATEFORWARD
);
702 IExplorerBrowser_BrowseToObject(browser
,NULL
,SBSP_PARENT
);
708 update_window_size(info
,HIWORD(lParam
),LOWORD(lParam
));
711 return DefWindowProcW(hwnd
,uMsg
,wParam
,lParam
);
716 static void register_explorer_window_class(void)
718 WNDCLASSEXW window_class
;
719 window_class
.cbSize
= sizeof(WNDCLASSEXW
);
720 window_class
.style
= 0;
721 window_class
.cbClsExtra
= 0;
722 window_class
.cbWndExtra
= sizeof(LONG_PTR
);
723 window_class
.lpfnWndProc
= explorer_wnd_proc
;
724 window_class
.hInstance
= explorer_hInstance
;
725 window_class
.hIcon
= NULL
;
726 window_class
.hCursor
= NULL
;
727 window_class
.hbrBackground
= (HBRUSH
)COLOR_BACKGROUND
;
728 window_class
.lpszMenuName
= NULL
;
729 window_class
.lpszClassName
= EXPLORER_CLASS
;
730 window_class
.hIconSm
= NULL
;
731 RegisterClassExW(&window_class
);
734 static WCHAR
*copy_path_string(WCHAR
*target
, WCHAR
*source
)
738 while (iswspace(*source
)) source
++;
743 while (*source
&& *source
!= '\"') target
[i
++] = *source
++;
745 if (*source
) source
++;
749 while (*source
&& *source
!= ',') target
[i
++] = *source
++;
752 PathRemoveBackslashW(target
);
757 static void copy_path_root(LPWSTR root
, LPWSTR path
)
766 while (*p
!='\\' && p
> path
)
783 * Command Line parameters are:
784 * [/n] Opens in single-paned view for each selected items. This is default
785 * [/e,] Uses Windows Explorer View
786 * [/cd,object] Specifies the root level of the view
787 * [/root,object] Specifies the root level of the view
788 * [/select,object] parent folder is opened and specified object is selected
790 static void parse_command_line(LPWSTR commandline
,parameters_struct
*parameters
)
792 static const WCHAR arg_n
[] = {'/','n'};
793 static const WCHAR arg_e
[] = {'/','e',','};
794 static const WCHAR arg_cd
[] = {'/','c','d',','};
795 static const WCHAR arg_root
[] = {'/','r','o','o','t',','};
796 static const WCHAR arg_select
[] = {'/','s','e','l','e','c','t',','};
797 static const WCHAR arg_desktop
[] = {'/','d','e','s','k','t','o','p'};
798 static const WCHAR arg_desktop_quotes
[] = {'"','/','d','e','s','k','t','o','p'};
800 LPWSTR p
= commandline
;
804 while (iswspace(*p
)) p
++;
805 if (wcsncmp(p
, arg_n
, ARRAY_SIZE( arg_n
))==0)
807 parameters
->explorer_mode
= FALSE
;
808 p
+= ARRAY_SIZE( arg_n
);
810 else if (wcsncmp(p
, arg_e
, ARRAY_SIZE( arg_e
))==0)
812 parameters
->explorer_mode
= TRUE
;
813 p
+= ARRAY_SIZE( arg_e
);
815 else if (wcsncmp(p
, arg_cd
, ARRAY_SIZE( arg_cd
))==0)
817 p
+= ARRAY_SIZE( arg_cd
);
818 p
= copy_path_string(parameters
->root
,p
);
820 else if (wcsncmp(p
, arg_root
, ARRAY_SIZE( arg_root
))==0)
822 p
+= ARRAY_SIZE( arg_root
);
823 p
= copy_path_string(parameters
->root
,p
);
825 else if (wcsncmp(p
, arg_select
, ARRAY_SIZE( arg_select
))==0)
827 p
+= ARRAY_SIZE( arg_select
);
828 p
= copy_path_string(parameters
->selection
,p
);
829 if (!parameters
->root
[0])
830 copy_path_root(parameters
->root
,
831 parameters
->selection
);
833 else if (wcsncmp(p
, arg_desktop
, ARRAY_SIZE( arg_desktop
))==0)
835 p
+= ARRAY_SIZE( arg_desktop
);
836 manage_desktop( p
); /* the rest of the command line is handled by desktop mode */
838 /* workaround for Worms Armageddon that hardcodes a /desktop option with quotes */
839 else if (wcsncmp(p
, arg_desktop_quotes
, ARRAY_SIZE( arg_desktop_quotes
))==0)
841 p
+= ARRAY_SIZE( arg_desktop_quotes
);
842 manage_desktop( p
); /* the rest of the command line is handled by desktop mode */
846 /* left over command line is generally the path to be opened */
847 copy_path_string(parameters
->root
,p
);
853 int WINAPI
wWinMain(HINSTANCE hinstance
,
854 HINSTANCE previnstance
,
859 parameters_struct parameters
;
861 INITCOMMONCONTROLSEX init_info
;
863 memset(¶meters
,0,sizeof(parameters
));
864 explorer_hInstance
= hinstance
;
865 parse_command_line(cmdline
,¶meters
);
866 hres
= OleInitialize(NULL
);
869 WINE_ERR("Could not initialize COM\n");
870 ExitProcess(EXIT_FAILURE
);
872 if(parameters
.root
[0] && !PathIsDirectoryW(parameters
.root
))
873 if(ShellExecuteW(NULL
,NULL
,parameters
.root
,NULL
,NULL
,SW_SHOWDEFAULT
) > (HINSTANCE
)32)
874 ExitProcess(EXIT_SUCCESS
);
875 init_info
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
876 init_info
.dwICC
= ICC_USEREX_CLASSES
| ICC_BAR_CLASSES
| ICC_COOL_CLASSES
;
877 if(!InitCommonControlsEx(&init_info
))
879 WINE_ERR("Could not initialize Comctl\n");
880 ExitProcess(EXIT_FAILURE
);
882 register_explorer_window_class();
883 make_explorer_window(¶meters
);