user32: Add constness to params and variables.
[wine] / dlls / shdocvw / iexplore.c
1 /*
2  * SHDOCVW - Internet Explorer main frame window
3  *
4  * Copyright 2006 Mike McCormack (for CodeWeavers)
5  * Copyright 2006 Jacek Caban (for CodeWeavers)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define COBJMACROS
23
24 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "wingdi.h"
29 #include "winnls.h"
30 #include "ole2.h"
31 #include "exdisp.h"
32 #include "oleidl.h"
33
34 #include "shdocvw.h"
35 #include "mshtmcid.h"
36 #include "shellapi.h"
37 #include "winreg.h"
38 #include "shlwapi.h"
39 #include "intshcut.h"
40
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
44
45 #define IDI_APPICON 1
46
47 static const WCHAR szIEWinFrame[] = { 'I','E','F','r','a','m','e',0 };
48
49 /* Windows uses "Microsoft Internet Explorer" */
50 static const WCHAR wszWineInternetExplorer[] =
51         {'W','i','n','e',' ','I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',0};
52
53 HRESULT update_ie_statustext(InternetExplorer* This, LPCWSTR text)
54 {
55     if(!SendMessageW(This->status_hwnd, SB_SETTEXTW, MAKEWORD(SB_SIMPLEID, 0), (LPARAM)text))
56         return E_FAIL;
57
58     return S_OK;
59 }
60
61 static void adjust_ie_docobj_rect(HWND frame, RECT* rc)
62 {
63     HWND hwndRebar = GetDlgItem(frame, IDC_BROWSE_REBAR);
64     HWND hwndStatus = GetDlgItem(frame, IDC_BROWSE_STATUSBAR);
65     INT barHeight = SendMessageW(hwndRebar, RB_GETBARHEIGHT, 0, 0);
66
67     rc->top += barHeight;
68     rc->bottom -= barHeight;
69
70     if(IsWindowVisible(hwndStatus))
71     {
72         RECT statusrc;
73
74         GetClientRect(hwndStatus, &statusrc);
75         rc->bottom -= statusrc.bottom - statusrc.top;
76     }
77 }
78
79 static HMENU get_tb_menu(HMENU menu)
80 {
81     HMENU menu_view = GetSubMenu(menu, 1);
82
83     return GetSubMenu(menu_view, 0);
84 }
85
86 static HMENU get_fav_menu(HMENU menu)
87 {
88     return GetSubMenu(menu, 2);
89 }
90
91 static LPWSTR get_fav_url_from_id(HMENU menu, UINT id)
92 {
93     MENUITEMINFOW item;
94
95     item.cbSize = sizeof(item);
96     item.fMask = MIIM_DATA;
97
98     if(!GetMenuItemInfoW(menu, id, FALSE, &item))
99         return NULL;
100
101     return (LPWSTR)item.dwItemData;
102 }
103
104 static void free_fav_menu_data(HMENU menu)
105 {
106     LPWSTR url;
107     int i;
108
109     for(i = 0; (url = get_fav_url_from_id(menu, ID_BROWSE_GOTOFAV_FIRST + i)); i++)
110         heap_free( url );
111 }
112
113 static int get_menu_item_count(HMENU menu)
114 {
115     MENUITEMINFOW item;
116     int count = 0;
117     int i;
118
119     item.cbSize = sizeof(item);
120     item.fMask = MIIM_DATA | MIIM_SUBMENU;
121
122     for(i = 0; GetMenuItemInfoW(menu, i, TRUE, &item); i++)
123     {
124         if(item.hSubMenu)
125             count += get_menu_item_count(item.hSubMenu);
126         else
127             count++;
128     }
129
130     return count;
131 }
132
133 static void add_fav_to_menu(HMENU favmenu, HMENU menu, LPWSTR title, LPCWSTR url)
134 {
135     MENUITEMINFOW item;
136     /* Subtract the number of standard elements in the Favorites menu */
137     int favcount = get_menu_item_count(favmenu) - 2;
138     LPWSTR urlbuf;
139
140     if(favcount > (ID_BROWSE_GOTOFAV_MAX - ID_BROWSE_GOTOFAV_FIRST))
141     {
142         FIXME("Add support for more than %d Favorites\n", favcount);
143         return;
144     }
145
146     urlbuf = heap_alloc((lstrlenW(url) + 1) * sizeof(WCHAR));
147
148     if(!urlbuf)
149         return;
150
151     lstrcpyW(urlbuf, url);
152
153     item.cbSize = sizeof(item);
154     item.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_DATA | MIIM_ID;
155     item.fType = MFT_STRING;
156     item.dwTypeData = title;
157     item.wID = ID_BROWSE_GOTOFAV_FIRST + favcount;
158     item.dwItemData = (ULONG_PTR)urlbuf;
159     InsertMenuItemW(menu, -1, TRUE, &item);
160 }
161
162 static void add_favs_to_menu(HMENU favmenu, HMENU menu, LPCWSTR dir)
163 {
164     WCHAR path[MAX_PATH*2];
165     const WCHAR search[] = {'*',0};
166     WCHAR* filename;
167     HANDLE findhandle;
168     WIN32_FIND_DATAW finddata;
169     IUniformResourceLocatorW* urlobj;
170     IPersistFile* urlfile;
171     HRESULT res;
172
173     lstrcpyW(path, dir);
174     PathAppendW(path, search);
175
176     findhandle = FindFirstFileW(path, &finddata);
177
178     if(findhandle == INVALID_HANDLE_VALUE)
179         return;
180
181     res = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, &IID_IUniformResourceLocatorW, (PVOID*)&urlobj);
182
183     if(SUCCEEDED(res))
184         res = IUnknown_QueryInterface(urlobj, &IID_IPersistFile, (PVOID*)&urlfile);
185
186     if(SUCCEEDED(res))
187     {
188         filename = path + lstrlenW(path) - lstrlenW(search);
189
190         do
191         {
192             lstrcpyW(filename, finddata.cFileName);
193
194             if(finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
195             {
196                 MENUITEMINFOW item;
197                 const WCHAR ignore1[] = {'.','.',0};
198                 const WCHAR ignore2[] = {'.',0};
199
200                 if(!lstrcmpW(filename, ignore1) || !lstrcmpW(filename, ignore2))
201                     continue;
202
203                 item.cbSize = sizeof(item);
204                 item.fMask = MIIM_STRING | MIIM_SUBMENU;
205                 item.dwTypeData = filename;
206                 item.hSubMenu = CreatePopupMenu();
207                 InsertMenuItemW(menu, -1, TRUE, &item);
208                 add_favs_to_menu(favmenu, item.hSubMenu, path);
209             } else
210             {
211                 WCHAR* fileext;
212                 WCHAR* url = NULL;
213                 const WCHAR urlext[] = {'.','u','r','l',0};
214
215                 if(lstrcmpiW(PathFindExtensionW(filename), urlext))
216                     continue;
217
218                 if(FAILED(IPersistFile_Load(urlfile, path, 0)))
219                     continue;
220
221                 urlobj->lpVtbl->GetURL(urlobj, &url);
222
223                 if(!url)
224                     continue;
225
226                 fileext = filename + lstrlenW(filename) - lstrlenW(urlext);
227                 *fileext = 0;
228                 add_fav_to_menu(favmenu, menu, filename, url);
229             }
230         } while(FindNextFileW(findhandle, &finddata));
231     }
232
233     if(urlfile)
234         IPersistFile_Release(urlfile);
235
236     if(urlobj)
237         IUnknown_Release(urlobj);
238
239     FindClose(findhandle);
240 }
241
242 static void add_tbs_to_menu(HMENU menu)
243 {
244     HUSKEY toolbar_handle;
245     WCHAR toolbar_key[] = {'S','o','f','t','w','a','r','e','\\',
246                            'M','i','c','r','o','s','o','f','t','\\',
247                            'I','n','t','e','r','n','e','t',' ',
248                            'E','x','p','l','o','r','e','r','\\',
249                            'T','o','o','l','b','a','r',0};
250
251     if(SHRegOpenUSKeyW(toolbar_key, KEY_READ, NULL, &toolbar_handle, TRUE) == ERROR_SUCCESS)
252     {
253         HUSKEY classes_handle;
254         WCHAR classes_key[] = {'S','o','f','t','w','a','r','e','\\',
255                                'C','l','a','s','s','e','s','\\','C','L','S','I','D',0};
256         WCHAR guid[39];
257         DWORD value_len = sizeof(guid)/sizeof(guid[0]);
258         int i;
259
260         if(SHRegOpenUSKeyW(classes_key, KEY_READ, NULL, &classes_handle, TRUE) != ERROR_SUCCESS)
261         {
262             SHRegCloseUSKey(toolbar_handle);
263             ERR("Failed to open key %s\n", debugstr_w(classes_key));
264             return;
265         }
266
267         for(i = 0; SHRegEnumUSValueW(toolbar_handle, i, guid, &value_len, NULL, NULL, NULL, SHREGENUM_HKLM) == ERROR_SUCCESS; i++)
268         {
269             WCHAR tb_name[100];
270             DWORD tb_name_len = sizeof(tb_name)/sizeof(tb_name[0]);
271             HUSKEY tb_class_handle;
272             MENUITEMINFOW item;
273             LSTATUS ret;
274             value_len = sizeof(guid)/sizeof(guid[0]);
275
276             if(lstrlenW(guid) != 38)
277             {
278                 TRACE("Found invalid IE toolbar entry: %s\n", debugstr_w(guid));
279                 continue;
280             }
281
282             if(SHRegOpenUSKeyW(guid, KEY_READ, classes_handle, &tb_class_handle, TRUE) != ERROR_SUCCESS)
283             {
284                 ERR("Failed to get class info for %s\n", debugstr_w(guid));
285                 continue;
286             }
287
288             ret = SHRegQueryUSValueW(tb_class_handle, NULL, NULL, tb_name, &tb_name_len, TRUE, NULL, 0);
289
290             SHRegCloseUSKey(tb_class_handle);
291
292             if(ret != ERROR_SUCCESS)
293             {
294                 ERR("Failed to get toolbar name for %s\n", debugstr_w(guid));
295                 continue;
296             }
297
298             item.cbSize = sizeof(item);
299             item.fMask = MIIM_STRING;
300             item.dwTypeData = tb_name;
301             InsertMenuItemW(menu, GetMenuItemCount(menu), TRUE, &item);
302         }
303
304         SHRegCloseUSKey(classes_handle);
305         SHRegCloseUSKey(toolbar_handle);
306     }
307 }
308
309 static HMENU create_ie_menu(void)
310 {
311     HMENU menu = LoadMenuW(shdocvw_hinstance, MAKEINTRESOURCEW(IDR_BROWSE_MAIN_MENU));
312     HMENU favmenu = get_fav_menu(menu);
313     WCHAR path[MAX_PATH];
314
315     add_tbs_to_menu(get_tb_menu(menu));
316
317     if(SHGetFolderPathW(NULL, CSIDL_COMMON_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path) == S_OK)
318         add_favs_to_menu(favmenu, favmenu, path);
319
320     if(SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path) == S_OK)
321         add_favs_to_menu(favmenu, favmenu, path);
322
323     return menu;
324 }
325
326 static void ie_navigate(InternetExplorer* This, LPCWSTR url)
327 {
328     VARIANT variant;
329
330     V_VT(&variant) = VT_BSTR;
331     V_BSTR(&variant) = SysAllocString(url);
332
333     IWebBrowser2_Navigate2(&This->IWebBrowser2_iface, &variant, NULL, NULL, NULL, NULL);
334
335     SysFreeString(V_BSTR(&variant));
336 }
337
338 static INT_PTR CALLBACK ie_dialog_open_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
339 {
340     static InternetExplorer* This;
341
342     switch(msg)
343     {
344         case WM_INITDIALOG:
345             This = (InternetExplorer*)lparam;
346             EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
347             return TRUE;
348
349         case WM_COMMAND:
350             switch(LOWORD(wparam))
351             {
352                 case IDC_BROWSE_OPEN_URL:
353                 {
354                     HWND hwndurl = GetDlgItem(hwnd, IDC_BROWSE_OPEN_URL);
355                     int len = GetWindowTextLengthW(hwndurl);
356
357                     EnableWindow(GetDlgItem(hwnd, IDOK), len ? TRUE : FALSE);
358                     break;
359                 }
360                 case IDOK:
361                 {
362                     HWND hwndurl = GetDlgItem(hwnd, IDC_BROWSE_OPEN_URL);
363                     int len = GetWindowTextLengthW(hwndurl);
364
365                     if(len)
366                     {
367                         VARIANT url;
368
369                         V_VT(&url) = VT_BSTR;
370                         V_BSTR(&url) = SysAllocStringLen(NULL, len);
371
372                         GetWindowTextW(hwndurl, V_BSTR(&url), len + 1);
373                         IWebBrowser2_Navigate2(&This->IWebBrowser2_iface, &url, NULL, NULL, NULL, NULL);
374
375                         SysFreeString(V_BSTR(&url));
376                     }
377                 }
378                 /* fall through */
379                 case IDCANCEL:
380                     EndDialog(hwnd, wparam);
381                     return TRUE;
382             }
383     }
384     return FALSE;
385 }
386
387 static void ie_dialog_about(HWND hwnd)
388 {
389     HICON icon = LoadImageW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDI_APPICON), IMAGE_ICON, 48, 48, LR_SHARED);
390
391     ShellAboutW(hwnd, wszWineInternetExplorer, NULL, icon);
392
393     DestroyIcon(icon);
394 }
395
396 static void add_tb_separator(HWND hwnd)
397 {
398     TBBUTTON btn;
399
400     ZeroMemory(&btn, sizeof(btn));
401
402     btn.iBitmap = 3;
403     btn.fsStyle = BTNS_SEP;
404     SendMessageW(hwnd, TB_ADDBUTTONSW, 1, (LPARAM)&btn);
405 }
406
407 static void add_tb_button(HWND hwnd, int bmp, int cmd, int strId)
408 {
409     TBBUTTON btn;
410     WCHAR buf[30];
411
412     LoadStringW(shdocvw_hinstance, strId, buf, sizeof(buf)/sizeof(buf[0]));
413
414     btn.iBitmap = bmp;
415     btn.idCommand = cmd;
416     btn.fsState = TBSTATE_ENABLED;
417     btn.fsStyle = BTNS_SHOWTEXT;
418     btn.dwData = 0;
419     btn.iString = (INT_PTR)buf;
420
421     SendMessageW(hwnd, TB_ADDBUTTONSW, 1, (LPARAM)&btn);
422 }
423
424 static void create_rebar(HWND hwnd)
425 {
426     HWND hwndRebar;
427     HWND hwndAddress;
428     HWND hwndToolbar;
429     REBARINFO rebarinf;
430     REBARBANDINFOW bandinf;
431     WCHAR addr[40];
432     HIMAGELIST imagelist;
433     WCHAR idb_ietoolbar[] = {'I','D','B','_','I','E','T','O','O','L','B','A','R',0};
434
435     LoadStringW(shdocvw_hinstance, IDS_ADDRESS, addr, sizeof(addr)/sizeof(addr[0]));
436
437     hwndRebar = CreateWindowExW(WS_EX_TOOLWINDOW, REBARCLASSNAMEW, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|RBS_VARHEIGHT|CCS_TOP|CCS_NODIVIDER, 0, 0, 0, 0, hwnd, (HMENU)IDC_BROWSE_REBAR, shdocvw_hinstance, NULL);
438
439     rebarinf.cbSize = sizeof(rebarinf);
440     rebarinf.fMask = 0;
441     rebarinf.himl = NULL;
442     rebarinf.cbSize = sizeof(rebarinf);
443
444     SendMessageW(hwndRebar, RB_SETBARINFO, 0, (LPARAM)&rebarinf);
445
446     hwndToolbar = CreateWindowExW(TBSTYLE_EX_MIXEDBUTTONS, TOOLBARCLASSNAMEW, NULL, TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwndRebar, (HMENU)IDC_BROWSE_TOOLBAR, shdocvw_hinstance, NULL);
447
448     imagelist = ImageList_LoadImageW(shdocvw_hinstance, idb_ietoolbar, 32, 0, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION);
449
450     SendMessageW(hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)imagelist);
451     SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
452     add_tb_button(hwndToolbar, 0, 0, IDS_TB_BACK);
453     add_tb_button(hwndToolbar, 1, 0, IDS_TB_FORWARD);
454     add_tb_button(hwndToolbar, 2, 0, IDS_TB_STOP);
455     add_tb_button(hwndToolbar, 3, 0, IDS_TB_REFRESH);
456     add_tb_button(hwndToolbar, 4, ID_BROWSE_HOME, IDS_TB_HOME);
457     add_tb_separator(hwndToolbar);
458     add_tb_button(hwndToolbar, 5, ID_BROWSE_PRINT, IDS_TB_PRINT);
459     SendMessageW(hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(55,50));
460     SendMessageW(hwndToolbar, TB_AUTOSIZE, 0, 0);
461
462     bandinf.cbSize = sizeof(bandinf);
463     bandinf.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
464     bandinf.fStyle = RBBS_CHILDEDGE;
465     bandinf.cx = 100;
466     bandinf.cyMinChild = 52;
467     bandinf.hwndChild = hwndToolbar;
468
469     SendMessageW(hwndRebar, RB_INSERTBANDW, -1, (LPARAM)&bandinf);
470
471     hwndAddress = CreateWindowExW(0, WC_COMBOBOXEXW, NULL, WS_BORDER|WS_CHILD|WS_VISIBLE|CBS_DROPDOWN, 0, 0, 100,20,hwndRebar, (HMENU)IDC_BROWSE_ADDRESSBAR, shdocvw_hinstance, NULL);
472
473     bandinf.fMask |= RBBIM_TEXT;
474     bandinf.fStyle = RBBS_CHILDEDGE | RBBS_BREAK;
475     bandinf.lpText = addr;
476     bandinf.cyMinChild = 20;
477     bandinf.hwndChild = hwndAddress;
478
479     SendMessageW(hwndRebar, RB_INSERTBANDW, -1, (LPARAM)&bandinf);
480 }
481
482 static LRESULT iewnd_OnCreate(HWND hwnd, LPCREATESTRUCTW lpcs)
483 {
484     InternetExplorer* This = (InternetExplorer*)lpcs->lpCreateParams;
485     SetWindowLongPtrW(hwnd, 0, (LONG_PTR) lpcs->lpCreateParams);
486
487     This->menu = create_ie_menu();
488
489     This->status_hwnd = CreateStatusWindowW(WS_VISIBLE|WS_CHILD|SBT_NOBORDERS|CCS_NODIVIDER,
490                                             NULL, hwnd, IDC_BROWSE_STATUSBAR);
491     SendMessageW(This->status_hwnd, SB_SIMPLE, TRUE, 0);
492
493     create_rebar(hwnd);
494
495     return 0;
496 }
497
498 static LRESULT iewnd_OnSize(InternetExplorer *This, INT width, INT height)
499 {
500     HWND hwndRebar = GetDlgItem(This->frame_hwnd, IDC_BROWSE_REBAR);
501     INT barHeight = SendMessageW(hwndRebar, RB_GETBARHEIGHT, 0, 0);
502     RECT docarea = {0, 0, width, height};
503
504     SendMessageW(This->status_hwnd, WM_SIZE, 0, 0);
505
506     adjust_ie_docobj_rect(This->frame_hwnd, &docarea);
507
508     if(This->doc_host.hwnd)
509         SetWindowPos(This->doc_host.hwnd, NULL, docarea.left, docarea.top, docarea.right, docarea.bottom,
510                      SWP_NOZORDER | SWP_NOACTIVATE);
511
512     SetWindowPos(hwndRebar, NULL, 0, 0, width, barHeight, SWP_NOZORDER | SWP_NOACTIVATE);
513
514     return 0;
515 }
516
517 static LRESULT iewnd_OnNotify(InternetExplorer *This, WPARAM wparam, LPARAM lparam)
518 {
519     NMHDR* hdr = (NMHDR*)lparam;
520
521     if(hdr->idFrom == IDC_BROWSE_ADDRESSBAR && hdr->code == CBEN_ENDEDITW)
522     {
523         NMCBEENDEDITW* info = (NMCBEENDEDITW*)lparam;
524
525         if(info->fChanged && info->iWhy == CBENF_RETURN && info->szText)
526         {
527             VARIANT vt;
528
529             V_VT(&vt) = VT_BSTR;
530             V_BSTR(&vt) = SysAllocString(info->szText);
531
532             IWebBrowser2_Navigate2(&This->IWebBrowser2_iface, &vt, NULL, NULL, NULL, NULL);
533
534             SysFreeString(V_BSTR(&vt));
535
536             return 0;
537         }
538     }
539
540     return 0;
541 }
542
543 static LRESULT iewnd_OnDestroy(InternetExplorer *This)
544 {
545     HWND hwndRebar = GetDlgItem(This->frame_hwnd, IDC_BROWSE_REBAR);
546     HWND hwndToolbar = GetDlgItem(hwndRebar, IDC_BROWSE_TOOLBAR);
547     HIMAGELIST list = (HIMAGELIST)SendMessageW(hwndToolbar, TB_GETIMAGELIST, 0, 0);
548
549     TRACE("%p\n", This);
550
551     free_fav_menu_data(get_fav_menu(This->menu));
552     ImageList_Destroy(list);
553     This->frame_hwnd = NULL;
554     PostQuitMessage(0); /* FIXME */
555
556     return 0;
557 }
558
559 static LRESULT iewnd_OnCommand(InternetExplorer *This, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
560 {
561     switch(LOWORD(wparam))
562     {
563         case ID_BROWSE_OPEN:
564             DialogBoxParamW(shdocvw_hinstance, MAKEINTRESOURCEW(IDD_BROWSE_OPEN), hwnd, ie_dialog_open_proc, (LPARAM)This);
565             break;
566
567         case ID_BROWSE_PRINT:
568             if(This->doc_host.document)
569             {
570                 IOleCommandTarget* target;
571
572                 if(FAILED(IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target)))
573                     break;
574
575                 IOleCommandTarget_Exec(target, &CGID_MSHTML, IDM_PRINT, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
576
577                 IOleCommandTarget_Release(target);
578             }
579             break;
580
581         case ID_BROWSE_HOME:
582             IWebBrowser2_GoHome(&This->IWebBrowser2_iface);
583             break;
584
585         case ID_BROWSE_ABOUT:
586             ie_dialog_about(hwnd);
587             break;
588
589         case ID_BROWSE_QUIT:
590             iewnd_OnDestroy(This);
591             break;
592
593         default:
594             if(LOWORD(wparam) >= ID_BROWSE_GOTOFAV_FIRST && LOWORD(wparam) <= ID_BROWSE_GOTOFAV_MAX)
595             {
596                 LPCWSTR url = get_fav_url_from_id(get_fav_menu(This->menu), LOWORD(wparam));
597
598                 if(url)
599                     ie_navigate(This, url);
600             }
601             return DefWindowProcW(hwnd, msg, wparam, lparam);
602     }
603     return 0;
604 }
605
606 static LRESULT update_addrbar(InternetExplorer *This, LPARAM lparam)
607 {
608     HWND hwndRebar = GetDlgItem(This->frame_hwnd, IDC_BROWSE_REBAR);
609     HWND hwndAddress = GetDlgItem(hwndRebar, IDC_BROWSE_ADDRESSBAR);
610     HWND hwndEdit = (HWND)SendMessageW(hwndAddress, CBEM_GETEDITCONTROL, 0, 0);
611     LPCWSTR url = (LPCWSTR)lparam;
612
613     SendMessageW(hwndEdit, WM_SETTEXT, 0, (LPARAM)url);
614
615     return 0;
616 }
617
618 static LRESULT CALLBACK
619 ie_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
620 {
621     InternetExplorer *This = (InternetExplorer*) GetWindowLongPtrW(hwnd, 0);
622
623     switch (msg)
624     {
625     case WM_CREATE:
626         return iewnd_OnCreate(hwnd, (LPCREATESTRUCTW)lparam);
627     case WM_DESTROY:
628         return iewnd_OnDestroy(This);
629     case WM_SIZE:
630         return iewnd_OnSize(This, LOWORD(lparam), HIWORD(lparam));
631     case WM_COMMAND:
632         return iewnd_OnCommand(This, hwnd, msg, wparam, lparam);
633     case WM_NOTIFY:
634         return iewnd_OnNotify(This, wparam, lparam);
635     case WM_DOCHOSTTASK:
636         return process_dochost_task(&This->doc_host, lparam);
637     case WM_UPDATEADDRBAR:
638         return update_addrbar(This, lparam);
639     }
640     return DefWindowProcW(hwnd, msg, wparam, lparam);
641 }
642
643 void register_iewindow_class(void)
644 {
645     WNDCLASSEXW wc;
646
647     memset(&wc, 0, sizeof wc);
648     wc.cbSize = sizeof(wc);
649     wc.style = 0;
650     wc.lpfnWndProc = ie_window_proc;
651     wc.cbClsExtra = 0;
652     wc.cbWndExtra = sizeof(InternetExplorer*);
653     wc.hInstance = shdocvw_hinstance;
654     wc.hIcon = LoadIconW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDI_APPICON));
655     wc.hIconSm = LoadImageW(GetModuleHandleW(0), MAKEINTRESOURCEW(IDI_APPICON), IMAGE_ICON,
656                             GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
657     wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW));
658     wc.hbrBackground = 0;
659     wc.lpszClassName = szIEWinFrame;
660     wc.lpszMenuName = NULL;
661
662     RegisterClassExW(&wc);
663 }
664
665 void unregister_iewindow_class(void)
666 {
667     UnregisterClassW(szIEWinFrame, shdocvw_hinstance);
668 }
669
670 static void create_frame_hwnd(InternetExplorer *This)
671 {
672     This->frame_hwnd = CreateWindowExW(
673             WS_EX_WINDOWEDGE,
674             szIEWinFrame, wszWineInternetExplorer,
675             WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
676                 | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
677             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
678             NULL, NULL /* FIXME */, shdocvw_hinstance, This);
679 }
680
681 static IWebBrowser2 *create_ie_window(LPCSTR cmdline)
682 {
683     IWebBrowser2 *wb = NULL;
684
685     InternetExplorer_Create(NULL, &IID_IWebBrowser2, (void**)&wb);
686     if(!wb)
687         return NULL;
688
689     IWebBrowser2_put_Visible(wb, VARIANT_TRUE);
690     IWebBrowser2_put_MenuBar(wb, VARIANT_TRUE);
691
692     if(!*cmdline) {
693         IWebBrowser2_GoHome(wb);
694     }else {
695         VARIANT var_url;
696         DWORD len;
697         int cmdlen;
698
699         if(!strncasecmp(cmdline, "-nohome", 7))
700             cmdline += 7;
701         while(*cmdline == ' ' || *cmdline == '\t')
702             cmdline++;
703         cmdlen = lstrlenA(cmdline);
704         if(cmdlen > 2 && cmdline[0] == '"' && cmdline[cmdlen-1] == '"') {
705             cmdline++;
706             cmdlen -= 2;
707         }
708
709         V_VT(&var_url) = VT_BSTR;
710
711         len = MultiByteToWideChar(CP_ACP, 0, cmdline, cmdlen, NULL, 0);
712         V_BSTR(&var_url) = SysAllocStringLen(NULL, len);
713         MultiByteToWideChar(CP_ACP, 0, cmdline, cmdlen, V_BSTR(&var_url), len);
714
715         /* navigate to the first page */
716         IWebBrowser2_Navigate2(wb, &var_url, NULL, NULL, NULL, NULL);
717
718         SysFreeString(V_BSTR(&var_url));
719     }
720
721     return wb;
722 }
723
724 static inline InternetExplorer *impl_from_DocHost(DocHost *iface)
725 {
726     return CONTAINING_RECORD(iface, InternetExplorer, doc_host);
727 }
728
729 static void WINAPI DocHostContainer_GetDocObjRect(DocHost* This, RECT* rc)
730 {
731     GetClientRect(This->frame_hwnd, rc);
732     adjust_ie_docobj_rect(This->frame_hwnd, rc);
733 }
734
735 static HRESULT WINAPI DocHostContainer_SetStatusText(DocHost* This, LPCWSTR text)
736 {
737     InternetExplorer* ie = impl_from_DocHost(This);
738     return update_ie_statustext(ie, text);
739 }
740
741 static void WINAPI DocHostContainer_SetURL(DocHost* This, LPCWSTR url)
742 {
743     SendMessageW(This->frame_hwnd, WM_UPDATEADDRBAR, 0, (LPARAM)url);
744 }
745
746 static HRESULT DocHostContainer_exec(DocHost* This, const GUID *cmd_group, DWORD cmdid, DWORD execopt, VARIANT *in,
747         VARIANT *out)
748 {
749     return S_OK;
750 }
751 static const IDocHostContainerVtbl DocHostContainerVtbl = {
752     DocHostContainer_GetDocObjRect,
753     DocHostContainer_SetStatusText,
754     DocHostContainer_SetURL,
755     DocHostContainer_exec
756 };
757
758 HRESULT InternetExplorer_Create(IUnknown *pOuter, REFIID riid, void **ppv)
759 {
760     InternetExplorer *ret;
761     HRESULT hres;
762
763     TRACE("(%p %s %p)\n", pOuter, debugstr_guid(riid), ppv);
764
765     ret = heap_alloc_zero(sizeof(InternetExplorer));
766     ret->ref = 0;
767
768     ret->doc_host.disp = (IDispatch*)&ret->IWebBrowser2_iface;
769     DocHost_Init(&ret->doc_host, (IDispatch*)&ret->IWebBrowser2_iface, &DocHostContainerVtbl);
770
771     InternetExplorer_WebBrowser_Init(ret);
772
773     HlinkFrame_Init(&ret->hlink_frame, (IUnknown*)&ret->IWebBrowser2_iface, &ret->doc_host);
774
775     create_frame_hwnd(ret);
776     ret->doc_host.frame_hwnd = ret->frame_hwnd;
777
778     hres = IWebBrowser2_QueryInterface(&ret->IWebBrowser2_iface, riid, ppv);
779     if(FAILED(hres)) {
780         heap_free(ret);
781         return hres;
782     }
783
784     return hres;
785 }
786
787 /******************************************************************
788  *              IEWinMain            (SHDOCVW.101)
789  *
790  * Only returns on error.
791  */
792 DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow)
793 {
794     IWebBrowser2 *wb = NULL;
795     MSG msg;
796     HRESULT hres;
797
798     TRACE("%s %d\n", debugstr_a(szCommandLine), nShowWindow);
799
800     if(*szCommandLine == '-' || *szCommandLine == '/') {
801         if(!strcasecmp(szCommandLine+1, "regserver"))
802             return register_iexplore(TRUE);
803         if(!strcasecmp(szCommandLine+1, "unregserver"))
804             return register_iexplore(FALSE);
805     }
806
807     CoInitialize(NULL);
808
809     hres = register_class_object(TRUE);
810     if(FAILED(hres)) {
811         CoUninitialize();
812         ExitProcess(1);
813     }
814
815     if(strcasecmp(szCommandLine, "-embedding"))
816         wb = create_ie_window(szCommandLine);
817
818     /* run the message loop for this thread */
819     while (GetMessageW(&msg, 0, 0, 0))
820     {
821         TranslateMessage(&msg);
822         DispatchMessageW(&msg);
823     }
824
825     if(wb)
826         IWebBrowser2_Release(wb);
827
828     register_class_object(FALSE);
829
830     CoUninitialize();
831
832     ExitProcess(0);
833     return 0;
834 }