Home | History | Annotate | Download | only in ControlPanel
      1 /* -*- Mode: C; tab-width: 4 -*-
      2  *
      3  * Copyright (c) 2002-2007 Apple Inc. All rights reserved.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 
     19 #include "ControlPanelExe.h"
     20 #include "ConfigDialog.h"
     21 #include "ConfigPropertySheet.h"
     22 #include "resource.h"
     23 
     24 #include <DebugServices.h>
     25 #include "loclibrary.h"
     26 
     27 
     28 #ifdef _DEBUG
     29 #define new DEBUG_NEW
     30 #undef THIS_FILE
     31 static char THIS_FILE[] = __FILE__;
     32 #endif
     33 
     34 #ifndef HeapEnableTerminationOnCorruption
     35 #	define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS) 1
     36 #endif
     37 
     38 
     39 // Stash away pointers to our resource DLLs
     40 
     41 static HINSTANCE g_nonLocalizedResources	= NULL;
     42 static HINSTANCE g_localizedResources		= NULL;
     43 
     44 
     45 HINSTANCE	GetNonLocalizedResources()
     46 {
     47 	return g_nonLocalizedResources;
     48 }
     49 
     50 
     51 HINSTANCE	GetLocalizedResources()
     52 {
     53 	return g_localizedResources;
     54 }
     55 
     56 
     57 //---------------------------------------------------------------------------------------------------------------------------
     58 //	Static Declarations
     59 //---------------------------------------------------------------------------------------------------------------------------
     60 DEFINE_GUID(CLSID_ControlPanel,
     61 
     62 0x1207552c, 0xe59, 0x4d9f, 0x85, 0x54, 0xf1, 0xf8, 0x6, 0xcd, 0x7f, 0xa9);
     63 
     64 static LPCTSTR g_controlPanelGUID			=	TEXT( "{1207552C-0E59-4d9f-8554-F1F806CD7FA9}" );
     65 static LPCTSTR g_controlPanelName			=	TEXT( "Bonjour" );
     66 static LPCTSTR g_controlPanelCanonicalName	=	TEXT( "Apple.Bonjour" );
     67 static LPCTSTR g_controlPanelCategory		=	TEXT( "3,8" );
     68 
     69 static CCPApp theApp;
     70 
     71 //===========================================================================================================================
     72 //	MyRegDeleteKey
     73 //===========================================================================================================================
     74 
     75 DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey )
     76 {
     77     LPTSTR lpEnd;
     78     OSStatus err;
     79     DWORD dwSize;
     80     TCHAR szName[MAX_PATH];
     81     HKEY hKey;
     82     FILETIME ftWrite;
     83 
     84     // First, see if we can delete the key without having to recurse.
     85 
     86     err = RegDeleteKey( hKeyRoot, lpSubKey );
     87 
     88     if ( !err )
     89 	{
     90 		goto exit;
     91 	}
     92 
     93     err = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey );
     94 	require_noerr( err, exit );
     95 
     96     // Check for an ending slash and add one if it is missing.
     97 
     98     lpEnd = lpSubKey + lstrlen(lpSubKey);
     99 
    100     if ( *( lpEnd - 1 ) != TEXT( '\\' ) )
    101     {
    102         *lpEnd =  TEXT('\\');
    103         lpEnd++;
    104         *lpEnd =  TEXT('\0');
    105     }
    106 
    107     // Enumerate the keys
    108 
    109     dwSize = MAX_PATH;
    110     err = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
    111 
    112     if ( !err )
    113     {
    114         do
    115 		{
    116             lstrcpy (lpEnd, szName);
    117 
    118             if ( !MyRegDeleteKey( hKeyRoot, lpSubKey ) )
    119 			{
    120                 break;
    121             }
    122 
    123             dwSize = MAX_PATH;
    124 
    125             err = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
    126 
    127         }
    128 		while ( !err );
    129     }
    130 
    131     lpEnd--;
    132     *lpEnd = TEXT('\0');
    133 
    134     RegCloseKey( hKey );
    135 
    136     // Try again to delete the key.
    137 
    138     err = RegDeleteKey(hKeyRoot, lpSubKey);
    139 	require_noerr( err, exit );
    140 
    141 exit:
    142 
    143 	return err;
    144 }
    145 
    146 
    147 
    148 //---------------------------------------------------------------------------------------------------------------------------
    149 //	CCPApp::CCPApp
    150 //---------------------------------------------------------------------------------------------------------------------------
    151 IMPLEMENT_DYNAMIC(CCPApp, CWinApp);
    152 
    153 CCPApp::CCPApp()
    154 {
    155 	debug_initialize( kDebugOutputTypeWindowsEventLog, "DNS-SD Control Panel", GetModuleHandle( NULL ) );
    156 	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
    157 }
    158 
    159 
    160 //---------------------------------------------------------------------------------------------------------------------------
    161 //	CCPApp::~CCPApp
    162 //---------------------------------------------------------------------------------------------------------------------------
    163 
    164 CCPApp::~CCPApp()
    165 {
    166 }
    167 
    168 
    169 void
    170 CCPApp::Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCanonicalName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath )
    171 {
    172 	typedef struct	RegistryBuilder		RegistryBuilder;
    173 
    174 	struct	RegistryBuilder
    175 	{
    176 		HKEY		rootKey;
    177 		LPCTSTR		subKey;
    178 		LPCTSTR		valueName;
    179 		DWORD		valueType;
    180 		LPCTSTR		data;
    181 	};
    182 
    183 	OSStatus			err;
    184 	size_t				n;
    185 	size_t				i;
    186 	HKEY				key;
    187 	TCHAR				keyName[ MAX_PATH ];
    188 	RegistryBuilder		entries[] =
    189 	{
    190 		{ HKEY_LOCAL_MACHINE,	TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s" ),	NULL,									REG_SZ,		inName },
    191 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			NULL,									NULL,		NULL },
    192 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "System.ApplicationName" ),		REG_SZ,		inCanonicalName },
    193 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "System.ControlPanel.Category" ),	REG_SZ,		inCategory },
    194 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "LocalizedString" ),				REG_SZ,		inLocalizedName },
    195 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "InfoTip" ),						REG_SZ,		inInfoTip },
    196 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\DefaultIcon" ),																NULL,									REG_SZ,		inIconPath },
    197 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\Shell" ),																		NULL,									NULL,		NULL },
    198 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\Shell\\Open" ),																NULL,									NULL,		NULL },
    199 		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\Shell\\Open\\Command" ),														NULL,									REG_SZ,		inExePath }
    200 	};
    201 	DWORD				size;
    202 
    203 	// Register the registry entries.
    204 
    205 	n = sizeof_array( entries );
    206 	for( i = 0; i < n; ++i )
    207 	{
    208 		wsprintf( keyName, entries[ i ].subKey, inClsidString );
    209 		err = RegCreateKeyEx( entries[ i ].rootKey, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
    210 		require_noerr( err, exit );
    211 
    212 		if ( entries[ i ].data )
    213 		{
    214 			size = (DWORD)( ( lstrlen( entries[ i ].data ) + 1 ) * sizeof( TCHAR ) );
    215 			err = RegSetValueEx( key, entries[ i ].valueName, 0, entries[ i ].valueType, (LPBYTE) entries[ i ].data, size );
    216 			require_noerr( err, exit );
    217 		}
    218 
    219 		RegCloseKey( key );
    220 	}
    221 
    222 exit:
    223 	return;
    224 }
    225 
    226 
    227 //-----------------------------------------------------------
    228 //	CCPApp::Unregister
    229 //-----------------------------------------------------------
    230 void
    231 CCPApp::Unregister( LPCTSTR clsidString )
    232 {
    233 	TCHAR keyName[ MAX_PATH * 2 ];
    234 
    235 	wsprintf( keyName, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s", clsidString );
    236 	MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName );
    237 
    238 	wsprintf( keyName, L"CLSID\\%s", clsidString );
    239 	MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName );
    240 }
    241 
    242 
    243 
    244 //-----------------------------------------------------------
    245 //	CCPApp::InitInstance
    246 //-----------------------------------------------------------
    247 
    248 BOOL
    249 CCPApp::InitInstance()
    250 {
    251 	CCommandLineInfo	commandLine;
    252 	wchar_t				resource[MAX_PATH];
    253 	CString				errorMessage;
    254 	CString				errorCaption;
    255 	int					res;
    256 	OSStatus			err = kNoErr;
    257 
    258 	HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
    259 
    260 	//
    261 	// initialize the debugging framework
    262 	//
    263 	debug_initialize( kDebugOutputTypeWindowsDebugger, "ControlPanel", NULL );
    264 	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
    265 
    266 	// Before we load the resources, let's load the error string
    267 
    268 	errorMessage.LoadString( IDS_REINSTALL );
    269 	errorCaption.LoadString( IDS_REINSTALL_CAPTION );
    270 
    271 	res = PathForResource( NULL, L"ControlPanelResources.dll", resource, MAX_PATH );
    272 	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
    273 	require_noerr( err, exit );
    274 
    275 	g_nonLocalizedResources = LoadLibrary( resource );
    276 	translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
    277 	require_noerr( err, exit );
    278 
    279 	res = PathForResource( NULL, L"ControlPanelLocalized.dll", resource, MAX_PATH );
    280 	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
    281 	require_noerr( err, exit );
    282 
    283 	g_localizedResources = LoadLibrary( resource );
    284 	translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
    285 	require_noerr( err, exit );
    286 
    287 	AfxSetResourceHandle( g_localizedResources );
    288 
    289 	// InitCommonControls() is required on Windows XP if an application
    290 	// manifest specifies use of ComCtl32.dll version 6 or later to enable
    291 	// visual styles.  Otherwise, any window creation will fail.
    292 
    293 	InitCommonControls();
    294 
    295 	CWinApp::InitInstance();
    296 
    297 	AfxEnableControlContainer();
    298 
    299 	ParseCommandLine( commandLine );
    300 
    301 	if ( commandLine.m_nShellCommand == CCommandLineInfo::AppRegister )
    302 	{
    303 		CString		localizedName;
    304 		CString		toolTip;
    305 		TCHAR		iconPath[ MAX_PATH + 12 ]	= TEXT( "" );
    306 		TCHAR		exePath[ MAX_PATH ]			= TEXT( "" );
    307 		DWORD		nChars;
    308 		OSStatus	err;
    309 
    310 		nChars = GetModuleFileName( NULL, exePath, sizeof_array( exePath ) );
    311 
    312 		err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
    313 
    314 		require_noerr( err, exit );
    315 
    316 		wsprintf( iconPath, L"%s,-%d", exePath, IDR_APPLET );
    317 
    318 		localizedName.LoadString( IDS_APPLET_NAME );
    319 		toolTip.LoadString( IDS_APPLET_TOOLTIP );
    320 
    321 		Register( g_controlPanelGUID, g_controlPanelName, g_controlPanelCanonicalName, g_controlPanelCategory, localizedName, toolTip, iconPath, exePath );
    322 	}
    323 	else if ( commandLine.m_nShellCommand == CCommandLineInfo::AppUnregister )
    324 	{
    325 		Unregister( g_controlPanelGUID );
    326 	}
    327 	else
    328 	{
    329 		CString					name;
    330 		CConfigPropertySheet	dlg;
    331 
    332 		name.LoadString( IDR_APPLET );
    333 		dlg.Construct( name, NULL, 0 );
    334 
    335 		m_pMainWnd = &dlg;
    336 
    337 		try
    338 		{
    339 			INT_PTR nResponse = dlg.DoModal();
    340 
    341 			if (nResponse == IDOK)
    342 			{
    343 				// TODO: Place code here to handle when the dialog is
    344 				//  dismissed with OK
    345 			}
    346 			else if (nResponse == IDCANCEL)
    347 			{
    348 				// TODO: Place code here to handle when the dialog is
    349 				//  dismissed with Cancel
    350 			}
    351 		}
    352 		catch (...)
    353 		{
    354 			MessageBox(NULL, L"", L"", MB_OK|MB_ICONEXCLAMATION);
    355 		}
    356 	}
    357 
    358 	if ( err )
    359 	{
    360 		MessageBox( NULL, L"", L"", MB_ICONERROR | MB_OK );
    361 	}
    362 
    363 exit:
    364 
    365 	if ( err )
    366 	{
    367 		MessageBox( NULL, errorMessage, errorCaption, MB_ICONERROR | MB_OK );
    368 	}
    369 
    370 	// Since the dialog has been closed, return FALSE so that we exit the
    371 	//  application, rather than start the application's message pump.
    372 	return FALSE;
    373 }
    374