1 /*************************************************************************
2  *
3  *  The Contents of this file are made available subject to the terms of
4  *  the BSD license.
5  *
6  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *************************************************************************/
34 
35 // SOActiveX.cpp : Implementation of CSOActiveX
36 
37 #include "stdafx2.h"
38 #include "so_activex.h"
39 #include "SOActiveX.h"
40 #include "SOComWindowPeer.h"
41 
42 #define STAROFFICE_WINDOWCLASS "SOParentWindow"
43 
44 #define BARS_NUMBER  3
45 #define BARS_TO_SHOW 2
46 
47 OLECHAR* pSlotUrl[BARS_NUMBER] =
48 						{L"slot:5910" // SID_TOGGLEFUNCTIONBAR
49 						,L"slot:5920" // SID_TOGGLESTATUSBAR
50 						,L"slot:6661" // SID_TOGGLE_MENUBAR
51 //						,L"slot:10603" // SID_HYPERLINK_INSERT
52 						};
53 
54 OLECHAR* pSlotName[BARS_NUMBER] =
55 						{L"FunctionBarVisible"		// SID_TOGGLEFUNCTIONBAR
56 						,L"StatusBarVisible"		// SID_TOGGLESTATUSBAR
57 						,L"MenuBarVisible"			// SID_TOGGLE_MENUBAR
58 //						,L"InsertHyperlink"			// SID_HYPERLINK_INSERT
59 						};
60 
61 
62 
63 /////////////////////////////////////////////////////////////////////////////
64 
65 HRESULT ExecuteFunc( IDispatch* idispUnoObject,
66 					 OLECHAR* sFuncName,
67 					 CComVariant* params,
68 					 unsigned int count,
69 					 CComVariant* pResult )
70 {
71 	if( !idispUnoObject )
72 		return E_FAIL;
73 
74 	DISPID id;
75 	HRESULT hr = idispUnoObject->GetIDsOfNames( IID_NULL, &sFuncName, 1, LOCALE_USER_DEFAULT, &id);
76 	if( !SUCCEEDED( hr ) ) return hr;
77 
78 	DISPPARAMS dispparams= { params, 0, count, 0};
79 
80 	// DEBUG
81 	EXCEPINFO myInfo;
82 	return idispUnoObject->Invoke( id, IID_NULL,LOCALE_USER_DEFAULT, DISPATCH_METHOD,
83                     &dispparams, pResult, &myInfo, 0);
84 }
85 
86 HRESULT GetIDispByFunc( IDispatch* idispUnoObject,
87 					  	OLECHAR* sFuncName,
88 					  	CComVariant* params,
89 					  	unsigned int count,
90 					  	CComPtr<IDispatch>& pdispResult )
91 {
92 	if( !idispUnoObject )
93 		return E_FAIL;
94 
95 	CComVariant result;
96 	HRESULT hr = ExecuteFunc( idispUnoObject, sFuncName, params, count, &result );
97 	if( !SUCCEEDED( hr ) ) return hr;
98 
99 	if( result.vt != VT_DISPATCH || result.pdispVal == NULL )
100 		return hr;
101 
102 	pdispResult = CComPtr<IDispatch>( result.pdispVal );
103 
104 	return S_OK;
105 }
106 
107 HRESULT PutPropertiesToIDisp( IDispatch* pdispObject,
108 							  OLECHAR** sMemberNames,
109 							  CComVariant* pVariant,
110 							  unsigned int count )
111 {
112 	for( unsigned int ind = 0; ind < count; ind++ )
113 	{
114 		DISPID id;
115 		HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, &sMemberNames[ind], 1, LOCALE_USER_DEFAULT, &id );
116 		if( !SUCCEEDED( hr ) ) return hr;
117 
118 		hr = CComDispatchDriver::PutProperty( pdispObject, id, &pVariant[ind] );
119 		if( !SUCCEEDED( hr ) ) return hr;
120 	}
121 
122 	return S_OK;
123 }
124 
125 /////////////////////////////////////////////////////////////////////////////
126 // CSOActiveX
127 
128 CSOActiveX::CSOActiveX()
129 : mCookie(0)
130 , mCurFileUrl( L"private:factory/swriter" )
131 , mbLoad( FALSE )
132 , mParentWin( NULL )
133 , mOffWin( NULL )
134 , mbViewOnly( FALSE )
135 {
136 	CLSID clsFactory = {0x82154420,0x0FBF,0x11d4,{0x83, 0x13,0x00,0x50,0x04,0x52,0x6A,0xB4}};
137 	HRESULT hr = CoCreateInstance( clsFactory, NULL, CLSCTX_ALL, __uuidof(IDispatch), (void**)&mpDispFactory);
138 
139     mPWinClass.style			= CS_HREDRAW|CS_VREDRAW;
140     mPWinClass.lpfnWndProc		= ::DefWindowProc;
141     mPWinClass.cbClsExtra		= 0;
142     mPWinClass.cbWndExtra		= 0;
143     mPWinClass.hInstance		= (HINSTANCE) GetModuleHandle(NULL); //myInstance;
144     mPWinClass.hIcon			= NULL;
145     mPWinClass.hCursor			= NULL;
146     mPWinClass.hbrBackground	= (HBRUSH) COLOR_BACKGROUND;
147     mPWinClass.lpszMenuName	    = NULL;
148     mPWinClass.lpszClassName	= STAROFFICE_WINDOWCLASS;
149 
150 	RegisterClass(&mPWinClass);
151 }
152 
153 CSOActiveX::~CSOActiveX()
154 {
155 	Cleanup();
156 
157 }
158 
159 HRESULT CSOActiveX::Cleanup()
160 {
161 	if( mpDispFrame && mbViewOnly )
162 	{
163 		ShowSomeBars();
164 		mbViewOnly = FALSE;
165 	}
166 
167 	if( mpDispFrame )
168 	{
169 		// mpDispFrame->dispose();
170 		CComVariant dummyResult;
171 		ExecuteFunc( mpDispFrame, L"dispose", NULL, 0, &dummyResult );
172 		mpDispFrame = CComPtr< IDispatch >();
173 	}
174 
175 	if( ::IsWindow( mOffWin ) )
176 		::DestroyWindow( mOffWin );
177 
178 	return S_OK;
179 }
180 
181 
182 STDMETHODIMP CSOActiveX::InitNew ()
183 {
184 	mbLoad = TRUE;
185     return S_OK;
186 }
187 
188 STDMETHODIMP CSOActiveX::Load ( LPSTREAM pStm )
189 {
190 	mbLoad = TRUE;
191 
192 	// may be later?
193 	// for now just ignore
194 
195     return S_OK;
196 }
197 
198 STDMETHODIMP CSOActiveX::Load( LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog )
199 {
200     IPropertyBag2* pPropBag2;
201     HRESULT hr = pPropBag->QueryInterface( IID_IPropertyBag2, (void**)&pPropBag2 );
202     ATLASSERT( hr >= 0 );
203 
204     if( !SUCCEEDED( hr ) )
205         return hr;
206 
207     unsigned long aNum;
208     hr = pPropBag2->CountProperties( &aNum );
209     ATLASSERT( hr >= 0 );
210     if( !SUCCEEDED( hr ) )
211         return hr;
212 
213     PROPBAG2* aPropNames = new PROPBAG2[aNum];
214     unsigned long aReaded;
215 
216     hr = pPropBag2->GetPropertyInfo( 0,
217                                      aNum,
218                                      aPropNames,
219                                      &aReaded );
220     ATLASSERT( hr >= 0 );
221     if( !SUCCEEDED( hr ) )
222     {
223         delete[] aPropNames;
224         return hr;
225     }
226 
227 	CComVariant* aVal = new CComVariant[aNum];
228     HRESULT*     hvs = new HRESULT[aNum];
229 	hr = pPropBag2->Read( aNum,
230                           aPropNames,
231                           NULL,
232                           aVal,
233                           hvs );
234     ATLASSERT( hr >= 0 );
235     if( !SUCCEEDED( hr ) )
236     {
237         delete[] hvs;
238         delete[] aVal;
239         delete[] aPropNames;
240         return hr;
241     }
242 
243 	USES_CONVERSION;
244     for( unsigned long ind = 0; ind < aNum; ind++ )
245     {
246 		// all information from the 'object' tag is in strings
247 		if( aVal[ind].vt == VT_BSTR && !strcmp( OLE2T( aPropNames[ind].pstrName ), "src" ) )
248 		{
249             mCurFileUrl = wcsdup( aVal[ind].bstrVal );
250 		}
251 		else if( aVal[ind].vt == VT_BSTR
252 				&& !strcmp( OLE2T( aPropNames[ind].pstrName ), "readonly" ) )
253 		{
254 			if( !strcmp( OLE2T( aVal[ind].bstrVal ), "true" ) )
255 			{
256 				mbViewOnly = TRUE;
257 			}
258 			else
259 			{
260 				// the default value
261 				mbViewOnly = FALSE;
262 			}
263 		}
264     }
265 
266     delete[] hvs;
267     delete[] aVal;
268     delete[] aPropNames;
269 
270 	if( !mpDispFactory )
271 		return hr;
272 
273 	mbLoad = TRUE;
274 
275     Invalidate();
276     UpdateWindow();
277 
278 	return hr;
279 }
280 
281 HRESULT CSOActiveX::GetUnoStruct( OLECHAR* sStructName, CComPtr<IDispatch>& pdispResult )
282 {
283 	return GetIDispByFunc( mpDispFactory, L"Bridge_GetStruct", &CComVariant( sStructName ), 1, pdispResult );
284 }
285 
286 HRESULT CSOActiveX::GetUrlStruct( OLECHAR* sUrl, CComPtr<IDispatch>& pdispUrl )
287 {
288 	HRESULT hr = GetUnoStruct( L"com.sun.star.util.URL", pdispUrl );
289 	if( !SUCCEEDED( hr ) ) return hr;
290 
291 	OLECHAR* sURLMemberName = L"Complete";
292 	DISPID nURLID;
293 	hr = pdispUrl->GetIDsOfNames( IID_NULL, &sURLMemberName, 1, LOCALE_USER_DEFAULT, &nURLID );
294 	if( !SUCCEEDED( hr ) ) return hr;
295 	hr = CComDispatchDriver::PutProperty( pdispUrl, nURLID, &CComVariant( sUrl ) );
296 	if( !SUCCEEDED( hr ) ) return hr;
297 
298 	CComPtr<IDispatch> pdispTransformer;
299 	hr = GetIDispByFunc( mpDispFactory,
300 						 L"createInstance",
301 						 &CComVariant( L"com.sun.star.util.URLTransformer" ),
302 						 1,
303 						 pdispTransformer );
304 	if( !SUCCEEDED( hr ) ) return hr;
305 
306 	CComVariant dummyResult;
307 	CComVariant aInOutParam;
308 	aInOutParam.ppdispVal = &pdispUrl;
309 	aInOutParam.vt = VT_DISPATCH | VT_BYREF;
310 	hr = ExecuteFunc( pdispTransformer, L"parseStrict", &aInOutParam, 1, &dummyResult );
311 	if( !SUCCEEDED( hr ) || dummyResult.vt != VT_BOOL || !dummyResult.boolVal ) return hr;
312 
313 	return S_OK;
314 }
315 
316 
317 HRESULT CSOActiveX::CreateFrameOldWay( HWND hwnd, int width, int height )
318 {
319 	if( !mpDispFactory )
320 		return E_FAIL;
321 
322 	// create window handle holder
323 	CComPtr< CComObject< SOComWindowPeer > > pPeerToSend = new CComObject<SOComWindowPeer>( hwnd );
324 	pPeerToSend->SetHWNDInternally( hwnd );
325 	CComQIPtr< IDispatch, &IID_IDispatch > pIDispToSend( pPeerToSend );
326 
327 	// create rectangle structure
328 	CComPtr<IDispatch> pdispRectangle;
329 	HRESULT hr = GetUnoStruct( L"com.sun.star.awt.Rectangle", pdispRectangle );
330 	if( !SUCCEEDED( hr ) ) return hr;
331 
332 	OLECHAR* sRectMemberNames[4] = { L"X",
333 								 	 L"Y",
334 								 	 L"Width",
335 								 	 L"Height" };
336 	CComVariant pRectVariant[4];
337 	pRectVariant[0] = pRectVariant[1] = pRectVariant[2] = pRectVariant[3] = CComVariant( 0 );
338 
339 	hr = PutPropertiesToIDisp( pdispRectangle, sRectMemberNames, pRectVariant, 4 );
340 	if( !SUCCEEDED( hr ) ) return hr;
341 
342 	// create WindowDescriptor structure
343 	CComPtr<IDispatch> pdispWinDescr;
344 	hr = GetUnoStruct( L"com.sun.star.awt.WindowDescriptor", pdispWinDescr );
345 	if( !SUCCEEDED( hr ) ) return hr;
346 
347 	// fill in descriptor with info
348 	OLECHAR* sDescriptorMemberNames[6] = { L"Type",
349 								 L"WindowServiceName",
350 								 L"ParentIndex",
351 								 L"Parent",
352 								 L"Bounds",
353 								 L"WindowAttributes" };
354 	CComVariant pDescriptorVar[6];
355 	pDescriptorVar[0] = CComVariant( 0 );
356 	pDescriptorVar[1] = CComVariant( L"workwindow" );
357 	pDescriptorVar[2] = CComVariant( 1 );
358 	pDescriptorVar[3] = CComVariant( pIDispToSend );
359 	pDescriptorVar[4] = CComVariant( pdispRectangle );
360 	pDescriptorVar[5] = CComVariant( 33 );
361 	hr = PutPropertiesToIDisp( pdispWinDescr, sDescriptorMemberNames, pDescriptorVar, 6 );
362 	if( !SUCCEEDED( hr ) ) return hr;
363 
364 	// create XToolkit instance
365 	CComPtr<IDispatch> pdispToolkit;
366 	hr = GetIDispByFunc( mpDispFactory, L"createInstance", &CComVariant( L"com.sun.star.awt.Toolkit" ), 1, pdispToolkit );
367 	if( !SUCCEEDED( hr ) ) return hr;
368 
369 	// create window with toolkit
370 	hr = GetIDispByFunc( pdispToolkit, L"createWindow", &CComVariant( pdispWinDescr ), 1, mpDispWin );
371 	if( !SUCCEEDED( hr ) ) return hr;
372 
373 	// create frame
374 	hr = GetIDispByFunc( mpDispFactory, L"createInstance", &CComVariant( L"com.sun.star.frame.Task" ), 1, mpDispFrame );
375 	if( !SUCCEEDED( hr ) || !mpDispFrame )
376 	{
377 		// the interface com.sun.star.frame.Task is removed in 6.1
378 		// but the interface com.sun.star.frame.Frame has some bugs in 6.0
379 		hr = GetIDispByFunc( mpDispFactory, L"createInstance", &CComVariant( L"com.sun.star.frame.Frame" ), 1, mpDispFrame );
380 		if( !SUCCEEDED( hr ) ) return hr;
381 	}
382 
383 	// initialize frame
384 	CComVariant dummyResult;
385 	hr = ExecuteFunc( mpDispFrame, L"initialize", &CComVariant( mpDispWin ), 1, &dummyResult );
386 	if( !SUCCEEDED( hr ) ) return hr;
387 
388 	// create desktop
389 	CComPtr<IDispatch> pdispDesktop;
390 	hr = GetIDispByFunc( mpDispFactory, L"createInstance", &CComVariant( L"com.sun.star.frame.Desktop" ), 1, pdispDesktop );
391 	if( !SUCCEEDED( hr ) ) return hr;
392 
393 	// create tree of frames
394 	CComPtr<IDispatch> pdispChildren;
395 	hr = GetIDispByFunc( pdispDesktop, L"getFrames", NULL, 0, pdispChildren );
396 	if( !SUCCEEDED( hr ) ) return hr;
397 
398 	// insert new frame into desctop hierarchy
399 	hr = ExecuteFunc( pdispChildren, L"append", &CComVariant( mpDispFrame ), 1, &dummyResult );
400 	if( !SUCCEEDED( hr ) ) return hr;
401 
402 	// initialize window
403 	hr = ExecuteFunc( mpDispWin, L"setBackground", &CComVariant( (long)0xFFFFFFFF ), 1, &dummyResult );
404 	if( !SUCCEEDED( hr ) ) return hr;
405 
406 	hr = ExecuteFunc( mpDispWin, L"setVisible", &CComVariant( TRUE ), 1, &dummyResult );
407 	if( !SUCCEEDED( hr ) ) return hr;
408 
409 	CComVariant aPosArgs[5];
410 	aPosArgs[4] = CComVariant( 0 );
411 	aPosArgs[3] = CComVariant( 0 );
412 	aPosArgs[2] = CComVariant( width );
413 	aPosArgs[1] = CComVariant( height );
414 	aPosArgs[0] = CComVariant( 12 );
415 	hr = ExecuteFunc( mpDispWin, L"setPosSize", aPosArgs, 5, &dummyResult );
416 	if( !SUCCEEDED( hr ) ) return hr;
417 
418 
419 	return S_OK;
420 }
421 
422 HRESULT CSOActiveX::CallDispatch1PBool( OLECHAR* sUrl, OLECHAR* sArgName, BOOL sArgVal )
423 {
424 	CComPtr<IDispatch> pdispURL;
425 	HRESULT hr = GetUrlStruct( sUrl, pdispURL );
426 	if( !SUCCEEDED( hr ) ) return hr;
427 
428 	CComPtr<IDispatch> pdispXDispatch;
429 	CComVariant aArgs[3];
430 	aArgs[2] = CComVariant( pdispURL );
431 	aArgs[1] = CComVariant( L"" );
432 	aArgs[0] = CComVariant( (int)0 );
433 	hr = GetIDispByFunc( mpDispFrame,
434 						 L"queryDispatch",
435 						 aArgs,
436 						 3,
437 						 pdispXDispatch );
438 	if( !SUCCEEDED( hr ) ) return hr;
439 
440 	SAFEARRAY FAR* pPropVals = SafeArrayCreateVector( VT_DISPATCH, 0, 1 );
441 	long ix = 0;
442 	CComPtr<IDispatch> pdispPropVal;
443 	hr = GetUnoStruct( L"com.sun.star.beans.PropertyValue", pdispPropVal );
444 	if( !SUCCEEDED( hr ) ) return hr;
445 
446 	OLECHAR* 	sPropMemberNames[2] = { L"Name", L"Value" };
447 	CComVariant pPropVar[2];
448 	pPropVar[0] = CComVariant( sArgName );
449 	pPropVar[1] = CComVariant(); pPropVar[1].vt = VT_BOOL; pPropVar[1].boolVal = sArgVal ? VARIANT_TRUE : VARIANT_FALSE ;
450 	hr = PutPropertiesToIDisp( pdispPropVal, sPropMemberNames, pPropVar, 2 );
451 	if( !SUCCEEDED( hr ) ) return hr;
452 
453 	SafeArrayPutElement( pPropVals, &ix, pdispPropVal );
454 
455 	CComVariant aDispArgs[2];
456 	aDispArgs[1] = CComVariant( pdispURL );
457 	// aDispArgs[0] = CComVariant( pPropVals ); such constructor is not defined ??!
458 	aDispArgs[0] = CComVariant(); aDispArgs[0].vt = VT_ARRAY | VT_DISPATCH; aDispArgs[0].parray = pPropVals;
459 
460 	CComVariant dummyResult;
461 	hr = ExecuteFunc( pdispXDispatch, L"dispatch", aDispArgs, 2, &dummyResult );
462 	if( !SUCCEEDED( hr ) ) return hr;
463 
464 	return S_OK;
465 }
466 
467 HRESULT CSOActiveX::ShowSomeBars()
468 {
469 	// show FunctionBar and StatusBar
470 	for( int ind = 0; ind < BARS_TO_SHOW; ind ++ )
471 	{
472 		HRESULT hr = CallDispatch1PBool( pSlotUrl[ind], pSlotName[ind], TRUE );
473 		if( !SUCCEEDED( hr ) ) return hr;
474 	}
475 
476 	return S_OK;
477 }
478 
479 HRESULT CSOActiveX::HideAllBars()
480 {
481 	for( int ind = 0; ind < BARS_NUMBER; ind ++ )
482 	{
483 		HRESULT hr = CallDispatch1PBool( pSlotUrl[ind], pSlotName[ind], FALSE );
484 		if( !SUCCEEDED( hr ) ) return hr;
485 	}
486 
487 	return S_OK;
488 }
489 
490 HRESULT CSOActiveX::LoadURLToFrame( )
491 {
492 	HRESULT hr = CallDispatch1PBool( mCurFileUrl, L"ReadOnly", mbViewOnly );
493 	if( !SUCCEEDED( hr ) ) return hr;
494 
495 	if( mbViewOnly )
496 		HideAllBars();
497 
498 	return S_OK;
499 }
500 
501 HRESULT CSOActiveX::OnDrawAdvanced( ATL_DRAWINFO& di )
502 {
503     if( m_spInPlaceSite && mCurFileUrl )
504     {
505     	HWND hwnd;
506 	    HRESULT hr = m_spInPlaceSite->GetWindow( &hwnd );
507 		if( !SUCCEEDED( hr ) ) return hr;
508 
509         if( mParentWin != hwnd || !mOffWin )
510         {
511 			if( mpDispFrame )
512 			{
513 				CComVariant dummyResult;
514 				ExecuteFunc( mpDispFrame, L"dispose", NULL, 0, &dummyResult );
515 				mpDispFrame = CComPtr<IDispatch>();
516 			}
517 
518             mParentWin = hwnd;
519             mOffWin = CreateWindow(
520 								STAROFFICE_WINDOWCLASS,
521 								"OfficeContainer",
522 								WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,
523 								di.prcBounds->left,
524 								di.prcBounds->top,
525 								di.prcBounds->right - di.prcBounds->left,
526 								di.prcBounds->bottom - di.prcBounds->top,
527 								mParentWin,
528 								NULL,
529 								NULL,
530 								NULL );
531 
532 			::ShowWindow( mOffWin, SW_SHOW );
533         }
534         else
535         {
536             RECT aRect;
537             ::GetWindowRect( mOffWin, &aRect );
538 
539             if( aRect.left !=  di.prcBounds->left || aRect.top != di.prcBounds->top
540              || aRect.right != di.prcBounds->right || aRect.bottom != di.prcBounds->bottom )
541 			{
542 				// on this state the office window should exist already
543                 ::SetWindowPos( mOffWin,
544                               HWND_TOP,
545 							  di.prcBounds->left,
546 							  di.prcBounds->top,
547 							  di.prcBounds->right - di.prcBounds->left,
548 							  di.prcBounds->bottom - di.prcBounds->top,
549                               SWP_NOZORDER );
550 
551 				CComVariant aPosArgs[5];
552 				aPosArgs[4] = CComVariant( 0 );
553 				aPosArgs[3] = CComVariant( 0 );
554 				aPosArgs[2] = CComVariant( int(di.prcBounds->right - di.prcBounds->left) );
555 				aPosArgs[1] = CComVariant( int(di.prcBounds->bottom - di.prcBounds->top) );
556 				aPosArgs[0] = CComVariant( 12 );
557 				CComVariant dummyResult;
558 				hr = ExecuteFunc( mpDispWin, L"setPosSize", aPosArgs, 5, &dummyResult );
559 				if( !SUCCEEDED( hr ) ) return hr;
560 			}
561         }
562 
563 		if( ! mpDispFrame )
564 		{
565 			hr = CreateFrameOldWay( mOffWin,
566 							di.prcBounds->right - di.prcBounds->left,
567 							di.prcBounds->bottom - di.prcBounds->top );
568 			if( !SUCCEEDED( hr ) ) return hr;
569 		}
570 
571 		if( mbLoad )
572 		{
573 			hr = LoadURLToFrame();
574 			if( !SUCCEEDED( hr ) ) return hr;
575 			mbLoad = FALSE;
576 		}
577 	}
578 
579 	return S_OK;
580 }
581 
582 
583 STDMETHODIMP CSOActiveX::SetClientSite( IOleClientSite* aClientSite )
584 {
585 	HRESULT hr = IOleObjectImpl<CSOActiveX>::SetClientSite( aClientSite );
586 
587 	if( !aClientSite )
588 	{
589 		ATLASSERT( mWebBrowser2 );
590 		if( mWebBrowser2 )
591 			AtlUnadvise( mWebBrowser2, DIID_DWebBrowserEvents2, mCookie );
592 		return hr;
593 	}
594 
595 	CComPtr<IOleContainer> aContainer;
596 	m_spClientSite->GetContainer( &aContainer );
597 	ATLASSERT( aContainer );
598 
599 	if( SUCCEEDED( hr )  && aContainer )
600 	{
601 		CComQIPtr<IServiceProvider, &IID_IServiceProvider> aServiceProvider( aContainer );
602 		ATLASSERT( aServiceProvider );
603 
604 		if( aServiceProvider )
605 		{
606 			aServiceProvider->QueryService( SID_SInternetExplorer,
607 											IID_IWebBrowser,
608 											(void**)&mWebBrowser2 );
609 			ATLASSERT( mWebBrowser2 );
610 			if( mWebBrowser2 )
611 				AtlAdvise( mWebBrowser2, GetUnknown(), DIID_DWebBrowserEvents2, &mCookie );
612 		}
613 	}
614 
615 	return hr;
616 }
617 
618 STDMETHODIMP CSOActiveX::Invoke(DISPID dispidMember,
619 							    REFIID riid,
620 							    LCID lcid,
621                                 WORD wFlags,
622 							    DISPPARAMS* pDispParams,
623                                 VARIANT* pvarResult,
624 							    EXCEPINFO* pExcepInfo,
625                                 UINT* puArgErr)
626 {
627     if (riid != IID_NULL)
628         return DISP_E_UNKNOWNINTERFACE;
629 
630     if (!pDispParams)
631         return DISP_E_PARAMNOTOPTIONAL;
632 
633 	if ( dispidMember == DISPID_ONQUIT )
634 		Cleanup();
635 
636     IDispatchImpl<ISOActiveX, &IID_ISOActiveX,
637                   &LIBID_SO_ACTIVEXLib>::Invoke(
638              dispidMember, riid, lcid, wFlags, pDispParams,
639              pvarResult, pExcepInfo, puArgErr);
640 
641     return S_OK;
642 }
643 
644 // ---------------------------------------------------------------------------
645 
646