po: Updated Korean translation.
[wine.git] / programs / explorer / explorer.c
blob5c9cad208ca5bc6d2a946629ca404b3dda11f924
1 /*
2 * explorer.exe
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
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "wine/unicode.h"
27 #include "wine/debug.h"
28 #include "explorer_private.h"
29 #include "resource.h"
31 #include <initguid.h>
32 #include <windows.h>
33 #include <shobjidl.h>
34 #include <shlobj.h>
35 #include <commoncontrols.h>
36 #include <commctrl.h>
38 WINE_DEFAULT_DEBUG_CHANNEL(explorer);
40 #define EXPLORER_INFO_INDEX 0
42 #define NAV_TOOLBAR_HEIGHT 30
43 #define PATHBOX_HEIGHT 24
45 #define DEFAULT_WIDTH 640
46 #define DEFAULT_HEIGHT 480
49 static const WCHAR EXPLORER_CLASS[] = {'W','I','N','E','_','E','X','P','L','O','R','E','R','\0'};
50 static const WCHAR PATH_BOX_NAME[] = {'\0'};
52 HINSTANCE explorer_hInstance;
54 typedef struct parametersTAG {
55 BOOL explorer_mode;
56 WCHAR root[MAX_PATH];
57 WCHAR selection[MAX_PATH];
58 } parameters_struct;
60 typedef struct
62 IExplorerBrowser *browser;
63 HWND main_window,path_box;
64 INT rebar_height;
65 LPCITEMIDLIST pidl;
66 IImageList *icon_list;
67 } explorer_info;
69 enum
71 BACK_BUTTON,FORWARD_BUTTON,UP_BUTTON
74 typedef struct
76 IExplorerBrowserEvents IExplorerBrowserEvents_iface;
77 explorer_info* info;
78 LONG ref;
79 } IExplorerBrowserEventsImpl;
81 static IExplorerBrowserEventsImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
83 return CONTAINING_RECORD(iface, IExplorerBrowserEventsImpl, IExplorerBrowserEvents_iface);
86 static HRESULT WINAPI IExplorerBrowserEventsImpl_fnQueryInterface(IExplorerBrowserEvents *iface, REFIID riid, void **ppvObject)
88 return E_NOINTERFACE;
91 static ULONG WINAPI IExplorerBrowserEventsImpl_fnAddRef(IExplorerBrowserEvents *iface)
93 IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface);
94 return InterlockedIncrement(&This->ref);
97 static ULONG WINAPI IExplorerBrowserEventsImpl_fnRelease(IExplorerBrowserEvents *iface)
99 IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface);
100 ULONG ref = InterlockedDecrement(&This->ref);
101 if(!ref)
102 HeapFree(GetProcessHeap(),0,This);
103 return ref;
106 static BOOL create_combobox_item(IShellFolder *folder, LPCITEMIDLIST pidl, IImageList *icon_list, COMBOBOXEXITEMW *item)
108 STRRET strret;
109 HRESULT hres;
110 IExtractIconW *extract_icon;
111 UINT reserved;
112 WCHAR icon_file[MAX_PATH];
113 INT icon_index;
114 UINT icon_flags;
115 HICON icon;
116 strret.uType=STRRET_WSTR;
117 hres = IShellFolder_GetDisplayNameOf(folder,pidl,SHGDN_FORADDRESSBAR,&strret);
118 if(FAILED(hres))
120 WINE_WARN("Could not get name for pidl\n");
121 return FALSE;
123 switch(strret.uType)
125 case STRRET_WSTR:
126 item->pszText = strret.u.pOleStr;
127 break;
128 default:
129 WINE_FIXME("Unimplemented STRRET type:%u\n",strret.uType);
130 break;
132 hres = IShellFolder_GetUIObjectOf(folder,NULL,1,&pidl,&IID_IExtractIconW,
133 &reserved,(void**)&extract_icon);
134 if(SUCCEEDED(hres))
136 item->mask |= CBEIF_IMAGE;
137 IExtractIconW_GetIconLocation(extract_icon,GIL_FORSHELL,icon_file,
138 sizeof(icon_file)/sizeof(WCHAR),
139 &icon_index,&icon_flags);
140 IExtractIconW_Extract(extract_icon,icon_file,icon_index,NULL,&icon,20);
141 item->iImage = ImageList_AddIcon((HIMAGELIST)icon_list,icon);
143 else
145 item->mask &= ~CBEIF_IMAGE;
146 WINE_WARN("Could not get an icon for %s\n",wine_dbgstr_w(item->pszText));
148 return TRUE;
151 static void update_path_box(explorer_info *info)
153 COMBOBOXEXITEMW item;
154 COMBOBOXEXITEMW main_item;
155 IShellFolder *desktop;
156 IPersistFolder2 *persist;
157 LPITEMIDLIST desktop_pidl;
158 IEnumIDList *ids;
160 ImageList_Remove((HIMAGELIST)info->icon_list,-1);
161 SendMessageW(info->path_box,CB_RESETCONTENT,0,0);
162 SHGetDesktopFolder(&desktop);
163 IShellFolder_QueryInterface(desktop,&IID_IPersistFolder2,(void**)&persist);
164 IPersistFolder2_GetCurFolder(persist,&desktop_pidl);
165 IPersistFolder2_Release(persist);
166 persist = NULL;
167 /*Add Desktop*/
168 item.iItem = -1;
169 item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_LPARAM;
170 item.iIndent = 0;
171 create_combobox_item(desktop,desktop_pidl,info->icon_list,&item);
172 item.lParam = (LPARAM)desktop_pidl;
173 SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
174 if(ILIsEqual(info->pidl,desktop_pidl))
175 main_item = item;
176 else
177 CoTaskMemFree(item.pszText);
178 /*Add all direct subfolders of Desktop*/
179 if(SUCCEEDED(IShellFolder_EnumObjects(desktop,NULL,SHCONTF_FOLDERS,&ids))
180 && ids!=NULL)
182 LPITEMIDLIST curr_pidl;
183 HRESULT hres;
185 item.iIndent = 1;
186 while(1)
188 hres = IEnumIDList_Next(ids,1,&curr_pidl,NULL);
189 if(FAILED(hres) || hres == S_FALSE)
190 break;
191 if(!create_combobox_item(desktop,curr_pidl,info->icon_list,&item))
192 WINE_WARN("Could not create a combobox item\n");
193 else
195 LPITEMIDLIST full_pidl = ILCombine(desktop_pidl,curr_pidl);
196 item.lParam = (LPARAM)full_pidl;
197 SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
198 if(ILIsEqual(full_pidl,info->pidl))
199 main_item = item;
200 else if(ILIsParent(full_pidl,info->pidl,FALSE))
202 /*add all parents of the pidl passed in*/
203 LPITEMIDLIST next_pidl = ILFindChild(full_pidl,info->pidl);
204 IShellFolder *curr_folder = NULL, *temp;
205 hres = IShellFolder_BindToObject(desktop,curr_pidl,NULL,
206 &IID_IShellFolder,
207 (void**)&curr_folder);
208 if(FAILED(hres))
209 WINE_WARN("Could not get an IShellFolder\n");
210 while(!ILIsEmpty(next_pidl))
212 LPITEMIDLIST first = ILCloneFirst(next_pidl);
213 CoTaskMemFree(item.pszText);
214 if(!create_combobox_item(curr_folder,first,
215 info->icon_list,&item))
217 WINE_WARN("Could not create a combobox item\n");
218 break;
220 ++item.iIndent;
221 full_pidl = ILCombine(full_pidl,first);
222 item.lParam = (LPARAM)full_pidl;
223 SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
224 temp=NULL;
225 hres = IShellFolder_BindToObject(curr_folder,first,NULL,
226 &IID_IShellFolder,
227 (void**)&temp);
228 if(FAILED(hres))
230 WINE_WARN("Could not get an IShellFolder\n");
231 break;
233 IShellFolder_Release(curr_folder);
234 curr_folder = temp;
236 ILFree(first);
237 next_pidl = ILGetNext(next_pidl);
239 memcpy(&main_item,&item,sizeof(item));
240 if(curr_folder)
241 IShellFolder_Release(curr_folder);
242 item.iIndent = 1;
244 else
245 CoTaskMemFree(item.pszText);
249 else
250 WINE_WARN("Could not enumerate the desktop\n");
251 SendMessageW(info->path_box,CBEM_SETITEMW,0,(LPARAM)&main_item);
252 CoTaskMemFree(main_item.pszText);
255 static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
257 IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface);
258 This->info->pidl = pidl;
259 update_path_box(This->info);
260 return S_OK;
263 static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationFailed(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
265 return S_OK;
268 static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationPending(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
270 return S_OK;
273 static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnViewCreated(IExplorerBrowserEvents *iface, IShellView *psv)
275 return S_OK;
278 static IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents =
280 IExplorerBrowserEventsImpl_fnQueryInterface,
281 IExplorerBrowserEventsImpl_fnAddRef,
282 IExplorerBrowserEventsImpl_fnRelease,
283 IExplorerBrowserEventsImpl_fnOnNavigationPending,
284 IExplorerBrowserEventsImpl_fnOnViewCreated,
285 IExplorerBrowserEventsImpl_fnOnNavigationComplete,
286 IExplorerBrowserEventsImpl_fnOnNavigationFailed
289 static IExplorerBrowserEvents *make_explorer_events(explorer_info *info)
291 IExplorerBrowserEventsImpl *ret
292 = HeapAlloc(GetProcessHeap(), 0, sizeof(IExplorerBrowserEventsImpl));
293 ret->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
294 ret->info = info;
295 SHGetImageList(SHIL_SMALL,&IID_IImageList,(void**)&(ret->info->icon_list));
296 SendMessageW(info->path_box,CBEM_SETIMAGELIST,0,(LPARAM)ret->info->icon_list);
297 IExplorerBrowserEvents_AddRef(&ret->IExplorerBrowserEvents_iface);
298 return &ret->IExplorerBrowserEvents_iface;
301 static void make_explorer_window(IShellFolder* startFolder)
303 RECT explorerRect;
304 HWND rebar,nav_toolbar;
305 FOLDERSETTINGS fs;
306 IExplorerBrowserEvents *events;
307 explorer_info *info;
308 HRESULT hres;
309 DWORD cookie;
310 WCHAR explorer_title[100];
311 WCHAR pathbox_label[50];
312 TBADDBITMAP bitmap_info;
313 TBBUTTON nav_buttons[3];
314 int hist_offset,view_offset;
315 REBARBANDINFOW band_info;
316 memset(nav_buttons,0,sizeof(nav_buttons));
317 LoadStringW(explorer_hInstance,IDS_EXPLORER_TITLE,explorer_title,
318 sizeof(explorer_title)/sizeof(WCHAR));
319 LoadStringW(explorer_hInstance,IDS_PATHBOX_LABEL,pathbox_label,
320 sizeof(pathbox_label)/sizeof(WCHAR));
321 info = HeapAlloc(GetProcessHeap(),0,sizeof(explorer_info));
322 if(!info)
324 WINE_ERR("Could not allocate a explorer_info struct\n");
325 return;
327 hres = CoCreateInstance(&CLSID_ExplorerBrowser,NULL,CLSCTX_INPROC_SERVER,
328 &IID_IExplorerBrowser,(LPVOID*)&info->browser);
329 if(!SUCCEEDED(hres))
331 WINE_ERR("Could not obtain an instance of IExplorerBrowser\n");
332 HeapFree(GetProcessHeap(),0,info);
333 return;
335 info->rebar_height=0;
336 info->main_window
337 = CreateWindowW(EXPLORER_CLASS,explorer_title,WS_OVERLAPPEDWINDOW,
338 CW_USEDEFAULT,CW_USEDEFAULT,DEFAULT_WIDTH,
339 DEFAULT_HEIGHT,NULL,NULL,explorer_hInstance,NULL);
341 fs.ViewMode = FVM_DETAILS;
342 fs.fFlags = FWF_AUTOARRANGE;
343 explorerRect.left = 0;
344 explorerRect.top = 0;
345 explorerRect.right = DEFAULT_WIDTH;
346 explorerRect.bottom = DEFAULT_HEIGHT;
348 IExplorerBrowser_Initialize(info->browser,info->main_window,&explorerRect,&fs);
349 IExplorerBrowser_SetOptions(info->browser,EBO_SHOWFRAMES);
350 SetWindowLongPtrW(info->main_window,EXPLORER_INFO_INDEX,(LONG_PTR)info);
352 /*setup navbar*/
353 rebar = CreateWindowExW(WS_EX_TOOLWINDOW,REBARCLASSNAMEW,NULL,
354 WS_CHILD|WS_VISIBLE|RBS_VARHEIGHT|CCS_TOP|CCS_NODIVIDER,
355 0,0,0,0,info->main_window,NULL,explorer_hInstance,NULL);
356 nav_toolbar
357 = CreateWindowExW(TBSTYLE_EX_MIXEDBUTTONS,TOOLBARCLASSNAMEW,NULL,
358 WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT,0,0,0,0,rebar,NULL,
359 explorer_hInstance,NULL);
361 bitmap_info.hInst = HINST_COMMCTRL;
362 bitmap_info.nID = IDB_HIST_LARGE_COLOR;
363 hist_offset= SendMessageW(nav_toolbar,TB_ADDBITMAP,0,(LPARAM)&bitmap_info);
364 bitmap_info.nID = IDB_VIEW_LARGE_COLOR;
365 view_offset= SendMessageW(nav_toolbar,TB_ADDBITMAP,0,(LPARAM)&bitmap_info);
367 nav_buttons[0].iBitmap=hist_offset+HIST_BACK;
368 nav_buttons[0].idCommand=BACK_BUTTON;
369 nav_buttons[0].fsState=TBSTATE_ENABLED;
370 nav_buttons[0].fsStyle=BTNS_BUTTON|BTNS_AUTOSIZE;
371 nav_buttons[1].iBitmap=hist_offset+HIST_FORWARD;
372 nav_buttons[1].idCommand=FORWARD_BUTTON;
373 nav_buttons[1].fsState=TBSTATE_ENABLED;
374 nav_buttons[1].fsStyle=BTNS_BUTTON|BTNS_AUTOSIZE;
375 nav_buttons[2].iBitmap=view_offset+VIEW_PARENTFOLDER;
376 nav_buttons[2].idCommand=UP_BUTTON;
377 nav_buttons[2].fsState=TBSTATE_ENABLED;
378 nav_buttons[2].fsStyle=BTNS_BUTTON|BTNS_AUTOSIZE;
379 SendMessageW(nav_toolbar,TB_BUTTONSTRUCTSIZE,sizeof(TBBUTTON),0);
380 SendMessageW(nav_toolbar,TB_ADDBUTTONSW,sizeof(nav_buttons)/sizeof(TBBUTTON),(LPARAM)nav_buttons);
382 band_info.cbSize = sizeof(band_info);
383 band_info.fMask = RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
384 band_info.hwndChild = nav_toolbar;
385 band_info.fStyle=RBBS_GRIPPERALWAYS|RBBS_CHILDEDGE;
386 band_info.cyChild=NAV_TOOLBAR_HEIGHT;
387 band_info.cx=0;
388 band_info.cyMinChild=NAV_TOOLBAR_HEIGHT;
389 band_info.cxMinChild=0;
390 SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info);
391 info->path_box = CreateWindowW(WC_COMBOBOXEXW,PATH_BOX_NAME,
392 WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
393 0,0,DEFAULT_WIDTH,PATHBOX_HEIGHT,rebar,NULL,
394 explorer_hInstance,NULL);
395 band_info.cyChild=PATHBOX_HEIGHT;
396 band_info.cx=0;
397 band_info.cyMinChild=PATHBOX_HEIGHT;
398 band_info.cxMinChild=0;
399 band_info.fMask|=RBBIM_TEXT;
400 band_info.lpText=pathbox_label;
401 band_info.fStyle|=RBBS_BREAK;
402 band_info.hwndChild=info->path_box;
403 SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info);
404 events = make_explorer_events(info);
405 IExplorerBrowser_Advise(info->browser,events,&cookie);
406 IExplorerBrowser_BrowseToObject(info->browser,(IUnknown*)startFolder,
407 SBSP_ABSOLUTE);
408 ShowWindow(info->main_window,SW_SHOWDEFAULT);
409 UpdateWindow(info->main_window);
410 IExplorerBrowserEvents_Release(events);
413 static void update_window_size(explorer_info *info, int height, int width)
415 RECT new_rect;
416 new_rect.left = 0;
417 new_rect.top = info->rebar_height;
418 new_rect.right = width;
419 new_rect.bottom = height;
420 IExplorerBrowser_SetRect(info->browser,NULL,new_rect);
423 static void do_exit(int code)
425 OleUninitialize();
426 ExitProcess(code);
429 static LRESULT explorer_on_end_edit(explorer_info *info,NMCBEENDEDITW *edit_info)
431 LPITEMIDLIST pidl = NULL;
433 WINE_TRACE("iWhy=%x\n",edit_info->iWhy);
434 switch(edit_info->iWhy)
436 case CBENF_DROPDOWN:
437 if(edit_info->iNewSelection!=CB_ERR)
438 pidl = (LPITEMIDLIST)SendMessageW(edit_info->hdr.hwndFrom,
439 CB_GETITEMDATA,
440 edit_info->iNewSelection,0);
441 break;
442 case CBENF_RETURN:
444 WCHAR path[MAX_PATH];
445 HWND edit_ctrl = (HWND)SendMessageW(edit_info->hdr.hwndFrom,
446 CBEM_GETEDITCONTROL,0,0);
447 *((WORD*)path)=MAX_PATH;
448 SendMessageW(edit_ctrl,EM_GETLINE,0,(LPARAM)path);
449 pidl = ILCreateFromPathW(path);
450 break;
452 case CBENF_ESCAPE:
453 /*make sure the that the path box resets*/
454 update_path_box(info);
455 return 0;
456 default:
457 return 0;
459 if(pidl)
460 IExplorerBrowser_BrowseToIDList(info->browser,pidl,SBSP_ABSOLUTE);
461 if(edit_info->iWhy==CBENF_RETURN)
462 ILFree(pidl);
463 return 0;
466 static LRESULT update_rebar_size(explorer_info* info,NMRBAUTOSIZE *size_info)
468 RECT new_rect;
469 RECT window_rect;
470 info->rebar_height = size_info->rcTarget.bottom-size_info->rcTarget.top;
471 GetWindowRect(info->main_window,&window_rect);
472 new_rect.left = 0;
473 new_rect.top = info->rebar_height;
474 new_rect.right = window_rect.right-window_rect.left;
475 new_rect.bottom = window_rect.bottom-window_rect.top;
476 IExplorerBrowser_SetRect(info->browser,NULL,new_rect);
477 return 0;
480 static LRESULT explorer_on_notify(explorer_info* info,NMHDR* notification)
482 WINE_TRACE("code=%i\n",notification->code);
483 switch(notification->code)
485 case CBEN_BEGINEDIT:
487 WCHAR path[MAX_PATH];
488 HWND edit_ctrl = (HWND)SendMessageW(notification->hwndFrom,
489 CBEM_GETEDITCONTROL,0,0);
490 SHGetPathFromIDListW(info->pidl,path);
491 SetWindowTextW(edit_ctrl,path);
492 break;
494 case CBEN_ENDEDITA:
496 NMCBEENDEDITA *edit_info_a = (NMCBEENDEDITA*)notification;
497 NMCBEENDEDITW edit_info_w;
498 edit_info_w.hdr = edit_info_a->hdr;
499 edit_info_w.fChanged = edit_info_a->fChanged;
500 edit_info_w.iNewSelection = edit_info_a->iNewSelection;
501 MultiByteToWideChar(CP_ACP,0,edit_info_a->szText,-1,
502 edit_info_w.szText,CBEMAXSTRLEN);
503 edit_info_w.iWhy = edit_info_a->iWhy;
504 return explorer_on_end_edit(info,&edit_info_w);
506 case CBEN_ENDEDITW:
507 return explorer_on_end_edit(info,(NMCBEENDEDITW*)notification);
508 case CBEN_DELETEITEM:
510 NMCOMBOBOXEXW *entry = (NMCOMBOBOXEXW*)notification;
511 if(entry->ceItem.lParam)
512 ILFree((LPITEMIDLIST)entry->ceItem.lParam);
513 break;
515 case RBN_AUTOSIZE:
516 return update_rebar_size(info,(NMRBAUTOSIZE*)notification);
517 default:
518 break;
520 return 0;
523 static LRESULT CALLBACK explorer_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
525 explorer_info *info
526 = (explorer_info*)GetWindowLongPtrW(hwnd,EXPLORER_INFO_INDEX);
527 IExplorerBrowser *browser = NULL;
529 WINE_TRACE("(hwnd=%p,uMsg=%u,wParam=%lx,lParam=%lx)\n",hwnd,uMsg,wParam,lParam);
530 if(info)
531 browser = info->browser;
532 switch(uMsg)
534 case WM_DESTROY:
535 IExplorerBrowser_Release(browser);
536 HeapFree(GetProcessHeap(),0,info);
537 PostQuitMessage(0);
538 break;
539 case WM_QUIT:
540 do_exit(wParam);
541 case WM_NOTIFY:
542 return explorer_on_notify(info,(NMHDR*)lParam);
543 case WM_COMMAND:
544 if(HIWORD(wParam)==BN_CLICKED)
546 switch(LOWORD(wParam))
548 case BACK_BUTTON:
549 IExplorerBrowser_BrowseToObject(browser,NULL,SBSP_NAVIGATEBACK);
550 break;
551 case FORWARD_BUTTON:
552 IExplorerBrowser_BrowseToObject(browser,NULL,SBSP_NAVIGATEFORWARD);
553 break;
554 case UP_BUTTON:
555 IExplorerBrowser_BrowseToObject(browser,NULL,SBSP_PARENT);
556 break;
559 break;
560 case WM_SIZE:
561 update_window_size(info,HIWORD(lParam),LOWORD(lParam));
562 break;
563 default:
564 return DefWindowProcW(hwnd,uMsg,wParam,lParam);
566 return 0;
569 static void register_explorer_window_class(void)
571 WNDCLASSEXW window_class;
572 window_class.cbSize = sizeof(WNDCLASSEXW);
573 window_class.style = 0;
574 window_class.cbClsExtra = 0;
575 window_class.cbWndExtra = sizeof(LONG_PTR);
576 window_class.lpfnWndProc = explorer_wnd_proc;
577 window_class.hInstance = explorer_hInstance;
578 window_class.hIcon = NULL;
579 window_class.hCursor = NULL;
580 window_class.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
581 window_class.lpszMenuName = NULL;
582 window_class.lpszClassName = EXPLORER_CLASS;
583 window_class.hIconSm = NULL;
584 RegisterClassExW(&window_class);
587 static IShellFolder* get_starting_shell_folder(parameters_struct* params)
589 IShellFolder* desktop,*folder;
590 LPITEMIDLIST root_pidl;
591 HRESULT hres;
593 SHGetDesktopFolder(&desktop);
594 if (!params->root[0])
596 return desktop;
598 hres = IShellFolder_ParseDisplayName(desktop,NULL,NULL,
599 params->root,NULL,
600 &root_pidl,NULL);
602 if(FAILED(hres))
604 return desktop;
606 hres = IShellFolder_BindToObject(desktop,root_pidl,NULL,
607 &IID_IShellFolder,
608 (void**)&folder);
609 if(FAILED(hres))
611 return desktop;
613 IShellFolder_Release(desktop);
614 return folder;
617 static int copy_path_string(LPWSTR target, LPWSTR source)
619 INT i = 0;
621 while (isspaceW(*source)) source++;
623 if (*source == '\"')
625 source ++;
626 while (*source != '\"') target[i++] = *source++;
627 target[i] = 0;
628 source ++;
629 i+=2;
631 else
633 while (*source && !isspaceW(*source)) target[i++] = *source++;
634 target[i] = 0;
636 return i;
640 static void copy_path_root(LPWSTR root, LPWSTR path)
642 LPWSTR p,p2;
643 INT i = 0;
645 p = path;
646 while (*p!=0)
647 p++;
649 while (*p!='\\' && p > path)
650 p--;
652 if (p == path)
653 return;
655 p2 = path;
656 while (p2 != p)
658 root[i] = *p2;
659 i++;
660 p2++;
662 root[i] = 0;
666 * Command Line parameters are:
667 * [/n] Opens in single-paned view for each selected items. This is default
668 * [/e,] Uses Windows Explorer View
669 * [/root,object] Specifies the root level of the view
670 * [/select,object] parent folder is opened and specified object is selected
672 static void parse_command_line(LPWSTR commandline,parameters_struct *parameters)
674 static const WCHAR arg_n[] = {'/','n'};
675 static const WCHAR arg_e[] = {'/','e',','};
676 static const WCHAR arg_root[] = {'/','r','o','o','t',','};
677 static const WCHAR arg_select[] = {'/','s','e','l','e','c','t',','};
678 static const WCHAR arg_desktop[] = {'/','d','e','s','k','t','o','p'};
680 LPWSTR p, p2;
682 p2 = commandline;
683 p = strchrW(commandline,'/');
684 while(p)
686 if (strncmpW(p, arg_n, sizeof(arg_n)/sizeof(WCHAR))==0)
688 parameters->explorer_mode = FALSE;
689 p += sizeof(arg_n)/sizeof(WCHAR);
691 else if (strncmpW(p, arg_e, sizeof(arg_e)/sizeof(WCHAR))==0)
693 parameters->explorer_mode = TRUE;
694 p += sizeof(arg_e)/sizeof(WCHAR);
696 else if (strncmpW(p, arg_root, sizeof(arg_root)/sizeof(WCHAR))==0)
698 p += sizeof(arg_root)/sizeof(WCHAR);
699 p+=copy_path_string(parameters->root,p);
701 else if (strncmpW(p, arg_select, sizeof(arg_select)/sizeof(WCHAR))==0)
703 p += sizeof(arg_select)/sizeof(WCHAR);
704 p+=copy_path_string(parameters->selection,p);
705 if (!parameters->root[0])
706 copy_path_root(parameters->root,
707 parameters->selection);
709 else if (strncmpW(p, arg_desktop, sizeof(arg_desktop)/sizeof(WCHAR))==0)
711 p += sizeof(arg_desktop)/sizeof(WCHAR);
712 manage_desktop( p ); /* the rest of the command line is handled by desktop mode */
714 else p++;
716 p2 = p;
717 p = strchrW(p,'/');
719 if (p2 && *p2)
721 /* left over command line is generally the path to be opened */
722 copy_path_string(parameters->root,p2);
726 int WINAPI wWinMain(HINSTANCE hinstance,
727 HINSTANCE previnstance,
728 LPWSTR cmdline,
729 int cmdshow)
732 parameters_struct parameters;
733 HRESULT hres;
734 MSG msg;
735 IShellFolder *folder;
736 INITCOMMONCONTROLSEX init_info;
738 memset(&parameters,0,sizeof(parameters));
739 explorer_hInstance = hinstance;
740 parse_command_line(cmdline,&parameters);
741 hres = OleInitialize(NULL);
742 if(!SUCCEEDED(hres))
744 WINE_ERR("Could not initialize COM\n");
745 ExitProcess(EXIT_FAILURE);
747 init_info.dwSize = sizeof(INITCOMMONCONTROLSEX);
748 init_info.dwICC = ICC_USEREX_CLASSES | ICC_BAR_CLASSES | ICC_COOL_CLASSES;
749 if(!InitCommonControlsEx(&init_info))
751 WINE_ERR("Could not initialize Comctl\n");
752 ExitProcess(EXIT_FAILURE);
754 register_explorer_window_class();
755 folder = get_starting_shell_folder(&parameters);
756 make_explorer_window(folder);
757 IShellFolder_Release(folder);
758 while(GetMessageW( &msg, NULL, 0, 0 ) != 0)
760 TranslateMessage(&msg);
761 DispatchMessageW(&msg);
763 return 0;