]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/ExplorerPlugin/ExplorerPlugin.cpp
mDNSResponder-107.5.tar.gz
[apple/mdnsresponder.git] / Clients / ExplorerPlugin / ExplorerPlugin.cpp
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: ExplorerPlugin.cpp,v $
26 Revision 1.8 2005/06/30 18:01:54 shersche
27 <rdar://problem/4130635> Cause IE to rebuild cache so we don't have to reboot following an install.
28
29 Revision 1.7 2005/02/23 02:00:45 shersche
30 <rdar://problem/4014479> Delete all the registry entries when component is unregistered
31
32 Revision 1.6 2005/01/25 17:56:45 shersche
33 <rdar://problem/3911084> Load resource DLLs, get icons and bitmaps from resource DLLs
34 Bug #: 3911084
35
36 Revision 1.5 2004/09/15 10:33:54 shersche
37 <rdar://problem/3721611> Install XP toolbar button (8 bit mask) if running on XP platform, otherwise install 1 bit mask toolbar button
38 Bug #: 3721611
39
40 Revision 1.4 2004/07/13 21:24:21 rpantos
41 Fix for <rdar://problem/3701120>.
42
43 Revision 1.3 2004/06/26 14:12:07 shersche
44 Register the toolbar button
45
46 Revision 1.2 2004/06/24 20:09:39 shersche
47 Change text
48 Submitted by: herscher
49
50 Revision 1.1 2004/06/18 04:34:59 rpantos
51 Move to Clients from mDNSWindows
52
53 Revision 1.1 2004/01/30 03:01:56 bradley
54 Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
55
56 */
57
58 #include "StdAfx.h"
59
60 // The following 2 includes have to be in this order and INITGUID must be defined here, before including the file
61 // that specifies the GUID(s), and nowhere else. The reason for this is that initguid.h doesn't provide separate
62 // define and declare macros for GUIDs so you have to #define INITGUID in the single file where you want to define
63 // your GUID then in all the other files that just need the GUID declared, INITGUID must not be defined.
64
65 #define INITGUID
66 #include <initguid.h>
67 #include "ExplorerPlugin.h"
68
69 #include <comcat.h>
70 #include <Shlwapi.h>
71
72 #include "CommonServices.h"
73 #include "DebugServices.h"
74
75 #include "ClassFactory.h"
76 #include "Resource.h"
77
78 #include "loclibrary.h"
79
80 // MFC Debugging
81
82 #ifdef _DEBUG
83 #define new DEBUG_NEW
84 #undef THIS_FILE
85 static char THIS_FILE[] = __FILE__;
86 #endif
87
88 #if 0
89 #pragma mark == Prototypes ==
90 #endif
91
92 //===========================================================================================================================
93 // Prototypes
94 //===========================================================================================================================
95
96 // DLL Exports
97
98 extern "C" BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved );
99
100 // MFC Support
101
102 DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance );
103 DEBUG_LOCAL void MFCDLLProcessDetach( HINSTANCE inInstance );
104 DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance );
105
106 // Utilities
107
108 DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName );
109 DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister );
110 DEBUG_LOCAL OSStatus UnregisterServer( CLSID inCLSID );
111 DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey );
112
113 // Stash away pointers to our resource DLLs
114
115 static HINSTANCE g_nonLocalizedResources = NULL;
116 static CString g_nonLocalizedResourcesName;
117 static HINSTANCE g_localizedResources = NULL;
118
119 HINSTANCE
120 GetNonLocalizedResources()
121 {
122 return g_nonLocalizedResources;
123 }
124
125 HINSTANCE
126 GetLocalizedResources()
127 {
128 return g_localizedResources;
129 }
130
131 // This is the class GUID for an undocumented hook into IE that will allow us to register
132 // and have IE notice our new ExplorerBar without rebooting.
133 // {8C7461EF-2B13-11d2-BE35-3078302C2030}
134
135 DEFINE_GUID(CLSID_CompCatCacheDaemon,
136 0x8C7461EF, 0x2b13, 0x11d2, 0xbe, 0x35, 0x30, 0x78, 0x30, 0x2c, 0x20, 0x30);
137
138
139 #if 0
140 #pragma mark == Globals ==
141 #endif
142
143 //===========================================================================================================================
144 // Globals
145 //===========================================================================================================================
146
147 HINSTANCE gInstance = NULL;
148 int gDLLRefCount = 0;
149 CWinApp gApp;
150
151 #if 0
152 #pragma mark -
153 #pragma mark == DLL Exports ==
154 #endif
155
156 //===========================================================================================================================
157 // DllMain
158 //===========================================================================================================================
159
160 BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
161 {
162 BOOL ok;
163 OSStatus err;
164
165 DEBUG_UNUSED( inReserved );
166
167 ok = TRUE;
168 switch( inReason )
169 {
170 case DLL_PROCESS_ATTACH:
171 gInstance = inInstance;
172 debug_initialize( kDebugOutputTypeWindowsEventLog, "DNSServices Bar", inInstance );
173 debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
174 dlog( kDebugLevelTrace, "\nDllMain: process attach\n" );
175
176 err = MFCDLLProcessAttach( inInstance );
177 ok = ( err == kNoErr );
178 require_noerr( err, exit );
179 break;
180
181 case DLL_PROCESS_DETACH:
182 dlog( kDebugLevelTrace, "DllMain: process detach\n" );
183 MFCDLLProcessDetach( inInstance );
184 break;
185
186 case DLL_THREAD_ATTACH:
187 dlog( kDebugLevelTrace, "DllMain: thread attach\n" );
188 break;
189
190 case DLL_THREAD_DETACH:
191 dlog( kDebugLevelTrace, "DllMain: thread detach\n" );
192 MFCDLLThreadDetach( inInstance );
193 break;
194
195 default:
196 dlog( kDebugLevelTrace, "DllMain: unknown reason code (%d)\n",inReason );
197 break;
198 }
199
200 exit:
201 return( ok );
202 }
203
204 //===========================================================================================================================
205 // DllCanUnloadNow
206 //===========================================================================================================================
207
208 STDAPI DllCanUnloadNow( void )
209 {
210 dlog( kDebugLevelTrace, "DllCanUnloadNow (refCount=%d)\n", gDLLRefCount );
211
212 return( gDLLRefCount == 0 );
213 }
214
215 //===========================================================================================================================
216 // DllGetClassObject
217 //===========================================================================================================================
218
219 STDAPI DllGetClassObject( REFCLSID inCLSID, REFIID inIID, LPVOID *outResult )
220 {
221 HRESULT err;
222 BOOL ok;
223 ClassFactory * factory;
224
225 dlog( kDebugLevelTrace, "DllGetClassObject\n" );
226
227 *outResult = NULL;
228
229 // Check if the class ID is supported.
230
231 ok = IsEqualCLSID( inCLSID, CLSID_ExplorerBar );
232 require_action_quiet( ok, exit, err = CLASS_E_CLASSNOTAVAILABLE );
233
234 // Create the ClassFactory object.
235
236 factory = NULL;
237 try
238 {
239 factory = new ClassFactory( inCLSID );
240 }
241 catch( ... )
242 {
243 // Do not let exception escape.
244 }
245 require_action( factory, exit, err = E_OUTOFMEMORY );
246
247 // Query for the specified interface. Release the factory since QueryInterface retains it.
248
249 err = factory->QueryInterface( inIID, outResult );
250 factory->Release();
251
252 exit:
253 return( err );
254 }
255
256 //===========================================================================================================================
257 // DllRegisterServer
258 //===========================================================================================================================
259
260 STDAPI DllRegisterServer( void )
261 {
262 IRunnableTask * pTask = NULL;
263 HRESULT err;
264 BOOL ok;
265 CString s;
266
267 dlog( kDebugLevelTrace, "DllRegisterServer\n" );
268
269 ok = s.LoadString( IDS_NAME );
270 require_action( ok, exit, err = E_UNEXPECTED );
271
272 err = RegisterServer( gInstance, CLSID_ExplorerBar, s );
273 require_noerr( err, exit );
274
275 err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, TRUE );
276 require_noerr( err, exit );
277
278 // <rdar://problem/4130635> Clear IE cache so it will rebuild the cache when it runs next. This
279 // will allow us to install and not reboot
280
281 err = CoCreateInstance(CLSID_CompCatCacheDaemon, NULL, CLSCTX_INPROC, IID_IRunnableTask, (void**) &pTask);
282 require_noerr( err, exit );
283
284 pTask->Run();
285 pTask->Release();
286
287 exit:
288 return( err );
289 }
290
291 //===========================================================================================================================
292 // DllUnregisterServer
293 //===========================================================================================================================
294
295 STDAPI DllUnregisterServer( void )
296 {
297 HRESULT err;
298
299 dlog( kDebugLevelTrace, "DllUnregisterServer\n" );
300
301 err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE );
302 require_noerr( err, exit );
303
304 err = UnregisterServer( CLSID_ExplorerBar );
305 require_noerr( err, exit );
306
307 exit:
308 return( err );
309 }
310
311 #if 0
312 #pragma mark -
313 #pragma mark == MFC Support ==
314 #endif
315
316 //===========================================================================================================================
317 // MFCDLLProcessAttach
318 //===========================================================================================================================
319
320 DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance )
321 {
322 wchar_t resource[MAX_PATH];
323 OSStatus err;
324 _AFX_THREAD_STATE * threadState;
325 AFX_MODULE_STATE * previousModuleState;
326 BOOL ok;
327 int res;
328 CWinApp * app;
329
330 app = NULL;
331
332 // Simulate what is done in dllmodul.cpp.
333
334 threadState = AfxGetThreadState();
335 check( threadState );
336 previousModuleState = threadState->m_pPrevModuleState;
337
338 ok = AfxWinInit( inInstance, NULL, TEXT( "" ), 0 );
339 require_action( ok, exit, err = kUnknownErr );
340
341 app = AfxGetApp();
342 require_action( ok, exit, err = kNotInitializedErr );
343
344 // Before we load the resources, let's load the error string
345
346 // errorMessage.LoadString( IDS_REINSTALL );
347 // errorCaption.LoadString( IDS_REINSTALL_CAPTION );
348
349 // Load Resources
350
351 res = PathForResource( inInstance, L"ExplorerPluginResources.dll", resource, MAX_PATH );
352
353 err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
354 require_noerr( err, exit );
355
356 g_nonLocalizedResources = LoadLibrary( resource );
357 translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
358 require_noerr( err, exit );
359
360 g_nonLocalizedResourcesName = resource;
361
362 res = PathForResource( inInstance, L"ExplorerPluginLocalized.dll", resource, MAX_PATH );
363 err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
364 require_noerr( err, exit );
365
366 g_localizedResources = LoadLibrary( resource );
367 translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
368 require_noerr( err, exit );
369
370 AfxSetResourceHandle( g_localizedResources );
371
372 ok = app->InitInstance();
373 require_action( ok, exit, err = kUnknownErr );
374
375 threadState->m_pPrevModuleState = previousModuleState;
376 threadState = NULL;
377 AfxInitLocalData( inInstance );
378 err = kNoErr;
379
380 exit:
381 if( err )
382 {
383 if( app )
384 {
385 app->ExitInstance();
386 }
387 AfxWinTerm();
388 }
389 if( threadState )
390 {
391 threadState->m_pPrevModuleState = previousModuleState;
392 }
393 return( err );
394 }
395
396 //===========================================================================================================================
397 // MFCDLLProcessDetach
398 //===========================================================================================================================
399
400 DEBUG_LOCAL void MFCDLLProcessDetach( HINSTANCE inInstance )
401 {
402 CWinApp * app;
403
404 // Simulate what is done in dllmodul.cpp.
405
406 app = AfxGetApp();
407 if( app )
408 {
409 app->ExitInstance();
410 }
411
412 #if( DEBUG )
413 if( AfxGetModuleThreadState()->m_nTempMapLock != 0 )
414 {
415 dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock );
416 }
417 #endif
418
419 AfxLockTempMaps();
420 AfxUnlockTempMaps( -1 );
421
422 // Terminate the library before destructors are called.
423
424 AfxWinTerm();
425 AfxTermLocalData( inInstance, TRUE );
426 }
427
428 //===========================================================================================================================
429 // MFCDLLFinalize
430 //===========================================================================================================================
431
432 DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance )
433 {
434 // Simulate what is done in dllmodul.cpp.
435
436 #if( DEBUG )
437 if( AfxGetModuleThreadState()->m_nTempMapLock != 0 )
438 {
439 dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock );
440 }
441 #endif
442
443 AfxLockTempMaps();
444 AfxUnlockTempMaps( -1 );
445 AfxTermThread( inInstance );
446 }
447
448 #if 0
449 #pragma mark -
450 #pragma mark == Utilities ==
451 #endif
452
453 //===========================================================================================================================
454 // RegisterServer
455 //===========================================================================================================================
456
457 DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName )
458 {
459 typedef struct RegistryBuilder RegistryBuilder;
460 struct RegistryBuilder
461 {
462 HKEY rootKey;
463 LPCTSTR subKey;
464 LPCTSTR valueName;
465 LPCTSTR data;
466 };
467
468 OSStatus err;
469 LPWSTR clsidWideString;
470 TCHAR clsidString[ 64 ];
471 DWORD nChars;
472 size_t n;
473 size_t i;
474 HKEY key;
475 TCHAR keyName[ MAX_PATH ];
476 TCHAR moduleName[ MAX_PATH ] = TEXT( "" );
477 TCHAR data[ MAX_PATH ];
478 RegistryBuilder entries[] =
479 {
480 { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), NULL, inName },
481 { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s\\InprocServer32" ), NULL, moduleName },
482 { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s\\InprocServer32" ), TEXT( "ThreadingModel" ), TEXT( "Apartment" ) }
483 };
484 DWORD size;
485 OSVERSIONINFO versionInfo;
486
487 // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
488
489 err = StringFromIID( inCLSID, &clsidWideString );
490 require_noerr( err, exit );
491 require_action( clsidWideString, exit, err = kNoMemoryErr );
492
493 #ifdef UNICODE
494 lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) );
495 CoTaskMemFree( clsidWideString );
496 #else
497 nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL );
498 err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
499 CoTaskMemFree( clsidWideString );
500 require_noerr( err, exit );
501 #endif
502
503 // Register the CLSID entries.
504
505 nChars = GetModuleFileName( inInstance, moduleName, sizeof_array( moduleName ) );
506 err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
507 require_noerr( err, exit );
508
509 n = sizeof_array( entries );
510 for( i = 0; i < n; ++i )
511 {
512 wsprintf( keyName, entries[ i ].subKey, clsidString );
513 err = RegCreateKeyEx( entries[ i ].rootKey, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
514 require_noerr( err, exit );
515
516 size = (DWORD)( ( lstrlen( entries[ i ].data ) + 1 ) * sizeof( TCHAR ) );
517 err = RegSetValueEx( key, entries[ i ].valueName, 0, REG_SZ, (LPBYTE) entries[ i ].data, size );
518 RegCloseKey( key );
519 require_noerr( err, exit );
520 }
521
522 // If running on NT, register the extension as approved.
523
524 versionInfo.dwOSVersionInfoSize = sizeof( versionInfo );
525 GetVersionEx( &versionInfo );
526 if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
527 {
528 lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) );
529 err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
530 require_noerr( err, exit );
531
532 lstrcpyn( data, inName, sizeof_array( data ) );
533 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
534 err = RegSetValueEx( key, clsidString, 0, REG_SZ, (LPBYTE) data, size );
535 RegCloseKey( key );
536 }
537
538 // register toolbar button
539 lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) );
540 err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
541 require_noerr( err, exit );
542
543 lstrcpyn( data, L"Yes", sizeof_array( data ) );
544 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
545 RegSetValueEx( key, L"Default Visible", 0, REG_SZ, (LPBYTE) data, size );
546
547 lstrcpyn( data, inName, sizeof_array( data ) );
548 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
549 RegSetValueEx( key, L"ButtonText", 0, REG_SZ, (LPBYTE) data, size );
550
551 lstrcpyn( data, L"{E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16}", sizeof_array( data ) );
552 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
553 RegSetValueEx( key, L"CLSID", 0, REG_SZ, (LPBYTE) data, size );
554
555 lstrcpyn( data, clsidString, sizeof_array( data ) );
556 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
557 RegSetValueEx( key, L"BandCLSID", 0, REG_SZ, (LPBYTE) data, size );
558
559 // check if we're running XP or later
560 if ( ( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) &&
561 ( versionInfo.dwMajorVersion == 5 ) &&
562 ( versionInfo.dwMinorVersion >= 1 ) )
563 {
564 wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_XP );
565 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
566 RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size);
567
568 wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_XP );
569 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
570 RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size);
571 }
572 else
573 {
574 wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_2K );
575 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
576 RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size);
577
578 wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_2K );
579 size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
580 RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size);
581 }
582
583 RegCloseKey( key );
584
585 exit:
586 return( err );
587 }
588
589 //===========================================================================================================================
590 // RegisterCOMCategory
591 //===========================================================================================================================
592
593 DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister )
594 {
595 HRESULT err;
596 ICatRegister * cat;
597
598 err = CoInitialize( NULL );
599 require( SUCCEEDED( err ), exit );
600
601 err = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID *) &cat );
602 check( SUCCEEDED( err ) );
603 if( SUCCEEDED( err ) )
604 {
605 if( inRegister )
606 {
607 err = cat->RegisterClassImplCategories( inCLSID, 1, &inCategoryID );
608 check_noerr( err );
609 }
610 else
611 {
612 err = cat->UnRegisterClassImplCategories( inCLSID, 1, &inCategoryID );
613 check_noerr( err );
614 }
615 cat->Release();
616 }
617 CoUninitialize();
618
619 exit:
620 return( err );
621 }
622
623
624 //===========================================================================================================================
625 // UnregisterServer
626 //===========================================================================================================================
627
628 DEBUG_LOCAL OSStatus UnregisterServer( CLSID inCLSID )
629 {
630 OSStatus err = 0;
631 LPWSTR clsidWideString;
632 TCHAR clsidString[ 64 ];
633 HKEY key;
634 TCHAR keyName[ MAX_PATH * 2 ];
635 OSVERSIONINFO versionInfo;
636
637 // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
638
639 err = StringFromIID( inCLSID, &clsidWideString );
640 require_noerr( err, exit );
641 require_action( clsidWideString, exit, err = kNoMemoryErr );
642
643 #ifdef UNICODE
644 lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) );
645 CoTaskMemFree( clsidWideString );
646 #else
647 nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL );
648 err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
649 CoTaskMemFree( clsidWideString );
650 require_noerr( err, exit );
651 #endif
652
653 wsprintf( keyName, L"CLSID\\%s", clsidString );
654 MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName );
655
656 // If running on NT, de-register the extension as approved.
657
658 versionInfo.dwOSVersionInfoSize = sizeof( versionInfo );
659 GetVersionEx( &versionInfo );
660 if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
661 {
662 lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) );
663 err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
664 require_noerr( err, exit );
665
666 RegDeleteValue( key, clsidString );
667
668 err = RegCloseKey( key );
669 require_noerr( err, exit );
670 }
671
672 // de-register toolbar button
673
674 lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) );
675 MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName );
676
677 exit:
678 return( err );
679 }
680
681
682
683 //===========================================================================================================================
684 // MyRegDeleteKey
685 //===========================================================================================================================
686
687 DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey )
688 {
689 LPTSTR lpEnd;
690 OSStatus err;
691 DWORD dwSize;
692 TCHAR szName[MAX_PATH];
693 HKEY hKey;
694 FILETIME ftWrite;
695
696 // First, see if we can delete the key without having to recurse.
697
698 err = RegDeleteKey( hKeyRoot, lpSubKey );
699
700 if ( !err )
701 {
702 goto exit;
703 }
704
705 err = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey );
706 require_noerr( err, exit );
707
708 // Check for an ending slash and add one if it is missing.
709
710 lpEnd = lpSubKey + lstrlen(lpSubKey);
711
712 if ( *( lpEnd - 1 ) != TEXT( '\\' ) )
713 {
714 *lpEnd = TEXT('\\');
715 lpEnd++;
716 *lpEnd = TEXT('\0');
717 }
718
719 // Enumerate the keys
720
721 dwSize = MAX_PATH;
722 err = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
723
724 if ( !err )
725 {
726 do
727 {
728 lstrcpy (lpEnd, szName);
729
730 if ( !MyRegDeleteKey( hKeyRoot, lpSubKey ) )
731 {
732 break;
733 }
734
735 dwSize = MAX_PATH;
736
737 err = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
738
739 }
740 while ( !err );
741 }
742
743 lpEnd--;
744 *lpEnd = TEXT('\0');
745
746 RegCloseKey( hKey );
747
748 // Try again to delete the key.
749
750 err = RegDeleteKey(hKeyRoot, lpSubKey);
751 require_noerr( err, exit );
752
753 exit:
754
755 return err;
756 }