windows.gaming.input: Avoid leaking IDirectInputEffect reference (Valgrind).
[wine.git] / programs / explorer / desktop.c
blob81eb0d1d01bacc4cc7294bc78f9559b81bd5945b
1 /*
2 * Explorer desktop support
4 * Copyright 2006 Alexandre Julliard
5 * Copyright 2013 Hans Leidekker for CodeWeavers
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.
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.
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
22 #include <stdio.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #define OEMRESOURCE
28 #include <windows.h>
29 #include <rpc.h>
30 #include <shlobj.h>
31 #include <shellapi.h>
32 #include <ntuser.h>
33 #include "exdisp.h"
35 #include "wine/debug.h"
36 #include "explorer_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(explorer);
40 #define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769))
41 #define DESKTOP_ALL_ACCESS 0x01ff
43 static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0};
45 static BOOL using_root;
47 struct launcher
49 WCHAR *path;
50 HICON icon;
51 WCHAR *title;
54 static WCHAR *desktop_folder;
55 static WCHAR *desktop_folder_public;
57 static int icon_cx, icon_cy, icon_offset_cx, icon_offset_cy;
58 static int title_cx, title_cy, title_offset_cx, title_offset_cy;
59 static int desktop_width, launcher_size, launchers_per_row;
61 static struct launcher **launchers;
62 static unsigned int nb_launchers, nb_allocated;
64 static REFIID tid_ids[] =
66 &IID_IShellWindows,
67 &IID_IWebBrowser2
70 typedef enum
72 IShellWindows_tid,
73 IWebBrowser2_tid,
74 LAST_tid
75 } tid_t;
77 static ITypeLib *typelib;
78 static ITypeInfo *typeinfos[LAST_tid];
80 static HRESULT load_typelib(void)
82 HRESULT hres;
83 ITypeLib *tl;
85 hres = LoadRegTypeLib(&LIBID_SHDocVw, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
86 if (FAILED(hres))
88 ERR("LoadRegTypeLib failed: %08lx\n", hres);
89 return hres;
92 if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
93 ITypeLib_Release(tl);
94 return hres;
97 static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
99 HRESULT hres;
101 if (!typelib)
102 hres = load_typelib();
103 if (!typelib)
104 return hres;
106 if (!typeinfos[tid]) {
107 ITypeInfo *ti;
109 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
110 if (FAILED(hres)) {
111 ERR("GetTypeInfoOfGuid(%s) failed: %08lx\n", debugstr_guid(tid_ids[tid]), hres);
112 return hres;
115 if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
116 ITypeInfo_Release(ti);
119 *typeinfo = typeinfos[tid];
120 ITypeInfo_AddRef(*typeinfo);
121 return S_OK;
124 static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size)
126 unsigned int new_capacity, max_capacity;
127 void *new_elements;
129 if (count <= *capacity)
130 return TRUE;
132 max_capacity = ~(SIZE_T)0 / size;
133 if (count > max_capacity)
134 return FALSE;
136 new_capacity = max(4, *capacity);
137 while (new_capacity < count && new_capacity <= max_capacity / 2)
138 new_capacity *= 2;
139 if (new_capacity < count)
140 new_capacity = max_capacity;
142 if (!(new_elements = realloc(*elements, new_capacity * size)))
143 return FALSE;
145 *elements = new_elements;
146 *capacity = new_capacity;
148 return TRUE;
151 static LONG cookie_counter;
153 struct window
155 LONG cookie, hwnd;
156 int class;
157 ITEMIDLIST *pidl;
160 struct shellwindows
162 IShellWindows IShellWindows_iface;
163 CRITICAL_SECTION cs;
165 unsigned int count, max;
166 struct window *windows;
169 /* This is not limited to desktop itself, every file browser window that
170 explorer creates supports that. Desktop instance is special in some
171 aspects, for example navigation is not possible, you can't show/hide it,
172 or bring up a menu. CLSID_ShellBrowserWindow class could be used to
173 create instances like that, and they should be registered with
174 IShellWindows as well. */
175 struct shellbrowserwindow
177 IWebBrowser2 IWebBrowser2_iface;
178 IServiceProvider IServiceProvider_iface;
179 IShellBrowser IShellBrowser_iface;
180 IShellView *view;
183 static struct shellwindows shellwindows;
184 static struct shellbrowserwindow desktopshellbrowserwindow;
186 static inline struct shellwindows *impl_from_IShellWindows(IShellWindows *iface)
188 return CONTAINING_RECORD(iface, struct shellwindows, IShellWindows_iface);
191 static inline struct shellbrowserwindow *impl_from_IWebBrowser2(IWebBrowser2 *iface)
193 return CONTAINING_RECORD(iface, struct shellbrowserwindow, IWebBrowser2_iface);
196 static inline struct shellbrowserwindow *impl_from_IServiceProvider(IServiceProvider *iface)
198 return CONTAINING_RECORD(iface, struct shellbrowserwindow, IServiceProvider_iface);
201 static inline struct shellbrowserwindow *impl_from_IShellBrowser(IShellBrowser *iface)
203 return CONTAINING_RECORD(iface, struct shellbrowserwindow, IShellBrowser_iface);
206 static void shellwindows_init(void);
207 static void desktopshellbrowserwindow_init(void);
209 static RECT get_icon_rect( unsigned int index )
211 RECT rect;
212 unsigned int row = index / launchers_per_row;
213 unsigned int col = index % launchers_per_row;
215 rect.left = col * launcher_size + icon_offset_cx;
216 rect.right = rect.left + icon_cx;
217 rect.top = row * launcher_size + icon_offset_cy;
218 rect.bottom = rect.top + icon_cy;
219 return rect;
222 static RECT get_title_rect( unsigned int index )
224 RECT rect;
225 unsigned int row = index / launchers_per_row;
226 unsigned int col = index % launchers_per_row;
228 rect.left = col * launcher_size + title_offset_cx;
229 rect.right = rect.left + title_cx;
230 rect.top = row * launcher_size + title_offset_cy;
231 rect.bottom = rect.top + title_cy;
232 return rect;
235 static const struct launcher *launcher_from_point( int x, int y )
237 RECT icon, title;
238 unsigned int index;
240 if (!nb_launchers) return NULL;
241 index = x / launcher_size + (y / launcher_size) * launchers_per_row;
242 if (index >= nb_launchers) return NULL;
244 icon = get_icon_rect( index );
245 title = get_title_rect( index );
246 if ((x < icon.left || x > icon.right || y < icon.top || y > icon.bottom) &&
247 (x < title.left || x > title.right || y < title.top || y > title.bottom)) return NULL;
248 return launchers[index];
251 static void draw_launchers( HDC hdc, RECT update_rect )
253 COLORREF color = SetTextColor( hdc, RGB(255,255,255) ); /* FIXME: depends on background color */
254 int mode = SetBkMode( hdc, TRANSPARENT );
255 unsigned int i;
256 LOGFONTW lf;
257 HFONT font;
259 SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0 );
260 font = SelectObject( hdc, CreateFontIndirectW( &lf ) );
262 for (i = 0; i < nb_launchers; i++)
264 RECT dummy, icon = get_icon_rect( i ), title = get_title_rect( i );
266 if (IntersectRect( &dummy, &icon, &update_rect ))
267 DrawIconEx( hdc, icon.left, icon.top, launchers[i]->icon, icon_cx, icon_cy,
268 0, 0, DI_DEFAULTSIZE|DI_NORMAL );
270 if (IntersectRect( &dummy, &title, &update_rect ))
271 DrawTextW( hdc, launchers[i]->title, -1, &title,
272 DT_CENTER|DT_WORDBREAK|DT_EDITCONTROL|DT_END_ELLIPSIS );
275 SelectObject( hdc, font );
276 SetTextColor( hdc, color );
277 SetBkMode( hdc, mode );
280 static void do_launch( const struct launcher *launcher )
282 static const WCHAR openW[] = {'o','p','e','n',0};
283 ShellExecuteW( NULL, openW, launcher->path, NULL, NULL, 0 );
286 static WCHAR *append_path( const WCHAR *path, const WCHAR *filename, int len_filename )
288 int len_path = lstrlenW( path );
289 WCHAR *ret;
291 if (len_filename == -1) len_filename = lstrlenW( filename );
292 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len_path + len_filename + 2) * sizeof(WCHAR) )))
293 return NULL;
294 memcpy( ret, path, len_path * sizeof(WCHAR) );
295 ret[len_path] = '\\';
296 memcpy( ret + len_path + 1, filename, len_filename * sizeof(WCHAR) );
297 ret[len_path + 1 + len_filename] = 0;
298 return ret;
301 static IShellLinkW *load_shelllink( const WCHAR *path )
303 HRESULT hr;
304 IShellLinkW *link;
305 IPersistFile *file;
307 hr = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW,
308 (void **)&link );
309 if (FAILED( hr )) return NULL;
311 hr = IShellLinkW_QueryInterface( link, &IID_IPersistFile, (void **)&file );
312 if (FAILED( hr ))
314 IShellLinkW_Release( link );
315 return NULL;
317 hr = IPersistFile_Load( file, path, 0 );
318 IPersistFile_Release( file );
319 if (FAILED( hr ))
321 IShellLinkW_Release( link );
322 return NULL;
324 return link;
327 static HICON extract_icon( IShellLinkW *link )
329 WCHAR tmp_path[MAX_PATH], icon_path[MAX_PATH], target_path[MAX_PATH];
330 HICON icon = NULL;
331 int index;
333 tmp_path[0] = 0;
334 IShellLinkW_GetIconLocation( link, tmp_path, MAX_PATH, &index );
335 ExpandEnvironmentStringsW( tmp_path, icon_path, MAX_PATH );
337 if (icon_path[0]) ExtractIconExW( icon_path, index, &icon, NULL, 1 );
338 if (!icon)
340 tmp_path[0] = 0;
341 IShellLinkW_GetPath( link, tmp_path, MAX_PATH, NULL, SLGP_RAWPATH );
342 ExpandEnvironmentStringsW( tmp_path, target_path, MAX_PATH );
343 ExtractIconExW( target_path, index, &icon, NULL, 1 );
345 return icon;
348 static WCHAR *build_title( const WCHAR *filename, int len )
350 const WCHAR *p;
351 WCHAR *ret;
353 if (len == -1) len = lstrlenW( filename );
354 for (p = filename + len - 1; p >= filename; p--)
356 if (*p == '.')
358 len = p - filename;
359 break;
362 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
363 memcpy( ret, filename, len * sizeof(WCHAR) );
364 ret[len] = 0;
365 return ret;
368 static BOOL add_launcher( const WCHAR *folder, const WCHAR *filename, int len_filename )
370 struct launcher *launcher;
371 IShellLinkW *link;
373 if (nb_launchers == nb_allocated)
375 unsigned int count = nb_allocated * 2;
376 struct launcher **tmp = HeapReAlloc( GetProcessHeap(), 0, launchers, count * sizeof(*tmp) );
377 if (!tmp) return FALSE;
378 launchers = tmp;
379 nb_allocated = count;
382 if (!(launcher = HeapAlloc( GetProcessHeap(), 0, sizeof(*launcher) ))) return FALSE;
383 if (!(launcher->path = append_path( folder, filename, len_filename ))) goto error;
384 if (!(link = load_shelllink( launcher->path ))) goto error;
386 launcher->icon = extract_icon( link );
387 launcher->title = build_title( filename, len_filename );
388 IShellLinkW_Release( link );
389 if (launcher->icon && launcher->title)
391 launchers[nb_launchers++] = launcher;
392 return TRUE;
394 HeapFree( GetProcessHeap(), 0, launcher->title );
395 DestroyIcon( launcher->icon );
397 error:
398 HeapFree( GetProcessHeap(), 0, launcher->path );
399 HeapFree( GetProcessHeap(), 0, launcher );
400 return FALSE;
403 static void free_launcher( struct launcher *launcher )
405 DestroyIcon( launcher->icon );
406 HeapFree( GetProcessHeap(), 0, launcher->path );
407 HeapFree( GetProcessHeap(), 0, launcher->title );
408 HeapFree( GetProcessHeap(), 0, launcher );
411 static BOOL remove_launcher( const WCHAR *folder, const WCHAR *filename, int len_filename )
413 UINT i;
414 WCHAR *path;
415 BOOL ret = FALSE;
417 if (!(path = append_path( folder, filename, len_filename ))) return FALSE;
418 for (i = 0; i < nb_launchers; i++)
420 if (!wcsicmp( launchers[i]->path, path ))
422 free_launcher( launchers[i] );
423 if (--nb_launchers)
424 memmove( &launchers[i], &launchers[i + 1], sizeof(launchers[i]) * (nb_launchers - i) );
425 ret = TRUE;
426 break;
429 HeapFree( GetProcessHeap(), 0, path );
430 return ret;
433 static BOOL get_icon_text_metrics( HWND hwnd, TEXTMETRICW *tm )
435 BOOL ret;
436 HDC hdc;
437 LOGFONTW lf;
438 HFONT hfont;
440 hdc = GetDC( hwnd );
441 SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0 );
442 hfont = SelectObject( hdc, CreateFontIndirectW( &lf ) );
443 ret = GetTextMetricsW( hdc, tm );
444 SelectObject( hdc, hfont );
445 ReleaseDC( hwnd, hdc );
446 return ret;
449 static BOOL process_changes( const WCHAR *folder, char *buf )
451 FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)buf;
452 BOOL ret = FALSE;
454 for (;;)
456 switch (info->Action)
458 case FILE_ACTION_ADDED:
459 case FILE_ACTION_RENAMED_NEW_NAME:
460 if (add_launcher( folder, info->FileName, info->FileNameLength / sizeof(WCHAR) ))
461 ret = TRUE;
462 break;
464 case FILE_ACTION_REMOVED:
465 case FILE_ACTION_RENAMED_OLD_NAME:
466 if (remove_launcher( folder, info->FileName, info->FileNameLength / sizeof(WCHAR) ))
467 ret = TRUE;
468 break;
470 default:
471 WARN( "unexpected action %lu\n", info->Action );
472 break;
474 if (!info->NextEntryOffset) break;
475 info = (FILE_NOTIFY_INFORMATION *)((char *)info + info->NextEntryOffset);
477 return ret;
480 static DWORD CALLBACK watch_desktop_folders( LPVOID param )
482 HWND hwnd = param;
483 HRESULT init = CoInitialize( NULL );
484 HANDLE dir0, dir1, events[2];
485 OVERLAPPED ovl0, ovl1;
486 char *buf0 = NULL, *buf1 = NULL;
487 DWORD count, size = 4096, error = ERROR_OUTOFMEMORY;
488 BOOL ret, redraw;
490 dir0 = CreateFileW( desktop_folder, FILE_LIST_DIRECTORY|SYNCHRONIZE, FILE_SHARE_READ|FILE_SHARE_WRITE,
491 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
492 if (dir0 == INVALID_HANDLE_VALUE) return GetLastError();
493 dir1 = CreateFileW( desktop_folder_public, FILE_LIST_DIRECTORY|SYNCHRONIZE, FILE_SHARE_READ|FILE_SHARE_WRITE,
494 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
495 if (dir1 == INVALID_HANDLE_VALUE)
497 CloseHandle( dir0 );
498 return GetLastError();
500 if (!(ovl0.hEvent = events[0] = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error;
501 if (!(ovl1.hEvent = events[1] = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error;
502 if (!(buf0 = HeapAlloc( GetProcessHeap(), 0, size ))) goto error;
503 if (!(buf1 = HeapAlloc( GetProcessHeap(), 0, size ))) goto error;
505 for (;;)
507 ret = ReadDirectoryChangesW( dir0, buf0, size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ovl0, NULL );
508 if (!ret)
510 error = GetLastError();
511 goto error;
513 ret = ReadDirectoryChangesW( dir1, buf1, size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ovl1, NULL );
514 if (!ret)
516 error = GetLastError();
517 goto error;
520 redraw = FALSE;
521 switch ((error = WaitForMultipleObjects( 2, events, FALSE, INFINITE )))
523 case WAIT_OBJECT_0:
524 if (!GetOverlappedResult( dir0, &ovl0, &count, FALSE ) || !count) break;
525 if (process_changes( desktop_folder, buf0 )) redraw = TRUE;
526 break;
528 case WAIT_OBJECT_0 + 1:
529 if (!GetOverlappedResult( dir1, &ovl1, &count, FALSE ) || !count) break;
530 if (process_changes( desktop_folder_public, buf1 )) redraw = TRUE;
531 break;
533 default:
534 goto error;
536 if (redraw) InvalidateRect( hwnd, NULL, TRUE );
539 error:
540 CloseHandle( dir0 );
541 CloseHandle( dir1 );
542 CloseHandle( events[0] );
543 CloseHandle( events[1] );
544 HeapFree( GetProcessHeap(), 0, buf0 );
545 HeapFree( GetProcessHeap(), 0, buf1 );
546 if (SUCCEEDED( init )) CoUninitialize();
547 return error;
550 static void add_folder( const WCHAR *folder )
552 static const WCHAR lnkW[] = {'\\','*','.','l','n','k',0};
553 int len = lstrlenW( folder ) + lstrlenW( lnkW );
554 WIN32_FIND_DATAW data;
555 HANDLE handle;
556 WCHAR *glob;
558 if (!(glob = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return;
559 lstrcpyW( glob, folder );
560 lstrcatW( glob, lnkW );
562 if ((handle = FindFirstFileW( glob, &data )) != INVALID_HANDLE_VALUE)
564 do { add_launcher( folder, data.cFileName, -1 ); } while (FindNextFileW( handle, &data ));
565 FindClose( handle );
567 HeapFree( GetProcessHeap(), 0, glob );
570 #define BORDER_SIZE 4
571 #define PADDING_SIZE 4
572 #define TITLE_CHARS 14
574 static void initialize_launchers( HWND hwnd )
576 HRESULT hr, init;
577 TEXTMETRICW tm;
578 int icon_size;
580 if (!(get_icon_text_metrics( hwnd, &tm ))) return;
582 icon_cx = GetSystemMetrics( SM_CXICON );
583 icon_cy = GetSystemMetrics( SM_CYICON );
584 icon_size = max( icon_cx, icon_cy );
585 title_cy = tm.tmHeight * 2;
586 title_cx = max( tm.tmAveCharWidth * TITLE_CHARS, icon_size + PADDING_SIZE + title_cy );
587 launcher_size = BORDER_SIZE + title_cx + BORDER_SIZE;
588 icon_offset_cx = (launcher_size - icon_cx) / 2;
589 icon_offset_cy = BORDER_SIZE + (icon_size - icon_cy) / 2;
590 title_offset_cx = BORDER_SIZE;
591 title_offset_cy = BORDER_SIZE + icon_size + PADDING_SIZE;
592 desktop_width = GetSystemMetrics( SM_CXSCREEN );
593 launchers_per_row = desktop_width / launcher_size;
594 if (!launchers_per_row) launchers_per_row = 1;
596 hr = SHGetKnownFolderPath( &FOLDERID_Desktop, KF_FLAG_CREATE, NULL, &desktop_folder );
597 if (FAILED( hr ))
599 WINE_ERR("Could not get user desktop folder\n");
600 return;
602 hr = SHGetKnownFolderPath( &FOLDERID_PublicDesktop, KF_FLAG_CREATE, NULL, &desktop_folder_public );
603 if (FAILED( hr ))
605 WINE_ERR("Could not get public desktop folder\n");
606 CoTaskMemFree( desktop_folder );
607 return;
609 if ((launchers = HeapAlloc( GetProcessHeap(), 0, 2 * sizeof(launchers[0]) )))
611 nb_allocated = 2;
613 init = CoInitialize( NULL );
614 add_folder( desktop_folder );
615 add_folder( desktop_folder_public );
616 if (SUCCEEDED( init )) CoUninitialize();
618 CreateThread( NULL, 0, watch_desktop_folders, hwnd, 0, NULL );
622 /**************************************************************************
623 * wait_clipboard_mutex
625 * Make sure that there's only one clipboard thread per window station.
627 static BOOL wait_clipboard_mutex(void)
629 static const WCHAR prefix[] = L"__wine_clipboard_";
630 WCHAR buffer[MAX_PATH + ARRAY_SIZE( prefix )];
631 HANDLE mutex;
633 memcpy( buffer, prefix, sizeof(prefix) );
634 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_NAME,
635 buffer + ARRAY_SIZE( prefix ) - 1,
636 sizeof(buffer) - sizeof(prefix), NULL ))
638 ERR( "failed to get winstation name\n" );
639 return FALSE;
641 mutex = CreateMutexW( NULL, TRUE, buffer );
642 if (GetLastError() == ERROR_ALREADY_EXISTS)
644 TRACE( "waiting for mutex %s\n", debugstr_w( buffer ));
645 WaitForSingleObject( mutex, INFINITE );
647 return TRUE;
651 /**************************************************************************
652 * clipboard_wndproc
654 * Window procedure for the clipboard manager.
656 static LRESULT CALLBACK clipboard_wndproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
658 switch (msg)
660 case WM_NCCREATE:
661 case WM_CLIPBOARDUPDATE:
662 case WM_RENDERFORMAT:
663 case WM_TIMER:
664 case WM_DESTROYCLIPBOARD:
665 case WM_USER:
666 return NtUserMessageCall( hwnd, msg, wp, lp, 0, NtUserClipboardWindowProc, FALSE );
669 return DefWindowProcW( hwnd, msg, wp, lp );
673 /**************************************************************************
674 * clipboard_thread
676 * Thread running inside the desktop process to manage the clipboard
678 static DWORD WINAPI clipboard_thread( void *arg )
680 static const WCHAR clipboard_classname[] = L"__wine_clipboard_manager";
681 WNDCLASSW class;
682 ATOM atom;
683 MSG msg;
685 if (!wait_clipboard_mutex()) return 0;
687 memset( &class, 0, sizeof(class) );
688 class.lpfnWndProc = clipboard_wndproc;
689 class.lpszClassName = clipboard_classname;
691 if (!(atom = RegisterClassW( &class )) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
693 ERR( "could not register clipboard window class err %lu\n", GetLastError() );
694 return 0;
696 if (!CreateWindowW( clipboard_classname, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL ))
698 TRACE( "failed to create clipboard window err %lu\n", GetLastError() );
699 UnregisterClassW( MAKEINTRESOURCEW(atom), NULL );
700 return 0;
703 while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
704 return 0;
707 static WNDPROC desktop_orig_wndproc;
709 /* window procedure for the desktop window */
710 static LRESULT WINAPI desktop_wnd_proc( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
712 WINE_TRACE( "got msg %04x wp %Ix lp %Ix\n", message, wp, lp );
714 switch(message)
716 case WM_SYSCOMMAND:
717 switch(wp & 0xfff0)
719 case SC_CLOSE:
720 ExitWindows( 0, 0 );
721 return 0;
723 break;
725 case WM_CLOSE:
726 PostQuitMessage(0);
727 return 0;
729 case WM_SETCURSOR:
730 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
732 case WM_NCHITTEST:
733 return HTCLIENT;
735 case WM_ERASEBKGND:
736 if (!using_root) PaintDesktop( (HDC)wp );
737 return TRUE;
739 case WM_SETTINGCHANGE:
740 if (wp == SPI_SETDESKWALLPAPER)
741 SystemParametersInfoW( SPI_SETDESKWALLPAPER, 0, NULL, FALSE );
742 return 0;
744 case WM_PARENTNOTIFY:
745 handle_parent_notify( (HWND)lp, wp );
746 return 0;
748 case WM_LBUTTONDBLCLK:
749 if (!using_root)
751 const struct launcher *launcher = launcher_from_point( (short)LOWORD(lp), (short)HIWORD(lp) );
752 if (launcher) do_launch( launcher );
754 return 0;
756 case WM_PAINT:
758 PAINTSTRUCT ps;
759 BeginPaint( hwnd, &ps );
760 if (!using_root)
762 if (ps.fErase) PaintDesktop( ps.hdc );
763 draw_launchers( ps.hdc, ps.rcPaint );
765 EndPaint( hwnd, &ps );
767 return 0;
770 return desktop_orig_wndproc( hwnd, message, wp, lp );
773 /* create the desktop and the associated driver window, and make it the current desktop */
774 static BOOL create_desktop( HMODULE driver, const WCHAR *name, unsigned int width, unsigned int height )
776 BOOL ret = FALSE;
777 BOOL (CDECL *create_desktop_func)(unsigned int, unsigned int);
779 if (driver)
781 create_desktop_func = (void *)GetProcAddress( driver, "wine_create_desktop" );
782 if (create_desktop_func) ret = create_desktop_func( width, height );
784 return ret;
787 /* parse the desktop size specification */
788 static BOOL parse_size( const WCHAR *size, unsigned int *width, unsigned int *height )
790 WCHAR *end;
792 *width = wcstoul( size, &end, 10 );
793 if (end == size) return FALSE;
794 if (*end != 'x') return FALSE;
795 size = end + 1;
796 *height = wcstoul( size, &end, 10 );
797 return !*end;
800 /* retrieve the desktop name to use if not specified on the command line */
801 static const WCHAR *get_default_desktop_name(void)
803 static const WCHAR desktopW[] = {'D','e','s','k','t','o','p',0};
804 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',0};
805 static const WCHAR explorer_keyW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
806 'E','x','p','l','o','r','e','r',0};
807 static WCHAR buffer[MAX_PATH];
808 DWORD size = sizeof(buffer);
809 HDESK desk = GetThreadDesktop( GetCurrentThreadId() );
810 WCHAR *ret = NULL;
811 HKEY hkey;
813 if (desk && GetUserObjectInformationW( desk, UOI_NAME, buffer, ARRAY_SIZE( buffer ), NULL ))
815 if (wcsicmp( buffer, defaultW )) return buffer;
818 /* @@ Wine registry key: HKCU\Software\Wine\Explorer */
819 if (!RegOpenKeyW( HKEY_CURRENT_USER, explorer_keyW, &hkey ))
821 if (!RegQueryValueExW( hkey, desktopW, 0, NULL, (LPBYTE)buffer, &size ) && *buffer) ret = buffer;
822 RegCloseKey( hkey );
824 return ret;
827 /* retrieve the default desktop size from the registry */
828 static BOOL get_default_desktop_size( const WCHAR *name, unsigned int *width, unsigned int *height )
830 static const WCHAR desktop_keyW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
831 'E','x','p','l','o','r','e','r','\\',
832 'D','e','s','k','t','o','p','s',0};
833 HKEY hkey;
834 WCHAR buffer[64];
835 DWORD size = sizeof(buffer);
836 BOOL found = FALSE;
838 *width = 800;
839 *height = 600;
841 /* @@ Wine registry key: HKCU\Software\Wine\Explorer\Desktops */
842 if (!RegOpenKeyW( HKEY_CURRENT_USER, desktop_keyW, &hkey ))
844 if (!RegQueryValueExW( hkey, name, 0, NULL, (LPBYTE)buffer, &size ))
846 found = TRUE;
847 if (!parse_size( buffer, width, height )) *width = *height = 0;
849 RegCloseKey( hkey );
851 return found;
854 static BOOL get_default_enable_shell( const WCHAR *name )
856 static const WCHAR desktop_keyW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
857 'E','x','p','l','o','r','e','r','\\',
858 'D','e','s','k','t','o','p','s',0};
859 static const WCHAR enable_shellW[] = {'E','n','a','b','l','e','S','h','e','l','l',0};
860 static const WCHAR shellW[] = {'s','h','e','l','l',0};
861 HKEY hkey;
862 BOOL found = FALSE;
863 BOOL result;
864 DWORD size = sizeof(result);
866 /* @@ Wine registry key: HKCU\Software\Wine\Explorer\Desktops */
867 if (!RegOpenKeyW( HKEY_CURRENT_USER, desktop_keyW, &hkey ))
869 if (!RegGetValueW( hkey, name, enable_shellW, RRF_RT_REG_DWORD, NULL, &result, &size ))
870 found = TRUE;
871 RegCloseKey( hkey );
873 /* Default off, except for the magic desktop name "shell" */
874 if (!found)
875 result = (lstrcmpiW( name, shellW ) == 0);
876 return result;
879 static HMODULE load_graphics_driver( const WCHAR *driver, GUID *guid )
881 static const WCHAR device_keyW[] = {
882 'S','y','s','t','e','m','\\',
883 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
884 'C','o','n','t','r','o','l','\\',
885 'V','i','d','e','o','\\',
886 '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-',
887 '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x','%','0','2','x',
888 '%','0','2','x','%','0','2','x','%','0','2','x','}','\\','0','0','0','0',0};
889 static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
890 static const WCHAR driversW[] = {'S','o','f','t','w','a','r','e','\\',
891 'W','i','n','e','\\','D','r','i','v','e','r','s',0};
892 static const WCHAR graphicsW[] = {'G','r','a','p','h','i','c','s',0};
893 static const WCHAR drv_formatW[] = {'w','i','n','e','%','s','.','d','r','v',0};
895 WCHAR buffer[MAX_PATH], libname[32], *name, *next;
896 WCHAR key[ARRAY_SIZE( device_keyW ) + 39];
897 BOOL null_driver = FALSE;
898 HMODULE module = 0;
899 HKEY hkey;
900 char error[80];
902 if (!driver)
904 lstrcpyW( buffer, default_driver );
906 /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
907 if (!RegOpenKeyW( HKEY_CURRENT_USER, driversW, &hkey ))
909 DWORD count = sizeof(buffer);
910 RegQueryValueExW( hkey, graphicsW, 0, NULL, (LPBYTE)buffer, &count );
911 RegCloseKey( hkey );
914 else lstrcpynW( buffer, driver, ARRAY_SIZE( buffer ));
916 name = buffer;
917 while (name)
919 next = wcschr( name, ',' );
920 if (next) *next++ = 0;
922 if (!wcscmp( name, L"null" ))
924 memset( guid, 0, sizeof(*guid) );
925 TRACE( "display %s using null driver\n", debugstr_guid(guid) );
926 wcscpy( libname, L"null" );
927 null_driver = TRUE;
928 break;
931 swprintf( libname, ARRAY_SIZE( libname ), drv_formatW, name );
932 if ((module = LoadLibraryW( libname )) != 0) break;
933 switch (GetLastError())
935 case ERROR_MOD_NOT_FOUND:
936 strcpy( error, "The graphics driver is missing. Check your build!" );
937 break;
938 case ERROR_DLL_INIT_FAILED:
939 strcpy( error, "Make sure that your X server is running and that $DISPLAY is set correctly." );
940 break;
941 default:
942 sprintf( error, "Unknown error (%lu).", GetLastError() );
943 break;
945 name = next;
948 TRACE( "display %s driver %s\n", debugstr_guid(guid), debugstr_w(libname) );
950 swprintf( key, ARRAY_SIZE(key), device_keyW, guid->Data1, guid->Data2, guid->Data3,
951 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
952 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
954 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, key, 0, NULL,
955 REG_OPTION_VOLATILE, KEY_SET_VALUE, NULL, &hkey, NULL ))
957 if (module || null_driver)
958 RegSetValueExW( hkey, graphics_driverW, 0, REG_SZ,
959 (BYTE *)libname, (lstrlenW(libname) + 1) * sizeof(WCHAR) );
960 else
961 RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 );
962 RegCloseKey( hkey );
965 return module;
968 static void initialize_display_settings(void)
970 DISPLAY_DEVICEW ddW;
971 DEVMODEW dmW;
972 DWORD i = 0;
974 /* Store current display mode in the registry */
975 ddW.cb = sizeof(ddW);
976 memset(&dmW, 0, sizeof(dmW));
977 dmW.dmSize = sizeof(dmW);
978 while (EnumDisplayDevicesW( NULL, i++, &ddW, 0 ))
980 if (!EnumDisplaySettingsExW( ddW.DeviceName, ENUM_CURRENT_SETTINGS, &dmW, 0))
982 WINE_ERR( "Failed to query current display settings for %s.\n",
983 wine_dbgstr_w( ddW.DeviceName ) );
984 continue;
987 WINE_TRACE( "Device %s current display mode %lux%lu %luBits %luHz at %ld,%ld.\n",
988 wine_dbgstr_w( ddW.DeviceName ), dmW.dmPelsWidth, dmW.dmPelsHeight,
989 dmW.dmBitsPerPel, dmW.dmDisplayFrequency, dmW.u1.s2.dmPosition.x,
990 dmW.u1.s2.dmPosition.y );
992 if (ChangeDisplaySettingsExW( ddW.DeviceName, &dmW, 0,
993 CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, 0 ))
994 WINE_ERR( "Failed to initialize registry display settings for %s.\n",
995 wine_dbgstr_w( ddW.DeviceName ) );
999 static void set_desktop_window_title( HWND hwnd, const WCHAR *name )
1001 static const WCHAR desktop_nameW[] = {'W','i','n','e',' ','d','e','s','k','t','o','p',0};
1002 static const WCHAR desktop_name_separatorW[] = {' ', '-', ' ', 0};
1003 WCHAR *window_titleW = NULL;
1004 int window_title_len;
1006 if (!name[0])
1008 SetWindowTextW( hwnd, desktop_nameW );
1009 return;
1012 window_title_len = lstrlenW(name) * sizeof(WCHAR)
1013 + sizeof(desktop_name_separatorW)
1014 + sizeof(desktop_nameW);
1015 window_titleW = HeapAlloc( GetProcessHeap(), 0, window_title_len );
1016 if (!window_titleW)
1018 SetWindowTextW( hwnd, desktop_nameW );
1019 return;
1022 lstrcpyW( window_titleW, name );
1023 lstrcatW( window_titleW, desktop_name_separatorW );
1024 lstrcatW( window_titleW, desktop_nameW );
1026 SetWindowTextW( hwnd, window_titleW );
1027 HeapFree( GetProcessHeap(), 0, window_titleW );
1030 static inline BOOL is_whitespace(WCHAR c)
1032 return c == ' ' || c == '\t';
1035 /* main desktop management function */
1036 void manage_desktop( WCHAR *arg )
1038 static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
1039 HDESK desktop = 0;
1040 GUID guid;
1041 MSG msg;
1042 HWND hwnd;
1043 HMODULE graphics_driver;
1044 unsigned int width, height;
1045 WCHAR *cmdline = NULL, *driver = NULL;
1046 WCHAR *p = arg;
1047 const WCHAR *name = NULL;
1048 BOOL enable_shell = FALSE;
1049 void (WINAPI *pShellDDEInit)( BOOL ) = NULL;
1050 HMODULE shell32;
1051 HANDLE thread;
1052 DWORD id;
1054 /* get the rest of the command line (if any) */
1055 while (*p && !is_whitespace(*p)) p++;
1056 if (*p)
1058 *p++ = 0;
1059 while (*p && is_whitespace(*p)) p++;
1060 if (*p) cmdline = p;
1063 /* parse the desktop option */
1064 /* the option is of the form /desktop=name[,widthxheight[,driver]] */
1065 if ((arg[0] == '=' || arg[0] == ',') && arg[1] && arg[1] != ',')
1067 arg++;
1068 name = arg;
1069 if ((p = wcschr( arg, ',' )))
1071 *p++ = 0;
1072 if ((driver = wcschr( p, ',' ))) *driver++ = 0;
1074 if (!p || !parse_size( p, &width, &height ))
1075 get_default_desktop_size( name, &width, &height );
1077 else if ((name = get_default_desktop_name()))
1079 if (!get_default_desktop_size( name, &width, &height )) width = height = 0;
1082 if (name)
1083 enable_shell = get_default_enable_shell( name );
1085 if (name && width && height)
1087 if (!(desktop = CreateDesktopW( name, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL )))
1089 WINE_ERR( "failed to create desktop %s error %ld\n", wine_dbgstr_w(name), GetLastError() );
1090 ExitProcess( 1 );
1092 SetThreadDesktop( desktop );
1095 UuidCreate( &guid );
1096 TRACE( "display guid %s\n", debugstr_guid(&guid) );
1097 graphics_driver = load_graphics_driver( driver, &guid );
1099 /* create the desktop window */
1100 hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL,
1101 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, &guid );
1103 if (hwnd)
1105 /* create the HWND_MESSAGE parent */
1106 CreateWindowExW( 0, messageW, NULL, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
1107 0, 0, 100, 100, 0, 0, 0, NULL );
1109 desktop_orig_wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC,
1110 (LONG_PTR)desktop_wnd_proc );
1111 using_root = !desktop || !create_desktop( graphics_driver, name, width, height );
1112 SendMessageW( hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW( 0, MAKEINTRESOURCEW(OIC_WINLOGO)));
1113 if (name) set_desktop_window_title( hwnd, name );
1114 SetWindowPos( hwnd, 0, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
1115 GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN),
1116 SWP_SHOWWINDOW );
1117 thread = CreateThread( NULL, 0, clipboard_thread, NULL, 0, &id );
1118 if (thread) CloseHandle( thread );
1119 SystemParametersInfoW( SPI_SETDESKWALLPAPER, 0, NULL, FALSE );
1120 ClipCursor( NULL );
1121 initialize_display_settings();
1122 initialize_appbar();
1124 if (using_root) enable_shell = FALSE;
1126 initialize_systray( graphics_driver, using_root, enable_shell );
1127 if (!using_root) initialize_launchers( hwnd );
1129 if ((shell32 = LoadLibraryW( L"shell32.dll" )) &&
1130 (pShellDDEInit = (void *)GetProcAddress( shell32, (LPCSTR)188)))
1132 pShellDDEInit( TRUE );
1136 /* if we have a command line, execute it */
1137 if (cmdline)
1139 STARTUPINFOW si;
1140 PROCESS_INFORMATION pi;
1142 memset( &si, 0, sizeof(si) );
1143 si.cb = sizeof(si);
1144 WINE_TRACE( "starting %s\n", wine_dbgstr_w(cmdline) );
1145 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
1147 CloseHandle( pi.hThread );
1148 CloseHandle( pi.hProcess );
1152 desktopshellbrowserwindow_init();
1153 shellwindows_init();
1155 /* run the desktop message loop */
1156 if (hwnd)
1158 WINE_TRACE( "desktop message loop starting on hwnd %p\n", hwnd );
1159 while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
1160 WINE_TRACE( "desktop message loop exiting for hwnd %p\n", hwnd );
1163 if (pShellDDEInit) pShellDDEInit( FALSE );
1165 ExitProcess( 0 );
1168 /* IShellWindows implementation */
1169 static HRESULT WINAPI shellwindows_QueryInterface(IShellWindows *iface, REFIID riid, void **ppvObject)
1171 struct shellwindows *This = impl_from_IShellWindows(iface);
1173 TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
1175 if (IsEqualGUID(riid, &IID_IShellWindows) ||
1176 IsEqualGUID(riid, &IID_IDispatch) ||
1177 IsEqualGUID(riid, &IID_IUnknown))
1179 *ppvObject = &This->IShellWindows_iface;
1181 else
1183 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1184 *ppvObject = NULL;
1187 if (*ppvObject)
1189 IUnknown_AddRef((IUnknown*)*ppvObject);
1190 return S_OK;
1193 return E_NOINTERFACE;
1196 static ULONG WINAPI shellwindows_AddRef(IShellWindows *iface)
1198 return 2;
1201 static ULONG WINAPI shellwindows_Release(IShellWindows *iface)
1203 return 1;
1206 static HRESULT WINAPI shellwindows_GetTypeInfoCount(IShellWindows *iface, UINT *pctinfo)
1208 TRACE("%p\n", pctinfo);
1209 *pctinfo = 1;
1210 return S_OK;
1213 static HRESULT WINAPI shellwindows_GetTypeInfo(IShellWindows *iface,
1214 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1216 TRACE("%d %ld %p\n", iTInfo, lcid, ppTInfo);
1217 return get_typeinfo(IShellWindows_tid, ppTInfo);
1220 static HRESULT WINAPI shellwindows_GetIDsOfNames(IShellWindows *iface,
1221 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
1222 DISPID *rgDispId)
1224 ITypeInfo *typeinfo;
1225 HRESULT hr;
1227 TRACE("%s %p %d %ld %p\n", debugstr_guid(riid), rgszNames, cNames,
1228 lcid, rgDispId);
1230 if (!rgszNames || cNames == 0 || !rgDispId)
1231 return E_INVALIDARG;
1233 hr = get_typeinfo(IShellWindows_tid, &typeinfo);
1234 if (SUCCEEDED(hr))
1236 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1237 ITypeInfo_Release(typeinfo);
1240 return hr;
1243 static HRESULT WINAPI shellwindows_Invoke(IShellWindows *iface,
1244 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
1245 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1246 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1248 ITypeInfo *typeinfo;
1249 HRESULT hr;
1251 TRACE("%ld %s %ld %08x %p %p %p %p\n", dispIdMember, debugstr_guid(riid),
1252 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1254 hr = get_typeinfo(IShellWindows_tid, &typeinfo);
1255 if (SUCCEEDED(hr))
1257 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1258 pDispParams, pVarResult, pExcepInfo, puArgErr);
1259 ITypeInfo_Release(typeinfo);
1262 return hr;
1265 static HRESULT WINAPI shellwindows_get_Count(IShellWindows *iface, LONG *count)
1267 FIXME("%p\n", count);
1268 return E_NOTIMPL;
1271 static HRESULT WINAPI shellwindows_Item(IShellWindows *iface, VARIANT index,
1272 IDispatch **folder)
1274 FIXME("%s %p\n", debugstr_variant(&index), folder);
1275 return E_NOTIMPL;
1278 static HRESULT WINAPI shellwindows__NewEnum(IShellWindows *iface, IUnknown **ppunk)
1280 FIXME("%p\n", ppunk);
1281 return E_NOTIMPL;
1284 static HRESULT WINAPI shellwindows_Register(IShellWindows *iface,
1285 IDispatch *disp, LONG hwnd, int class, LONG *cookie)
1287 struct shellwindows *sw = impl_from_IShellWindows(iface);
1288 struct window *window;
1290 TRACE("iface %p, disp %p, hwnd %#lx, class %u, cookie %p.\n", iface, disp, hwnd, class, cookie);
1292 if (!hwnd)
1293 return E_POINTER;
1295 if (disp)
1296 FIXME("Ignoring IDispatch %p.\n", disp);
1298 EnterCriticalSection(&sw->cs);
1300 if (!array_reserve((void **)&sw->windows, &sw->max, sw->count + 1, sizeof(*sw->windows)))
1302 LeaveCriticalSection(&sw->cs);
1303 return E_OUTOFMEMORY;
1306 window = &sw->windows[sw->count++];
1307 window->hwnd = hwnd;
1308 window->class = class;
1309 *cookie = window->cookie = ++cookie_counter;
1310 window->pidl = NULL;
1312 LeaveCriticalSection(&sw->cs);
1313 return S_OK;
1316 static HRESULT WINAPI shellwindows_RegisterPending(IShellWindows *iface,
1317 LONG threadid, VARIANT *loc, VARIANT *root, int class, LONG *cookie)
1319 FIXME("0x%lx %s %s 0x%x %p\n", threadid, debugstr_variant(loc), debugstr_variant(root),
1320 class, cookie);
1321 return E_NOTIMPL;
1324 static HRESULT WINAPI shellwindows_Revoke(IShellWindows *iface, LONG cookie)
1326 struct shellwindows *sw = impl_from_IShellWindows(iface);
1327 unsigned int i;
1329 TRACE("iface %p, cookie %lu.\n", iface, cookie);
1331 EnterCriticalSection(&sw->cs);
1333 for (i = 0; i < sw->count; ++i)
1335 if (sw->windows[i].cookie == cookie)
1337 --sw->count;
1338 memmove(&sw->windows[i], &sw->windows[i + 1], (sw->count - i) * sizeof(*sw->windows));
1339 LeaveCriticalSection(&sw->cs);
1340 return S_OK;
1344 LeaveCriticalSection(&sw->cs);
1345 return S_FALSE;
1348 static HRESULT WINAPI shellwindows_OnNavigate(IShellWindows *iface, LONG cookie, VARIANT *location)
1350 struct shellwindows *sw = impl_from_IShellWindows(iface);
1351 unsigned int i;
1353 TRACE("iface %p, cookie %lu, location %s.\n", iface, cookie, debugstr_variant(location));
1355 if (V_VT(location) != (VT_ARRAY | VT_UI1))
1357 FIXME("Unexpected variant type %s.\n", debugstr_vt(V_VT(location)));
1358 return E_NOTIMPL;
1361 EnterCriticalSection(&sw->cs);
1363 for (i = 0; i < sw->count; ++i)
1365 if (sw->windows[i].cookie == cookie)
1367 size_t len = V_ARRAY(location)->rgsabound[0].cElements;
1368 if (!(sw->windows[i].pidl = realloc(sw->windows[i].pidl, len)))
1370 LeaveCriticalSection(&sw->cs);
1371 return E_OUTOFMEMORY;
1373 memcpy(sw->windows[i].pidl, V_ARRAY(location)->pvData, len);
1375 LeaveCriticalSection(&sw->cs);
1376 return S_OK;
1380 LeaveCriticalSection(&sw->cs);
1381 return E_INVALIDARG;
1384 static HRESULT WINAPI shellwindows_OnActivated(IShellWindows *iface, LONG cookie, VARIANT_BOOL active)
1386 FIXME("0x%lx 0x%x\n", cookie, active);
1387 return E_NOTIMPL;
1390 static HRESULT WINAPI shellwindows_FindWindowSW(IShellWindows *iface, VARIANT *location,
1391 VARIANT *root, int class, LONG *hwnd, int options, IDispatch **disp)
1393 struct shellwindows *sw = impl_from_IShellWindows(iface);
1394 unsigned int i;
1396 TRACE("iface %p, location %p, root %p, class %#x, hwnd %p, options %#x, disp %p.\n",
1397 iface, location, root, class, hwnd, options, disp);
1399 if (class == SWC_DESKTOP)
1401 *hwnd = (LONG)(LONG_PTR)GetDesktopWindow();
1402 if (options & SWFO_NEEDDISPATCH)
1404 *disp = (IDispatch *)&desktopshellbrowserwindow.IWebBrowser2_iface;
1405 IDispatch_AddRef(*disp);
1407 return S_OK;
1410 if (options)
1411 FIXME("Ignoring options %#x.\n", options);
1413 if (V_VT(location) != (VT_ARRAY | VT_UI1))
1415 FIXME("Unexpected variant type %s.\n", debugstr_vt(V_VT(location)));
1416 return E_NOTIMPL;
1419 EnterCriticalSection(&sw->cs);
1421 for (i = 0; i < sw->count; ++i)
1423 if (sw->windows[i].class == class && ILIsEqual(V_ARRAY(location)->pvData, sw->windows[i].pidl))
1425 *hwnd = sw->windows[i].hwnd;
1426 LeaveCriticalSection(&sw->cs);
1427 return S_OK;
1431 LeaveCriticalSection(&sw->cs);
1432 return S_FALSE;
1435 static HRESULT WINAPI shellwindows_OnCreated(IShellWindows *iface, LONG cookie, IUnknown *punk)
1437 FIXME("0x%lx %p\n", cookie, punk);
1438 return E_NOTIMPL;
1441 static HRESULT WINAPI shellwindows_ProcessAttachDetach(IShellWindows *iface, VARIANT_BOOL attach)
1443 FIXME("0x%x\n", attach);
1444 return E_NOTIMPL;
1447 static const IShellWindowsVtbl shellwindowsvtbl =
1449 shellwindows_QueryInterface,
1450 shellwindows_AddRef,
1451 shellwindows_Release,
1452 shellwindows_GetTypeInfoCount,
1453 shellwindows_GetTypeInfo,
1454 shellwindows_GetIDsOfNames,
1455 shellwindows_Invoke,
1456 shellwindows_get_Count,
1457 shellwindows_Item,
1458 shellwindows__NewEnum,
1459 shellwindows_Register,
1460 shellwindows_RegisterPending,
1461 shellwindows_Revoke,
1462 shellwindows_OnNavigate,
1463 shellwindows_OnActivated,
1464 shellwindows_FindWindowSW,
1465 shellwindows_OnCreated,
1466 shellwindows_ProcessAttachDetach
1469 struct shellwindows_classfactory
1471 IClassFactory IClassFactory_iface;
1472 DWORD classreg;
1475 static inline struct shellwindows_classfactory *impl_from_IClassFactory(IClassFactory *iface)
1477 return CONTAINING_RECORD(iface, struct shellwindows_classfactory, IClassFactory_iface);
1480 static HRESULT WINAPI swclassfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppvObject)
1482 struct shellwindows_classfactory *This = impl_from_IClassFactory(iface);
1484 TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
1486 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IClassFactory))
1488 *ppvObject = &This->IClassFactory_iface;
1490 else
1492 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1493 *ppvObject = NULL;
1496 if (*ppvObject)
1498 IUnknown_AddRef((IUnknown*)*ppvObject);
1499 return S_OK;
1502 return E_NOINTERFACE;
1505 static ULONG WINAPI swclassfactory_AddRef(IClassFactory *iface)
1507 return 2;
1510 static ULONG WINAPI swclassfactory_Release(IClassFactory *iface)
1512 return 1;
1515 static HRESULT WINAPI swclassfactory_CreateInstance(IClassFactory *iface,
1516 IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
1518 TRACE("%p %s %p\n", pUnkOuter, debugstr_guid(riid), ppvObject);
1519 return IShellWindows_QueryInterface(&shellwindows.IShellWindows_iface, riid, ppvObject);
1522 static HRESULT WINAPI swclassfactory_LockServer(IClassFactory *iface, BOOL lock)
1524 TRACE("%u\n", lock);
1525 return E_NOTIMPL;
1528 static const IClassFactoryVtbl swclassfactoryvtbl =
1530 swclassfactory_QueryInterface,
1531 swclassfactory_AddRef,
1532 swclassfactory_Release,
1533 swclassfactory_CreateInstance,
1534 swclassfactory_LockServer
1537 static struct shellwindows_classfactory shellwindows_classfactory = { { &swclassfactoryvtbl } };
1539 static HRESULT WINAPI webbrowser_QueryInterface(IWebBrowser2 *iface, REFIID riid, void **ppv)
1541 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1543 *ppv = NULL;
1545 if (IsEqualGUID(&IID_IWebBrowser2, riid) ||
1546 IsEqualGUID(&IID_IWebBrowserApp, riid) ||
1547 IsEqualGUID(&IID_IWebBrowser, riid) ||
1548 IsEqualGUID(&IID_IDispatch, riid) ||
1549 IsEqualGUID(&IID_IUnknown, riid))
1551 *ppv = &This->IWebBrowser2_iface;
1553 else if (IsEqualGUID(&IID_IServiceProvider, riid))
1555 *ppv = &This->IServiceProvider_iface;
1558 if (*ppv)
1560 IUnknown_AddRef((IUnknown*)*ppv);
1561 return S_OK;
1564 FIXME("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv);
1565 return E_NOINTERFACE;
1568 static ULONG WINAPI webbrowser_AddRef(IWebBrowser2 *iface)
1570 return 2;
1573 static ULONG WINAPI webbrowser_Release(IWebBrowser2 *iface)
1575 return 1;
1578 /* IDispatch methods */
1579 static HRESULT WINAPI webbrowser_GetTypeInfoCount(IWebBrowser2 *iface, UINT *pctinfo)
1581 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1582 TRACE("(%p)->(%p)\n", This, pctinfo);
1583 *pctinfo = 1;
1584 return S_OK;
1587 static HRESULT WINAPI webbrowser_GetTypeInfo(IWebBrowser2 *iface, UINT iTInfo, LCID lcid,
1588 LPTYPEINFO *ppTInfo)
1590 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1591 TRACE("(%p)->(%d %ld %p)\n", This, iTInfo, lcid, ppTInfo);
1592 return get_typeinfo(IWebBrowser2_tid, ppTInfo);
1595 static HRESULT WINAPI webbrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid,
1596 LPOLESTR *rgszNames, UINT cNames,
1597 LCID lcid, DISPID *rgDispId)
1599 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1600 ITypeInfo *typeinfo;
1601 HRESULT hr;
1603 TRACE("(%p)->(%s %p %d %ld %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1604 lcid, rgDispId);
1606 if(!rgszNames || cNames == 0 || !rgDispId)
1607 return E_INVALIDARG;
1609 hr = get_typeinfo(IWebBrowser2_tid, &typeinfo);
1610 if (SUCCEEDED(hr))
1612 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1613 ITypeInfo_Release(typeinfo);
1616 return hr;
1619 static HRESULT WINAPI webbrowser_Invoke(IWebBrowser2 *iface, DISPID dispIdMember,
1620 REFIID riid, LCID lcid, WORD wFlags,
1621 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1622 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1624 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1625 ITypeInfo *typeinfo;
1626 HRESULT hr;
1628 TRACE("(%p)->(%ld %s %ld %08x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1629 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1631 hr = get_typeinfo(IWebBrowser2_tid, &typeinfo);
1632 if (SUCCEEDED(hr))
1634 hr = ITypeInfo_Invoke(typeinfo, &This->IWebBrowser2_iface, dispIdMember, wFlags,
1635 pDispParams, pVarResult, pExcepInfo, puArgErr);
1636 ITypeInfo_Release(typeinfo);
1639 return hr;
1642 /* IWebBrowser methods */
1643 static HRESULT WINAPI webbrowser_GoBack(IWebBrowser2 *iface)
1645 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1646 FIXME("(%p): stub\n", This);
1647 return E_NOTIMPL;
1650 static HRESULT WINAPI webbrowser_GoForward(IWebBrowser2 *iface)
1652 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1653 FIXME("(%p): stub\n", This);
1654 return E_NOTIMPL;
1657 static HRESULT WINAPI webbrowser_GoHome(IWebBrowser2 *iface)
1659 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1660 FIXME("(%p): stub\n", This);
1661 return E_NOTIMPL;
1664 static HRESULT WINAPI webbrowser_GoSearch(IWebBrowser2 *iface)
1666 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1667 FIXME("(%p)\n", This);
1668 return E_NOTIMPL;
1671 static HRESULT WINAPI webbrowser_Navigate(IWebBrowser2 *iface, BSTR szUrl,
1672 VARIANT *Flags, VARIANT *TargetFrameName,
1673 VARIANT *PostData, VARIANT *Headers)
1675 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1676 FIXME("(%p)->(%s %s %s %s %s): stub\n", This, debugstr_w(szUrl), debugstr_variant(Flags),
1677 debugstr_variant(TargetFrameName), debugstr_variant(PostData),
1678 debugstr_variant(Headers));
1679 return E_NOTIMPL;
1682 static HRESULT WINAPI webbrowser_Refresh(IWebBrowser2 *iface)
1684 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1685 FIXME("(%p): stub\n", This);
1686 return E_NOTIMPL;
1689 static HRESULT WINAPI webbrowser_Refresh2(IWebBrowser2 *iface, VARIANT *Level)
1691 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1692 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(Level));
1693 return E_NOTIMPL;
1696 static HRESULT WINAPI webbrowser_Stop(IWebBrowser2 *iface)
1698 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1699 FIXME("(%p): stub\n", This);
1700 return E_NOTIMPL;
1703 static HRESULT WINAPI webbrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp)
1705 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1707 TRACE("(%p)->(%p)\n", This, ppDisp);
1709 *ppDisp = (IDispatch*)iface;
1710 IDispatch_AddRef(*ppDisp);
1712 return S_OK;
1715 static HRESULT WINAPI webbrowser_get_Parent(IWebBrowser2 *iface, IDispatch **ppDisp)
1717 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1718 FIXME("(%p)->(%p)\n", This, ppDisp);
1719 return E_NOTIMPL;
1722 static HRESULT WINAPI webbrowser_get_Container(IWebBrowser2 *iface, IDispatch **ppDisp)
1724 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1725 FIXME("(%p)->(%p)\n", This, ppDisp);
1726 return E_NOTIMPL;
1729 static HRESULT WINAPI webbrowser_get_Document(IWebBrowser2 *iface, IDispatch **ppDisp)
1731 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1732 FIXME("(%p)->(%p)\n", This, ppDisp);
1733 return E_NOTIMPL;
1736 static HRESULT WINAPI webbrowser_get_TopLevelContainer(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1738 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1739 FIXME("(%p)->(%p)\n", This, pBool);
1740 return E_NOTIMPL;
1743 static HRESULT WINAPI webbrowser_get_Type(IWebBrowser2 *iface, BSTR *Type)
1745 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1746 FIXME("(%p)->(%p)\n", This, Type);
1747 return E_NOTIMPL;
1750 static HRESULT WINAPI webbrowser_get_Left(IWebBrowser2 *iface, LONG *pl)
1752 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1753 FIXME("(%p)->(%p)\n", This, pl);
1754 return E_NOTIMPL;
1757 static HRESULT WINAPI webbrowser_put_Left(IWebBrowser2 *iface, LONG Left)
1759 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1760 FIXME("(%p)->(%ld)\n", This, Left);
1761 return E_NOTIMPL;
1764 static HRESULT WINAPI webbrowser_get_Top(IWebBrowser2 *iface, LONG *pl)
1766 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1767 FIXME("(%p)->(%p)\n", This, pl);
1768 return E_NOTIMPL;
1771 static HRESULT WINAPI webbrowser_put_Top(IWebBrowser2 *iface, LONG Top)
1773 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1774 FIXME("(%p)->(%ld)\n", This, Top);
1775 return E_NOTIMPL;
1778 static HRESULT WINAPI webbrowser_get_Width(IWebBrowser2 *iface, LONG *pl)
1780 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1781 FIXME("(%p)->(%p)\n", This, pl);
1782 return E_NOTIMPL;
1785 static HRESULT WINAPI webbrowser_put_Width(IWebBrowser2 *iface, LONG Width)
1787 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1788 FIXME("(%p)->(%ld)\n", This, Width);
1789 return E_NOTIMPL;
1792 static HRESULT WINAPI webbrowser_get_Height(IWebBrowser2 *iface, LONG *pl)
1794 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1795 FIXME("(%p)->(%p)\n", This, pl);
1796 return E_NOTIMPL;
1799 static HRESULT WINAPI webbrowser_put_Height(IWebBrowser2 *iface, LONG Height)
1801 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1802 FIXME("(%p)->(%ld)\n", This, Height);
1803 return E_NOTIMPL;
1806 static HRESULT WINAPI webbrowser_get_LocationName(IWebBrowser2 *iface, BSTR *LocationName)
1808 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1809 FIXME("(%p)->(%p)\n", This, LocationName);
1810 return E_NOTIMPL;
1813 static HRESULT WINAPI webbrowser_get_LocationURL(IWebBrowser2 *iface, BSTR *LocationURL)
1815 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1816 FIXME("(%p)->(%p)\n", This, LocationURL);
1817 return E_NOTIMPL;
1820 static HRESULT WINAPI webbrowser_get_Busy(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1822 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1823 FIXME("(%p)->(%p)\n", This, pBool);
1824 return E_NOTIMPL;
1827 static HRESULT WINAPI webbrowser_Quit(IWebBrowser2 *iface)
1829 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1830 FIXME("(%p)\n", This);
1831 return E_NOTIMPL;
1834 static HRESULT WINAPI webbrowser_ClientToWindow(IWebBrowser2 *iface, int *pcx, int *pcy)
1836 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1837 FIXME("(%p)->(%p %p)\n", This, pcx, pcy);
1838 return E_NOTIMPL;
1841 static HRESULT WINAPI webbrowser_PutProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT vtValue)
1843 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1844 FIXME("(%p)->(%s %s)\n", This, debugstr_w(szProperty), debugstr_variant(&vtValue));
1845 return E_NOTIMPL;
1848 static HRESULT WINAPI webbrowser_GetProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT *pvtValue)
1850 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1851 FIXME("(%p)->(%s %s)\n", This, debugstr_w(szProperty), debugstr_variant(pvtValue));
1852 return E_NOTIMPL;
1855 static HRESULT WINAPI webbrowser_get_Name(IWebBrowser2 *iface, BSTR *Name)
1857 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1858 FIXME("(%p)->(%p)\n", This, Name);
1859 return E_NOTIMPL;
1862 static HRESULT WINAPI webbrowser_get_HWND(IWebBrowser2 *iface, SHANDLE_PTR *pHWND)
1864 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1865 FIXME("(%p)->(%p)\n", This, pHWND);
1866 return E_NOTIMPL;
1869 static HRESULT WINAPI webbrowser_get_FullName(IWebBrowser2 *iface, BSTR *FullName)
1871 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1872 FIXME("(%p)->(%p)\n", This, FullName);
1873 return E_NOTIMPL;
1876 static HRESULT WINAPI webbrowser_get_Path(IWebBrowser2 *iface, BSTR *Path)
1878 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1879 FIXME("(%p)->(%p)\n", This, Path);
1880 return E_NOTIMPL;
1883 static HRESULT WINAPI webbrowser_get_Visible(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1885 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1886 FIXME("(%p)->(%p)\n", This, pBool);
1887 return E_NOTIMPL;
1890 static HRESULT WINAPI webbrowser_put_Visible(IWebBrowser2 *iface, VARIANT_BOOL Value)
1892 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1893 FIXME("(%p)->(%x)\n", This, Value);
1894 return E_NOTIMPL;
1897 static HRESULT WINAPI webbrowser_get_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1899 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1900 FIXME("(%p)->(%p)\n", This, pBool);
1901 return E_NOTIMPL;
1904 static HRESULT WINAPI webbrowser_put_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
1906 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1907 FIXME("(%p)->(%x)\n", This, Value);
1908 return E_NOTIMPL;
1911 static HRESULT WINAPI webbrowser_get_StatusText(IWebBrowser2 *iface, BSTR *StatusText)
1913 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1914 FIXME("(%p)->(%p)\n", This, StatusText);
1915 return E_NOTIMPL;
1918 static HRESULT WINAPI webbrowser_put_StatusText(IWebBrowser2 *iface, BSTR StatusText)
1920 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1921 FIXME("(%p)->(%s)\n", This, debugstr_w(StatusText));
1922 return E_NOTIMPL;
1925 static HRESULT WINAPI webbrowser_get_ToolBar(IWebBrowser2 *iface, int *Value)
1927 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1928 FIXME("(%p)->(%p)\n", This, Value);
1929 return E_NOTIMPL;
1932 static HRESULT WINAPI webbrowser_put_ToolBar(IWebBrowser2 *iface, int Value)
1934 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1935 FIXME("(%p)->(%x)\n", This, Value);
1936 return E_NOTIMPL;
1939 static HRESULT WINAPI webbrowser_get_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL *Value)
1941 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1942 FIXME("(%p)->(%p)\n", This, Value);
1943 return E_NOTIMPL;
1946 static HRESULT WINAPI webbrowser_put_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
1948 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1949 FIXME("(%p)->(%x)\n", This, Value);
1950 return E_NOTIMPL;
1953 static HRESULT WINAPI webbrowser_get_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL *pbFullScreen)
1955 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1956 FIXME("(%p)->(%p)\n", This, pbFullScreen);
1957 return E_NOTIMPL;
1960 static HRESULT WINAPI webbrowser_put_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL bFullScreen)
1962 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1963 FIXME("(%p)->(%x)\n", This, bFullScreen);
1964 return E_NOTIMPL;
1967 static HRESULT WINAPI webbrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VARIANT *Flags,
1968 VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
1970 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1971 FIXME("(%p)->(%s %s %s %s %s)\n", This, debugstr_variant(URL), debugstr_variant(Flags),
1972 debugstr_variant(TargetFrameName), debugstr_variant(PostData), debugstr_variant(Headers));
1973 return E_NOTIMPL;
1976 static HRESULT WINAPI webbrowser_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf)
1978 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1979 FIXME("(%p)->(%d %p)\n", This, cmdID, pcmdf);
1980 return E_NOTIMPL;
1983 static HRESULT WINAPI webbrowser_ExecWB(IWebBrowser2 *iface, OLECMDID cmdID,
1984 OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1986 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1987 FIXME("(%p)->(%d %d %s %p)\n", This, cmdID, cmdexecopt, debugstr_variant(pvaIn), pvaOut);
1988 return E_NOTIMPL;
1991 static HRESULT WINAPI webbrowser_ShowBrowserBar(IWebBrowser2 *iface, VARIANT *pvaClsid,
1992 VARIANT *pvarShow, VARIANT *pvarSize)
1994 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1995 FIXME("(%p)->(%s %s %s)\n", This, debugstr_variant(pvaClsid), debugstr_variant(pvarShow),
1996 debugstr_variant(pvarSize));
1997 return E_NOTIMPL;
2000 static HRESULT WINAPI webbrowser_get_ReadyState(IWebBrowser2 *iface, READYSTATE *lpReadyState)
2002 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2003 FIXME("(%p)->(%p)\n", This, lpReadyState);
2004 return E_NOTIMPL;
2007 static HRESULT WINAPI webbrowser_get_Offline(IWebBrowser2 *iface, VARIANT_BOOL *pbOffline)
2009 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2010 FIXME("(%p)->(%p)\n", This, pbOffline);
2011 return E_NOTIMPL;
2014 static HRESULT WINAPI webbrowser_put_Offline(IWebBrowser2 *iface, VARIANT_BOOL bOffline)
2016 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2017 FIXME("(%p)->(%x)\n", This, bOffline);
2018 return E_NOTIMPL;
2021 static HRESULT WINAPI webbrowser_get_Silent(IWebBrowser2 *iface, VARIANT_BOOL *pbSilent)
2023 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2024 FIXME("(%p)->(%p)\n", This, pbSilent);
2025 return E_NOTIMPL;
2028 static HRESULT WINAPI webbrowser_put_Silent(IWebBrowser2 *iface, VARIANT_BOOL bSilent)
2030 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2031 FIXME("(%p)->(%x)\n", This, bSilent);
2032 return E_NOTIMPL;
2035 static HRESULT WINAPI webbrowser_get_RegisterAsBrowser(IWebBrowser2 *iface,
2036 VARIANT_BOOL *pbRegister)
2038 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2039 FIXME("(%p)->(%p)\n", This, pbRegister);
2040 return E_NOTIMPL;
2043 static HRESULT WINAPI webbrowser_put_RegisterAsBrowser(IWebBrowser2 *iface,
2044 VARIANT_BOOL bRegister)
2046 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2047 FIXME("(%p)->(%x)\n", This, bRegister);
2048 return E_NOTIMPL;
2051 static HRESULT WINAPI webbrowser_get_RegisterAsDropTarget(IWebBrowser2 *iface,
2052 VARIANT_BOOL *pbRegister)
2054 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2055 FIXME("(%p)->(%p)\n", This, pbRegister);
2056 return E_NOTIMPL;
2059 static HRESULT WINAPI webbrowser_put_RegisterAsDropTarget(IWebBrowser2 *iface,
2060 VARIANT_BOOL bRegister)
2062 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2063 FIXME("(%p)->(%x)\n", This, bRegister);
2064 return E_NOTIMPL;
2067 static HRESULT WINAPI webbrowser_get_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL *pbRegister)
2069 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2070 FIXME("(%p)->(%p)\n", This, pbRegister);
2071 return E_NOTIMPL;
2074 static HRESULT WINAPI webbrowser_put_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL bRegister)
2076 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2077 TRACE("(%p)->(%x)\n", This, bRegister);
2078 return E_NOTIMPL;
2081 static HRESULT WINAPI webbrowser_get_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL *Value)
2083 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2084 FIXME("(%p)->(%p)\n", This, Value);
2085 return E_NOTIMPL;
2088 static HRESULT WINAPI webbrowser_put_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
2090 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2091 FIXME("(%p)->(%x)\n", This, Value);
2092 return E_NOTIMPL;
2095 static HRESULT WINAPI webbrowser_get_Resizable(IWebBrowser2 *iface, VARIANT_BOOL *Value)
2097 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2098 FIXME("(%p)->(%p)\n", This, Value);
2099 return E_NOTIMPL;
2102 static HRESULT WINAPI webbrowser_put_Resizable(IWebBrowser2 *iface, VARIANT_BOOL Value)
2104 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2105 FIXME("(%p)->(%x)\n", This, Value);
2106 return E_NOTIMPL;
2109 static const IWebBrowser2Vtbl webbrowser2vtbl =
2111 webbrowser_QueryInterface,
2112 webbrowser_AddRef,
2113 webbrowser_Release,
2114 webbrowser_GetTypeInfoCount,
2115 webbrowser_GetTypeInfo,
2116 webbrowser_GetIDsOfNames,
2117 webbrowser_Invoke,
2118 webbrowser_GoBack,
2119 webbrowser_GoForward,
2120 webbrowser_GoHome,
2121 webbrowser_GoSearch,
2122 webbrowser_Navigate,
2123 webbrowser_Refresh,
2124 webbrowser_Refresh2,
2125 webbrowser_Stop,
2126 webbrowser_get_Application,
2127 webbrowser_get_Parent,
2128 webbrowser_get_Container,
2129 webbrowser_get_Document,
2130 webbrowser_get_TopLevelContainer,
2131 webbrowser_get_Type,
2132 webbrowser_get_Left,
2133 webbrowser_put_Left,
2134 webbrowser_get_Top,
2135 webbrowser_put_Top,
2136 webbrowser_get_Width,
2137 webbrowser_put_Width,
2138 webbrowser_get_Height,
2139 webbrowser_put_Height,
2140 webbrowser_get_LocationName,
2141 webbrowser_get_LocationURL,
2142 webbrowser_get_Busy,
2143 webbrowser_Quit,
2144 webbrowser_ClientToWindow,
2145 webbrowser_PutProperty,
2146 webbrowser_GetProperty,
2147 webbrowser_get_Name,
2148 webbrowser_get_HWND,
2149 webbrowser_get_FullName,
2150 webbrowser_get_Path,
2151 webbrowser_get_Visible,
2152 webbrowser_put_Visible,
2153 webbrowser_get_StatusBar,
2154 webbrowser_put_StatusBar,
2155 webbrowser_get_StatusText,
2156 webbrowser_put_StatusText,
2157 webbrowser_get_ToolBar,
2158 webbrowser_put_ToolBar,
2159 webbrowser_get_MenuBar,
2160 webbrowser_put_MenuBar,
2161 webbrowser_get_FullScreen,
2162 webbrowser_put_FullScreen,
2163 webbrowser_Navigate2,
2164 webbrowser_QueryStatusWB,
2165 webbrowser_ExecWB,
2166 webbrowser_ShowBrowserBar,
2167 webbrowser_get_ReadyState,
2168 webbrowser_get_Offline,
2169 webbrowser_put_Offline,
2170 webbrowser_get_Silent,
2171 webbrowser_put_Silent,
2172 webbrowser_get_RegisterAsBrowser,
2173 webbrowser_put_RegisterAsBrowser,
2174 webbrowser_get_RegisterAsDropTarget,
2175 webbrowser_put_RegisterAsDropTarget,
2176 webbrowser_get_TheaterMode,
2177 webbrowser_put_TheaterMode,
2178 webbrowser_get_AddressBar,
2179 webbrowser_put_AddressBar,
2180 webbrowser_get_Resizable,
2181 webbrowser_put_Resizable
2184 static HRESULT WINAPI serviceprovider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
2186 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2187 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
2190 static ULONG WINAPI serviceprovider_AddRef(IServiceProvider *iface)
2192 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2193 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
2196 static ULONG WINAPI serviceprovider_Release(IServiceProvider *iface)
2198 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2199 return IWebBrowser2_Release(&This->IWebBrowser2_iface);
2202 static HRESULT WINAPI serviceprovider_QueryService(IServiceProvider *iface, REFGUID service,
2203 REFIID riid, void **ppv)
2205 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2207 TRACE("%s %s %p\n", debugstr_guid(service), debugstr_guid(riid), ppv);
2209 if (IsEqualGUID(service, &SID_STopLevelBrowser))
2210 return IShellBrowser_QueryInterface(&This->IShellBrowser_iface, riid, ppv);
2212 WARN("unknown service id %s\n", debugstr_guid(service));
2213 return E_NOTIMPL;
2216 static const IServiceProviderVtbl serviceprovidervtbl =
2218 serviceprovider_QueryInterface,
2219 serviceprovider_AddRef,
2220 serviceprovider_Release,
2221 serviceprovider_QueryService
2224 /* IShellBrowser */
2225 static HRESULT WINAPI shellbrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv)
2227 TRACE("%s %p\n", debugstr_guid(riid), ppv);
2229 *ppv = NULL;
2231 if (IsEqualGUID(&IID_IShellBrowser, riid) ||
2232 IsEqualGUID(&IID_IOleWindow, riid) ||
2233 IsEqualGUID(&IID_IUnknown, riid))
2235 *ppv = iface;
2238 if (*ppv)
2240 IUnknown_AddRef((IUnknown*)*ppv);
2241 return S_OK;
2244 return E_NOINTERFACE;
2247 static ULONG WINAPI shellbrowser_AddRef(IShellBrowser *iface)
2249 struct shellbrowserwindow *This = impl_from_IShellBrowser(iface);
2250 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
2253 static ULONG WINAPI shellbrowser_Release(IShellBrowser *iface)
2255 struct shellbrowserwindow *This = impl_from_IShellBrowser(iface);
2256 return IWebBrowser2_Release(&This->IWebBrowser2_iface);
2259 static HRESULT WINAPI shellbrowser_GetWindow(IShellBrowser *iface, HWND *phwnd)
2261 FIXME("%p\n", phwnd);
2262 return E_NOTIMPL;
2265 static HRESULT WINAPI shellbrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL mode)
2267 FIXME("%d\n", mode);
2268 return E_NOTIMPL;
2271 static HRESULT WINAPI shellbrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared,
2272 OLEMENUGROUPWIDTHS *menuwidths)
2274 FIXME("%p %p\n", hmenuShared, menuwidths);
2275 return E_NOTIMPL;
2278 static HRESULT WINAPI shellbrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared,
2279 HOLEMENU holemenuReserved, HWND hwndActiveObject)
2281 FIXME("%p %p %p\n", hmenuShared, holemenuReserved, hwndActiveObject);
2282 return E_NOTIMPL;
2285 static HRESULT WINAPI shellbrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared)
2287 FIXME("%p\n", hmenuShared);
2288 return E_NOTIMPL;
2291 static HRESULT WINAPI shellbrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR text)
2293 FIXME("%s\n", debugstr_w(text));
2294 return E_NOTIMPL;
2297 static HRESULT WINAPI shellbrowser_EnableModelessSB(IShellBrowser *iface, BOOL enable)
2299 FIXME("%d\n", enable);
2300 return E_NOTIMPL;
2303 static HRESULT WINAPI shellbrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID)
2305 FIXME("%p 0x%x\n", pmsg, wID);
2306 return E_NOTIMPL;
2309 static HRESULT WINAPI shellbrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT flags)
2311 FIXME("%p %x\n", pidl, flags);
2312 return E_NOTIMPL;
2315 static HRESULT WINAPI shellbrowser_GetViewStateStream(IShellBrowser *iface, DWORD mode, IStream **stream)
2317 FIXME("0x%lx %p\n", mode, stream);
2318 return E_NOTIMPL;
2321 static HRESULT WINAPI shellbrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd)
2323 FIXME("%d %p\n", id, phwnd);
2324 return E_NOTIMPL;
2327 static HRESULT WINAPI shellbrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg,
2328 WPARAM wParam, LPARAM lParam, LRESULT *pret)
2330 FIXME("%d %d %Ix %Ix %p\n", id, uMsg, wParam, lParam, pret);
2331 return E_NOTIMPL;
2334 static HRESULT WINAPI shellbrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **view)
2336 TRACE("%p\n", view);
2338 *view = desktopshellbrowserwindow.view;
2339 IShellView_AddRef(*view);
2340 return S_OK;
2343 static HRESULT WINAPI shellbrowser_OnViewWindowActive(IShellBrowser *iface, IShellView *view)
2345 FIXME("%p\n", view);
2346 return E_NOTIMPL;
2349 static HRESULT WINAPI shellbrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB buttons,
2350 UINT count, UINT flags)
2352 FIXME("%p %d 0x%x\n", buttons, count, flags);
2353 return E_NOTIMPL;
2356 static const IShellBrowserVtbl shellbrowservtbl = {
2357 shellbrowser_QueryInterface,
2358 shellbrowser_AddRef,
2359 shellbrowser_Release,
2360 shellbrowser_GetWindow,
2361 shellbrowser_ContextSensitiveHelp,
2362 shellbrowser_InsertMenusSB,
2363 shellbrowser_SetMenuSB,
2364 shellbrowser_RemoveMenusSB,
2365 shellbrowser_SetStatusTextSB,
2366 shellbrowser_EnableModelessSB,
2367 shellbrowser_TranslateAcceleratorSB,
2368 shellbrowser_BrowseObject,
2369 shellbrowser_GetViewStateStream,
2370 shellbrowser_GetControlWindow,
2371 shellbrowser_SendControlMsg,
2372 shellbrowser_QueryActiveShellView,
2373 shellbrowser_OnViewWindowActive,
2374 shellbrowser_SetToolbarItems
2377 static void desktopshellbrowserwindow_init(void)
2379 IShellFolder *folder;
2381 desktopshellbrowserwindow.IWebBrowser2_iface.lpVtbl = &webbrowser2vtbl;
2382 desktopshellbrowserwindow.IServiceProvider_iface.lpVtbl = &serviceprovidervtbl;
2383 desktopshellbrowserwindow.IShellBrowser_iface.lpVtbl = &shellbrowservtbl;
2385 if (FAILED(SHGetDesktopFolder(&folder)))
2386 return;
2388 IShellFolder_CreateViewObject(folder, NULL, &IID_IShellView, (void**)&desktopshellbrowserwindow.view);
2391 static void shellwindows_init(void)
2393 HRESULT hr;
2395 CoInitialize(NULL);
2397 shellwindows.IShellWindows_iface.lpVtbl = &shellwindowsvtbl;
2398 InitializeCriticalSection(&shellwindows.cs);
2399 shellwindows.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": shellwindows.cs");
2401 hr = CoRegisterClassObject(&CLSID_ShellWindows,
2402 (IUnknown*)&shellwindows_classfactory.IClassFactory_iface,
2403 CLSCTX_LOCAL_SERVER,
2404 REGCLS_MULTIPLEUSE,
2405 &shellwindows_classfactory.classreg);
2407 if (FAILED(hr))
2408 WARN("Failed to register ShellWindows object: %08lx\n", hr);