• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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