X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/8e92c31c9a45a66732f5bc7afbc9f5596c17e91d..7f0064bd55e3fa98568d2c359429ff8a38b23a6c:/Clients/ExplorerPlugin/ExplorerPlugin.cpp diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.cpp b/Clients/ExplorerPlugin/ExplorerPlugin.cpp new file mode 100644 index 0000000..5de124d --- /dev/null +++ b/Clients/ExplorerPlugin/ExplorerPlugin.cpp @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ExplorerPlugin.cpp,v $ +Revision 1.5 2004/09/15 10:33:54 shersche + Install XP toolbar button (8 bit mask) if running on XP platform, otherwise install 1 bit mask toolbar button +Bug #: 3721611 + +Revision 1.4 2004/07/13 21:24:21 rpantos +Fix for . + +Revision 1.3 2004/06/26 14:12:07 shersche +Register the toolbar button + +Revision 1.2 2004/06/24 20:09:39 shersche +Change text +Submitted by: herscher + +Revision 1.1 2004/06/18 04:34:59 rpantos +Move to Clients from mDNSWindows + +Revision 1.1 2004/01/30 03:01:56 bradley +Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer. + +*/ + +#include "StdAfx.h" + +// The following 2 includes have to be in this order and INITGUID must be defined here, before including the file +// that specifies the GUID(s), and nowhere else. The reason for this is that initguid.h doesn't provide separate +// define and declare macros for GUIDs so you have to #define INITGUID in the single file where you want to define +// your GUID then in all the other files that just need the GUID declared, INITGUID must not be defined. + +#define INITGUID +#include +#include "ExplorerPlugin.h" + +#include +#include + +#include "CommonServices.h" +#include "DebugServices.h" + +#include "ClassFactory.h" +#include "Resource.h" + +// MFC Debugging + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#if 0 +#pragma mark == Prototypes == +#endif + +//=========================================================================================================================== +// Prototypes +//=========================================================================================================================== + +// DLL Exports + +extern "C" BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved ); + +// MFC Support + +DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance ); +DEBUG_LOCAL void MFCDLLProcessDetach( HINSTANCE inInstance ); +DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance ); + +// Utilities + +DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName ); +DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister ); + +#if 0 +#pragma mark == Globals == +#endif + +//=========================================================================================================================== +// Globals +//=========================================================================================================================== + +HINSTANCE gInstance = NULL; +int gDLLRefCount = 0; +CWinApp gApp; + +#if 0 +#pragma mark - +#pragma mark == DLL Exports == +#endif + +//=========================================================================================================================== +// DllMain +//=========================================================================================================================== + +BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved ) +{ + BOOL ok; + OSStatus err; + + DEBUG_UNUSED( inReserved ); + + ok = TRUE; + switch( inReason ) + { + case DLL_PROCESS_ATTACH: + gInstance = inInstance; + debug_initialize( kDebugOutputTypeWindowsEventLog, "DNSServices Bar", inInstance ); + debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace ); + dlog( kDebugLevelTrace, "\nDllMain: process attach\n" ); + + err = MFCDLLProcessAttach( inInstance ); + ok = ( err == kNoErr ); + require_noerr( err, exit ); + break; + + case DLL_PROCESS_DETACH: + dlog( kDebugLevelTrace, "DllMain: process detach\n" ); + MFCDLLProcessDetach( inInstance ); + break; + + case DLL_THREAD_ATTACH: + dlog( kDebugLevelTrace, "DllMain: thread attach\n" ); + break; + + case DLL_THREAD_DETACH: + dlog( kDebugLevelTrace, "DllMain: thread detach\n" ); + MFCDLLThreadDetach( inInstance ); + break; + + default: + dlog( kDebugLevelTrace, "DllMain: unknown reason code (%d)\n",inReason ); + break; + } + +exit: + return( ok ); +} + +//=========================================================================================================================== +// DllCanUnloadNow +//=========================================================================================================================== + +STDAPI DllCanUnloadNow( void ) +{ + dlog( kDebugLevelTrace, "DllCanUnloadNow (refCount=%d)\n", gDLLRefCount ); + + return( gDLLRefCount == 0 ); +} + +//=========================================================================================================================== +// DllGetClassObject +//=========================================================================================================================== + +STDAPI DllGetClassObject( REFCLSID inCLSID, REFIID inIID, LPVOID *outResult ) +{ + HRESULT err; + BOOL ok; + ClassFactory * factory; + + dlog( kDebugLevelTrace, "DllGetClassObject\n" ); + + *outResult = NULL; + + // Check if the class ID is supported. + + ok = IsEqualCLSID( inCLSID, CLSID_ExplorerBar ); + require_action_quiet( ok, exit, err = CLASS_E_CLASSNOTAVAILABLE ); + + // Create the ClassFactory object. + + factory = NULL; + try + { + factory = new ClassFactory( inCLSID ); + } + catch( ... ) + { + // Do not let exception escape. + } + require_action( factory, exit, err = E_OUTOFMEMORY ); + + // Query for the specified interface. Release the factory since QueryInterface retains it. + + err = factory->QueryInterface( inIID, outResult ); + factory->Release(); + +exit: + return( err ); +} + +//=========================================================================================================================== +// DllRegisterServer +//=========================================================================================================================== + +STDAPI DllRegisterServer( void ) +{ + HRESULT err; + BOOL ok; + CString s; + + dlog( kDebugLevelTrace, "DllRegisterServer\n" ); + + ok = s.LoadString( IDS_NAME ); + require_action( ok, exit, err = E_UNEXPECTED ); + + err = RegisterServer( gInstance, CLSID_ExplorerBar, s ); + require_noerr( err, exit ); + + err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, TRUE ); + require_noerr( err, exit ); + +exit: + return( err ); +} + +//=========================================================================================================================== +// DllUnregisterServer +//=========================================================================================================================== + +STDAPI DllUnregisterServer( void ) +{ + HRESULT err; + + dlog( kDebugLevelTrace, "DllUnregisterServer\n" ); + + err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE ); + require_noerr( err, exit ); + +exit: + return( err ); +} + +#if 0 +#pragma mark - +#pragma mark == MFC Support == +#endif + +//=========================================================================================================================== +// MFCDLLProcessAttach +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus MFCDLLProcessAttach( HINSTANCE inInstance ) +{ + OSStatus err; + _AFX_THREAD_STATE * threadState; + AFX_MODULE_STATE * previousModuleState; + BOOL ok; + CWinApp * app; + + app = NULL; + + // Simulate what is done in dllmodul.cpp. + + threadState = AfxGetThreadState(); + check( threadState ); + previousModuleState = threadState->m_pPrevModuleState; + + ok = AfxWinInit( inInstance, NULL, TEXT( "" ), 0 ); + require_action( ok, exit, err = kUnknownErr ); + + app = AfxGetApp(); + require_action( ok, exit, err = kNotInitializedErr ); + + ok = app->InitInstance(); + require_action( ok, exit, err = kUnknownErr ); + + threadState->m_pPrevModuleState = previousModuleState; + threadState = NULL; + AfxInitLocalData( inInstance ); + err = kNoErr; + +exit: + if( err ) + { + if( app ) + { + app->ExitInstance(); + } + AfxWinTerm(); + } + if( threadState ) + { + threadState->m_pPrevModuleState = previousModuleState; + } + return( err ); +} + +//=========================================================================================================================== +// MFCDLLProcessDetach +//=========================================================================================================================== + +DEBUG_LOCAL void MFCDLLProcessDetach( HINSTANCE inInstance ) +{ + CWinApp * app; + + // Simulate what is done in dllmodul.cpp. + + app = AfxGetApp(); + if( app ) + { + app->ExitInstance(); + } + +#if( DEBUG ) + if( AfxGetModuleThreadState()->m_nTempMapLock != 0 ) + { + dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock ); + } +#endif + + AfxLockTempMaps(); + AfxUnlockTempMaps( -1 ); + + // Terminate the library before destructors are called. + + AfxWinTerm(); + AfxTermLocalData( inInstance, TRUE ); +} + +//=========================================================================================================================== +// MFCDLLFinalize +//=========================================================================================================================== + +DEBUG_LOCAL void MFCDLLThreadDetach( HINSTANCE inInstance ) +{ + // Simulate what is done in dllmodul.cpp. + +#if( DEBUG ) + if( AfxGetModuleThreadState()->m_nTempMapLock != 0 ) + { + dlog( kDebugLevelWarning, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock ); + } +#endif + + AfxLockTempMaps(); + AfxUnlockTempMaps( -1 ); + AfxTermThread( inInstance ); +} + +#if 0 +#pragma mark - +#pragma mark == Utilities == +#endif + +//=========================================================================================================================== +// RegisterServer +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName ) +{ + typedef struct RegistryBuilder RegistryBuilder; + struct RegistryBuilder + { + HKEY rootKey; + LPCTSTR subKey; + LPCTSTR valueName; + LPCTSTR data; + }; + + OSStatus err; + LPWSTR clsidWideString; + TCHAR clsidString[ 64 ]; + DWORD nChars; + size_t n; + size_t i; + HKEY key; + TCHAR keyName[ MAX_PATH ]; + TCHAR moduleName[ MAX_PATH ] = TEXT( "" ); + TCHAR data[ MAX_PATH ]; + RegistryBuilder entries[] = + { + { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s" ), NULL, inName }, + { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s\\InprocServer32" ), NULL, moduleName }, + { HKEY_CLASSES_ROOT, TEXT( "CLSID\\%s\\InprocServer32" ), TEXT( "ThreadingModel" ), TEXT( "Apartment" ) } + }; + DWORD size; + OSVERSIONINFO versionInfo; + + // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode). + + err = StringFromIID( inCLSID, &clsidWideString ); + require_noerr( err, exit ); + require_action( clsidWideString, exit, err = kNoMemoryErr ); + + #ifdef UNICODE + lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) ); + CoTaskMemFree( clsidWideString ); + #else + nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL ); + err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr ); + CoTaskMemFree( clsidWideString ); + require_noerr( err, exit ); + #endif + + // Register the CLSID entries. + + nChars = GetModuleFileName( inInstance, moduleName, sizeof_array( moduleName ) ); + err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + + n = sizeof_array( entries ); + for( i = 0; i < n; ++i ) + { + wsprintf( keyName, entries[ i ].subKey, clsidString ); + err = RegCreateKeyEx( entries[ i ].rootKey, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL ); + require_noerr( err, exit ); + + size = (DWORD)( ( lstrlen( entries[ i ].data ) + 1 ) * sizeof( TCHAR ) ); + err = RegSetValueEx( key, entries[ i ].valueName, 0, REG_SZ, (LPBYTE) entries[ i ].data, size ); + RegCloseKey( key ); + require_noerr( err, exit ); + } + + // If running on NT, register the extension as approved. + + versionInfo.dwOSVersionInfoSize = sizeof( versionInfo ); + GetVersionEx( &versionInfo ); + if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) + { + lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) ); + err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL ); + require_noerr( err, exit ); + + lstrcpyn( data, inName, sizeof_array( data ) ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + err = RegSetValueEx( key, clsidString, 0, REG_SZ, (LPBYTE) data, size ); + RegCloseKey( key ); + } + + // register toolbar button + lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) ); + err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL ); + require_noerr( err, exit ); + + lstrcpyn( data, L"Yes", sizeof_array( data ) ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"Default Visible", 0, REG_SZ, (LPBYTE) data, size ); + + lstrcpyn( data, inName, sizeof_array( data ) ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"ButtonText", 0, REG_SZ, (LPBYTE) data, size ); + + lstrcpyn( data, L"{E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16}", sizeof_array( data ) ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"CLSID", 0, REG_SZ, (LPBYTE) data, size ); + + lstrcpyn( data, clsidString, sizeof_array( data ) ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"BandCLSID", 0, REG_SZ, (LPBYTE) data, size ); + + // check if we're running XP or later + if ( ( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) && + ( versionInfo.dwMajorVersion == 5 ) && + ( versionInfo.dwMinorVersion >= 1 ) ) + { + wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_XP ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size); + + wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_XP ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size); + } + else + { + wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_2K ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size); + + wsprintf( data, L"%s,%d", moduleName, IDI_BUTTON_2K ); + size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) ); + RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size); + } + + RegCloseKey( key ); + +exit: + return( err ); +} + +//=========================================================================================================================== +// RegisterCOMCategory +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister ) +{ + HRESULT err; + ICatRegister * cat; + + err = CoInitialize( NULL ); + require( SUCCEEDED( err ), exit ); + + err = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID *) &cat ); + check( SUCCEEDED( err ) ); + if( SUCCEEDED( err ) ) + { + if( inRegister ) + { + err = cat->RegisterClassImplCategories( inCLSID, 1, &inCategoryID ); + check_noerr( err ); + } + else + { + err = cat->UnRegisterClassImplCategories( inCLSID, 1, &inCategoryID ); + check_noerr( err ); + } + cat->Release(); + } + CoUninitialize(); + +exit: + return( err ); +}