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
GetNonLocalizedResources()45 HINSTANCE GetNonLocalizedResources()
46 {
47 return g_nonLocalizedResources;
48 }
49
50
GetLocalizedResources()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
MyRegDeleteKey(HKEY hKeyRoot,LPTSTR lpSubKey)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
CCPApp()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
~CCPApp()164 CCPApp::~CCPApp()
165 {
166 }
167
168
169 void
Register(LPCTSTR inClsidString,LPCTSTR inName,LPCTSTR inCanonicalName,LPCTSTR inCategory,LPCTSTR inLocalizedName,LPCTSTR inInfoTip,LPCTSTR inIconPath,LPCTSTR inExePath)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
Unregister(LPCTSTR clsidString)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
InitInstance()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