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