2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
27 $Log: ExplorerPlugin.cpp,v $
28 Revision 1.1 2004/01/30 03:01:56 bradley
29 Explorer Plugin to browse for Rendezvous-enabled Web and FTP servers from within Internet Explorer.
35 // The following 2 includes have to be in this order and INITGUID must be defined here, before including the file
36 // that specifies the GUID(s), and nowhere else. The reason for this is that initguid.h doesn't provide separate
37 // define and declare macros for GUIDs so you have to #define INITGUID in the single file where you want to define
38 // your GUID then in all the other files that just need the GUID declared, INITGUID must not be defined.
42 #include "ExplorerPlugin.h"
47 #include "CommonServices.h"
48 #include "DebugServices.h"
50 #include "ClassFactory.h"
58 static char THIS_FILE
[] = __FILE__
;
62 #pragma mark == Prototypes ==
65 //===========================================================================================================================
67 //===========================================================================================================================
71 extern "C" BOOL WINAPI
DllMain( HINSTANCE inInstance
, DWORD inReason
, LPVOID inReserved
);
75 DEBUG_LOCAL OSStatus
MFCDLLProcessAttach( HINSTANCE inInstance
);
76 DEBUG_LOCAL
void MFCDLLProcessDetach( HINSTANCE inInstance
);
77 DEBUG_LOCAL
void MFCDLLThreadDetach( HINSTANCE inInstance
);
81 DEBUG_LOCAL OSStatus
RegisterServer( HINSTANCE inInstance
, CLSID inCLSID
, LPCTSTR inName
);
82 DEBUG_LOCAL OSStatus
RegisterCOMCategory( CLSID inCLSID
, CATID inCategoryID
, BOOL inRegister
);
85 #pragma mark == Globals ==
88 //===========================================================================================================================
90 //===========================================================================================================================
92 HINSTANCE gInstance
= NULL
;
98 #pragma mark == DLL Exports ==
101 //===========================================================================================================================
103 //===========================================================================================================================
105 BOOL WINAPI
DllMain( HINSTANCE inInstance
, DWORD inReason
, LPVOID inReserved
)
110 DEBUG_UNUSED( inReserved
);
115 case DLL_PROCESS_ATTACH
:
116 gInstance
= inInstance
;
117 debug_initialize( kDebugOutputTypeWindowsEventLog
, "RendezvousBar", inInstance
);
118 debug_set_property( kDebugPropertyTagPrintLevel
, kDebugLevelTrace
);
119 dlog( kDebugLevelTrace
, "\nDllMain: process attach\n" );
121 err
= MFCDLLProcessAttach( inInstance
);
122 ok
= ( err
== kNoErr
);
123 require_noerr( err
, exit
);
126 case DLL_PROCESS_DETACH
:
127 dlog( kDebugLevelTrace
, "DllMain: process detach\n" );
128 MFCDLLProcessDetach( inInstance
);
131 case DLL_THREAD_ATTACH
:
132 dlog( kDebugLevelTrace
, "DllMain: thread attach\n" );
135 case DLL_THREAD_DETACH
:
136 dlog( kDebugLevelTrace
, "DllMain: thread detach\n" );
137 MFCDLLThreadDetach( inInstance
);
141 dlog( kDebugLevelTrace
, "DllMain: unknown reason code (%d)\n",inReason
);
149 //===========================================================================================================================
151 //===========================================================================================================================
153 STDAPI
DllCanUnloadNow( void )
155 dlog( kDebugLevelTrace
, "DllCanUnloadNow (refCount=%d)\n", gDLLRefCount
);
157 return( gDLLRefCount
== 0 );
160 //===========================================================================================================================
162 //===========================================================================================================================
164 STDAPI
DllGetClassObject( REFCLSID inCLSID
, REFIID inIID
, LPVOID
*outResult
)
168 ClassFactory
* factory
;
170 dlog( kDebugLevelTrace
, "DllGetClassObject\n" );
174 // Check if the class ID is supported.
176 ok
= IsEqualCLSID( inCLSID
, CLSID_ExplorerBar
);
177 require_action_quiet( ok
, exit
, err
= CLASS_E_CLASSNOTAVAILABLE
);
179 // Create the ClassFactory object.
184 factory
= new ClassFactory( inCLSID
);
188 // Do not let exception escape.
190 require_action( factory
, exit
, err
= E_OUTOFMEMORY
);
192 // Query for the specified interface. Release the factory since QueryInterface retains it.
194 err
= factory
->QueryInterface( inIID
, outResult
);
201 //===========================================================================================================================
203 //===========================================================================================================================
205 STDAPI
DllRegisterServer( void )
211 dlog( kDebugLevelTrace
, "DllRegisterServer\n" );
213 ok
= s
.LoadString( IDS_NAME
);
214 require_action( ok
, exit
, err
= E_UNEXPECTED
);
216 err
= RegisterServer( gInstance
, CLSID_ExplorerBar
, s
);
217 require_noerr( err
, exit
);
219 err
= RegisterCOMCategory( CLSID_ExplorerBar
, CATID_InfoBand
, TRUE
);
220 require_noerr( err
, exit
);
226 //===========================================================================================================================
227 // DllUnregisterServer
228 //===========================================================================================================================
230 STDAPI
DllUnregisterServer( void )
234 dlog( kDebugLevelTrace
, "DllUnregisterServer\n" );
236 err
= RegisterCOMCategory( CLSID_ExplorerBar
, CATID_InfoBand
, FALSE
);
237 require_noerr( err
, exit
);
245 #pragma mark == MFC Support ==
248 //===========================================================================================================================
249 // MFCDLLProcessAttach
250 //===========================================================================================================================
252 DEBUG_LOCAL OSStatus
MFCDLLProcessAttach( HINSTANCE inInstance
)
255 _AFX_THREAD_STATE
* threadState
;
256 AFX_MODULE_STATE
* previousModuleState
;
262 // Simulate what is done in dllmodul.cpp.
264 threadState
= AfxGetThreadState();
265 check( threadState
);
266 previousModuleState
= threadState
->m_pPrevModuleState
;
268 ok
= AfxWinInit( inInstance
, NULL
, TEXT( "" ), 0 );
269 require_action( ok
, exit
, err
= kUnknownErr
);
272 require_action( ok
, exit
, err
= kNotInitializedErr
);
274 ok
= app
->InitInstance();
275 require_action( ok
, exit
, err
= kUnknownErr
);
277 threadState
->m_pPrevModuleState
= previousModuleState
;
279 AfxInitLocalData( inInstance
);
293 threadState
->m_pPrevModuleState
= previousModuleState
;
298 //===========================================================================================================================
299 // MFCDLLProcessDetach
300 //===========================================================================================================================
302 DEBUG_LOCAL
void MFCDLLProcessDetach( HINSTANCE inInstance
)
306 // Simulate what is done in dllmodul.cpp.
315 if( AfxGetModuleThreadState()->m_nTempMapLock
!= 0 )
317 dlog( kDebugLevelWarning
, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock
);
322 AfxUnlockTempMaps( -1 );
324 // Terminate the library before destructors are called.
327 AfxTermLocalData( inInstance
, TRUE
);
330 //===========================================================================================================================
332 //===========================================================================================================================
334 DEBUG_LOCAL
void MFCDLLThreadDetach( HINSTANCE inInstance
)
336 // Simulate what is done in dllmodul.cpp.
339 if( AfxGetModuleThreadState()->m_nTempMapLock
!= 0 )
341 dlog( kDebugLevelWarning
, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock
);
346 AfxUnlockTempMaps( -1 );
347 AfxTermThread( inInstance
);
352 #pragma mark == Utilities ==
355 //===========================================================================================================================
357 //===========================================================================================================================
359 DEBUG_LOCAL OSStatus
RegisterServer( HINSTANCE inInstance
, CLSID inCLSID
, LPCTSTR inName
)
361 typedef struct RegistryBuilder RegistryBuilder
;
362 struct RegistryBuilder
371 LPWSTR clsidWideString
;
372 TCHAR clsidString
[ 64 ];
377 TCHAR keyName
[ MAX_PATH
];
378 TCHAR moduleName
[ MAX_PATH
] = TEXT( "" );
379 TCHAR data
[ MAX_PATH
];
380 RegistryBuilder entries
[] =
382 { HKEY_CLASSES_ROOT
, TEXT( "CLSID\\%s" ), NULL
, inName
},
383 { HKEY_CLASSES_ROOT
, TEXT( "CLSID\\%s\\InprocServer32" ), NULL
, moduleName
},
384 { HKEY_CLASSES_ROOT
, TEXT( "CLSID\\%s\\InprocServer32" ), TEXT( "ThreadingModel" ), TEXT( "Apartment" ) }
387 OSVERSIONINFO versionInfo
;
389 // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
391 err
= StringFromIID( inCLSID
, &clsidWideString
);
392 require_noerr( err
, exit
);
393 require_action( clsidWideString
, exit
, err
= kNoMemoryErr
);
396 lstrcpyn( clsidString
, clsidWideString
, sizeof_array( clsidString
) );
397 CoTaskMemFree( clsidWideString
);
399 nChars
= WideCharToMultiByte( CP_ACP
, 0, clsidWideString
, -1, clsidString
, sizeof_array( clsidString
), NULL
, NULL
);
400 err
= translate_errno( nChars
> 0, (OSStatus
) GetLastError(), kUnknownErr
);
401 CoTaskMemFree( clsidWideString
);
402 require_noerr( err
, exit
);
405 // Register the CLSID entries.
407 nChars
= GetModuleFileName( inInstance
, moduleName
, sizeof_array( moduleName
) );
408 err
= translate_errno( nChars
> 0, (OSStatus
) GetLastError(), kUnknownErr
);
409 require_noerr( err
, exit
);
411 n
= sizeof_array( entries
);
412 for( i
= 0; i
< n
; ++i
)
414 wsprintf( keyName
, entries
[ i
].subKey
, clsidString
);
415 err
= RegCreateKeyEx( entries
[ i
].rootKey
, keyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &key
, NULL
);
416 require_noerr( err
, exit
);
418 size
= (DWORD
)( ( lstrlen( entries
[ i
].data
) + 1 ) * sizeof( TCHAR
) );
419 err
= RegSetValueEx( key
, entries
[ i
].valueName
, 0, REG_SZ
, (LPBYTE
) entries
[ i
].data
, size
);
421 require_noerr( err
, exit
);
424 // If running on NT, register the extension as approved.
426 versionInfo
.dwOSVersionInfoSize
= sizeof( versionInfo
);
427 GetVersionEx( &versionInfo
);
428 if( versionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
430 lstrcpyn( keyName
, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName
) );
431 err
= RegCreateKeyEx( HKEY_LOCAL_MACHINE
, keyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &key
, NULL
);
432 require_noerr( err
, exit
);
434 lstrcpyn( data
, inName
, sizeof_array( data
) );
435 size
= (DWORD
)( ( lstrlen( data
) + 1 ) * sizeof( TCHAR
) );
436 err
= RegSetValueEx( key
, clsidString
, 0, REG_SZ
, (LPBYTE
) data
, size
);
445 //===========================================================================================================================
446 // RegisterCOMCategory
447 //===========================================================================================================================
449 DEBUG_LOCAL OSStatus
RegisterCOMCategory( CLSID inCLSID
, CATID inCategoryID
, BOOL inRegister
)
454 err
= CoInitialize( NULL
);
455 require( SUCCEEDED( err
), exit
);
457 err
= CoCreateInstance( CLSID_StdComponentCategoriesMgr
, NULL
, CLSCTX_INPROC_SERVER
, IID_ICatRegister
, (LPVOID
*) &cat
);
458 check( SUCCEEDED( err
) );
459 if( SUCCEEDED( err
) )
463 err
= cat
->RegisterClassImplCategories( inCLSID
, 1, &inCategoryID
);
468 err
= cat
->UnRegisterClassImplCategories( inCLSID
, 1, &inCategoryID
);