include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / programs / explorer / desktop.c
blobfb59258ad367ad48c9c4b57b2ac0ced41ad7f104
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 OEMRESOURCE
26 #include <windows.h>
27 #include <rpc.h>
28 #include <shlobj.h>
29 #include <shellapi.h>
30 #include <ntuser.h>
31 #include "exdisp.h"
33 #include "wine/debug.h"
34 #include "explorer_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(explorer);
38 #define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769))
39 #define DESKTOP_ALL_ACCESS 0x01ff
41 static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0};
43 static BOOL using_root = TRUE;
45 struct launcher
47 WCHAR *path;
48 HICON icon;
49 WCHAR *title;
52 static WCHAR *desktop_folder;
53 static WCHAR *desktop_folder_public;
55 static int icon_cx, icon_cy, icon_offset_cx, icon_offset_cy;
56 static int title_cx, title_cy, title_offset_cx, title_offset_cy;
57 static int desktop_width, launcher_size, launchers_per_row;
59 static struct launcher **launchers;
60 static unsigned int nb_launchers, nb_allocated;
62 static REFIID tid_ids[] =
64 &IID_IShellWindows,
65 &IID_IWebBrowser2
68 typedef enum
70 IShellWindows_tid,
71 IWebBrowser2_tid,
72 LAST_tid
73 } tid_t;
75 static ITypeLib *typelib;
76 static ITypeInfo *typeinfos[LAST_tid];
78 static HRESULT load_typelib(void)
80 HRESULT hres;
81 ITypeLib *tl;
83 hres = LoadRegTypeLib(&LIBID_SHDocVw, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
84 if (FAILED(hres))
86 ERR("LoadRegTypeLib failed: %08lx\n", hres);
87 return hres;
90 if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
91 ITypeLib_Release(tl);
92 return hres;
95 static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
97 HRESULT hres;
99 if (!typelib) {
100 hres = load_typelib();
101 if (!typelib)
102 return hres;
105 if (!typeinfos[tid]) {
106 ITypeInfo *ti;
108 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
109 if (FAILED(hres)) {
110 ERR("GetTypeInfoOfGuid(%s) failed: %08lx\n", debugstr_guid(tid_ids[tid]), hres);
111 return hres;
114 if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
115 ITypeInfo_Release(ti);
118 *typeinfo = typeinfos[tid];
119 ITypeInfo_AddRef(*typeinfo);
120 return S_OK;
123 static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size)
125 unsigned int new_capacity, max_capacity;
126 void *new_elements;
128 if (count <= *capacity)
129 return TRUE;
131 max_capacity = ~(SIZE_T)0 / size;
132 if (count > max_capacity)
133 return FALSE;
135 new_capacity = max(4, *capacity);
136 while (new_capacity < count && new_capacity <= max_capacity / 2)
137 new_capacity *= 2;
138 if (new_capacity < count)
139 new_capacity = max_capacity;
141 if (!(new_elements = realloc(*elements, new_capacity * size)))
142 return FALSE;
144 *elements = new_elements;
145 *capacity = new_capacity;
147 return TRUE;
150 static LONG cookie_counter;
152 struct window
154 LONG cookie, hwnd;
155 int class;
156 ITEMIDLIST *pidl;
159 struct shellwindows
161 IShellWindows IShellWindows_iface;
162 CRITICAL_SECTION cs;
164 unsigned int count, max;
165 struct window *windows;
168 /* This is not limited to desktop itself, every file browser window that
169 explorer creates supports that. Desktop instance is special in some
170 aspects, for example navigation is not possible, you can't show/hide it,
171 or bring up a menu. CLSID_ShellBrowserWindow class could be used to
172 create instances like that, and they should be registered with
173 IShellWindows as well. */
174 struct shellbrowserwindow
176 IWebBrowser2 IWebBrowser2_iface;
177 IServiceProvider IServiceProvider_iface;
178 IShellBrowser IShellBrowser_iface;
179 IShellView *view;
182 static struct shellwindows shellwindows;
183 static struct shellbrowserwindow desktopshellbrowserwindow;
185 static inline struct shellwindows *impl_from_IShellWindows(IShellWindows *iface)
187 return CONTAINING_RECORD(iface, struct shellwindows, IShellWindows_iface);
190 static inline struct shellbrowserwindow *impl_from_IWebBrowser2(IWebBrowser2 *iface)
192 return CONTAINING_RECORD(iface, struct shellbrowserwindow, IWebBrowser2_iface);
195 static inline struct shellbrowserwindow *impl_from_IServiceProvider(IServiceProvider *iface)
197 return CONTAINING_RECORD(iface, struct shellbrowserwindow, IServiceProvider_iface);
200 static inline struct shellbrowserwindow *impl_from_IShellBrowser(IShellBrowser *iface)
202 return CONTAINING_RECORD(iface, struct shellbrowserwindow, IShellBrowser_iface);
205 static void shellwindows_init(void);
206 static void desktopshellbrowserwindow_init(void);
208 static RECT get_icon_rect( unsigned int index )
210 RECT rect;
211 unsigned int row = index / launchers_per_row;
212 unsigned int col = index % launchers_per_row;
214 rect.left = col * launcher_size + icon_offset_cx;
215 rect.right = rect.left + icon_cx;
216 rect.top = row * launcher_size + icon_offset_cy;
217 rect.bottom = rect.top + icon_cy;
218 return rect;
221 static RECT get_title_rect( unsigned int index )
223 RECT rect;
224 unsigned int row = index / launchers_per_row;
225 unsigned int col = index % launchers_per_row;
227 rect.left = col * launcher_size + title_offset_cx;
228 rect.right = rect.left + title_cx;
229 rect.top = row * launcher_size + title_offset_cy;
230 rect.bottom = rect.top + title_cy;
231 return rect;
234 static const struct launcher *launcher_from_point( int x, int y )
236 RECT icon, title;
237 unsigned int index;
239 if (!nb_launchers) return NULL;
240 index = x / launcher_size + (y / launcher_size) * launchers_per_row;
241 if (index >= nb_launchers) return NULL;
243 icon = get_icon_rect( index );
244 title = get_title_rect( index );
245 if ((x < icon.left || x > icon.right || y < icon.top || y > icon.bottom) &&
246 (x < title.left || x > title.right || y < title.top || y > title.bottom)) return NULL;
247 return launchers[index];
250 static void draw_launchers( HDC hdc, RECT update_rect )
252 COLORREF color = SetTextColor( hdc, RGB(255,255,255) ); /* FIXME: depends on background color */
253 int mode = SetBkMode( hdc, TRANSPARENT );
254 unsigned int i;
255 LOGFONTW lf;
256 HFONT font;
258 SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0 );
259 font = SelectObject( hdc, CreateFontIndirectW( &lf ) );
261 for (i = 0; i < nb_launchers; i++)
263 RECT dummy, icon = get_icon_rect( i ), title = get_title_rect( i );
265 if (IntersectRect( &dummy, &icon, &update_rect ))
266 DrawIconEx( hdc, icon.left, icon.top, launchers[i]->icon, icon_cx, icon_cy,
267 0, 0, DI_DEFAULTSIZE|DI_NORMAL );
269 if (IntersectRect( &dummy, &title, &update_rect ))
270 DrawTextW( hdc, launchers[i]->title, -1, &title,
271 DT_CENTER|DT_WORDBREAK|DT_EDITCONTROL|DT_END_ELLIPSIS );
274 font = SelectObject( hdc, font );
275 DeleteObject( font );
276 SetTextColor( hdc, color );
277 SetBkMode( hdc, mode );
280 static WCHAR *append_path( const WCHAR *path, const WCHAR *filename, int len_filename )
282 int len_path = lstrlenW( path );
283 WCHAR *ret;
285 if (len_filename == -1) len_filename = lstrlenW( filename );
286 if (!(ret = malloc( (len_path + len_filename + 2) * sizeof(WCHAR) ))) return NULL;
287 memcpy( ret, path, len_path * sizeof(WCHAR) );
288 ret[len_path] = '\\';
289 memcpy( ret + len_path + 1, filename, len_filename * sizeof(WCHAR) );
290 ret[len_path + 1 + len_filename] = 0;
291 return ret;
294 static IShellLinkW *load_shelllink( const WCHAR *path )
296 HRESULT hr;
297 IShellLinkW *link;
298 IPersistFile *file;
300 hr = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW,
301 (void **)&link );
302 if (FAILED( hr )) return NULL;
304 hr = IShellLinkW_QueryInterface( link, &IID_IPersistFile, (void **)&file );
305 if (FAILED( hr ))
307 IShellLinkW_Release( link );
308 return NULL;
310 hr = IPersistFile_Load( file, path, 0 );
311 IPersistFile_Release( file );
312 if (FAILED( hr ))
314 IShellLinkW_Release( link );
315 return NULL;
317 return link;
320 static HICON extract_icon( IShellLinkW *link )
322 WCHAR tmp_path[MAX_PATH], icon_path[MAX_PATH], target_path[MAX_PATH];
323 HICON icon = NULL;
324 int index;
326 tmp_path[0] = 0;
327 IShellLinkW_GetIconLocation( link, tmp_path, MAX_PATH, &index );
328 ExpandEnvironmentStringsW( tmp_path, icon_path, MAX_PATH );
330 if (icon_path[0]) ExtractIconExW( icon_path, index, &icon, NULL, 1 );
331 if (!icon)
333 tmp_path[0] = 0;
334 IShellLinkW_GetPath( link, tmp_path, MAX_PATH, NULL, SLGP_RAWPATH );
335 ExpandEnvironmentStringsW( tmp_path, target_path, MAX_PATH );
336 ExtractIconExW( target_path, index, &icon, NULL, 1 );
338 return icon;
341 static WCHAR *build_title( const WCHAR *filename, int len )
343 const WCHAR *p;
344 WCHAR *ret;
346 if (len == -1) len = lstrlenW( filename );
347 for (p = filename + len - 1; p >= filename; p--)
349 if (*p == '.')
351 len = p - filename;
352 break;
355 if (!(ret = malloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
356 memcpy( ret, filename, len * sizeof(WCHAR) );
357 ret[len] = 0;
358 return ret;
361 static BOOL add_launcher( const WCHAR *folder, const WCHAR *filename, int len_filename )
363 struct launcher *launcher;
364 IShellLinkW *link;
366 if (nb_launchers == nb_allocated)
368 unsigned int count = nb_allocated * 2;
369 struct launcher **tmp = realloc( launchers, count * sizeof(*tmp) );
370 if (!tmp) return FALSE;
371 launchers = tmp;
372 nb_allocated = count;
375 if (!(launcher = malloc( sizeof(*launcher) ))) return FALSE;
376 if (!(launcher->path = append_path( folder, filename, len_filename ))) goto error;
377 if (!(link = load_shelllink( launcher->path ))) goto error;
379 launcher->icon = extract_icon( link );
380 launcher->title = build_title( filename, len_filename );
381 IShellLinkW_Release( link );
382 if (launcher->icon && launcher->title)
384 launchers[nb_launchers++] = launcher;
385 return TRUE;
387 free( launcher->title );
388 DestroyIcon( launcher->icon );
390 error:
391 free( launcher->path );
392 free( launcher );
393 return FALSE;
396 static void free_launcher( struct launcher *launcher )
398 DestroyIcon( launcher->icon );
399 free( launcher->path );
400 free( launcher->title );
401 free( launcher );
404 static BOOL remove_launcher( const WCHAR *folder, const WCHAR *filename, int len_filename )
406 UINT i;
407 WCHAR *path;
408 BOOL ret = FALSE;
410 if (!(path = append_path( folder, filename, len_filename ))) return FALSE;
411 for (i = 0; i < nb_launchers; i++)
413 if (!wcsicmp( launchers[i]->path, path ))
415 free_launcher( launchers[i] );
416 if (--nb_launchers)
417 memmove( &launchers[i], &launchers[i + 1], sizeof(launchers[i]) * (nb_launchers - i) );
418 ret = TRUE;
419 break;
422 free( path );
423 return ret;
426 static BOOL get_icon_text_metrics( HWND hwnd, TEXTMETRICW *tm )
428 BOOL ret;
429 HDC hdc;
430 LOGFONTW lf;
431 HFONT hfont;
433 hdc = GetDC( hwnd );
434 SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0 );
435 hfont = SelectObject( hdc, CreateFontIndirectW( &lf ) );
436 ret = GetTextMetricsW( hdc, tm );
437 hfont = SelectObject( hdc, hfont );
438 DeleteObject( hfont );
439 ReleaseDC( hwnd, hdc );
440 return ret;
443 static BOOL process_changes( const WCHAR *folder, char *buf )
445 FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)buf;
446 BOOL ret = FALSE;
448 for (;;)
450 switch (info->Action)
452 case FILE_ACTION_ADDED:
453 case FILE_ACTION_RENAMED_NEW_NAME:
454 if (add_launcher( folder, info->FileName, info->FileNameLength / sizeof(WCHAR) ))
455 ret = TRUE;
456 break;
458 case FILE_ACTION_REMOVED:
459 case FILE_ACTION_RENAMED_OLD_NAME:
460 if (remove_launcher( folder, info->FileName, info->FileNameLength / sizeof(WCHAR) ))
461 ret = TRUE;
462 break;
464 default:
465 WARN( "unexpected action %lu\n", info->Action );
466 break;
468 if (!info->NextEntryOffset) break;
469 info = (FILE_NOTIFY_INFORMATION *)((char *)info + info->NextEntryOffset);
471 return ret;
474 static DWORD CALLBACK watch_desktop_folders( LPVOID param )
476 HWND hwnd = param;
477 HRESULT init = CoInitialize( NULL );
478 HANDLE dir0, dir1, events[2];
479 OVERLAPPED ovl0, ovl1;
480 char *buf0 = NULL, *buf1 = NULL;
481 DWORD count, size = 4096, error = ERROR_OUTOFMEMORY;
482 BOOL ret, redraw;
484 dir0 = CreateFileW( desktop_folder, FILE_LIST_DIRECTORY|SYNCHRONIZE, FILE_SHARE_READ|FILE_SHARE_WRITE,
485 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
486 if (dir0 == INVALID_HANDLE_VALUE) return GetLastError();
487 dir1 = CreateFileW( desktop_folder_public, FILE_LIST_DIRECTORY|SYNCHRONIZE, FILE_SHARE_READ|FILE_SHARE_WRITE,
488 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
489 if (dir1 == INVALID_HANDLE_VALUE)
491 CloseHandle( dir0 );
492 return GetLastError();
494 if (!(ovl0.hEvent = events[0] = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error;
495 if (!(ovl1.hEvent = events[1] = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error;
496 if (!(buf0 = malloc( size ))) goto error;
497 if (!(buf1 = malloc( size ))) goto error;
499 for (;;)
501 ret = ReadDirectoryChangesW( dir0, buf0, size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ovl0, NULL );
502 if (!ret)
504 error = GetLastError();
505 goto error;
507 ret = ReadDirectoryChangesW( dir1, buf1, size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ovl1, NULL );
508 if (!ret)
510 error = GetLastError();
511 goto error;
514 redraw = FALSE;
515 switch ((error = WaitForMultipleObjects( 2, events, FALSE, INFINITE )))
517 case WAIT_OBJECT_0:
518 if (!GetOverlappedResult( dir0, &ovl0, &count, FALSE ) || !count) break;
519 if (process_changes( desktop_folder, buf0 )) redraw = TRUE;
520 break;
522 case WAIT_OBJECT_0 + 1:
523 if (!GetOverlappedResult( dir1, &ovl1, &count, FALSE ) || !count) break;
524 if (process_changes( desktop_folder_public, buf1 )) redraw = TRUE;
525 break;
527 default:
528 goto error;
530 if (redraw) InvalidateRect( hwnd, NULL, TRUE );
533 error:
534 CloseHandle( dir0 );
535 CloseHandle( dir1 );
536 CloseHandle( events[0] );
537 CloseHandle( events[1] );
538 free( buf0 );
539 free( buf1 );
540 if (SUCCEEDED( init )) CoUninitialize();
541 return error;
544 static void add_folder( const WCHAR *folder )
546 static const WCHAR lnkW[] = L"\\*.lnk";
547 int len = lstrlenW( folder ) + lstrlenW( lnkW );
548 WIN32_FIND_DATAW data;
549 HANDLE handle;
550 WCHAR *glob;
552 if (!(glob = malloc( (len + 1) * sizeof(WCHAR) ))) return;
553 lstrcpyW( glob, folder );
554 lstrcatW( glob, lnkW );
556 if ((handle = FindFirstFileW( glob, &data )) != INVALID_HANDLE_VALUE)
558 do { add_launcher( folder, data.cFileName, -1 ); } while (FindNextFileW( handle, &data ));
559 FindClose( handle );
561 free( glob );
564 #define BORDER_SIZE 4
565 #define PADDING_SIZE 4
566 #define TITLE_CHARS 14
568 static void initialize_launchers( HWND hwnd )
570 HRESULT hr, init;
571 TEXTMETRICW tm;
572 int icon_size;
574 if (!(get_icon_text_metrics( hwnd, &tm ))) return;
576 icon_cx = GetSystemMetrics( SM_CXICON );
577 icon_cy = GetSystemMetrics( SM_CYICON );
578 icon_size = max( icon_cx, icon_cy );
579 title_cy = tm.tmHeight * 2;
580 title_cx = max( tm.tmAveCharWidth * TITLE_CHARS, icon_size + PADDING_SIZE + title_cy );
581 launcher_size = BORDER_SIZE + title_cx + BORDER_SIZE;
582 icon_offset_cx = (launcher_size - icon_cx) / 2;
583 icon_offset_cy = BORDER_SIZE + (icon_size - icon_cy) / 2;
584 title_offset_cx = BORDER_SIZE;
585 title_offset_cy = BORDER_SIZE + icon_size + PADDING_SIZE;
586 desktop_width = GetSystemMetrics( SM_CXSCREEN );
587 launchers_per_row = desktop_width / launcher_size;
588 if (!launchers_per_row) launchers_per_row = 1;
590 hr = SHGetKnownFolderPath( &FOLDERID_Desktop, KF_FLAG_CREATE, NULL, &desktop_folder );
591 if (FAILED( hr ))
593 ERR( "Could not get user desktop folder\n" );
594 return;
596 hr = SHGetKnownFolderPath( &FOLDERID_PublicDesktop, KF_FLAG_CREATE, NULL, &desktop_folder_public );
597 if (FAILED( hr ))
599 ERR( "Could not get public desktop folder\n" );
600 CoTaskMemFree( desktop_folder );
601 return;
603 if ((launchers = malloc( 2 * sizeof(launchers[0]) )))
605 nb_allocated = 2;
607 init = CoInitialize( NULL );
608 add_folder( desktop_folder );
609 add_folder( desktop_folder_public );
610 if (SUCCEEDED( init )) CoUninitialize();
612 CreateThread( NULL, 0, watch_desktop_folders, hwnd, 0, NULL );
616 static void wait_named_mutex( const WCHAR *name )
618 HANDLE mutex;
620 mutex = CreateMutexW( NULL, TRUE, name );
621 if (GetLastError() == ERROR_ALREADY_EXISTS)
623 TRACE( "waiting for mutex %s\n", debugstr_w( name ));
624 WaitForSingleObject( mutex, INFINITE );
628 /**************************************************************************
629 * wait_clipboard_mutex
631 * Make sure that there's only one clipboard thread per window station.
633 static BOOL wait_clipboard_mutex(void)
635 static const WCHAR prefix[] = L"__wine_clipboard_";
636 WCHAR buffer[MAX_PATH + ARRAY_SIZE( prefix )];
638 memcpy( buffer, prefix, sizeof(prefix) );
639 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_NAME,
640 buffer + ARRAY_SIZE( prefix ) - 1,
641 sizeof(buffer) - sizeof(prefix), NULL ))
643 ERR( "failed to get winstation name\n" );
644 return FALSE;
646 wait_named_mutex( buffer );
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 HANDLE fullscreen_process;
709 static LRESULT WINAPI display_settings_restorer_wndproc( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
711 TRACE( "got msg %04x wp %Ix lp %Ix\n", message, wp, lp );
713 switch(message)
715 case WM_USER + 0:
716 TRACE( "fullscreen process id %Iu.\n", lp );
718 if (fullscreen_process)
720 CloseHandle( fullscreen_process );
721 fullscreen_process = NULL;
724 if (lp)
725 fullscreen_process = OpenProcess( SYNCHRONIZE, FALSE, lp );
727 return 0;
730 return DefWindowProcW( hwnd, message, wp, lp );
733 static DWORD WINAPI display_settings_restorer_thread( void *param )
735 static const WCHAR *display_settings_restorer_classname = L"__wine_display_settings_restorer";
736 DWORD wait_result;
737 WNDCLASSW class;
738 MSG msg;
740 SetThreadDescription( GetCurrentThread(), L"wine_explorer_display_settings_restorer" );
742 wait_named_mutex( L"__wine_display_settings_restorer_mutex" );
744 memset( &class, 0, sizeof(class) );
745 class.lpfnWndProc = display_settings_restorer_wndproc;
746 class.lpszClassName = display_settings_restorer_classname;
748 if (!RegisterClassW( &class ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
750 ERR( "could not register display settings restorer window class err %lu\n", GetLastError() );
751 return 0;
753 if (!CreateWindowW( display_settings_restorer_classname, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL ))
755 WARN( "failed to create display settings restorer window err %lu\n", GetLastError() );
756 UnregisterClassW( display_settings_restorer_classname, NULL );
757 return 0;
760 for (;;)
762 if (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
764 if (msg.message == WM_QUIT)
765 break;
766 DispatchMessageW( &msg );
767 continue;
770 wait_result = MsgWaitForMultipleObjects( fullscreen_process ? 1 : 0, &fullscreen_process,
771 FALSE, INFINITE, QS_ALLINPUT );
772 if (wait_result == WAIT_FAILED)
773 break;
774 if (!fullscreen_process || wait_result != WAIT_OBJECT_0)
775 continue;
777 TRACE( "restoring display settings on process exit\n" );
779 ChangeDisplaySettingsExW( NULL, NULL, NULL, 0, NULL );
781 CloseHandle( fullscreen_process );
782 fullscreen_process = NULL;
785 return 0;
788 static WNDPROC desktop_orig_wndproc;
790 /* window procedure for the desktop window */
791 static LRESULT WINAPI desktop_wnd_proc( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
793 TRACE( "got msg %04x wp %Ix lp %Ix\n", message, wp, lp );
795 switch(message)
797 case WM_SYSCOMMAND:
798 switch(wp & 0xfff0)
800 case SC_CLOSE:
801 ExitWindows( 0, 0 );
802 return 0;
804 break;
806 case WM_CLOSE:
807 PostQuitMessage(0);
808 return 0;
810 case WM_SETCURSOR:
811 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
813 case WM_NCHITTEST:
814 return HTCLIENT;
816 case WM_ERASEBKGND:
817 if (!using_root) PaintDesktop( (HDC)wp );
818 return TRUE;
820 case WM_SETTINGCHANGE:
821 if (wp == SPI_SETDESKWALLPAPER)
822 SystemParametersInfoW( SPI_SETDESKWALLPAPER, 0, NULL, FALSE );
823 return 0;
825 case WM_PARENTNOTIFY:
826 handle_parent_notify( (HWND)lp, wp );
827 return 0;
829 case WM_LBUTTONDBLCLK:
830 if (!using_root)
832 const struct launcher *launcher = launcher_from_point( (short)LOWORD(lp), (short)HIWORD(lp) );
833 if (launcher) ShellExecuteW( NULL, L"open", launcher->path, NULL, NULL, 0 );
835 return 0;
837 case WM_PAINT:
839 PAINTSTRUCT ps;
840 BeginPaint( hwnd, &ps );
841 if (!using_root)
843 if (ps.fErase) PaintDesktop( ps.hdc );
844 draw_launchers( ps.hdc, ps.rcPaint );
846 EndPaint( hwnd, &ps );
848 return 0;
851 return desktop_orig_wndproc( hwnd, message, wp, lp );
854 /* parse the desktop size specification */
855 static BOOL parse_size( const WCHAR *size, unsigned int *width, unsigned int *height )
857 WCHAR *end;
859 *width = wcstoul( size, &end, 10 );
860 if (end == size) return FALSE;
861 if (*end != 'x') return FALSE;
862 size = end + 1;
863 *height = wcstoul( size, &end, 10 );
864 return !*end;
867 /* retrieve the desktop name to use if not specified on the command line */
868 static const WCHAR *get_default_desktop_name(void)
870 static WCHAR buffer[MAX_PATH];
871 DWORD size = sizeof(buffer);
872 HDESK desk = GetThreadDesktop( GetCurrentThreadId() );
873 WCHAR *ret = NULL;
874 HKEY hkey;
876 if (desk && GetUserObjectInformationW( desk, UOI_NAME, buffer, ARRAY_SIZE( buffer ), NULL ))
878 if (wcsicmp( buffer, L"Default" )) return buffer;
881 /* @@ Wine registry key: HKCU\Software\Wine\Explorer */
882 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer", &hkey ))
884 if (!RegQueryValueExW( hkey, L"Desktop", 0, NULL, (LPBYTE)buffer, &size ) && *buffer) ret = buffer;
885 RegCloseKey( hkey );
887 return ret;
890 /* retrieve the default desktop size from the registry */
891 static BOOL get_default_desktop_size( const WCHAR *name, unsigned int *width, unsigned int *height )
893 HKEY hkey;
894 WCHAR buffer[64];
895 DWORD size = sizeof(buffer);
896 BOOL found = FALSE;
898 *width = 800;
899 *height = 600;
901 /* @@ Wine registry key: HKCU\Software\Wine\Explorer\Desktops */
902 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer\\Desktops", &hkey ))
904 if (!RegQueryValueExW( hkey, name, 0, NULL, (LPBYTE)buffer, &size ))
906 found = TRUE;
907 if (!parse_size( buffer, width, height )) *width = *height = 0;
909 RegCloseKey( hkey );
911 return found;
914 static BOOL get_default_enable_shell( const WCHAR *name )
916 HKEY hkey;
917 BOOL found = FALSE;
918 BOOL result;
919 DWORD size = sizeof(result);
921 /* @@ Wine registry key: HKCU\Software\Wine\Explorer\Desktops */
922 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer\\Desktops", &hkey ))
924 if (!RegGetValueW( hkey, name, L"EnableShell", RRF_RT_REG_DWORD, NULL, &result, &size ))
925 found = TRUE;
926 RegCloseKey( hkey );
928 /* Default off, except for the magic desktop name "shell" */
929 if (!found) result = (lstrcmpiW( name, L"shell" ) == 0);
930 return result;
933 static BOOL get_default_show_systray( const WCHAR *name )
935 HKEY hkey;
936 BOOL found = FALSE;
937 BOOL result;
938 DWORD size = sizeof(result);
940 /* @@ Wine registry key: HKCU\Software\Wine\Explorer\Desktops */
941 if (name && !RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer\\Desktops", &hkey ))
943 if (!RegGetValueW( hkey, name, L"ShowSystray", RRF_RT_REG_DWORD, NULL, &result, &size ))
944 found = TRUE;
945 RegCloseKey( hkey );
948 /* Try again with a global Explorer setting */
949 /* @@ Wine registry key: HKCU\Software\Wine\Explorer */
950 if (!found && !RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer", &hkey ))
952 if (!RegGetValueW( hkey, NULL, L"ShowSystray", RRF_RT_REG_DWORD, NULL, &result, &size ))
953 found = TRUE;
954 RegCloseKey( hkey );
957 /* Default on */
958 if (!found) result = TRUE;
959 return result;
962 static void load_graphics_driver( const WCHAR *driver, GUID *guid )
964 static const WCHAR device_keyW[] = L"System\\CurrentControlSet\\Control\\Video\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\0000";
966 WCHAR buffer[MAX_PATH], libname[32], *name, *next;
967 WCHAR key[ARRAY_SIZE( device_keyW ) + 39];
968 BOOL null_driver = FALSE;
969 HMODULE module = 0;
970 HKEY hkey;
971 char error[80];
973 if (!driver)
975 lstrcpyW( buffer, default_driver );
977 /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
978 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Drivers", &hkey ))
980 DWORD count = sizeof(buffer);
981 RegQueryValueExW( hkey, L"Graphics", 0, NULL, (LPBYTE)buffer, &count );
982 RegCloseKey( hkey );
985 else lstrcpynW( buffer, driver, ARRAY_SIZE( buffer ));
987 name = buffer;
988 while (name)
990 next = wcschr( name, ',' );
991 if (next) *next++ = 0;
993 if (!wcscmp( name, L"null" ))
995 memset( guid, 0, sizeof(*guid) );
996 TRACE( "display %s using null driver\n", debugstr_guid(guid) );
997 wcscpy( libname, L"null" );
998 null_driver = TRUE;
999 break;
1002 swprintf( libname, ARRAY_SIZE( libname ), L"wine%s.drv", name );
1003 if ((module = LoadLibraryW( libname )) != 0) break;
1004 switch (GetLastError())
1006 case ERROR_MOD_NOT_FOUND:
1007 strcpy( error, "The graphics driver is missing. Check your build!" );
1008 break;
1009 case ERROR_DLL_INIT_FAILED:
1010 strcpy( error, "Make sure that your X server is running and that $DISPLAY is set correctly." );
1011 break;
1012 default:
1013 sprintf( error, "Unknown error (%lu).", GetLastError() );
1014 break;
1016 name = next;
1019 TRACE( "display %s driver %s\n", debugstr_guid(guid), debugstr_w(libname) );
1021 swprintf( key, ARRAY_SIZE(key), device_keyW, guid->Data1, guid->Data2, guid->Data3,
1022 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
1023 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
1025 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, key, 0, NULL,
1026 REG_OPTION_VOLATILE, KEY_SET_VALUE, NULL, &hkey, NULL ))
1028 if (module || null_driver)
1029 RegSetValueExW( hkey, L"GraphicsDriver", 0, REG_SZ,
1030 (BYTE *)libname, (lstrlenW(libname) + 1) * sizeof(WCHAR) );
1031 else
1032 RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 );
1033 RegCloseKey( hkey );
1037 static const char *debugstr_devmodew( const DEVMODEW *devmode )
1039 char position[32] = {0};
1041 if (devmode->dmFields & DM_POSITION)
1043 snprintf( position, sizeof(position), " at (%d,%d)",
1044 (int)devmode->dmPosition.x, (int)devmode->dmPosition.y );
1047 return wine_dbg_sprintf( "%ux%u %ubits %uHz rotated %u degrees%s",
1048 (unsigned int)devmode->dmPelsWidth,
1049 (unsigned int)devmode->dmPelsHeight,
1050 (unsigned int)devmode->dmBitsPerPel,
1051 (unsigned int)devmode->dmDisplayFrequency,
1052 (unsigned int)devmode->dmDisplayOrientation * 90,
1053 position );
1056 static void initialize_display_settings( unsigned int width, unsigned int height )
1058 DISPLAY_DEVICEW device = {.cb = sizeof(DISPLAY_DEVICEW)};
1059 DWORD i = 0, flags = CDS_GLOBAL | CDS_UPDATEREGISTRY;
1060 HANDLE thread;
1062 /* Store current display mode in the registry */
1063 while (EnumDisplayDevicesW( NULL, i++, &device, 0 ))
1065 DEVMODEW devmode = {.dmSize = sizeof(DEVMODEW)};
1067 if (!EnumDisplaySettingsExW( device.DeviceName, ENUM_CURRENT_SETTINGS, &devmode, 0))
1069 ERR( "Failed to query current display settings for %s.\n", debugstr_w( device.DeviceName ) );
1070 continue;
1073 TRACE( "Device %s current display mode %s.\n", debugstr_w( device.DeviceName ), debugstr_devmodew( &devmode ) );
1075 if (ChangeDisplaySettingsExW( device.DeviceName, &devmode, 0, flags | CDS_NORESET, 0 ))
1076 ERR( "Failed to initialize registry display settings for %s.\n", debugstr_w( device.DeviceName ) );
1079 if (!using_root)
1081 DEVMODEW devmode =
1083 .dmSize = sizeof(DEVMODEW),
1084 .dmFields = DM_PELSWIDTH | DM_PELSHEIGHT,
1085 .dmPelsWidth = width,
1086 .dmPelsHeight = height,
1089 /* in virtual desktop mode, set the primary display settings to match desktop size */
1090 if (ChangeDisplaySettingsExW( NULL, &devmode, 0, flags, NULL ))
1091 ERR( "Failed to set primary display settings.\n" );
1094 thread = CreateThread( NULL, 0, display_settings_restorer_thread, NULL, 0, NULL );
1095 if (thread) CloseHandle( thread );
1098 static void set_desktop_window_title( HWND hwnd, const WCHAR *name )
1100 static const WCHAR desktop_nameW[] = L"Wine desktop";
1101 static const WCHAR desktop_name_separatorW[] = L" - ";
1102 WCHAR *window_titleW = NULL;
1103 int window_title_len;
1105 if (!name[0])
1107 SetWindowTextW( hwnd, desktop_nameW );
1108 return;
1111 window_title_len = lstrlenW(name) * sizeof(WCHAR)
1112 + sizeof(desktop_name_separatorW)
1113 + sizeof(desktop_nameW);
1114 window_titleW = malloc( window_title_len );
1115 if (!window_titleW)
1117 SetWindowTextW( hwnd, desktop_nameW );
1118 return;
1121 lstrcpyW( window_titleW, name );
1122 lstrcatW( window_titleW, desktop_name_separatorW );
1123 lstrcatW( window_titleW, desktop_nameW );
1125 SetWindowTextW( hwnd, window_titleW );
1126 free( window_titleW );
1129 static inline BOOL is_whitespace(WCHAR c)
1131 return c == ' ' || c == '\t';
1134 /* main desktop management function */
1135 void manage_desktop( WCHAR *arg )
1137 HDESK desktop = 0;
1138 GUID guid;
1139 MSG msg;
1140 HWND hwnd;
1141 unsigned int width, height;
1142 WCHAR *cmdline = NULL, *driver = NULL;
1143 WCHAR *p = arg;
1144 const WCHAR *name = NULL;
1145 BOOL enable_shell = FALSE, show_systray = TRUE;
1146 void (WINAPI *pShellDDEInit)( BOOL ) = NULL;
1147 HMODULE shell32;
1148 HANDLE thread;
1149 DWORD id;
1151 /* get the rest of the command line (if any) */
1152 while (*p && !is_whitespace(*p)) p++;
1153 if (*p)
1155 *p++ = 0;
1156 while (*p && is_whitespace(*p)) p++;
1157 if (*p) cmdline = p;
1160 /* parse the desktop option */
1161 /* the option is of the form /desktop=name[,widthxheight[,driver]] */
1162 if ((arg[0] == '=' || arg[0] == ',') && arg[1] && arg[1] != ',')
1164 arg++;
1165 name = arg;
1166 if ((p = wcschr( arg, ',' )))
1168 *p++ = 0;
1169 if ((driver = wcschr( p, ',' ))) *driver++ = 0;
1171 if (!p || !parse_size( p, &width, &height ))
1172 get_default_desktop_size( name, &width, &height );
1174 else if ((name = get_default_desktop_name()))
1176 if (!get_default_desktop_size( name, &width, &height )) width = height = 0;
1179 if (name) enable_shell = get_default_enable_shell( name );
1180 show_systray = get_default_show_systray( name );
1182 UuidCreate( &guid );
1183 TRACE( "display guid %s\n", debugstr_guid(&guid) );
1184 load_graphics_driver( driver, &guid );
1186 if (name && width && height)
1188 DEVMODEW devmode = {.dmPelsWidth = width, .dmPelsHeight = height};
1189 /* magic: desktop "root" means use the root window */
1190 if ((using_root = !wcsicmp( name, L"root" ))) desktop = CreateDesktopW( name, NULL, NULL, DF_WINE_ROOT_DESKTOP, DESKTOP_ALL_ACCESS, NULL );
1191 else desktop = CreateDesktopW( name, NULL, &devmode, DF_WINE_VIRTUAL_DESKTOP, DESKTOP_ALL_ACCESS, NULL );
1192 if (!desktop)
1194 ERR( "failed to create desktop %s error %ld\n", debugstr_w(name), GetLastError() );
1195 ExitProcess( 1 );
1197 SetThreadDesktop( desktop );
1200 /* create the desktop window */
1201 hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL,
1202 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, &guid );
1204 if (hwnd)
1206 /* create the HWND_MESSAGE parent */
1207 CreateWindowExW( 0, L"Message", NULL, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
1208 0, 0, 100, 100, 0, 0, 0, NULL );
1210 desktop_orig_wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC,
1211 (LONG_PTR)desktop_wnd_proc );
1212 SendMessageW( hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW( 0, MAKEINTRESOURCEW(OIC_WINLOGO)));
1213 if (name) set_desktop_window_title( hwnd, name );
1214 SetWindowPos( hwnd, 0, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
1215 GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN),
1216 SWP_SHOWWINDOW );
1217 thread = CreateThread( NULL, 0, clipboard_thread, NULL, 0, &id );
1218 if (thread) CloseHandle( thread );
1219 SystemParametersInfoW( SPI_SETDESKWALLPAPER, 0, NULL, FALSE );
1220 ClipCursor( NULL );
1221 initialize_display_settings( width, height );
1222 initialize_appbar();
1224 if (using_root) enable_shell = FALSE;
1226 initialize_systray( using_root, enable_shell, show_systray );
1227 if (!using_root) initialize_launchers( hwnd );
1229 if ((shell32 = LoadLibraryW( L"shell32.dll" )) &&
1230 (pShellDDEInit = (void *)GetProcAddress( shell32, (LPCSTR)188)))
1232 pShellDDEInit( TRUE );
1236 /* if we have a command line, execute it */
1237 if (cmdline)
1239 STARTUPINFOW si;
1240 PROCESS_INFORMATION pi;
1242 memset( &si, 0, sizeof(si) );
1243 si.cb = sizeof(si);
1244 TRACE( "starting %s\n", debugstr_w(cmdline) );
1245 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
1247 CloseHandle( pi.hThread );
1248 CloseHandle( pi.hProcess );
1252 desktopshellbrowserwindow_init();
1253 shellwindows_init();
1255 /* run the desktop message loop */
1256 if (hwnd)
1258 TRACE( "desktop message loop starting on hwnd %p\n", hwnd );
1259 while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
1260 TRACE( "desktop message loop exiting for hwnd %p\n", hwnd );
1263 if (pShellDDEInit) pShellDDEInit( FALSE );
1265 ExitProcess( 0 );
1268 /* IShellWindows implementation */
1269 static HRESULT WINAPI shellwindows_QueryInterface(IShellWindows *iface, REFIID riid, void **ppvObject)
1271 struct shellwindows *This = impl_from_IShellWindows(iface);
1273 TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
1275 if (IsEqualGUID(riid, &IID_IShellWindows) ||
1276 IsEqualGUID(riid, &IID_IDispatch) ||
1277 IsEqualGUID(riid, &IID_IUnknown))
1279 *ppvObject = &This->IShellWindows_iface;
1281 else
1283 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1284 *ppvObject = NULL;
1287 if (*ppvObject)
1289 IUnknown_AddRef((IUnknown*)*ppvObject);
1290 return S_OK;
1293 return E_NOINTERFACE;
1296 static ULONG WINAPI shellwindows_AddRef(IShellWindows *iface)
1298 return 2;
1301 static ULONG WINAPI shellwindows_Release(IShellWindows *iface)
1303 return 1;
1306 static HRESULT WINAPI shellwindows_GetTypeInfoCount(IShellWindows *iface, UINT *pctinfo)
1308 TRACE("%p\n", pctinfo);
1309 *pctinfo = 1;
1310 return S_OK;
1313 static HRESULT WINAPI shellwindows_GetTypeInfo(IShellWindows *iface,
1314 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1316 TRACE("%d %ld %p\n", iTInfo, lcid, ppTInfo);
1317 return get_typeinfo(IShellWindows_tid, ppTInfo);
1320 static HRESULT WINAPI shellwindows_GetIDsOfNames(IShellWindows *iface,
1321 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
1322 DISPID *rgDispId)
1324 ITypeInfo *typeinfo;
1325 HRESULT hr;
1327 TRACE("%s %p %d %ld %p\n", debugstr_guid(riid), rgszNames, cNames,
1328 lcid, rgDispId);
1330 if (!rgszNames || cNames == 0 || !rgDispId)
1331 return E_INVALIDARG;
1333 hr = get_typeinfo(IShellWindows_tid, &typeinfo);
1334 if (SUCCEEDED(hr))
1336 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1337 ITypeInfo_Release(typeinfo);
1340 return hr;
1343 static HRESULT WINAPI shellwindows_Invoke(IShellWindows *iface,
1344 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
1345 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1346 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1348 ITypeInfo *typeinfo;
1349 HRESULT hr;
1351 TRACE("%ld %s %ld %08x %p %p %p %p\n", dispIdMember, debugstr_guid(riid),
1352 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1354 hr = get_typeinfo(IShellWindows_tid, &typeinfo);
1355 if (SUCCEEDED(hr))
1357 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
1358 pDispParams, pVarResult, pExcepInfo, puArgErr);
1359 ITypeInfo_Release(typeinfo);
1362 return hr;
1365 static HRESULT WINAPI shellwindows_get_Count(IShellWindows *iface, LONG *count)
1367 FIXME("%p\n", count);
1368 return E_NOTIMPL;
1371 static HRESULT WINAPI shellwindows_Item(IShellWindows *iface, VARIANT index,
1372 IDispatch **folder)
1374 FIXME("%s %p\n", debugstr_variant(&index), folder);
1375 return E_NOTIMPL;
1378 static HRESULT WINAPI shellwindows__NewEnum(IShellWindows *iface, IUnknown **ppunk)
1380 FIXME("%p\n", ppunk);
1381 return E_NOTIMPL;
1384 static HRESULT WINAPI shellwindows_Register(IShellWindows *iface,
1385 IDispatch *disp, LONG hwnd, int class, LONG *cookie)
1387 struct shellwindows *sw = impl_from_IShellWindows(iface);
1388 struct window *window;
1390 TRACE("iface %p, disp %p, hwnd %#lx, class %u, cookie %p.\n", iface, disp, hwnd, class, cookie);
1392 if (!hwnd)
1393 return E_POINTER;
1395 if (disp)
1396 FIXME("Ignoring IDispatch %p.\n", disp);
1398 EnterCriticalSection(&sw->cs);
1400 if (!array_reserve((void **)&sw->windows, &sw->max, sw->count + 1, sizeof(*sw->windows)))
1402 LeaveCriticalSection(&sw->cs);
1403 return E_OUTOFMEMORY;
1406 window = &sw->windows[sw->count++];
1407 window->hwnd = hwnd;
1408 window->class = class;
1409 *cookie = window->cookie = ++cookie_counter;
1410 window->pidl = NULL;
1412 LeaveCriticalSection(&sw->cs);
1413 return S_OK;
1416 static HRESULT WINAPI shellwindows_RegisterPending(IShellWindows *iface,
1417 LONG threadid, VARIANT *loc, VARIANT *root, int class, LONG *cookie)
1419 FIXME("0x%lx %s %s 0x%x %p\n", threadid, debugstr_variant(loc), debugstr_variant(root),
1420 class, cookie);
1421 return E_NOTIMPL;
1424 static HRESULT WINAPI shellwindows_Revoke(IShellWindows *iface, LONG cookie)
1426 struct shellwindows *sw = impl_from_IShellWindows(iface);
1427 unsigned int i;
1429 TRACE("iface %p, cookie %lu.\n", iface, cookie);
1431 EnterCriticalSection(&sw->cs);
1433 for (i = 0; i < sw->count; ++i)
1435 if (sw->windows[i].cookie == cookie)
1437 --sw->count;
1438 memmove(&sw->windows[i], &sw->windows[i + 1], (sw->count - i) * sizeof(*sw->windows));
1439 LeaveCriticalSection(&sw->cs);
1440 return S_OK;
1444 LeaveCriticalSection(&sw->cs);
1445 return S_FALSE;
1448 static HRESULT WINAPI shellwindows_OnNavigate(IShellWindows *iface, LONG cookie, VARIANT *location)
1450 struct shellwindows *sw = impl_from_IShellWindows(iface);
1451 unsigned int i;
1453 TRACE("iface %p, cookie %lu, location %s.\n", iface, cookie, debugstr_variant(location));
1455 if (V_VT(location) != (VT_ARRAY | VT_UI1))
1457 FIXME("Unexpected variant type %s.\n", debugstr_vt(V_VT(location)));
1458 return E_NOTIMPL;
1461 EnterCriticalSection(&sw->cs);
1463 for (i = 0; i < sw->count; ++i)
1465 if (sw->windows[i].cookie == cookie)
1467 size_t len = V_ARRAY(location)->rgsabound[0].cElements;
1468 if (!(sw->windows[i].pidl = realloc(sw->windows[i].pidl, len)))
1470 LeaveCriticalSection(&sw->cs);
1471 return E_OUTOFMEMORY;
1473 memcpy(sw->windows[i].pidl, V_ARRAY(location)->pvData, len);
1475 LeaveCriticalSection(&sw->cs);
1476 return S_OK;
1480 LeaveCriticalSection(&sw->cs);
1481 return E_INVALIDARG;
1484 static HRESULT WINAPI shellwindows_OnActivated(IShellWindows *iface, LONG cookie, VARIANT_BOOL active)
1486 FIXME("0x%lx 0x%x\n", cookie, active);
1487 return E_NOTIMPL;
1490 static HRESULT WINAPI shellwindows_FindWindowSW(IShellWindows *iface, VARIANT *location,
1491 VARIANT *root, int class, LONG *hwnd, int options, IDispatch **disp)
1493 struct shellwindows *sw = impl_from_IShellWindows(iface);
1494 unsigned int i;
1496 TRACE("iface %p, location %p, root %p, class %#x, hwnd %p, options %#x, disp %p.\n",
1497 iface, location, root, class, hwnd, options, disp);
1499 if (class == SWC_DESKTOP)
1501 *hwnd = (LONG)(LONG_PTR)GetDesktopWindow();
1502 if (options & SWFO_NEEDDISPATCH)
1504 *disp = (IDispatch *)&desktopshellbrowserwindow.IWebBrowser2_iface;
1505 IDispatch_AddRef(*disp);
1507 return S_OK;
1510 if (options)
1511 FIXME("Ignoring options %#x.\n", options);
1513 if (V_VT(location) != (VT_ARRAY | VT_UI1))
1515 FIXME("Unexpected variant type %s.\n", debugstr_vt(V_VT(location)));
1516 return E_NOTIMPL;
1519 EnterCriticalSection(&sw->cs);
1521 for (i = 0; i < sw->count; ++i)
1523 if (sw->windows[i].class == class && ILIsEqual(V_ARRAY(location)->pvData, sw->windows[i].pidl))
1525 *hwnd = sw->windows[i].hwnd;
1526 LeaveCriticalSection(&sw->cs);
1527 return S_OK;
1531 LeaveCriticalSection(&sw->cs);
1532 return S_FALSE;
1535 static HRESULT WINAPI shellwindows_OnCreated(IShellWindows *iface, LONG cookie, IUnknown *punk)
1537 FIXME("0x%lx %p\n", cookie, punk);
1538 return E_NOTIMPL;
1541 static HRESULT WINAPI shellwindows_ProcessAttachDetach(IShellWindows *iface, VARIANT_BOOL attach)
1543 FIXME("0x%x\n", attach);
1544 return E_NOTIMPL;
1547 static const IShellWindowsVtbl shellwindowsvtbl =
1549 shellwindows_QueryInterface,
1550 shellwindows_AddRef,
1551 shellwindows_Release,
1552 shellwindows_GetTypeInfoCount,
1553 shellwindows_GetTypeInfo,
1554 shellwindows_GetIDsOfNames,
1555 shellwindows_Invoke,
1556 shellwindows_get_Count,
1557 shellwindows_Item,
1558 shellwindows__NewEnum,
1559 shellwindows_Register,
1560 shellwindows_RegisterPending,
1561 shellwindows_Revoke,
1562 shellwindows_OnNavigate,
1563 shellwindows_OnActivated,
1564 shellwindows_FindWindowSW,
1565 shellwindows_OnCreated,
1566 shellwindows_ProcessAttachDetach
1569 struct shellwindows_classfactory
1571 IClassFactory IClassFactory_iface;
1572 DWORD classreg;
1575 static inline struct shellwindows_classfactory *impl_from_IClassFactory(IClassFactory *iface)
1577 return CONTAINING_RECORD(iface, struct shellwindows_classfactory, IClassFactory_iface);
1580 static HRESULT WINAPI swclassfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppvObject)
1582 struct shellwindows_classfactory *This = impl_from_IClassFactory(iface);
1584 TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
1586 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IClassFactory))
1588 *ppvObject = &This->IClassFactory_iface;
1590 else
1592 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1593 *ppvObject = NULL;
1596 if (*ppvObject)
1598 IUnknown_AddRef((IUnknown*)*ppvObject);
1599 return S_OK;
1602 return E_NOINTERFACE;
1605 static ULONG WINAPI swclassfactory_AddRef(IClassFactory *iface)
1607 return 2;
1610 static ULONG WINAPI swclassfactory_Release(IClassFactory *iface)
1612 return 1;
1615 static HRESULT WINAPI swclassfactory_CreateInstance(IClassFactory *iface,
1616 IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
1618 TRACE("%p %s %p\n", pUnkOuter, debugstr_guid(riid), ppvObject);
1619 return IShellWindows_QueryInterface(&shellwindows.IShellWindows_iface, riid, ppvObject);
1622 static HRESULT WINAPI swclassfactory_LockServer(IClassFactory *iface, BOOL lock)
1624 TRACE("%u\n", lock);
1625 return E_NOTIMPL;
1628 static const IClassFactoryVtbl swclassfactoryvtbl =
1630 swclassfactory_QueryInterface,
1631 swclassfactory_AddRef,
1632 swclassfactory_Release,
1633 swclassfactory_CreateInstance,
1634 swclassfactory_LockServer
1637 static struct shellwindows_classfactory shellwindows_classfactory = { { &swclassfactoryvtbl } };
1639 static HRESULT WINAPI webbrowser_QueryInterface(IWebBrowser2 *iface, REFIID riid, void **ppv)
1641 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1643 *ppv = NULL;
1645 if (IsEqualGUID(&IID_IWebBrowser2, riid) ||
1646 IsEqualGUID(&IID_IWebBrowserApp, riid) ||
1647 IsEqualGUID(&IID_IWebBrowser, riid) ||
1648 IsEqualGUID(&IID_IDispatch, riid) ||
1649 IsEqualGUID(&IID_IUnknown, riid))
1651 *ppv = &This->IWebBrowser2_iface;
1653 else if (IsEqualGUID(&IID_IServiceProvider, riid))
1655 *ppv = &This->IServiceProvider_iface;
1658 if (*ppv)
1660 IUnknown_AddRef((IUnknown*)*ppv);
1661 return S_OK;
1664 FIXME("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv);
1665 return E_NOINTERFACE;
1668 static ULONG WINAPI webbrowser_AddRef(IWebBrowser2 *iface)
1670 return 2;
1673 static ULONG WINAPI webbrowser_Release(IWebBrowser2 *iface)
1675 return 1;
1678 /* IDispatch methods */
1679 static HRESULT WINAPI webbrowser_GetTypeInfoCount(IWebBrowser2 *iface, UINT *pctinfo)
1681 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1682 TRACE("(%p)->(%p)\n", This, pctinfo);
1683 *pctinfo = 1;
1684 return S_OK;
1687 static HRESULT WINAPI webbrowser_GetTypeInfo(IWebBrowser2 *iface, UINT iTInfo, LCID lcid,
1688 LPTYPEINFO *ppTInfo)
1690 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1691 TRACE("(%p)->(%d %ld %p)\n", This, iTInfo, lcid, ppTInfo);
1692 return get_typeinfo(IWebBrowser2_tid, ppTInfo);
1695 static HRESULT WINAPI webbrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid,
1696 LPOLESTR *rgszNames, UINT cNames,
1697 LCID lcid, DISPID *rgDispId)
1699 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1700 ITypeInfo *typeinfo;
1701 HRESULT hr;
1703 TRACE("(%p)->(%s %p %d %ld %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1704 lcid, rgDispId);
1706 if(!rgszNames || cNames == 0 || !rgDispId)
1707 return E_INVALIDARG;
1709 hr = get_typeinfo(IWebBrowser2_tid, &typeinfo);
1710 if (SUCCEEDED(hr))
1712 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1713 ITypeInfo_Release(typeinfo);
1716 return hr;
1719 static HRESULT WINAPI webbrowser_Invoke(IWebBrowser2 *iface, DISPID dispIdMember,
1720 REFIID riid, LCID lcid, WORD wFlags,
1721 DISPPARAMS *pDispParams, VARIANT *pVarResult,
1722 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1724 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1725 ITypeInfo *typeinfo;
1726 HRESULT hr;
1728 TRACE("(%p)->(%ld %s %ld %08x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1729 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1731 hr = get_typeinfo(IWebBrowser2_tid, &typeinfo);
1732 if (SUCCEEDED(hr))
1734 hr = ITypeInfo_Invoke(typeinfo, &This->IWebBrowser2_iface, dispIdMember, wFlags,
1735 pDispParams, pVarResult, pExcepInfo, puArgErr);
1736 ITypeInfo_Release(typeinfo);
1739 return hr;
1742 /* IWebBrowser methods */
1743 static HRESULT WINAPI webbrowser_GoBack(IWebBrowser2 *iface)
1745 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1746 FIXME("(%p): stub\n", This);
1747 return E_NOTIMPL;
1750 static HRESULT WINAPI webbrowser_GoForward(IWebBrowser2 *iface)
1752 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1753 FIXME("(%p): stub\n", This);
1754 return E_NOTIMPL;
1757 static HRESULT WINAPI webbrowser_GoHome(IWebBrowser2 *iface)
1759 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1760 FIXME("(%p): stub\n", This);
1761 return E_NOTIMPL;
1764 static HRESULT WINAPI webbrowser_GoSearch(IWebBrowser2 *iface)
1766 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1767 FIXME("(%p)\n", This);
1768 return E_NOTIMPL;
1771 static HRESULT WINAPI webbrowser_Navigate(IWebBrowser2 *iface, BSTR szUrl,
1772 VARIANT *Flags, VARIANT *TargetFrameName,
1773 VARIANT *PostData, VARIANT *Headers)
1775 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1776 FIXME("(%p)->(%s %s %s %s %s): stub\n", This, debugstr_w(szUrl), debugstr_variant(Flags),
1777 debugstr_variant(TargetFrameName), debugstr_variant(PostData),
1778 debugstr_variant(Headers));
1779 return E_NOTIMPL;
1782 static HRESULT WINAPI webbrowser_Refresh(IWebBrowser2 *iface)
1784 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1785 FIXME("(%p): stub\n", This);
1786 return E_NOTIMPL;
1789 static HRESULT WINAPI webbrowser_Refresh2(IWebBrowser2 *iface, VARIANT *Level)
1791 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1792 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(Level));
1793 return E_NOTIMPL;
1796 static HRESULT WINAPI webbrowser_Stop(IWebBrowser2 *iface)
1798 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1799 FIXME("(%p): stub\n", This);
1800 return E_NOTIMPL;
1803 static HRESULT WINAPI webbrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp)
1805 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1807 TRACE("(%p)->(%p)\n", This, ppDisp);
1809 *ppDisp = (IDispatch*)iface;
1810 IDispatch_AddRef(*ppDisp);
1812 return S_OK;
1815 static HRESULT WINAPI webbrowser_get_Parent(IWebBrowser2 *iface, IDispatch **ppDisp)
1817 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1818 FIXME("(%p)->(%p)\n", This, ppDisp);
1819 return E_NOTIMPL;
1822 static HRESULT WINAPI webbrowser_get_Container(IWebBrowser2 *iface, IDispatch **ppDisp)
1824 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1825 FIXME("(%p)->(%p)\n", This, ppDisp);
1826 return E_NOTIMPL;
1829 static HRESULT WINAPI webbrowser_get_Document(IWebBrowser2 *iface, IDispatch **ppDisp)
1831 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1832 FIXME("(%p)->(%p)\n", This, ppDisp);
1833 return E_NOTIMPL;
1836 static HRESULT WINAPI webbrowser_get_TopLevelContainer(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1838 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1839 FIXME("(%p)->(%p)\n", This, pBool);
1840 return E_NOTIMPL;
1843 static HRESULT WINAPI webbrowser_get_Type(IWebBrowser2 *iface, BSTR *Type)
1845 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1846 FIXME("(%p)->(%p)\n", This, Type);
1847 return E_NOTIMPL;
1850 static HRESULT WINAPI webbrowser_get_Left(IWebBrowser2 *iface, LONG *pl)
1852 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1853 FIXME("(%p)->(%p)\n", This, pl);
1854 return E_NOTIMPL;
1857 static HRESULT WINAPI webbrowser_put_Left(IWebBrowser2 *iface, LONG Left)
1859 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1860 FIXME("(%p)->(%ld)\n", This, Left);
1861 return E_NOTIMPL;
1864 static HRESULT WINAPI webbrowser_get_Top(IWebBrowser2 *iface, LONG *pl)
1866 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1867 FIXME("(%p)->(%p)\n", This, pl);
1868 return E_NOTIMPL;
1871 static HRESULT WINAPI webbrowser_put_Top(IWebBrowser2 *iface, LONG Top)
1873 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1874 FIXME("(%p)->(%ld)\n", This, Top);
1875 return E_NOTIMPL;
1878 static HRESULT WINAPI webbrowser_get_Width(IWebBrowser2 *iface, LONG *pl)
1880 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1881 FIXME("(%p)->(%p)\n", This, pl);
1882 return E_NOTIMPL;
1885 static HRESULT WINAPI webbrowser_put_Width(IWebBrowser2 *iface, LONG Width)
1887 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1888 FIXME("(%p)->(%ld)\n", This, Width);
1889 return E_NOTIMPL;
1892 static HRESULT WINAPI webbrowser_get_Height(IWebBrowser2 *iface, LONG *pl)
1894 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1895 FIXME("(%p)->(%p)\n", This, pl);
1896 return E_NOTIMPL;
1899 static HRESULT WINAPI webbrowser_put_Height(IWebBrowser2 *iface, LONG Height)
1901 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1902 FIXME("(%p)->(%ld)\n", This, Height);
1903 return E_NOTIMPL;
1906 static HRESULT WINAPI webbrowser_get_LocationName(IWebBrowser2 *iface, BSTR *LocationName)
1908 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1909 FIXME("(%p)->(%p)\n", This, LocationName);
1910 return E_NOTIMPL;
1913 static HRESULT WINAPI webbrowser_get_LocationURL(IWebBrowser2 *iface, BSTR *LocationURL)
1915 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1916 FIXME("(%p)->(%p)\n", This, LocationURL);
1917 return E_NOTIMPL;
1920 static HRESULT WINAPI webbrowser_get_Busy(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1922 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1923 FIXME("(%p)->(%p)\n", This, pBool);
1924 return E_NOTIMPL;
1927 static HRESULT WINAPI webbrowser_Quit(IWebBrowser2 *iface)
1929 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1930 FIXME("(%p)\n", This);
1931 return E_NOTIMPL;
1934 static HRESULT WINAPI webbrowser_ClientToWindow(IWebBrowser2 *iface, int *pcx, int *pcy)
1936 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1937 FIXME("(%p)->(%p %p)\n", This, pcx, pcy);
1938 return E_NOTIMPL;
1941 static HRESULT WINAPI webbrowser_PutProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT vtValue)
1943 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1944 FIXME("(%p)->(%s %s)\n", This, debugstr_w(szProperty), debugstr_variant(&vtValue));
1945 return E_NOTIMPL;
1948 static HRESULT WINAPI webbrowser_GetProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT *pvtValue)
1950 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1951 FIXME("(%p)->(%s %s)\n", This, debugstr_w(szProperty), debugstr_variant(pvtValue));
1952 return E_NOTIMPL;
1955 static HRESULT WINAPI webbrowser_get_Name(IWebBrowser2 *iface, BSTR *Name)
1957 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1958 FIXME("(%p)->(%p)\n", This, Name);
1959 return E_NOTIMPL;
1962 static HRESULT WINAPI webbrowser_get_HWND(IWebBrowser2 *iface, SHANDLE_PTR *pHWND)
1964 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1965 FIXME("(%p)->(%p)\n", This, pHWND);
1966 return E_NOTIMPL;
1969 static HRESULT WINAPI webbrowser_get_FullName(IWebBrowser2 *iface, BSTR *FullName)
1971 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1972 FIXME("(%p)->(%p)\n", This, FullName);
1973 return E_NOTIMPL;
1976 static HRESULT WINAPI webbrowser_get_Path(IWebBrowser2 *iface, BSTR *Path)
1978 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1979 FIXME("(%p)->(%p)\n", This, Path);
1980 return E_NOTIMPL;
1983 static HRESULT WINAPI webbrowser_get_Visible(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1985 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1986 FIXME("(%p)->(%p)\n", This, pBool);
1987 return E_NOTIMPL;
1990 static HRESULT WINAPI webbrowser_put_Visible(IWebBrowser2 *iface, VARIANT_BOOL Value)
1992 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
1993 FIXME("(%p)->(%x)\n", This, Value);
1994 return E_NOTIMPL;
1997 static HRESULT WINAPI webbrowser_get_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
1999 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2000 FIXME("(%p)->(%p)\n", This, pBool);
2001 return E_NOTIMPL;
2004 static HRESULT WINAPI webbrowser_put_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
2006 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2007 FIXME("(%p)->(%x)\n", This, Value);
2008 return E_NOTIMPL;
2011 static HRESULT WINAPI webbrowser_get_StatusText(IWebBrowser2 *iface, BSTR *StatusText)
2013 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2014 FIXME("(%p)->(%p)\n", This, StatusText);
2015 return E_NOTIMPL;
2018 static HRESULT WINAPI webbrowser_put_StatusText(IWebBrowser2 *iface, BSTR StatusText)
2020 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2021 FIXME("(%p)->(%s)\n", This, debugstr_w(StatusText));
2022 return E_NOTIMPL;
2025 static HRESULT WINAPI webbrowser_get_ToolBar(IWebBrowser2 *iface, int *Value)
2027 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2028 FIXME("(%p)->(%p)\n", This, Value);
2029 return E_NOTIMPL;
2032 static HRESULT WINAPI webbrowser_put_ToolBar(IWebBrowser2 *iface, int Value)
2034 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2035 FIXME("(%p)->(%x)\n", This, Value);
2036 return E_NOTIMPL;
2039 static HRESULT WINAPI webbrowser_get_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL *Value)
2041 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2042 FIXME("(%p)->(%p)\n", This, Value);
2043 return E_NOTIMPL;
2046 static HRESULT WINAPI webbrowser_put_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
2048 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2049 FIXME("(%p)->(%x)\n", This, Value);
2050 return E_NOTIMPL;
2053 static HRESULT WINAPI webbrowser_get_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL *pbFullScreen)
2055 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2056 FIXME("(%p)->(%p)\n", This, pbFullScreen);
2057 return E_NOTIMPL;
2060 static HRESULT WINAPI webbrowser_put_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL bFullScreen)
2062 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2063 FIXME("(%p)->(%x)\n", This, bFullScreen);
2064 return E_NOTIMPL;
2067 static HRESULT WINAPI webbrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VARIANT *Flags,
2068 VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
2070 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2071 FIXME("(%p)->(%s %s %s %s %s)\n", This, debugstr_variant(URL), debugstr_variant(Flags),
2072 debugstr_variant(TargetFrameName), debugstr_variant(PostData), debugstr_variant(Headers));
2073 return E_NOTIMPL;
2076 static HRESULT WINAPI webbrowser_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf)
2078 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2079 FIXME("(%p)->(%d %p)\n", This, cmdID, pcmdf);
2080 return E_NOTIMPL;
2083 static HRESULT WINAPI webbrowser_ExecWB(IWebBrowser2 *iface, OLECMDID cmdID,
2084 OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2086 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2087 FIXME("(%p)->(%d %d %s %p)\n", This, cmdID, cmdexecopt, debugstr_variant(pvaIn), pvaOut);
2088 return E_NOTIMPL;
2091 static HRESULT WINAPI webbrowser_ShowBrowserBar(IWebBrowser2 *iface, VARIANT *pvaClsid,
2092 VARIANT *pvarShow, VARIANT *pvarSize)
2094 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2095 FIXME("(%p)->(%s %s %s)\n", This, debugstr_variant(pvaClsid), debugstr_variant(pvarShow),
2096 debugstr_variant(pvarSize));
2097 return E_NOTIMPL;
2100 static HRESULT WINAPI webbrowser_get_ReadyState(IWebBrowser2 *iface, READYSTATE *lpReadyState)
2102 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2103 FIXME("(%p)->(%p)\n", This, lpReadyState);
2104 return E_NOTIMPL;
2107 static HRESULT WINAPI webbrowser_get_Offline(IWebBrowser2 *iface, VARIANT_BOOL *pbOffline)
2109 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2110 FIXME("(%p)->(%p)\n", This, pbOffline);
2111 return E_NOTIMPL;
2114 static HRESULT WINAPI webbrowser_put_Offline(IWebBrowser2 *iface, VARIANT_BOOL bOffline)
2116 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2117 FIXME("(%p)->(%x)\n", This, bOffline);
2118 return E_NOTIMPL;
2121 static HRESULT WINAPI webbrowser_get_Silent(IWebBrowser2 *iface, VARIANT_BOOL *pbSilent)
2123 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2124 FIXME("(%p)->(%p)\n", This, pbSilent);
2125 return E_NOTIMPL;
2128 static HRESULT WINAPI webbrowser_put_Silent(IWebBrowser2 *iface, VARIANT_BOOL bSilent)
2130 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2131 FIXME("(%p)->(%x)\n", This, bSilent);
2132 return E_NOTIMPL;
2135 static HRESULT WINAPI webbrowser_get_RegisterAsBrowser(IWebBrowser2 *iface,
2136 VARIANT_BOOL *pbRegister)
2138 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2139 FIXME("(%p)->(%p)\n", This, pbRegister);
2140 return E_NOTIMPL;
2143 static HRESULT WINAPI webbrowser_put_RegisterAsBrowser(IWebBrowser2 *iface,
2144 VARIANT_BOOL bRegister)
2146 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2147 FIXME("(%p)->(%x)\n", This, bRegister);
2148 return E_NOTIMPL;
2151 static HRESULT WINAPI webbrowser_get_RegisterAsDropTarget(IWebBrowser2 *iface,
2152 VARIANT_BOOL *pbRegister)
2154 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2155 FIXME("(%p)->(%p)\n", This, pbRegister);
2156 return E_NOTIMPL;
2159 static HRESULT WINAPI webbrowser_put_RegisterAsDropTarget(IWebBrowser2 *iface,
2160 VARIANT_BOOL bRegister)
2162 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2163 FIXME("(%p)->(%x)\n", This, bRegister);
2164 return E_NOTIMPL;
2167 static HRESULT WINAPI webbrowser_get_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL *pbRegister)
2169 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2170 FIXME("(%p)->(%p)\n", This, pbRegister);
2171 return E_NOTIMPL;
2174 static HRESULT WINAPI webbrowser_put_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL bRegister)
2176 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2177 TRACE("(%p)->(%x)\n", This, bRegister);
2178 return E_NOTIMPL;
2181 static HRESULT WINAPI webbrowser_get_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL *Value)
2183 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2184 FIXME("(%p)->(%p)\n", This, Value);
2185 return E_NOTIMPL;
2188 static HRESULT WINAPI webbrowser_put_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
2190 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2191 FIXME("(%p)->(%x)\n", This, Value);
2192 return E_NOTIMPL;
2195 static HRESULT WINAPI webbrowser_get_Resizable(IWebBrowser2 *iface, VARIANT_BOOL *Value)
2197 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2198 FIXME("(%p)->(%p)\n", This, Value);
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI webbrowser_put_Resizable(IWebBrowser2 *iface, VARIANT_BOOL Value)
2204 struct shellbrowserwindow *This = impl_from_IWebBrowser2(iface);
2205 FIXME("(%p)->(%x)\n", This, Value);
2206 return E_NOTIMPL;
2209 static const IWebBrowser2Vtbl webbrowser2vtbl =
2211 webbrowser_QueryInterface,
2212 webbrowser_AddRef,
2213 webbrowser_Release,
2214 webbrowser_GetTypeInfoCount,
2215 webbrowser_GetTypeInfo,
2216 webbrowser_GetIDsOfNames,
2217 webbrowser_Invoke,
2218 webbrowser_GoBack,
2219 webbrowser_GoForward,
2220 webbrowser_GoHome,
2221 webbrowser_GoSearch,
2222 webbrowser_Navigate,
2223 webbrowser_Refresh,
2224 webbrowser_Refresh2,
2225 webbrowser_Stop,
2226 webbrowser_get_Application,
2227 webbrowser_get_Parent,
2228 webbrowser_get_Container,
2229 webbrowser_get_Document,
2230 webbrowser_get_TopLevelContainer,
2231 webbrowser_get_Type,
2232 webbrowser_get_Left,
2233 webbrowser_put_Left,
2234 webbrowser_get_Top,
2235 webbrowser_put_Top,
2236 webbrowser_get_Width,
2237 webbrowser_put_Width,
2238 webbrowser_get_Height,
2239 webbrowser_put_Height,
2240 webbrowser_get_LocationName,
2241 webbrowser_get_LocationURL,
2242 webbrowser_get_Busy,
2243 webbrowser_Quit,
2244 webbrowser_ClientToWindow,
2245 webbrowser_PutProperty,
2246 webbrowser_GetProperty,
2247 webbrowser_get_Name,
2248 webbrowser_get_HWND,
2249 webbrowser_get_FullName,
2250 webbrowser_get_Path,
2251 webbrowser_get_Visible,
2252 webbrowser_put_Visible,
2253 webbrowser_get_StatusBar,
2254 webbrowser_put_StatusBar,
2255 webbrowser_get_StatusText,
2256 webbrowser_put_StatusText,
2257 webbrowser_get_ToolBar,
2258 webbrowser_put_ToolBar,
2259 webbrowser_get_MenuBar,
2260 webbrowser_put_MenuBar,
2261 webbrowser_get_FullScreen,
2262 webbrowser_put_FullScreen,
2263 webbrowser_Navigate2,
2264 webbrowser_QueryStatusWB,
2265 webbrowser_ExecWB,
2266 webbrowser_ShowBrowserBar,
2267 webbrowser_get_ReadyState,
2268 webbrowser_get_Offline,
2269 webbrowser_put_Offline,
2270 webbrowser_get_Silent,
2271 webbrowser_put_Silent,
2272 webbrowser_get_RegisterAsBrowser,
2273 webbrowser_put_RegisterAsBrowser,
2274 webbrowser_get_RegisterAsDropTarget,
2275 webbrowser_put_RegisterAsDropTarget,
2276 webbrowser_get_TheaterMode,
2277 webbrowser_put_TheaterMode,
2278 webbrowser_get_AddressBar,
2279 webbrowser_put_AddressBar,
2280 webbrowser_get_Resizable,
2281 webbrowser_put_Resizable
2284 static HRESULT WINAPI serviceprovider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
2286 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2287 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
2290 static ULONG WINAPI serviceprovider_AddRef(IServiceProvider *iface)
2292 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2293 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
2296 static ULONG WINAPI serviceprovider_Release(IServiceProvider *iface)
2298 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2299 return IWebBrowser2_Release(&This->IWebBrowser2_iface);
2302 static HRESULT WINAPI serviceprovider_QueryService(IServiceProvider *iface, REFGUID service,
2303 REFIID riid, void **ppv)
2305 struct shellbrowserwindow *This = impl_from_IServiceProvider(iface);
2307 TRACE("%s %s %p\n", debugstr_guid(service), debugstr_guid(riid), ppv);
2309 if (IsEqualGUID(service, &SID_STopLevelBrowser))
2310 return IShellBrowser_QueryInterface(&This->IShellBrowser_iface, riid, ppv);
2312 WARN("unknown service id %s\n", debugstr_guid(service));
2313 return E_NOTIMPL;
2316 static const IServiceProviderVtbl serviceprovidervtbl =
2318 serviceprovider_QueryInterface,
2319 serviceprovider_AddRef,
2320 serviceprovider_Release,
2321 serviceprovider_QueryService
2324 /* IShellBrowser */
2325 static HRESULT WINAPI shellbrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv)
2327 TRACE("%s %p\n", debugstr_guid(riid), ppv);
2329 *ppv = NULL;
2331 if (IsEqualGUID(&IID_IShellBrowser, riid) ||
2332 IsEqualGUID(&IID_IOleWindow, riid) ||
2333 IsEqualGUID(&IID_IUnknown, riid))
2335 *ppv = iface;
2338 if (*ppv)
2340 IUnknown_AddRef((IUnknown*)*ppv);
2341 return S_OK;
2344 return E_NOINTERFACE;
2347 static ULONG WINAPI shellbrowser_AddRef(IShellBrowser *iface)
2349 struct shellbrowserwindow *This = impl_from_IShellBrowser(iface);
2350 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
2353 static ULONG WINAPI shellbrowser_Release(IShellBrowser *iface)
2355 struct shellbrowserwindow *This = impl_from_IShellBrowser(iface);
2356 return IWebBrowser2_Release(&This->IWebBrowser2_iface);
2359 static HRESULT WINAPI shellbrowser_GetWindow(IShellBrowser *iface, HWND *phwnd)
2361 FIXME("%p\n", phwnd);
2362 return E_NOTIMPL;
2365 static HRESULT WINAPI shellbrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL mode)
2367 FIXME("%d\n", mode);
2368 return E_NOTIMPL;
2371 static HRESULT WINAPI shellbrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared,
2372 OLEMENUGROUPWIDTHS *menuwidths)
2374 FIXME("%p %p\n", hmenuShared, menuwidths);
2375 return E_NOTIMPL;
2378 static HRESULT WINAPI shellbrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared,
2379 HOLEMENU holemenuReserved, HWND hwndActiveObject)
2381 FIXME("%p %p %p\n", hmenuShared, holemenuReserved, hwndActiveObject);
2382 return E_NOTIMPL;
2385 static HRESULT WINAPI shellbrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared)
2387 FIXME("%p\n", hmenuShared);
2388 return E_NOTIMPL;
2391 static HRESULT WINAPI shellbrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR text)
2393 FIXME("%s\n", debugstr_w(text));
2394 return E_NOTIMPL;
2397 static HRESULT WINAPI shellbrowser_EnableModelessSB(IShellBrowser *iface, BOOL enable)
2399 FIXME("%d\n", enable);
2400 return E_NOTIMPL;
2403 static HRESULT WINAPI shellbrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID)
2405 FIXME("%p 0x%x\n", pmsg, wID);
2406 return E_NOTIMPL;
2409 static HRESULT WINAPI shellbrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT flags)
2411 FIXME("%p %x\n", pidl, flags);
2412 return E_NOTIMPL;
2415 static HRESULT WINAPI shellbrowser_GetViewStateStream(IShellBrowser *iface, DWORD mode, IStream **stream)
2417 FIXME("0x%lx %p\n", mode, stream);
2418 return E_NOTIMPL;
2421 static HRESULT WINAPI shellbrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd)
2423 FIXME("%d %p\n", id, phwnd);
2424 return E_NOTIMPL;
2427 static HRESULT WINAPI shellbrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg,
2428 WPARAM wParam, LPARAM lParam, LRESULT *pret)
2430 FIXME("%d %d %Ix %Ix %p\n", id, uMsg, wParam, lParam, pret);
2431 return E_NOTIMPL;
2434 static HRESULT WINAPI shellbrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **view)
2436 TRACE("%p\n", view);
2438 *view = desktopshellbrowserwindow.view;
2439 IShellView_AddRef(*view);
2440 return S_OK;
2443 static HRESULT WINAPI shellbrowser_OnViewWindowActive(IShellBrowser *iface, IShellView *view)
2445 FIXME("%p\n", view);
2446 return E_NOTIMPL;
2449 static HRESULT WINAPI shellbrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB buttons,
2450 UINT count, UINT flags)
2452 FIXME("%p %d 0x%x\n", buttons, count, flags);
2453 return E_NOTIMPL;
2456 static const IShellBrowserVtbl shellbrowservtbl = {
2457 shellbrowser_QueryInterface,
2458 shellbrowser_AddRef,
2459 shellbrowser_Release,
2460 shellbrowser_GetWindow,
2461 shellbrowser_ContextSensitiveHelp,
2462 shellbrowser_InsertMenusSB,
2463 shellbrowser_SetMenuSB,
2464 shellbrowser_RemoveMenusSB,
2465 shellbrowser_SetStatusTextSB,
2466 shellbrowser_EnableModelessSB,
2467 shellbrowser_TranslateAcceleratorSB,
2468 shellbrowser_BrowseObject,
2469 shellbrowser_GetViewStateStream,
2470 shellbrowser_GetControlWindow,
2471 shellbrowser_SendControlMsg,
2472 shellbrowser_QueryActiveShellView,
2473 shellbrowser_OnViewWindowActive,
2474 shellbrowser_SetToolbarItems
2477 static void desktopshellbrowserwindow_init(void)
2479 IShellFolder *folder;
2481 desktopshellbrowserwindow.IWebBrowser2_iface.lpVtbl = &webbrowser2vtbl;
2482 desktopshellbrowserwindow.IServiceProvider_iface.lpVtbl = &serviceprovidervtbl;
2483 desktopshellbrowserwindow.IShellBrowser_iface.lpVtbl = &shellbrowservtbl;
2485 if (FAILED(SHGetDesktopFolder(&folder)))
2486 return;
2488 IShellFolder_CreateViewObject(folder, NULL, &IID_IShellView, (void**)&desktopshellbrowserwindow.view);
2491 static void shellwindows_init(void)
2493 HRESULT hr;
2495 CoInitialize(NULL);
2497 shellwindows.IShellWindows_iface.lpVtbl = &shellwindowsvtbl;
2498 InitializeCriticalSectionEx(&shellwindows.cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
2499 shellwindows.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": shellwindows.cs");
2501 hr = CoRegisterClassObject(&CLSID_ShellWindows,
2502 (IUnknown*)&shellwindows_classfactory.IClassFactory_iface,
2503 CLSCTX_LOCAL_SERVER,
2504 REGCLS_MULTIPLEUSE,
2505 &shellwindows_classfactory.classreg);
2507 if (FAILED(hr))
2508 WARN("Failed to register ShellWindows object: %08lx\n", hr);