]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/Applications/ExplorerPlugin/ExplorerPlugin.cpp
95285776830c2f9c5177a0180c13c9727f0c1817
[apple/mdnsresponder.git] / mDNSWindows / Applications / ExplorerPlugin / ExplorerPlugin.cpp
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
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.
30
31 */
32
33 #include "StdAfx.h"
34
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.
39
40 #define INITGUID
41 #include <initguid.h>
42 #include "ExplorerPlugin.h"
43
44 #include <comcat.h>
45 #include <Shlwapi.h>
46
47 #include "CommonServices.h"
48 #include "DebugServices.h"
49
50 #include "ClassFactory.h"
51 #include "Resource.h"
52
53 // MFC Debugging
54
55 #ifdef _DEBUG
56 #define new DEBUG_NEW
57 #undef THIS_FILE
58 static char THIS_FILE[] = __FILE__;
59 #endif
60
61 #if 0
62 #pragma mark == Prototypes ==
63 #endif
64
65 //===========================================================================================================================
66 // Prototypes
67 //===========================================================================================================================
68
69 // DLL Exports
70
71 extern "C" BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved );
72
73 // MFC Support
74
75 DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance );
76 DEBUG_LOCAL void MFCDLLProcessDetach( HINSTANCE inInstance );
77 DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance );
78
79 // Utilities
80
81 DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName );
82 DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister );
83
84 #if 0
85 #pragma mark == Globals ==
86 #endif
87
88 //===========================================================================================================================
89 // Globals
90 //===========================================================================================================================
91
92 HINSTANCE gInstance = NULL;
93 int gDLLRefCount = 0;
94 CWinApp gApp;
95
96 #if 0
97 #pragma mark -
98 #pragma mark == DLL Exports ==
99 #endif
100
101 //===========================================================================================================================
102 // DllMain
103 //===========================================================================================================================
104
105 BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
106 {
107 BOOL ok;
108 OSStatus err;
109
110 DEBUG_UNUSED( inReserved );
111
112 ok = TRUE;
113 switch( inReason )
114 {
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" );
120
121 err = MFCDLLProcessAttach( inInstance );
122 ok = ( err == kNoErr );
123 require_noerr( err, exit );
124 break;
125
126 case DLL_PROCESS_DETACH:
127 dlog( kDebugLevelTrace, "DllMain: process detach\n" );
128 MFCDLLProcessDetach( inInstance );
129 break;
130
131 case DLL_THREAD_ATTACH:
132 dlog( kDebugLevelTrace, "DllMain: thread attach\n" );
133 break;
134
135 case DLL_THREAD_DETACH:
136 dlog( kDebugLevelTrace, "DllMain: thread detach\n" );
137 MFCDLLThreadDetach( inInstance );
138 break;
139
140 default:
141 dlog( kDebugLevelTrace, "DllMain: unknown reason code (%d)\n",inReason );
142 break;
143 }
144
145 exit:
146 return( ok );
147 }
148
149 //===========================================================================================================================
150 // DllCanUnloadNow
151 //===========================================================================================================================
152
153 STDAPI DllCanUnloadNow( void )
154 {
155 dlog( kDebugLevelTrace, "DllCanUnloadNow (refCount=%d)\n", gDLLRefCount );
156
157 return( gDLLRefCount == 0 );
158 }
159
160 //===========================================================================================================================
161 // DllGetClassObject
162 //===========================================================================================================================
163
164 STDAPI DllGetClassObject( REFCLSID inCLSID, REFIID inIID, LPVOID *outResult )
165 {
166 HRESULT err;
167 BOOL ok;
168 ClassFactory * factory;
169
170 dlog( kDebugLevelTrace, "DllGetClassObject\n" );
171
172 *outResult = NULL;
173
174 // Check if the class ID is supported.
175
176 ok = IsEqualCLSID( inCLSID, CLSID_ExplorerBar );
177 require_action_quiet( ok, exit, err = CLASS_E_CLASSNOTAVAILABLE );
178
179 // Create the ClassFactory object.
180
181 factory = NULL;
182 try
183 {
184 factory = new ClassFactory( inCLSID );
185 }
186 catch( ... )
187 {
188 // Do not let exception escape.
189 }
190 require_action( factory, exit, err = E_OUTOFMEMORY );
191
192 // Query for the specified interface. Release the factory since QueryInterface retains it.
193
194 err = factory->QueryInterface( inIID, outResult );
195 factory->Release();
196
197 exit:
198 return( err );
199 }
200
201 //===========================================================================================================================
202 // DllRegisterServer
203 //===========================================================================================================================
204
205 STDAPI DllRegisterServer( void )
206 {
207 HRESULT err;
208 BOOL ok;
209 CString s;
210
211 dlog( kDebugLevelTrace, "DllRegisterServer\n" );
212
213 ok = s.LoadString( IDS_NAME );
214 require_action( ok, exit, err = E_UNEXPECTED );
215
216 err = RegisterServer( gInstance, CLSID_ExplorerBar, s );
217 require_noerr( err, exit );
218
219 err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, TRUE );
220 require_noerr( err, exit );
221
222 exit:
223 return( err );
224 }
225
226 //===========================================================================================================================
227 // DllUnregisterServer
228 //===========================================================================================================================
229
230 STDAPI DllUnregisterServer( void )
231 {
232 HRESULT err;
233
234 dlog( kDebugLevelTrace, "DllUnregisterServer\n" );
235
236 err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE );
237 require_noerr( err, exit );
238
239 exit:
240 return( err );
241 }
242
243 #if 0
244 #pragma mark -
245 #pragma mark == MFC Support ==
246 #endif
247
248 //===========================================================================================================================
249 // MFCDLLProcessAttach
250 //===========================================================================================================================
251
252 DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance )
253 {
254 OSStatus err;
255 _AFX_THREAD_STATE * threadState;
256 AFX_MODULE_STATE * previousModuleState;
257 BOOL ok;
258 CWinApp * app;
259
260 app = NULL;
261
262 // Simulate what is done in dllmodul.cpp.
263
264 threadState = AfxGetThreadState();
265 check( threadState );
266 previousModuleState = threadState->m_pPrevModuleState;
267
268 ok = AfxWinInit( inInstance, NULL, TEXT( "" ), 0 );
269 require_action( ok, exit, err = kUnknownErr );
270
271 app = AfxGetApp();
272 require_action( ok, exit, err = kNotInitializedErr );
273
274 ok = app->InitInstance();
275 require_action( ok, exit, err = kUnknownErr );
276
277 threadState->m_pPrevModuleState = previousModuleState;
278 threadState = NULL;
279 AfxInitLocalData( inInstance );
280 err = kNoErr;
281
282 exit:
283 if( err )
284 {
285 if( app )
286 {
287 app->ExitInstance();
288 }
289 AfxWinTerm();
290 }
291 if( threadState )
292 {
293 threadState->m_pPrevModuleState = previousModuleState;
294 }
295 return( err );
296 }
297
298 //===========================================================================================================================
299 // MFCDLLProcessDetach
300 //===========================================================================================================================
301
302 DEBUG_LOCAL void MFCDLLProcessDetach( HINSTANCE inInstance )
303 {
304 CWinApp * app;
305
306 // Simulate what is done in dllmodul.cpp.
307
308 app = AfxGetApp();
309 if( app )
310 {
311 app->ExitInstance();
312 }
313
314 #if( DEBUG )
315 if( AfxGetModuleThreadState()->m_nTempMapLock != 0 )
316 {
317 dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock );
318 }
319 #endif
320
321 AfxLockTempMaps();
322 AfxUnlockTempMaps( -1 );
323
324 // Terminate the library before destructors are called.
325
326 AfxWinTerm();
327 AfxTermLocalData( inInstance, TRUE );
328 }
329
330 //===========================================================================================================================
331 // MFCDLLFinalize
332 //===========================================================================================================================
333
334 DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance )
335 {
336 // Simulate what is done in dllmodul.cpp.
337
338 #if( DEBUG )
339 if( AfxGetModuleThreadState()->m_nTempMapLock != 0 )
340 {
341 dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock );
342 }
343 #endif
344
345 AfxLockTempMaps();
346 AfxUnlockTempMaps( -1 );
347 AfxTermThread( inInstance );
348 }
349
350 #if 0
351 #pragma mark -
352 #pragma mark == Utilities ==
353 #endif
354
355 //===========================================================================================================================
356 // RegisterServer
357 //===========================================================================================================================
358
359 DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName )
360 {
361 typedef struct RegistryBuilder RegistryBuilder;
362 struct RegistryBuilder
363 {
364 HKEY rootKey;
365 LPCTSTR subKey;
366 LPCTSTR valueName;
367 LPCTSTR data;
368 };
369
370 OSStatus err;
371 LPWSTR clsidWideString;
372 TCHAR clsidString[ 64 ];
373 DWORD nChars;
374 size_t n;
375 size_t i;
376 HKEY key;
377 TCHAR keyName[ MAX_PATH ];
378 TCHAR moduleName[ MAX_PATH ] = TEXT( "" );
379 TCHAR data[ MAX_PATH ];
380 RegistryBuilder entries[] =
381 {
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" ) }
385 };
386 DWORD size;
387 OSVERSIONINFO versionInfo;
388
389 // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
390
391 err = StringFromIID( inCLSID, &clsidWideString );
392 require_noerr( err, exit );
393 require_action( clsidWideString, exit, err = kNoMemoryErr );
394
395 #ifdef UNICODE
396 lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) );
397 CoTaskMemFree( clsidWideString );
398 #else
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 );
403 #endif
404
405 // Register the CLSID entries.
406
407 nChars = GetModuleFileName( inInstance, moduleName, sizeof_array( moduleName ) );
408 err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
409 require_noerr( err, exit );
410
411 n = sizeof_array( entries );
412 for( i = 0; i < n; ++i )
413 {
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 );
417
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 );
420 RegCloseKey( key );
421 require_noerr( err, exit );
422 }
423
424 // If running on NT, register the extension as approved.
425
426 versionInfo.dwOSVersionInfoSize = sizeof( versionInfo );
427 GetVersionEx( &versionInfo );
428 if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
429 {
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 );
433
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 );
437 RegCloseKey( key );
438 }
439 err = kNoErr;
440
441 exit:
442 return( err );
443 }
444
445 //===========================================================================================================================
446 // RegisterCOMCategory
447 //===========================================================================================================================
448
449 DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister )
450 {
451 HRESULT err;
452 ICatRegister * cat;
453
454 err = CoInitialize( NULL );
455 require( SUCCEEDED( err ), exit );
456
457 err = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID *) &cat );
458 check( SUCCEEDED( err ) );
459 if( SUCCEEDED( err ) )
460 {
461 if( inRegister )
462 {
463 err = cat->RegisterClassImplCategories( inCLSID, 1, &inCategoryID );
464 check_noerr( err );
465 }
466 else
467 {
468 err = cat->UnRegisterClassImplCategories( inCLSID, 1, &inCategoryID );
469 check_noerr( err );
470 }
471 cat->Release();
472 }
473 CoUninitialize();
474
475 exit:
476 return( err );
477 }