1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include	"StdAfx.h"
19 
20 #include	"comutil.h"
21 #include	"ShObjIdl.h"
22 
23 #include	"DebugServices.h"
24 
25 #include	"Resource.h"
26 
27 #include	"ExplorerBar.h"
28 
29 #include	"About.h"
30 // MFC Debugging
31 
32 #ifdef _DEBUG
33 #define new DEBUG_NEW
34 #undef THIS_FILE
35 static char THIS_FILE[] = __FILE__;
36 #endif
37 
38 //===========================================================================================================================
39 //	Constants
40 //===========================================================================================================================
41 #define LENGTHOF(a) (sizeof(a) == sizeof(&*a)) ? 0 : (sizeof(a) / sizeof(*a))
42 #define MIN_SIZE_X		10
43 #define MIN_SIZE_Y		10
44 
45 //===========================================================================================================================
46 //	ExplorerBar
47 //===========================================================================================================================
48 
ExplorerBar(void)49 ExplorerBar::ExplorerBar( void )
50 {
51 	++gDLLRefCount;
52 
53 	mRefCount		= 1;
54 	mSite 			= NULL;
55 	mWebBrowser		= NULL;
56 	mParentWindow	= NULL;
57 	mFocus			= FALSE;
58 	mViewMode		= 0;
59 	mBandID			= 0;
60 }
61 
62 //===========================================================================================================================
63 //	~ExplorerBar
64 //===========================================================================================================================
65 
~ExplorerBar(void)66 ExplorerBar::~ExplorerBar( void )
67 {
68 	if( mWebBrowser )
69 	{
70 		mWebBrowser->Release();
71 		mWebBrowser = NULL;
72 	}
73 	if( mSite )
74 	{
75 		mSite->Release();
76 		mSite = NULL;
77 	}
78 
79 	--gDLLRefCount;
80 }
81 
82 #if 0
83 #pragma mark -
84 #pragma mark == IUnknown implementation ==
85 #endif
86 
87 //===========================================================================================================================
88 //	QueryInterface
89 //===========================================================================================================================
90 
QueryInterface(REFIID inID,LPVOID * outResult)91 STDMETHODIMP	ExplorerBar::QueryInterface( REFIID inID, LPVOID *outResult )
92 {
93 	HRESULT		err;
94 
95 	if( IsEqualIID( inID, IID_IUnknown ) )				// IUnknown
96 	{
97 		*outResult = this;
98 	}
99 	else if( IsEqualIID( inID, IID_IOleWindow ) )		// IOleWindow
100 	{
101 		*outResult = (IOleWindow *) this;
102 	}
103 	else if( IsEqualIID( inID, IID_IDockingWindow ) )	// IDockingWindow
104 	{
105 		*outResult = (IDockingWindow *) this;
106 	}
107 	else if( IsEqualIID( inID, IID_IDeskBand ) )		// IDeskBand
108 	{
109 		*outResult = (IDeskBand *) this;
110 	}
111 	else if( IsEqualIID( inID, IID_IInputObject ) )		// IInputObject
112 	{
113 		*outResult = (IInputObject *) this;
114 	}
115 	else if( IsEqualIID( inID, IID_IObjectWithSite ) )	// IObjectWithSite
116 	{
117 		*outResult = (IObjectWithSite *) this;
118 	}
119 	else if( IsEqualIID( inID, IID_IPersistStream ) )	// IPersistStream
120 	{
121 		*outResult = (IPersistStream *) this;
122 	}
123 	else if( IsEqualIID( inID, IID_IContextMenu ) )     // IContextMenu
124 	{
125 		*outResult = (IContextMenu *) this;
126 	}
127 	else
128 	{
129 		*outResult = NULL;
130 		err = E_NOINTERFACE;
131 		goto exit;
132 	}
133 
134 	( *( (LPUNKNOWN *) outResult ) )->AddRef();
135 	err = S_OK;
136 
137 exit:
138 	return( err );
139 }
140 
141 //===========================================================================================================================
142 //	AddRef
143 //===========================================================================================================================
144 
STDMETHODIMP_(DWORD)145 STDMETHODIMP_( DWORD )	ExplorerBar::AddRef( void )
146 {
147 	return( ++mRefCount );
148 }
149 
150 //===========================================================================================================================
151 //	Release
152 //===========================================================================================================================
153 
STDMETHODIMP_(DWORD)154 STDMETHODIMP_( DWORD )	ExplorerBar::Release( void )
155 {
156 	DWORD		count;
157 
158 	count = --mRefCount;
159 	if( count == 0 )
160 	{
161 		delete this;
162 	}
163 	return( count );
164 }
165 
166 #if 0
167 #pragma mark -
168 #pragma mark == IOleWindow implementation ==
169 #endif
170 
171 //===========================================================================================================================
172 //	GetWindow
173 //===========================================================================================================================
174 
GetWindow(HWND * outWindow)175 STDMETHODIMP	ExplorerBar::GetWindow( HWND *outWindow )
176 {
177 	*outWindow = mWindow.GetSafeHwnd();
178 	return( S_OK );
179 }
180 
181 //===========================================================================================================================
182 //	ContextSensitiveHelp
183 //===========================================================================================================================
184 
ContextSensitiveHelp(BOOL inEnterMode)185 STDMETHODIMP	ExplorerBar::ContextSensitiveHelp( BOOL inEnterMode )
186 {
187 	DEBUG_UNUSED( inEnterMode );
188 
189 	return( E_NOTIMPL );
190 }
191 
192 #if 0
193 #pragma mark -
194 #pragma mark == IDockingWindow implementation ==
195 #endif
196 
197 //===========================================================================================================================
198 //	ShowDW
199 //===========================================================================================================================
200 
ShowDW(BOOL inShow)201 STDMETHODIMP	ExplorerBar::ShowDW( BOOL inShow )
202 {
203 	if( mWindow.GetSafeHwnd() )
204 	{
205 		mWindow.ShowWindow( inShow ? SW_SHOW : SW_HIDE );
206 	}
207 	return( S_OK );
208 }
209 
210 //===========================================================================================================================
211 //	CloseDW
212 //===========================================================================================================================
213 
CloseDW(DWORD inReserved)214 STDMETHODIMP	ExplorerBar::CloseDW( DWORD inReserved )
215 {
216 	DEBUG_UNUSED( inReserved );
217 
218 	ShowDW( FALSE );
219 	if( mWindow.GetSafeHwnd() )
220 	{
221 		mWindow.SendMessage( WM_CLOSE );
222 	}
223 	return( S_OK );
224 }
225 
226 //===========================================================================================================================
227 //	ResizeBorderDW
228 //===========================================================================================================================
229 
ResizeBorderDW(LPCRECT inBorder,IUnknown * inPunkSite,BOOL inReserved)230 STDMETHODIMP	ExplorerBar::ResizeBorderDW( LPCRECT inBorder, IUnknown *inPunkSite, BOOL inReserved )
231 {
232 	DEBUG_UNUSED( inBorder );
233 	DEBUG_UNUSED( inPunkSite );
234 	DEBUG_UNUSED( inReserved );
235 
236 	return( E_NOTIMPL );
237 }
238 
239 #if 0
240 #pragma mark -
241 #pragma mark == IDeskBand implementation ==
242 #endif
243 
244 //===========================================================================================================================
245 //	GetBandInfo
246 //===========================================================================================================================
247 
GetBandInfo(DWORD inBandID,DWORD inViewMode,DESKBANDINFO * outInfo)248 STDMETHODIMP	ExplorerBar::GetBandInfo( DWORD inBandID, DWORD inViewMode, DESKBANDINFO *outInfo )
249 {
250 	HRESULT		err;
251 
252 	require_action( outInfo, exit, err = E_INVALIDARG );
253 
254 	mBandID   = inBandID;
255 	mViewMode = inViewMode;
256 
257 	if( outInfo->dwMask & DBIM_MINSIZE )
258 	{
259 		outInfo->ptMinSize.x = 100;
260 		outInfo->ptMinSize.y = 100;
261 	}
262 	if( outInfo->dwMask & DBIM_MAXSIZE )
263 	{
264 		// Unlimited max size.
265 
266 		outInfo->ptMaxSize.x = -1;
267 		outInfo->ptMaxSize.y = -1;
268 	}
269 	if( outInfo->dwMask & DBIM_INTEGRAL )
270 	{
271 		outInfo->ptIntegral.x = 1;
272 		outInfo->ptIntegral.y = 1;
273 	}
274 	if( outInfo->dwMask & DBIM_ACTUAL )
275 	{
276 		outInfo->ptActual.x = 0;
277 		outInfo->ptActual.y = 0;
278 	}
279 	if( outInfo->dwMask & DBIM_TITLE )
280 	{
281 		CString		s;
282 		BOOL		ok;
283 
284 		ok = s.LoadString( IDS_NAME );
285 		require_action( ok, exit, err = kNoResourcesErr );
286 
287 		#ifdef UNICODE
288 			lstrcpyn( outInfo->wszTitle, s, sizeof_array( outInfo->wszTitle ) );
289 		#else
290 			DWORD		nChars;
291 
292 			nChars = MultiByteToWideChar( CP_ACP, 0, s, -1, outInfo->wszTitle, sizeof_array( outInfo->wszTitle ) );
293 			err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
294 			require_noerr( err, exit );
295 		#endif
296 	}
297 	if( outInfo->dwMask & DBIM_MODEFLAGS )
298 	{
299 		outInfo->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
300 	}
301 
302 	// Force the default background color.
303 
304 	outInfo->dwMask &= ~DBIM_BKCOLOR;
305 	err = S_OK;
306 
307 exit:
308 	return( err );
309 }
310 
311 #if 0
312 #pragma mark -
313 #pragma mark == IInputObject implementation ==
314 #endif
315 
316 //===========================================================================================================================
317 //	UIActivateIO
318 //===========================================================================================================================
319 
UIActivateIO(BOOL inActivate,LPMSG inMsg)320 STDMETHODIMP	ExplorerBar::UIActivateIO( BOOL inActivate, LPMSG inMsg )
321 {
322 	DEBUG_UNUSED( inMsg );
323 
324 	if( inActivate )
325 	{
326 		mWindow.SetFocus();
327 	}
328 	return( S_OK );
329 }
330 
331 //===========================================================================================================================
332 //	HasFocusIO
333 //===========================================================================================================================
334 
HasFocusIO(void)335 STDMETHODIMP	ExplorerBar::HasFocusIO( void )
336 {
337 	if( mWindow.GetFocus()->GetSafeHwnd() == mWindow.GetSafeHwnd() )
338 	{
339 		return( S_OK );
340 	}
341 	return( S_FALSE );
342 }
343 
344 //===========================================================================================================================
345 //	TranslateAcceleratorIO
346 //===========================================================================================================================
347 
TranslateAcceleratorIO(LPMSG inMsg)348 STDMETHODIMP	ExplorerBar::TranslateAcceleratorIO( LPMSG inMsg )
349 {
350 	DEBUG_UNUSED( inMsg );
351 
352 	return( S_FALSE );
353 }
354 
355 #if 0
356 #pragma mark -
357 #pragma mark == IObjectWithSite implementation ==
358 #endif
359 
360 //===========================================================================================================================
361 //	SetSite
362 //===========================================================================================================================
363 
SetSite(IUnknown * inPunkSite)364 STDMETHODIMP	ExplorerBar::SetSite( IUnknown *inPunkSite )
365 {
366 	AFX_MANAGE_STATE( AfxGetStaticModuleState() );
367 
368 	HRESULT		err;
369 
370 	// Release the old interfaces.
371 
372 	if( mWebBrowser )
373 	{
374 		mWebBrowser->Release();
375 		mWebBrowser = NULL;
376 	}
377 	if( mSite )
378 	{
379 		mSite->Release();
380 		mSite = NULL;
381 	}
382 
383 	// A non-NULL site means we're setting the site. Otherwise, the site is being released (done above).
384 
385 	if( !inPunkSite )
386 	{
387 		err = S_OK;
388 		goto exit;
389 	}
390 
391 	// Get the parent window.
392 
393 	IOleWindow *		oleWindow;
394 
395 	mParentWindow = NULL;
396 	err = inPunkSite->QueryInterface( IID_IOleWindow, (LPVOID *) &oleWindow );
397 	require( SUCCEEDED( err ), exit );
398 
399 	err = oleWindow->GetWindow( &mParentWindow );
400 	oleWindow->Release();
401 	require_noerr( err, exit );
402 	require_action( mParentWindow, exit, err = E_FAIL );
403 
404 	// Get the IInputObject interface.
405 
406 	err = inPunkSite->QueryInterface( IID_IInputObjectSite, (LPVOID *) &mSite );
407 	require( SUCCEEDED( err ), exit );
408 	check( mSite );
409 
410 	// Get the IWebBrowser2 interface.
411 
412 	IOleCommandTarget *		oleCommandTarget;
413 
414 	err = inPunkSite->QueryInterface( IID_IOleCommandTarget, (LPVOID *) &oleCommandTarget );
415 	require( SUCCEEDED( err ), exit );
416 
417 	IServiceProvider *		serviceProvider;
418 
419 	err = oleCommandTarget->QueryInterface( IID_IServiceProvider, (LPVOID *) &serviceProvider );
420 	oleCommandTarget->Release();
421 	require( SUCCEEDED( err ), exit );
422 
423 	err = serviceProvider->QueryService( SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *) &mWebBrowser );
424 	serviceProvider->Release();
425 	require( SUCCEEDED( err ), exit );
426 
427 	// Create the main window.
428 
429 	err = SetupWindow();
430 	require_noerr( err, exit );
431 
432 exit:
433 	return( err );
434 }
435 
436 //===========================================================================================================================
437 //	GetSite
438 //===========================================================================================================================
439 
GetSite(REFIID inID,LPVOID * outResult)440 STDMETHODIMP	ExplorerBar::GetSite( REFIID inID, LPVOID *outResult )
441 {
442 	HRESULT		err;
443 
444 	*outResult = NULL;
445 	require_action( mSite, exit, err = E_FAIL );
446 
447 	err = mSite->QueryInterface( inID, outResult );
448 
449 exit:
450 	return( err );
451 }
452 
453 #if 0
454 #pragma mark -
455 #pragma mark == IPersistStream implementation ==
456 #endif
457 
458 //
459 // IPersistStream implementation
460 //
461 // This is only supported to allow the desk band to be dropped on the desktop and to prevent multiple instances of
462 // the desk band from showing up in the context menu. This desk band doesn't actually persist any data.
463 //
464 
465 //===========================================================================================================================
466 //	GetClassID
467 //===========================================================================================================================
468 
GetClassID(LPCLSID outClassID)469 STDMETHODIMP	ExplorerBar::GetClassID( LPCLSID outClassID )
470 {
471 	*outClassID = CLSID_ExplorerBar;
472 	return( S_OK );
473 }
474 
475 //===========================================================================================================================
476 //	IsDirty
477 //===========================================================================================================================
478 
IsDirty(void)479 STDMETHODIMP	ExplorerBar::IsDirty( void )
480 {
481 	return( S_FALSE );
482 }
483 
484 //===========================================================================================================================
485 //	Load
486 //===========================================================================================================================
487 
Load(LPSTREAM inStream)488 STDMETHODIMP	ExplorerBar::Load( LPSTREAM inStream )
489 {
490 	DEBUG_UNUSED( inStream );
491 
492 	return( S_OK );
493 }
494 
495 //===========================================================================================================================
496 //	Save
497 //===========================================================================================================================
498 
Save(LPSTREAM inStream,BOOL inClearDirty)499 STDMETHODIMP	ExplorerBar::Save( LPSTREAM inStream, BOOL inClearDirty )
500 {
501 	DEBUG_UNUSED( inStream );
502 	DEBUG_UNUSED( inClearDirty );
503 
504 	return( S_OK );
505 }
506 
507 //===========================================================================================================================
508 //	GetSizeMax
509 //===========================================================================================================================
510 
GetSizeMax(ULARGE_INTEGER * outSizeMax)511 STDMETHODIMP	ExplorerBar::GetSizeMax( ULARGE_INTEGER *outSizeMax )
512 {
513 	DEBUG_UNUSED( outSizeMax );
514 
515 	return( E_NOTIMPL );
516 }
517 
518 
519 //===========================================================================================================================
520 //	QueryContextMenu
521 //===========================================================================================================================
522 
QueryContextMenu(HMENU hShellContextMenu,UINT iContextMenuFirstItem,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)523 STDMETHODIMP  ExplorerBar::QueryContextMenu(HMENU hShellContextMenu, UINT iContextMenuFirstItem, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
524 {
525 	DEBUG_UNUSED( idCmdLast );
526 	DEBUG_UNUSED( uFlags );
527 
528 	CMenu menubar;
529 
530 	menubar.LoadMenu(IDR_CONTEXT_MENU);
531 	CMenu * menu = menubar.GetSubMenu(0);
532 
533 	CMenu shellmenu;
534 
535 	shellmenu.Attach(hShellContextMenu);
536 
537 	UINT iShellItem = iContextMenuFirstItem;	//! remove plus one
538 	UINT idShellCmd = idCmdFirst;
539 
540 	int n = menu->GetMenuItemCount();
541 
542 	for (int i=0; i<n; ++i)
543 	{
544 		MENUITEMINFO	mii;
545 		TCHAR				sz[128] = {0};
546 
547 		ZeroMemory(&mii, sizeof(mii));
548 		mii.fMask		= MIIM_TYPE | MIIM_ID;
549 		mii.fType		= MFT_STRING;
550 		mii.cbSize		= sizeof(mii);
551 		mii.cch			= LENGTHOF(sz);
552 		mii.dwTypeData	= sz;
553 
554 		menu->GetMenuItemInfo(i, &mii, TRUE);
555 
556 		mii.wID = idShellCmd++;
557 
558 		shellmenu.InsertMenuItem(iShellItem++, &mii, TRUE);
559 	}
560 
561 	shellmenu.Detach();
562 
563 	return n;
564 }
565 
566 
567 //===========================================================================================================================
568 //	GetCommandString
569 //===========================================================================================================================
570 
571 // Not called for explorer bars
GetCommandString(UINT_PTR idCmd,UINT uType,UINT * pwReserved,LPSTR pszName,UINT cchMax)572 STDMETHODIMP ExplorerBar::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax)
573 {
574 	DEBUG_UNUSED( idCmd );
575 	DEBUG_UNUSED( uType );
576 	DEBUG_UNUSED( pwReserved );
577 	DEBUG_UNUSED( pszName );
578 	DEBUG_UNUSED( cchMax );
579 
580 	return E_NOTIMPL;
581 }
582 
583 //===========================================================================================================================
584 //	InvokeCommand
585 //===========================================================================================================================
586 
587 //	The shell sends either strings or indexes
588 //	IE never sends strings
589 //	The indexes are into an array of my commands
590 //	So the verb for the first command I added to the menu is always 0x0000
591 //	Here - because I don't have any submenus -
592 //		I can treat the 'verb' as an menu item position
InvokeCommand(LPCMINVOKECOMMANDINFO lpici)593 STDMETHODIMP ExplorerBar::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
594 {
595 	// IE doesn't send string commands
596 	if (HIWORD(lpici->lpVerb) != 0) return 0;
597 
598 	CAbout dlg;
599 
600 	dlg.DoModal();
601 
602 	return S_OK;
603 }
604 
605 #if 0
606 #pragma mark -
607 #pragma mark == Other ==
608 #endif
609 
610 //===========================================================================================================================
611 //	SetupWindow
612 //===========================================================================================================================
613 
SetupWindow(void)614 OSStatus	ExplorerBar::SetupWindow( void )
615 {
616 	OSStatus		err;
617 	CWnd *			window;
618 	CRect			rect;
619 	CString			s;
620 	BOOL			ok;
621 
622 	window = CWnd::FromHandle( mParentWindow );
623 	check( window );
624 	window->GetClientRect( rect );
625 
626 	ok = s.LoadString( IDS_NAME );
627 	require_action( ok, exit, err = kNoResourcesErr );
628 
629 	ok = mWindow.Create( NULL, s, WS_CHILD | WS_VISIBLE, rect, window, 100 ) != 0;
630 	require_action( ok, exit, err = kNoResourcesErr );
631 
632 	mWindow.SetOwner( this );
633 	err = kNoErr;
634 
635 exit:
636 	return( err );
637 }
638 
639 //===========================================================================================================================
640 //	GoToURL
641 //===========================================================================================================================
642 
GoToURL(const CString & inURL)643 OSStatus	ExplorerBar::GoToURL( const CString &inURL )
644 {
645 	OSStatus		err;
646 	BSTR			s;
647 	VARIANT			empty;
648 
649 	s = inURL.AllocSysString();
650 	require_action( s, exit, err = kNoMemoryErr );
651 
652 	VariantInit( &empty );
653 	err = mWebBrowser->Navigate( s, &empty, &empty, &empty, &empty );
654 	SysFreeString( s );
655 	require_noerr( err, exit );
656 
657 exit:
658 	return( err );
659 }
660