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 31static 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 41static HINSTANCE g_nonLocalizedResources = NULL; 42static HINSTANCE g_localizedResources = NULL; 43 44 45HINSTANCE GetNonLocalizedResources() 46{ 47 return g_nonLocalizedResources; 48} 49 50 51HINSTANCE GetLocalizedResources() 52{ 53 return g_localizedResources; 54} 55 56 57//--------------------------------------------------------------------------------------------------------------------------- 58// Static Declarations 59//--------------------------------------------------------------------------------------------------------------------------- 60DEFINE_GUID(CLSID_ControlPanel, 61 620x1207552c, 0xe59, 0x4d9f, 0x85, 0x54, 0xf1, 0xf8, 0x6, 0xcd, 0x7f, 0xa9); 63 64static LPCTSTR g_controlPanelGUID = TEXT( "{1207552C-0E59-4d9f-8554-F1F806CD7FA9}" ); 65static LPCTSTR g_controlPanelName = TEXT( "Bonjour" ); 66static LPCTSTR g_controlPanelCanonicalName = TEXT( "Apple.Bonjour" ); 67static LPCTSTR g_controlPanelCategory = TEXT( "3,8" ); 68 69static CCPApp theApp; 70 71//=========================================================================================================================== 72// MyRegDeleteKey 73//=========================================================================================================================== 74 75DEBUG_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 141exit: 142 143 return err; 144} 145 146 147 148//--------------------------------------------------------------------------------------------------------------------------- 149// CCPApp::CCPApp 150//--------------------------------------------------------------------------------------------------------------------------- 151IMPLEMENT_DYNAMIC(CCPApp, CWinApp); 152 153CCPApp::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 164CCPApp::~CCPApp() 165{ 166} 167 168 169void 170CCPApp::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 222exit: 223 return; 224} 225 226 227//----------------------------------------------------------- 228// CCPApp::Unregister 229//----------------------------------------------------------- 230void 231CCPApp::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 248BOOL 249CCPApp::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 363exit: 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