--- /dev/null
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x17L\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "Bonjour Console Utility"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "dns-sd.exe"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "dns-sd.exe"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\r
+END\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="dns-sd"\r
+ ProjectGUID="{AA230639-E115-4A44-AA5A-44A61235BA50}"\r
+ Keyword="Win32Proj">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="Debug"\r
+ IntermediateDirectory="Debug"\r
+ ConfigurationType="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="../../mDNSShared"\r
+ PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF"\r
+ MinimalRebuild="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="5"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib ws2_32.lib"\r
+ OutputFile="$(OutDir)/dns-sd.exe"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/dns-sd.pdb"\r
+ SubSystem="1"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="1"\r
+ OmitFramePointers="TRUE"\r
+ AdditionalIncludeDirectories="../../mDNSShared"\r
+ PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF"\r
+ StringPooling="TRUE"\r
+ RuntimeLibrary="4"\r
+ EnableFunctionLevelLinking="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib "\r
+ OutputFile="$(OutDir)/dns-sd.exe"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="TRUE"\r
+ SubSystem="1"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ AdditionalIncludeDirectories="../../mDNSWindows"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">\r
+ <File\r
+ RelativePath="..\dns-sd.c">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc">\r
+ <File\r
+ RelativePath="resource.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+ <File\r
+ RelativePath="dns-sd.rc">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by dns-sd.rc\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 101\r
+#define _APS_NEXT_COMMAND_VALUE 40001\r
+#define _APS_NEXT_CONTROL_VALUE 1001\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
Change History (most recent first):
$Log: DNSServiceBrowser.cs,v $
+Revision 1.6 2005/02/10 22:35:06 cheshire
+<rdar://problem/3727944> Update name
+
Revision 1.5 2004/09/21 16:26:58 shersche
Check to make sure browse list selected item is not null before resolving
Submitted by: prepin@gmail.com
this.Load += new System.EventHandler(this.Form1_Load);
}
- private void Form1_Load(object sender, EventArgs e) \r
- {\r
- typeBox.SelectedItem = "_spike._tcp";\r
- }\r
+ private void Form1_Load(object sender, EventArgs e)
+
+ {
+
+ typeBox.SelectedItem = "_spike._tcp";
+
+ }
+
/// <summary>
/// Clean up any resources being used.
"_raop._tcp",
"_rce._tcp",
"_realplayfavs._tcp",
- "_rendezvouspong._tcp",
"_riousbprint._tcp",
"_rfb._tcp",
"_rtsp._tcp",
Change History (most recent first):
$Log: ExplorerBarWindow.cpp,v $
+Revision 1.18 2005/02/26 01:24:05 shersche
+Remove display lines in tree control
+
+Revision 1.17 2005/02/25 19:57:30 shersche
+<rdar://problem/4023323> Remove FTP browsing from plugin
+
+Revision 1.16 2005/02/08 23:31:06 shersche
+Move "About ..." item underneath WebSites, change icons for discovered sites and "About ..." item
+
Revision 1.15 2005/01/27 22:38:27 shersche
add About item to tree list
require_noerr( err, exit );
GetClientRect( rect );
- mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_NOHSCROLL , rect, this,
+ mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_NOHSCROLL , rect, this,
IDC_EXPLORER_TREE );
- s.LoadString( IDS_ABOUT );
- m_about = mTree.InsertItem( s, 0, 0 );
-
ServiceHandlerEntry * e;
// Web Site Handler
e->type = "_http._tcp";
e->urlScheme = "http://";
e->ref = NULL;
- e->treeItem = NULL;
- e->treeFirst = true;
e->obj = this;
e->needsLogin = false;
mServiceHandlers.Add( e );
-
- s.LoadString( IDS_WEB_SITES );
- e->treeItem = mTree.InsertItem( s, 1, 1 );
- mTree.Expand( e->treeItem, TVE_EXPAND );
-
- err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
- require_noerr( err, exit );
-
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
- require_noerr( err, exit );
- m_serviceRefs.push_back(e->ref);
+ s.LoadString( IDS_ABOUT );
+ m_about = mTree.InsertItem( s, 1, 1 );
- // FTP Site Handler
-
- e = new ServiceHandlerEntry;
- check( e );
- e->type = "_ftp._tcp";
- e->urlScheme = "ftp://";
- e->ref = NULL;
- e->treeItem = NULL;
- e->treeFirst = true;
- e->obj = this;
- e->needsLogin = true;
- mServiceHandlers.Add( e );
-
- s.LoadString( IDS_FTP_SITES );
- e->treeItem = mTree.InsertItem( s, 1, 1 );
- mTree.Expand( e->treeItem, TVE_EXPAND );
-
err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
require_noerr( err, exit );
err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
require_noerr( err, exit );
- m_serviceRefs.push_back(e->ref);
+ m_serviceRefs.push_back(e->ref);
m_imageList.Create( 16, 16, ILC_COLORDDB, 2, 0);
bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_GLOBE ) ) );
// Insert the new item in sorted order.
- afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : TVI_FIRST;
+ afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : m_about;
handler->array.InsertAt( index, service );
- service->item = mTree.InsertItem( service->displayName, 1, 1, handler->treeItem, afterItem );
+ service->item = mTree.InsertItem( service->displayName, 0, 0, NULL, afterItem );
mTree.SetItemData( service->item, (DWORD_PTR) service );
-
- // Make sure the item is visible if this is the first time a service was added.
-
- if( handler->treeFirst )
- {
- handler->treeFirst = false;
- mTree.EnsureVisible( service->item );
- }
}
return( 0 );
}
Change History (most recent first):
$Log: ExplorerBarWindow.h,v $
+Revision 1.7 2005/02/25 19:57:30 shersche
+<rdar://problem/4023323> Remove FTP browsing from plugin
+
Revision 1.6 2005/01/27 22:27:03 shersche
-Add m_about member for "About Rendezvous" tree item
+Add m_about member for "About ..." tree item
Revision 1.5 2004/07/26 05:47:31 shersche
use TXTRecord APIs, fix bug in locating service to be removed
const char * urlScheme;
DNSServiceRef ref;
ServiceInfoArray array;
- HTREEITEM treeItem;
- bool treeFirst;
ExplorerBarWindow * obj;
bool needsLogin;
type = NULL;
urlScheme = NULL;
ref = NULL;
- treeItem = NULL;
- treeFirst = true;
obj = NULL;
needsLogin = false;
}
Change History (most recent first):
$Log: ExplorerPlugin.cpp,v $
+Revision 1.7 2005/02/23 02:00:45 shersche
+<rdar://problem/4014479> Delete all the registry entries when component is unregistered
+
Revision 1.6 2005/01/25 17:56:45 shersche
<rdar://problem/3911084> Load resource DLLs, get icons and bitmaps from resource DLLs
Bug #: 3911084
DEBUG_LOCAL OSStatus RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName );
DEBUG_LOCAL OSStatus RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister );
+DEBUG_LOCAL OSStatus UnregisterServer( CLSID inCLSID );
+DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey );
// Stash away pointers to our resource DLLs
err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE );
require_noerr( err, exit );
+
+ err = UnregisterServer( CLSID_ExplorerBar );
+ require_noerr( err, exit );
exit:
return( err );
exit:
return( err );
}
+
+
+//===========================================================================================================================
+// UnregisterServer
+//===========================================================================================================================
+
+DEBUG_LOCAL OSStatus UnregisterServer( CLSID inCLSID )
+{
+ OSStatus err = 0;
+ LPWSTR clsidWideString;
+ TCHAR clsidString[ 64 ];
+ HKEY key;
+ TCHAR keyName[ MAX_PATH * 2 ];
+ OSVERSIONINFO versionInfo;
+
+ // Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
+
+ err = StringFromIID( inCLSID, &clsidWideString );
+ require_noerr( err, exit );
+ require_action( clsidWideString, exit, err = kNoMemoryErr );
+
+ #ifdef UNICODE
+ lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) );
+ CoTaskMemFree( clsidWideString );
+ #else
+ nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL );
+ err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
+ CoTaskMemFree( clsidWideString );
+ require_noerr( err, exit );
+ #endif
+
+ wsprintf( keyName, L"CLSID\\%s", clsidString );
+ MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName );
+
+ // If running on NT, de-register the extension as approved.
+
+ versionInfo.dwOSVersionInfoSize = sizeof( versionInfo );
+ GetVersionEx( &versionInfo );
+ if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
+ {
+ lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) );
+ err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
+ require_noerr( err, exit );
+
+ RegDeleteValue( key, clsidString );
+
+ err = RegCloseKey( key );
+ require_noerr( err, exit );
+ }
+
+ // de-register toolbar button
+
+ lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) );
+ MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName );
+
+exit:
+ return( err );
+}
+
+
+
+//===========================================================================================================================
+// MyRegDeleteKey
+//===========================================================================================================================
+
+DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey )
+{
+ LPTSTR lpEnd;
+ OSStatus err;
+ DWORD dwSize;
+ TCHAR szName[MAX_PATH];
+ HKEY hKey;
+ FILETIME ftWrite;
+
+ // First, see if we can delete the key without having to recurse.
+
+ err = RegDeleteKey( hKeyRoot, lpSubKey );
+
+ if ( !err )
+ {
+ goto exit;
+ }
+
+ err = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey );
+ require_noerr( err, exit );
+
+ // Check for an ending slash and add one if it is missing.
+
+ lpEnd = lpSubKey + lstrlen(lpSubKey);
+
+ if ( *( lpEnd - 1 ) != TEXT( '\\' ) )
+ {
+ *lpEnd = TEXT('\\');
+ lpEnd++;
+ *lpEnd = TEXT('\0');
+ }
+
+ // Enumerate the keys
+
+ dwSize = MAX_PATH;
+ err = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
+
+ if ( !err )
+ {
+ do
+ {
+ lstrcpy (lpEnd, szName);
+
+ if ( !MyRegDeleteKey( hKeyRoot, lpSubKey ) )
+ {
+ break;
+ }
+
+ dwSize = MAX_PATH;
+
+ err = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
+
+ }
+ while ( !err );
+ }
+
+ lpEnd--;
+ *lpEnd = TEXT('\0');
+
+ RegCloseKey( hKey );
+
+ // Try again to delete the key.
+
+ err = RegDeleteKey(hKeyRoot, lpSubKey);
+ require_noerr( err, exit );
+
+exit:
+
+ return err;
+}
BLOCK "040904b0"\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
- VALUE "FileDescription", "DNSServices Explorer Bar"\r
+ VALUE "FileDescription", "Bonjour Explorer Bar"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
VALUE "InternalName", "ExplorerPlugin.dll"\r
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\bin"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
SuppressStartupBanner="TRUE"\r
Detect64BitPortabilityProblems="TRUE"\r
CompileAs="0"/>\r
- <Tool\r
- Name="VCCustomBuildTool"\r
- Description="Registering"\r
- CommandLine="regsvr32.exe /s /c $(OutDir)/$(ProjectName).dll\r
-"\r
- Outputs="$(OUTDIR)\Register.out"/>\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalOptions="/MACHINE:I386 /IGNORE:4089 "\r
BLOCK "040904b0"\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
- VALUE "FileDescription", "DNS-SD Explorer Bar Resource Module"\r
+ VALUE "FileDescription", "Bonjour Resource Module"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
VALUE "InternalName", "ExplorerPluginLocalized.dll"\r
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
IDD_ABOUT DIALOGEX 0, 0, 219, 87\r
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
EXSTYLE WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR\r
-CAPTION "About Rendezvous"\r
+CAPTION "About Bonjour"\r
FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
BEGIN\r
CONTROL "",IDC_ABOUT_BACKGROUND,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,\r
BEGIN\r
POPUP "ContextMenu"\r
BEGIN\r
- MENUITEM "About Rendezvous...", ID_Menu\r
+ MENUITEM "About Bonjour...", ID_Menu\r
MENUITEM SEPARATOR\r
END\r
END\r
\r
STRINGTABLE \r
BEGIN\r
- IDS_ABOUT "About Rendezvous"\r
+ IDS_ABOUT "About Bonjour"\r
IDS_ABOUT_URL "http://www.apple.com/macosx/features/rendezvous"\r
- IDS_NAME "Rendezvous"\r
+ IDS_NAME "Bonjour"\r
IDS_WEB_SITES "Web Sites"\r
- IDS_FTP_SITES "FTP Sites"\r
IDS_PRINTERS "Printers"\r
- IDS_MDNSRESPONDER_NOT_AVAILABLE "Rendezvous Service Not Available"\r
+ IDS_MDNSRESPONDER_NOT_AVAILABLE "Bonjour Service Not Available"\r
IDS_FIREWALL "Check firewall settings"\r
END\r
\r
<Configurations>\r
<Configuration\r
Name="Debug|Win32"\r
- OutputDirectory=".\Debug\ExplorerPlugin.dll.Resources\en.lproj"\r
+ OutputDirectory=".\Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj"\r
IntermediateDirectory=".\Debug"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
+if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\ExplorerPlugin.dll.Resources\r
+if not exist Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj mkdir Debug\Resources\ExplorerPlugin.dll.Resources\en.lproj"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="_DEBUG"\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\bin\ExplorerPlugin.dll.Resources\en.lproj"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Release\Root mkdir Release\Root\r
+if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
+if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj""/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\r
BLOCK "040904b0"\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
- VALUE "FileDescription", "DNS-SD Explorer Bar Resource Module"\r
+ VALUE "FileDescription", "Bonjour Resource Module"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
VALUE "InternalName", "ExplorerPluginResources.dll"\r
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
<Configurations>\r
<Configuration\r
Name="Debug|Win32"\r
- OutputDirectory=".\Debug\ExplorerPlugin.dll.Resources"\r
+ OutputDirectory=".\Debug\Resources\ExplorerPlugin.dll.Resources"\r
IntermediateDirectory=".\Debug"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
+if not exist Debug\Resources\ExplorerPlugin.dll.Resources mkdir Debug\Resources\ExplorerPlugin.dll.Resources"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="_DEBUG"\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\bin\ExplorerPlugin.dll.Resources"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Release\Root mkdir Release\Root\r
+if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
+if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources""/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\r
//\r
#define IDS_NAME 106\r
#define IDS_WEB_SITES 107\r
-#define IDS_FTP_SITES 108\r
#define IDS_PRINTERS 109\r
#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110\r
#define IDS_FIREWALL 111\r
//\r
#define IDS_NAME 106\r
#define IDS_WEB_SITES 107\r
-#define IDS_FTP_SITES 108\r
#define IDS_PRINTERS 109\r
#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110\r
#define IDS_FIREWALL 111\r
//\r
#define IDS_NAME 106\r
#define IDS_WEB_SITES 107\r
-#define IDS_FTP_SITES 108\r
#define IDS_PRINTERS 109\r
#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110\r
#define IDS_FIREWALL 111\r
JAVASRC = .
.SUFFIXES : .java
{$(JAVASRC)}.java{$(BAOBJ)}.class:
- $(JAVAC) -d $(BAOBJ) -classpath $(BAOBJ) $<
+ $(JAVAC) -d $(BAOBJ) -classpath $(BAOBJ);$(DNS_SD) $<
{$(JAVASRC)}.java{$(SCOBJ)}.class:
- $(JAVAC) -d $(SCOBJ) -classpath $(SCOBJ) $<
+ $(JAVAC) -d $(SCOBJ) -classpath $(SCOBJ);$(DNS_SD) $<
Change History (most recent first):
$Log: FourthPage.cpp,v $
+Revision 1.6 2005/02/08 21:45:06 shersche
+<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
+
Revision 1.5 2005/01/06 08:17:08 shersche
Display the selected protocol ("Raw", "LPR", "IPP") rather than the port name
m_printerNameCtrl.SetWindowText( printer->actualName );
m_printerManufacturerCtrl.SetWindowText ( printer->manufacturer );
- m_printerModelCtrl.SetWindowText ( printer->model );
+ m_printerModelCtrl.SetWindowText ( printer->displayModelName );
Service * service = printer->services.front();
require_quiet( service, exit );
BLOCK "040904e4"\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
- VALUE "FileDescription", "Rendezvous Printer Wizard"\r
+ VALUE "FileDescription", "Bonjour Printer Wizard"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
- VALUE "InternalName", "RendezvousPrinterWizard.exe"\r
+ VALUE "InternalName", "PrinterWizard.exe"\r
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
- VALUE "OriginalFilename", "RendezvousPrinterWizard.exe"\r
+ VALUE "OriginalFilename", "PrinterWizard.exe"\r
VALUE "ProductName", MASTER_PROD_NAME\r
VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
END\r
\r
STRINGTABLE \r
BEGIN\r
- IDS_REINSTALL "Rendezvous Printer Wizard cannot run because some of its required files are missing. Please reinstall Rendezvous Printer Wizard."\r
- IDS_REINSTALL_CAPTION "Rendezvous Printer Wizard"\r
+ IDS_REINSTALL "Bonjour Printer Wizard cannot run because some of its required files are missing. Please reinstall Bonjour Printer Wizard."\r
+ IDS_REINSTALL_CAPTION "Bonjour Printer Wizard"\r
END\r
\r
#endif // English (U.S.) resources\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="../../mDNSWindows/DLL/Debug/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"\r
- OutputFile="$(OutDir)/RendezvousPrinterWizard.exe"\r
+ OutputFile="$(OutDir)/PrinterWizard.exe"\r
LinkIncremental="2"\r
GenerateDebugInformation="TRUE"\r
ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="1"\r
UseOfMFC="1"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="../../mDNSWindows/DLL/Release/dnssd.lib ws2_32.lib iphlpapi.lib winspool.lib"\r
- OutputFile="$(OutDir)/RendezvousPrinterWizard.exe"\r
+ OutputFile="$(OutDir)/PrinterWizard.exe"\r
LinkIncremental="1"\r
GenerateDebugInformation="TRUE"\r
ProgramDatabaseFile="$(IntDir)/$(ProjectName).pdb"\r
Change History (most recent first):
$Log: PrinterSetupWizardApp.cpp,v $
+Revision 1.7 2005/02/15 07:50:09 shersche
+<rdar://problem/4007151> Update name
+
+Revision 1.6 2005/02/10 22:35:10 cheshire
+<rdar://problem/3727944> Update name
+
Revision 1.5 2005/01/25 18:30:02 shersche
Fix call to PathForResource() by passing in NULL as first parameter.
// Load Resources
- res = PathForResource( NULL, L"RendezvousPrinterWizard.dll", resource, MAX_PATH );
+ res = PathForResource( NULL, L"PrinterWizard.dll", resource, MAX_PATH );
err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
require_noerr( err, exit );
translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
require_noerr( err, exit );
- res = PathForResource( NULL, L"RendezvousPrinterWizardLocalized.dll", resource, MAX_PATH );
+ res = PathForResource( NULL, L"PrinterWizardLocalized.dll", resource, MAX_PATH );
err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
require_noerr( err, exit );
g_localizedResources = LoadLibrary( resource );
translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
- require_noerr( err, exit );\r
- \r
- AfxSetResourceHandle( g_localizedResources );\r
+ require_noerr( err, exit );
+
+ AfxSetResourceHandle( g_localizedResources );
// InitCommonControls() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
\r
IDD_SECOND_PAGE DIALOGEX 0, 0, 290, 154\r
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
-CAPTION "Rendezvous Printer Wizard"\r
+CAPTION "Bonjour Printer Wizard"\r
FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
BEGIN\r
LTEXT "Shared printers:",IDC_STATIC,3,0,171,8\r
\r
IDD_FIRST_PAGE DIALOGEX 0, 0, 290, 199\r
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
-CAPTION "Rendezvous Printer Wizard"\r
+CAPTION "Bonjour Printer Wizard"\r
FONT 8, "MS Shell Dlg", 0, 0, 0x0\r
BEGIN\r
- LTEXT "Welcome to the Rendezvous Printer Setup Wizard",\r
+ LTEXT "Welcome to the Bonjour Printer Setup Wizard",\r
IDC_GREETING,114,7,171,46\r
LTEXT "Click next to continue.",IDC_STATIC,115,188,143,8\r
- LTEXT "This wizard helps you connect to a shared printer using Rendezvous. Make sure your printer is turned on and connected to your network.",\r
+ LTEXT "This wizard helps you connect to a shared printer using Bonjour. Make sure your printer is turned on and connected to your network.",\r
IDC_STATIC,146,60,139,62\r
ICON "",IDC_INFO,118,60,20,20,SS_REALSIZEIMAGE\r
END\r
IDD_THIRD_PAGE DIALOGEX 0, 0, 290, 154\r
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
WS_SYSMENU\r
-CAPTION "Rendezvous Printer Wizard"\r
+CAPTION "Bonjour Printer Wizard"\r
FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
BEGIN\r
CONTROL "",IDC_PRINTER_MODEL,"SysListView32",LVS_REPORT | \r
LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,2,58,105,76\r
ICON 1017,1,0,0,20,27\r
LTEXT "",IDC_PRINTER_NAME,40,5,173,8\r
- LTEXT "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.",\r
- IDC_PRINTER_SELECTION_TEXT,40,23,243,26\r
+ LTEXT "The Bonjour Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer.",\r
+ IDC_PRINTER_SELECTION_TEXT,40,18,243,33\r
CONTROL "Use this printer as the default printer",\r
IDC_DEFAULT_PRINTER,"Button",BS_AUTOCHECKBOX | \r
- WS_TABSTOP,3,142,224,10\r
+ WS_TABSTOP,3,142,140,10\r
PUSHBUTTON "Have Disk...",IDC_HAVE_DISK,238,140,50,14\r
END\r
\r
IDD_FOURTH_PAGE DIALOGEX 0, 0, 290, 199\r
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION\r
-CAPTION "Rendezvous Printer Wizard"\r
+CAPTION "Bonjour Printer Wizard"\r
FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
BEGIN\r
- LTEXT "Completing the Rendezvous Printer Wizard",IDC_GOODBYE,\r
+ LTEXT "Completing the Bonjour Printer Wizard",IDC_GOODBYE,\r
116,7,171,27\r
- LTEXT "You have successfully completed the Rendezvous Printer Wizard. The printer has the following settings:",\r
+ LTEXT "You have successfully completed the Bonjour Printer Wizard. The printer has the following settings:",\r
IDC_STATIC,116,42,158,31\r
LTEXT "Name:",IDC_STATIC,116,78,22,8\r
LTEXT "Manufacturer:",IDC_STATIC,116,91,47,8\r
BLOCK "040904e4"\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
- VALUE "FileDescription", "Rendezvous Printer Wizard Resource Module"\r
+ VALUE "FileDescription", "Bonjour Resource Module"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
- VALUE "InternalName", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "InternalName", "PrinterWizardLocalized.dll"\r
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
- VALUE "OriginalFilename", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "OriginalFilename", "PrinterWizardLocalized.dll"\r
VALUE "ProductName", MASTER_PROD_NAME\r
VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
END\r
STRINGTABLE \r
BEGIN\r
IDS_ABOUTBOX "&About Printer Setup Wizard..."\r
- IDS_GOODBYE "Completing the Rendezvous Printer Setup Wizard."\r
- IDS_GREETING "Welcome to the Rendezvous Printer Setup Wizard"\r
- IDS_BROWSE_TITLE "Browse for Rendezvous Printers"\r
+ IDS_GOODBYE "Completing the Bonjour Printer Setup Wizard."\r
+ IDS_GREETING "Welcome to the Bonjour Printer Setup Wizard"\r
+ IDS_BROWSE_TITLE "Browse for Bonjour Printers"\r
IDS_BROWSE_SUBTITLE "Select the printer you want to use from the list below."\r
- IDS_CAPTION "Rendezvous Printer Wizard"\r
- IDS_GOODBYE_GOOD1 "You have successfully completed the Rendezvous Printer Wizard. The printer has the following settings:"\r
+ IDS_CAPTION "Bonjour Printer Wizard"\r
+ IDS_GOODBYE_GOOD1 "You have successfully completed the Bonjour Printer Wizard. The printer has the following settings:"\r
IDS_SEARCHING "Searching for printers..."\r
IDS_GOODBYTE_GOOD2 "To close this wizard, click Finish."\r
- IDS_INSTALL_TITLE "Install Rendezvous Printer"\r
+ IDS_INSTALL_TITLE "Install Bonjour Printer"\r
IDS_INSTALL_SUBTITLE "The manufacturer and model determine which printer software to use."\r
END\r
\r
"You do not have sufficient access to your computer to connect to the selected printer."\r
IDS_MANUFACTURER_HEADING "Manufacturer"\r
IDS_MODEL_HEADING "Model"\r
- IDS_NO_RENDEZVOUS_PRINTERS "No Rendezvous Printers are available"\r
- IDS_NO_MDNSRESPONDER_SERVICE_TEXT "Rendezvous Service is not available."\r
+ IDS_NO_PRINTERS "No Bonjour Printers are available"\r
+ IDS_NO_MDNSRESPONDER_SERVICE_TEXT "Bonjour Service is not available."\r
IDS_NO_MDNSRESPONDER_SERVICE_CAPTION "Error"\r
- IDS_PRINTER_MATCH_GOOD "The Rendezvous Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer."\r
- IDS_PRINTER_MATCH_BAD "The Rendezvous Printer Wizard cannot find a driver for this printer. Manually select from the list, or click 'Have Disk' if your printer came with an installation disk. "\r
+ IDS_PRINTER_MATCH_GOOD "The Bonjour Printer Wizard has auto-selected the following printer settings. Click 'Next' to continue installing this printer."\r
+ IDS_PRINTER_MATCH_BAD "The Bonjour Printer Wizard cannot find a driver for this printer. Manually select from the list, or click 'Have Disk' if your printer came with an installation disk. "\r
+ IDS_PRINTER_MATCH_MAYBE "The Bonjour Printer Wizard has selected a generic printer driver for this printer. If your printer came with an installation disk, click 'Have Disk' now to load the manufacturer's drivers."\r
IDS_YES "Yes"\r
IDS_NO "No"\r
IDS_LARGE_FONT "MS Sans Serif"\r
- IDS_FIREWALL "Please check firewall setting to ensure the Rendezvous Printer Wizard operates correctly."\r
+ IDS_FIREWALL "Please check firewall setting to ensure the Bonjour Printer Wizard operates correctly."\r
IDS_ERROR_CAPTION "Error"\r
+ IDS_PRINTER_UNAVAILABLE "The Bonjour printer you have selected is no longer available. Please make sure the printer is powered-on and plugged-in."\r
END\r
\r
STRINGTABLE \r
<Configurations>\r
<Configuration\r
Name="Debug|Win32"\r
- OutputDirectory=".\Debug\RendezvousPrinterWizard.exe.Resources\en.lproj"\r
+ OutputDirectory=".\Debug\Resources\PrinterWizard.exe.Resources\en.lproj"\r
IntermediateDirectory=".\Debug"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
Name="VCCustomBuildTool"/>\r
<Tool\r
Name="VCLinkerTool"\r
- OutputFile="$(OutDir)/RendezvousPrinterWizardLocalized.dll"\r
+ OutputFile="$(OutDir)/PrinterWizardLocalized.dll"\r
LinkIncremental="2"\r
GenerateDebugInformation="TRUE"\r
SubSystem="2"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
+if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\PrinterWizard.exe.Resources\r
+if not exist Debug\Resources\PrinterWizard.exe.Resources\en.lproj mkdir Debug\Resources\PrinterWizard.exe.Resources\en.lproj\r
+"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="_DEBUG"\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\RendezvousPrinterWizard.exe.Resources\en.lproj"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
Name="VCCustomBuildTool"/>\r
<Tool\r
Name="VCLinkerTool"\r
- OutputFile="$(OutDir)/RendezvousPrinterWizardLocalized.dll"\r
+ OutputFile="$(OutDir)/PrinterWizardLocalized.dll"\r
LinkIncremental="1"\r
GenerateDebugInformation="FALSE"\r
SubSystem="2"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Release\Root mkdir Release\Root\r
+if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
+if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj""/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\r
BLOCK "040904e4"\r
BEGIN\r
VALUE "CompanyName", "Apple Computer, Inc."\r
- VALUE "FileDescription", "Rendezvous Printer Wizard Resource Module"\r
+ VALUE "FileDescription", "Bonjour Resource Module"\r
VALUE "FileVersion", MASTER_PROD_VERS_STR\r
- VALUE "InternalName", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "InternalName", "PrinterWizardLocalized.dll"\r
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
- VALUE "OriginalFilename", "RendezvousPrinterWizardLocalized.dll"\r
+ VALUE "OriginalFilename", "PrinterWizardLocalized.dll"\r
VALUE "ProductName", MASTER_PROD_NAME\r
VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
END\r
<Configurations>\r
<Configuration\r
Name="Debug|Win32"\r
- OutputDirectory=".\Debug\RendezvousPrinterWizard.exe.Resources"\r
+ OutputDirectory=".\Debug\Resources\PrinterWizard.exe.Resources"\r
IntermediateDirectory=".\Debug"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
Name="VCCustomBuildTool"/>\r
<Tool\r
Name="VCLinkerTool"\r
- OutputFile="$(OutDir)/RendezvousPrinterWizard.dll"\r
+ OutputFile="$(OutDir)/PrinterWizard.dll"\r
LinkIncremental="2"\r
GenerateDebugInformation="TRUE"\r
SubSystem="2"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Debug\Resources mkdir Debug\Resources\r
+if not exist Debug\Resources\PrinterWizard.exe.Resources mkdir Debug\Resources\PrinterWizard.exe.Resources"/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="_DEBUG"\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\RendezvousPrinterWizard.exe.Resources"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
UseOfMFC="1"\r
Name="VCCustomBuildTool"/>\r
<Tool\r
Name="VCLinkerTool"\r
- OutputFile="$(OutDir)/RendezvousPrinterWizard.dll"\r
+ OutputFile="$(OutDir)/PrinterWizard.dll"\r
LinkIncremental="1"\r
GenerateDebugInformation="FALSE"\r
SubSystem="2"\r
<Tool\r
Name="VCPreBuildEventTool"/>\r
<Tool\r
- Name="VCPreLinkEventTool"/>\r
+ Name="VCPreLinkEventTool"\r
+ Description="Building Output Directories"\r
+ CommandLine="if not exist Release\Root mkdir Release\Root\r
+if not exist "Release\Root\Program Files" mkdir "Release\Root\Program Files"\r
+if not exist "Release\Root\Program Files\Bonjour" mkdir "Release\Root\Program Files\Bonjour"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources" mkdir "Release\Root\Program Files\Bonjour\Resources"\r
+if not exist "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources" mkdir "Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources""/>\r
<Tool\r
Name="VCResourceCompilerTool"\r
PreprocessorDefinitions="NDEBUG"\r
Change History (most recent first):
$Log: PrinterSetupWizardSheet.cpp,v $
+Revision 1.29 2005/02/14 20:48:37 shersche
+<rdar://problem/4003710> Default pdl key to "application/postscript"
+
+Revision 1.28 2005/02/14 20:37:53 shersche
+<rdar://problem/4003944> Populate comment field with the model name that users see in the wizard UI.
+
+Revision 1.27 2005/02/09 05:04:03 shersche
+<rdar://problem/3946587> Use TXTRecordGetValuePtr() API in ParseTextRecord
+
+Revision 1.26 2005/02/08 21:45:06 shersche
+<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
+
+Revision 1.25 2005/02/08 18:54:17 shersche
+<rdar://problem/3987680> Default queue name is "lp" when rp key is not specified.
+
+Revision 1.24 2005/02/01 02:15:55 shersche
+<rdar://problem/3946587> Use TXTRecord parsing APIs in ParseTextRecord
+
+Revision 1.23 2005/01/31 23:54:30 shersche
+<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
+
Revision 1.22 2005/01/25 18:49:43 shersche
Get icon resources from resource DLL
// Private Messages
-#define WM_PROCESS_EVENT ( WM_USER + 0x100 )
+#define WM_SOCKET_EVENT ( WM_USER + 0x100 )
+#define WM_PROCESS_EVENT ( WM_USER + 0x101 )
// CPrinterSetupWizardSheet
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage),
m_selectedPrinter(NULL),
m_driverThreadExitCode( 0 ),
- m_driverThreadFinished( false )
+ m_driverThreadFinished( false ),
+ m_pdlBrowser( NULL ),
+ m_ippBrowser( NULL ),
+ m_lprBrowser( NULL )
{
m_arrow = LoadCursor(0, IDC_ARROW);
m_wait = LoadCursor(0, IDC_APPSTARTING);
m_self = this;
Init();
+
+ LoadPrinterNames();
}
CPrinterSetupWizardSheet::~CPrinterSetupWizardSheet()
{
- if ( m_selectedPrinter != NULL )
+ Printer * printer;
+
+ while ( m_printers.size() > 0 )
{
- delete m_selectedPrinter;
- m_selectedPrinter = NULL;
+ printer = m_printers.front();
+ m_printers.pop_front();
+
+ delete printer;
}
m_self = NULL;
}
+OSStatus
+CPrinterSetupWizardSheet::LoadPrinterNames()
+{
+ PBYTE buffer = NULL;
+ OSStatus err = 0;
+
+ //
+ // rdar://problem/3701926 - Printer can't be installed twice
+ //
+ // First thing we want to do is make sure the printer isn't already installed.
+ // If the printer name is found, we'll try and rename it until we
+ // find a unique name
+ //
+ DWORD dwNeeded = 0, dwNumPrinters = 0;
+
+ BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters);
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+
+ if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0))
+ {
+ try
+ {
+ buffer = new unsigned char[dwNeeded];
+ }
+ catch (...)
+ {
+ buffer = NULL;
+ }
+
+ require_action( buffer, exit, kNoMemoryErr );
+ ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters);
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ for (DWORD index = 0; index < dwNumPrinters; index++)
+ {
+ PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
+
+ m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName;
+ }
+ }
+
+exit:
+
+ if (buffer != NULL)
+ {
+ delete [] buffer;
+ }
+
+ return err;
+}
+
+
+
// ------------------------------------------------------
// InstallPrinter
//
pInfo.pServerName = NULL;
pInfo.pShareName = NULL;
pInfo.pPortName = printer->portName.GetBuffer();
- pInfo.pDriverName = printer->model.GetBuffer();
- pInfo.pComment = printer->model.GetBuffer();
+ pInfo.pDriverName = printer->modelName.GetBuffer();
+ pInfo.pComment = printer->displayModelName.GetBuffer();
pInfo.pLocation = service->location.GetBuffer();
pInfo.pDevMode = NULL;
pInfo.pDevMode = NULL;
pInfo.pPrinterName = printer->actualName.GetBuffer();
pInfo.pPortName = printer->portName.GetBuffer();
- pInfo.pDriverName = printer->model.GetBuffer();
+ pInfo.pDriverName = printer->modelName.GetBuffer();
pInfo.pPrintProcessor = L"winprint";
pInfo.pLocation = service->location.GetBuffer();
+ pInfo.pComment = printer->displayModelName.GetBuffer();
pInfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo);
BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet)
+ON_MESSAGE( WM_SOCKET_EVENT, OnSocketEvent )
ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent )
ON_WM_SETCURSOR()
ON_WM_TIMER()
//
BOOL CPrinterSetupWizardSheet::OnInitDialog()
{
+ OSStatus err;
+
CPropertySheet::OnInitDialog();
+ err = StartBrowse();
+ require_noerr( err, exit );
+
+exit:
+
+ if ( err )
+ {
+ StopBrowse();
+
+ if ( err == kDNSServiceErr_Firewall )
+ {
+ CString text, caption;
+
+ text.LoadString( IDS_FIREWALL );
+ caption.LoadString( IDS_FIREWALL_CAPTION );
+
+ MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
+ }
+ else
+ {
+ CPrinterSetupWizardSheet::WizardException exc;
+
+ exc.text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
+ exc.caption.LoadString( IDS_ERROR_CAPTION );
+
+ throw(exc);
+ }
+ }
+
return TRUE;
}
MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION);
}
+
+ StopBrowse();
}
}
+LONG
+CPrinterSetupWizardSheet::OnSocketEvent(WPARAM inWParam, LPARAM inLParam)
+{
+ if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
+ {
+ dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
+ }
+ else
+ {
+ SOCKET sock = (SOCKET) inWParam;
+
+ // iterate thru list
+ ServiceRefList::iterator begin = m_serviceRefList.begin();
+ ServiceRefList::iterator end = m_serviceRefList.end();
+
+ while (begin != end)
+ {
+ DNSServiceRef ref = *begin++;
+
+ check(ref != NULL);
+
+ if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
+ {
+ DNSServiceProcessResult(ref);
+ break;
+ }
+ }
+ }
+
+ return ( 0 );
+}
+
+
LONG
CPrinterSetupWizardSheet::OnProcessEvent(WPARAM inWParam, LPARAM inLParam)
{
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
- command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->model, (LPCTSTR) printer->infFileName );
+ command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->modelName, (LPCTSTR) printer->infFileName );
ok = CreateProcess(NULL, command.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
err = translate_errno( ok, errno_compat(), kUnknownErr );
return 0;
}
+
+
+void DNSSD_API
+CPrinterSetupWizardSheet::OnBrowse(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ void * inContext )
+{
+ DEBUG_UNUSED(inRef);
+
+ CPrinterSetupWizardSheet * self;
+ bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
+ CPropertyPage * active;
+ Printer * printer = NULL;
+ Service * service = NULL;
+ OSStatus err = kNoErr;
+
+ require_noerr( inErrorCode, exit );
+
+ self = reinterpret_cast <CPrinterSetupWizardSheet*>( inContext );
+ require_quiet( self, exit );
+
+ active = self->GetActivePage();
+ require_quiet( active, exit );
+
+ // Have we seen this printer before?
+
+ printer = self->Lookup( inName );
+
+ if ( printer )
+ {
+ service = printer->LookupService( inType );
+ }
+
+ if ( inFlags & kDNSServiceFlagsAdd )
+ {
+ if (printer == NULL)
+ {
+ // If not, then create a new one
+
+ printer = self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing );
+ require_action( printer, exit, err = kUnknownErr );
+ }
+
+ if ( !service )
+ {
+ err = self->OnAddService( printer, inInterfaceIndex, inName, inType, inDomain );
+ require_noerr( err, exit );
+ }
+ else
+ {
+ service->refs++;
+ }
+ }
+ else if ( printer )
+ {
+ check( service );
+
+ err = self->OnRemoveService( service );
+ require_noerr( err, exit );
+
+ if ( printer->services.size() == 0 )
+ {
+ err = self->OnRemovePrinter( printer, moreComing );
+ require_noerr( err, exit );
+ }
+ }
+
+exit:
+
+ return;
+}
+
+
+void DNSSD_API
+CPrinterSetupWizardSheet::OnResolve(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ const char * inHostName,
+ uint16_t inPort,
+ uint16_t inTXTSize,
+ const char * inTXT,
+ void * inContext )
+{
+ DEBUG_UNUSED(inFullName);
+ DEBUG_UNUSED(inInterfaceIndex);
+ DEBUG_UNUSED(inFlags);
+ DEBUG_UNUSED(inRef);
+
+ CPrinterSetupWizardSheet * self;
+ Service * service;
+ Queue * q;
+ uint32_t qpriority = kDefaultPriority;
+ CString qname;
+ int idx;
+ OSStatus err;
+
+ require_noerr( inErrorCode, exit );
+
+ service = reinterpret_cast<Service*>( inContext );
+ require_quiet( service, exit);
+
+ check( service->refs != 0 );
+
+ self = service->printer->window;
+ require_quiet( self, exit );
+
+ err = self->StopOperation( service->serviceRef );
+ require_noerr( err, exit );
+
+ //
+ // hold on to the hostname...
+ //
+ err = UTF8StringToStringObject( inHostName, service->hostname );
+ require_noerr( err, exit );
+
+ //
+ // <rdar://problem/3739200> remove the trailing dot on hostname
+ //
+ idx = service->hostname.ReverseFind('.');
+
+ if ((idx > 1) && ((service->hostname.GetLength() - 1) == idx))
+ {
+ service->hostname.Delete(idx, 1);
+ }
+
+ //
+ // hold on to the port
+ //
+ service->portNumber = ntohs(inPort);
+
+ //
+ // parse the text record.
+ //
+
+ err = self->ParseTextRecord( service, inTXTSize, inTXT, qname, qpriority );
+ require_noerr( err, exit );
+
+ if ( service->qtotal == 1 )
+ {
+ //
+ // create a new queue
+ //
+ try
+ {
+ q = new Queue;
+ }
+ catch (...)
+ {
+ q = NULL;
+ }
+
+ require_action( q, exit, err = E_OUTOFMEMORY );
+
+
+ q->name = qname;
+ q->priority = qpriority;
+
+ service->queues.push_back( q );
+
+ //
+ // we've completely resolved this service
+ //
+
+ self->OnResolveService( service );
+ }
+ else
+ {
+ //
+ // if qtotal is more than 1, then we need to get additional
+ // text records. if not, then this service is considered
+ // resolved
+ //
+
+ err = DNSServiceQueryRecord(&service->serviceRef, 0, inInterfaceIndex, inFullName, kDNSServiceType_TXT, kDNSServiceClass_IN, OnQuery, (void*) service );
+ require_noerr( err, exit );
+
+ err = self->StartOperation( service->serviceRef );
+ require_noerr( err, exit );
+ }
+
+exit:
+
+ return;
+}
+
+
+void DNSSD_API
+CPrinterSetupWizardSheet::OnQuery(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ uint16_t inRRType,
+ uint16_t inRRClass,
+ uint16_t inRDLen,
+ const void * inRData,
+ uint32_t inTTL,
+ void * inContext)
+{
+ DEBUG_UNUSED( inTTL );
+ DEBUG_UNUSED( inRRClass );
+ DEBUG_UNUSED( inRRType );
+ DEBUG_UNUSED( inFullName );
+ DEBUG_UNUSED( inInterfaceIndex );
+ DEBUG_UNUSED( inRef );
+
+ Service * service = NULL;
+ Queue * q;
+ CPrinterSetupWizardSheet * self;
+ OSStatus err = kNoErr;
+
+ require_noerr( inErrorCode, exit );
+
+ service = reinterpret_cast<Service*>( inContext );
+ require_quiet( service, exit);
+
+ self = service->printer->window;
+ require_quiet( self, exit );
+
+ if ( ( inFlags & kDNSServiceFlagsAdd ) && ( inRDLen > 0 ) && ( inRData != NULL ) )
+ {
+ const char * inTXT = ( const char * ) inRData;
+
+ //
+ // create a new queue
+ //
+ try
+ {
+ q = new Queue;
+ }
+ catch (...)
+ {
+ q = NULL;
+ }
+
+ require_action( q, exit, err = E_OUTOFMEMORY );
+
+ err = service->printer->window->ParseTextRecord( service, inRDLen, inTXT, q->name, q->priority );
+ require_noerr( err, exit );
+
+ //
+ // add this queue
+ //
+
+ service->queues.push_back( q );
+
+ if ( service->queues.size() == service->qtotal )
+ {
+ //
+ // else if moreComing is not set, then we're going
+ // to assume that we're done
+ //
+
+ self->StopOperation( service->serviceRef );
+
+ //
+ // sort the queues
+ //
+
+ service->queues.sort( OrderQueueFunc );
+
+ //
+ // we've completely resolved this service
+ //
+
+ self->OnResolveService( service );
+ }
+ }
+
+exit:
+
+ if ( err && service && ( service->serviceRef != NULL ) )
+ {
+ service->printer->window->StopOperation( service->serviceRef );
+ }
+
+ return;
+}
+
+
+Printer*
+CPrinterSetupWizardSheet::OnAddPrinter(
+ uint32_t inInterfaceIndex,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ bool moreComing)
+{
+ Printer * printer = NULL;
+ DWORD printerNameCount;
+ OSStatus err;
+
+ DEBUG_UNUSED( inInterfaceIndex );
+ DEBUG_UNUSED( inType );
+ DEBUG_UNUSED( inDomain );
+
+ try
+ {
+ printer = new Printer;
+ }
+ catch (...)
+ {
+ printer = NULL;
+ }
+
+ require_action( printer, exit, err = E_OUTOFMEMORY );
+
+ printer->window = this;
+ printer->name = inName;
+
+ err = UTF8StringToStringObject(inName, printer->displayName);
+ check_noerr( err );
+ printer->actualName = printer->displayName;
+ printer->installed = false;
+ printer->deflt = false;
+ printer->resolving = 0;
+
+ // Compare this name against printers that are already installed
+ // to avoid name clashes. Rename as necessary
+ // to come up with a unique name.
+
+ printerNameCount = 2;
+
+ for (;;)
+ {
+ CPrinterSetupWizardSheet::PrinterNameMap::iterator it;
+
+ it = m_printerNames.find(printer->actualName);
+
+ if (it != m_printerNames.end())
+ {
+ printer->actualName.Format(L"%s (%d)", printer->displayName, printerNameCount);
+ }
+ else
+ {
+ break;
+ }
+
+ printerNameCount++;
+ }
+
+ m_printers.push_back( printer );
+
+ if ( GetActivePage() == &m_pgSecond )
+ {
+ m_pgSecond.OnAddPrinter( printer, moreComing );
+ }
+
+exit:
+
+ return printer;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::OnAddService(
+ Printer * printer,
+ uint32_t inInterfaceIndex,
+ const char * inName,
+ const char * inType,
+ const char * inDomain)
+{
+ Service * service = NULL;
+ OSStatus err = kNoErr;
+
+ DEBUG_UNUSED( inName );
+ DEBUG_UNUSED( inDomain );
+
+ try
+ {
+ service = new Service;
+ }
+ catch (...)
+ {
+ service = NULL;
+ }
+
+ require_action( service, exit, err = E_OUTOFMEMORY );
+
+ service->printer = printer;
+ service->ifi = inInterfaceIndex;
+ service->type = inType;
+ service->domain = inDomain;
+ service->qtotal = 1;
+ service->refs = 1;
+ service->serviceRef = NULL;
+
+ printer->services.push_back( service );
+
+ //
+ // if the printer is selected, then we'll want to start a
+ // resolve on this guy
+ //
+
+ if ( printer == m_selectedPrinter )
+ {
+ StartResolve( service );
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::OnRemovePrinter( Printer * printer, bool moreComing )
+{
+ CPropertyPage * active = GetActivePage();
+ OSStatus err = kNoErr;
+
+ if ( active == &m_pgSecond )
+ {
+ m_pgSecond.OnRemovePrinter( printer, moreComing );
+ }
+
+ m_printers.remove( printer );
+
+ if ( m_selectedPrinter == printer )
+ {
+ m_selectedPrinter = NULL;
+
+ if ( ( active == &m_pgThird ) || ( active == &m_pgFourth ) )
+ {
+ CString caption;
+ CString message;
+
+ caption.LoadString( IDS_ERROR_CAPTION );
+ message.LoadString( IDS_PRINTER_UNAVAILABLE );
+
+ MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION);
+
+ SetActivePage( &m_pgSecond );
+ }
+ }
+
+ delete printer;
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::OnRemoveService( Service * service )
+{
+ OSStatus err = kNoErr;
+
+ if ( service && ( --service->refs == 0 ) )
+ {
+ if ( service->serviceRef != NULL )
+ {
+ err = StopResolve( service );
+ require_noerr( err, exit );
+ }
+
+ service->printer->services.remove( service );
+
+ delete service;
+ }
+
+exit:
+
+ return err;
+}
+
+
+void
+CPrinterSetupWizardSheet::OnResolveService( Service * service )
+{
+ // Make sure that the active page is page 2
+
+ check( GetActivePage() == &m_pgSecond );
+
+ if ( !--service->printer->resolving )
+ {
+ // sort the services now. we want the service that
+ // has the highest priority queue to be first in
+ // the list.
+
+ service->printer->services.sort( OrderServiceFunc );
+
+ // Now we can hit next
+
+ SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
+
+ // Reset the cursor
+
+ m_active = m_arrow;
+
+ // And tell page 2 about it
+
+ m_pgSecond.OnResolveService( service );
+ }
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StartBrowse()
+{
+ OSStatus err;
+
+ //
+ // setup the DNS-SD browsing
+ //
+ err = DNSServiceBrowse( &m_pdlBrowser, 0, 0, kPDLServiceType, NULL, OnBrowse, this );
+ require_noerr( err, exit );
+
+ err = StartOperation( m_pdlBrowser );
+ require_noerr( err, exit );
+
+ err = DNSServiceBrowse( &m_lprBrowser, 0, 0, kLPRServiceType, NULL, OnBrowse, this );
+ require_noerr( err, exit );
+
+ err = StartOperation( m_lprBrowser );
+ require_noerr( err, exit );
+
+ err = DNSServiceBrowse( &m_ippBrowser, 0, 0, kIPPServiceType, NULL, OnBrowse, this );
+ require_noerr( err, exit );
+
+ err = StartOperation( m_ippBrowser );
+ require_noerr( err, exit );
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StopBrowse()
+{
+ OSStatus err;
+
+ err = StopOperation( m_pdlBrowser );
+ require_noerr( err, exit );
+
+ err = StopOperation( m_lprBrowser );
+ require_noerr( err, exit );
+
+ err = StopOperation( m_ippBrowser );
+ require_noerr( err, exit );
+
+ while ( m_printers.size() > 0 )
+ {
+ Printer * printer = m_printers.front();
+
+ m_printers.pop_front();
+
+ if ( printer->resolving )
+ {
+ StopResolve( printer );
+ }
+
+ delete printer;
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StartResolve( Printer * printer )
+{
+ OSStatus err = kNoErr;
+ Services::iterator it;
+
+ check( printer );
+
+ for ( it = printer->services.begin(); it != printer->services.end(); it++ )
+ {
+ if ( (*it)->serviceRef == NULL )
+ {
+ err = StartResolve( *it );
+ require_noerr( err, exit );
+ }
+ }
+
+ m_selectedPrinter = printer;
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StartResolve( Service * service )
+{
+ OSStatus err = kNoErr;
+
+ check( service->serviceRef == NULL );
+
+ //
+ // clean out any queues that were collected during a previous
+ // resolve
+ //
+
+ service->EmptyQueues();
+
+ //
+ // now start the new resolve
+ //
+
+ err = DNSServiceResolve( &service->serviceRef, 0, 0, service->printer->name.c_str(), service->type.c_str(), service->domain.c_str(), (DNSServiceResolveReply) OnResolve, service );
+ require_noerr( err, exit );
+
+ err = StartOperation( service->serviceRef );
+ require_noerr( err, exit );
+
+ //
+ // If we're not currently resolving, then disable the next button
+ // and set the cursor to hourglass
+ //
+
+ if ( !service->printer->resolving )
+ {
+ SetWizardButtons( PSWIZB_BACK );
+
+ m_active = m_wait;
+ SetCursor(m_active);
+ }
+
+ service->printer->resolving++;
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StopResolve(Printer * printer)
+{
+ OSStatus err = kNoErr;
+
+ check( printer );
+
+ Services::iterator it;
+
+ for ( it = printer->services.begin(); it != printer->services.end(); it++ )
+ {
+ if ( (*it)->serviceRef )
+ {
+ err = StopResolve( *it );
+ require_noerr( err, exit );
+ }
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StopResolve( Service * service )
+{
+ OSStatus err;
+
+ check( service->serviceRef );
+
+ err = StopOperation( service->serviceRef );
+ require_noerr( err, exit );
+
+ service->printer->resolving--;
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StartOperation( DNSServiceRef ref )
+{
+ OSStatus err;
+
+ err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(ref), m_hWnd, WM_SOCKET_EVENT, FD_READ|FD_CLOSE);
+ require_noerr( err, exit );
+
+ m_serviceRefList.push_back( ref );
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::StopOperation( DNSServiceRef & ref )
+{
+ OSStatus err = kNoErr;
+
+ if ( ref )
+ {
+ m_serviceRefList.remove( ref );
+
+ if ( IsWindow( m_hWnd ) )
+ {
+ err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 );
+ require_noerr( err, exit );
+ }
+
+ DNSServiceRefDeallocate( ref );
+ ref = NULL;
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority )
+{
+ // <rdar://problem/3946587> Use TXTRecord APIs declared in dns_sd.h
+
+ bool qtotalDefined = false;
+ const void * val;
+ char buf[256];
+ uint8_t len;
+ OSStatus err = kNoErr;
+
+ // <rdar://problem/3987680> Default to queue "lp"
+
+ qname = L"lp";
+
+ // <rdar://problem/4003710> Default pdl key to be "application/postscript"
+
+ service->pdl = L"application/postscript";
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "rp", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, qname );
+ require_noerr( err, exit );
+ }
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "pdl", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, service->pdl );
+ require_noerr( err, exit );
+ }
+
+ if ( ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_mfg", &len ) ) != NULL ) ||
+ ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_manufacturer", &len ) ) != NULL ) )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, service->usb_MFG );
+ require_noerr( err, exit );
+ }
+
+ if ( ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_mdl", &len ) ) != NULL ) ||
+ ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_model", &len ) ) != NULL ) )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, service->usb_MDL );
+ require_noerr( err, exit );
+ }
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "ty", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, service->description );
+ require_noerr( err, exit );
+ }
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "product", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, service->product );
+ require_noerr( err, exit );
+ }
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "note", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ err = UTF8StringToStringObject( buf, service->location );
+ require_noerr( err, exit );
+ }
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "qtotal", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ service->qtotal = (unsigned short) atoi( buf );
+ qtotalDefined = true;
+ }
+
+ if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "priority", &len ) ) != NULL )
+ {
+ // Stringize val ( doesn't have trailing '\0' yet )
+
+ memcpy( buf, val, len );
+ buf[len] = '\0';
+
+ qpriority = atoi( buf );
+ }
+
+exit:
+
+ // The following code is to fix a problem with older HP
+ // printers that don't include "qtotal" in their text
+ // record. We'll check to see if the qname is "TEXT"
+ // and if so, we're going to modify it to be "lp" so
+ // that we don't use the wrong queue
+
+ if ( !err && !qtotalDefined && ( qname == L"TEXT" ) )
+ {
+ qname = "lp";
+ }
+
+ return err;
+}
+
+
+Printer*
+CPrinterSetupWizardSheet::Lookup(const char * inName)
+{
+ check( inName );
+
+ Printer * printer = NULL;
+ Printers::iterator it;
+
+ for ( it = m_printers.begin(); it != m_printers.end(); it++ )
+ {
+ if ( (*it)->name == inName )
+ {
+ printer = *it;
+ break;
+ }
+ }
+
+ return printer;
+}
+
+
+bool
+CPrinterSetupWizardSheet::OrderServiceFunc( const Service * a, const Service * b )
+{
+ Queue * q1, * q2;
+
+ q1 = (a->queues.size() > 0) ? a->queues.front() : NULL;
+
+ q2 = (b->queues.size() > 0) ? b->queues.front() : NULL;
+
+ if ( !q1 && !q2 )
+ {
+ return true;
+ }
+ else if ( q1 && !q2 )
+ {
+ return true;
+ }
+ else if ( !q1 && q2 )
+ {
+ return false;
+ }
+ else if ( q1->priority < q2->priority )
+ {
+ return true;
+ }
+ else if ( q1->priority > q2->priority )
+ {
+ return false;
+ }
+ else if ( ( a->type == kPDLServiceType ) || ( ( a->type == kLPRServiceType ) && ( b->type == kIPPServiceType ) ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool
+CPrinterSetupWizardSheet::OrderQueueFunc( const Queue * q1, const Queue * q2 )
+{
+ return ( q1->priority <= q2->priority ) ? true : false;
+}
+
+
+
Change History (most recent first):
$Log: PrinterSetupWizardSheet.h,v $
+Revision 1.8 2005/02/08 18:53:33 shersche
+Remove qtotalDefined parameter from ParseTextRecord()
+
+Revision 1.7 2005/01/31 23:54:29 shersche
+<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
+
Revision 1.6 2005/01/03 19:05:01 shersche
Store pointer to instance of wizard sheet so that print driver install thread sends a window message to the correct window
//
virtual LONG
OnProcessEvent(WPARAM inWParam, LPARAM inLParam);
+
+ virtual LONG
+ OnSocketEvent(WPARAM inWParam, LPARAM inLParam);
virtual BOOL
OnCommand(WPARAM wParam, LPARAM lParam);
afx_msg void
OnOK();
+ OSStatus
+ StartResolve( Printer * printer );
+
+ OSStatus
+ StopResolve( Printer * printer );
+
+ Printers m_printers;
+
HCURSOR m_active;
HCURSOR m_arrow;
HCURSOR m_wait;
private:
+ static void DNSSD_API
+ OnBrowse(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ void * inContext );
+
+ static void DNSSD_API
+ OnResolve(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ const char * inHostName,
+ uint16_t inPort,
+ uint16_t inTXTSize,
+ const char * inTXT,
+ void * inContext );
+
+ static void DNSSD_API
+ OnQuery(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ uint16_t inRRType,
+ uint16_t inRRClass,
+ uint16_t inRDLen,
+ const void * inRData,
+ uint32_t inTTL,
+ void * inContext);
+
+ Printer*
+ OnAddPrinter(
+ uint32_t inInterfaceIndex,
+ const char * inName,
+ const char * inType,
+ const char * inDomain,
+ bool moreComing);
+
+ OSStatus
+ OnRemovePrinter(
+ Printer * printer,
+ bool moreComing);
+
+ OSStatus
+ OnAddService(
+ Printer * printer,
+ uint32_t inInterfaceIndex,
+ const char * inName,
+ const char * inType,
+ const char * inDomain);
+
+ OSStatus
+ OnRemoveService(
+ Service * service);
+
+ void
+ OnResolveService(
+ Service * service );
+
+ static bool
+ OrderServiceFunc( const Service * a, const Service * b );
+
+ static bool
+ OrderQueueFunc( const Queue * q1, const Queue * q2 );
+
+ OSStatus
+ StartOperation( DNSServiceRef ref );
+
+ OSStatus
+ StopOperation( DNSServiceRef & ref );
+
+ OSStatus
+ StartBrowse();
+
+ OSStatus
+ StopBrowse();
+
+ OSStatus
+ StartResolve( Service * service );
+
+ OSStatus
+ StopResolve( Service * service );
+
+ OSStatus
+ ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, CString & qname, uint32_t & qpriority );
+
+ OSStatus
+ LoadPrinterNames();
+
+ Printer*
+ Lookup( const char * name );
+
OSStatus
InstallPrinter(Printer * printer);
static unsigned WINAPI
InstallDriverThread( LPVOID inParam );
+ typedef std::map<CString,CString> PrinterNameMap;
+ typedef std::list<DNSServiceRef> ServiceRefList;
static CPrinterSetupWizardSheet * m_self;
+ PrinterNameMap m_printerNames;
Printer * m_selectedPrinter;
bool m_driverThreadFinished;
DWORD m_driverThreadExitCode;
+ ServiceRefList m_serviceRefList;
+ DNSServiceRef m_pdlBrowser;
+ DNSServiceRef m_lprBrowser;
+ DNSServiceRef m_ippBrowser;
+ DNSServiceRef m_resolver;
};
Change History (most recent first):
$Log: SecondPage.cpp,v $
+Revision 1.13 2005/02/15 07:50:10 shersche
+<rdar://problem/4007151> Update name
+
+Revision 1.12 2005/02/10 22:35:11 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.11 2005/01/31 23:54:30 shersche
+<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
+
Revision 1.10 2005/01/20 19:54:38 shersche
Fix parse error when text record is NULL
// local variable is initialize but not referenced
#pragma warning(disable:4189)
-#define WM_SERVICE_EVENT ( WM_USER + 0x101 )
-
// CSecondPage dialog
IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
CSecondPage::CSecondPage()
- : CPropertyPage(CSecondPage::IDD),
- m_pdlBrowser( NULL ),
- m_lprBrowser( NULL ),
- m_ippBrowser( NULL ),
- m_selected( NULL )
+ : CPropertyPage(CSecondPage::IDD)
{
m_psp.dwFlags &= ~(PSP_HASHELP);
m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_BROWSE_TITLE);
m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE);
- m_resolver = NULL;
m_emptyListItem = NULL;
m_initialized = false;
m_waiting = false;
-
- LoadPrinterNames();
}
CSecondPage::~CSecondPage()
{
- StopBrowse();
-}
-
-
-OSStatus
-CSecondPage::LoadPrinterNames()
-{
- PBYTE buffer = NULL;
- OSStatus err = 0;
-
- //
- // rdar://problem/3701926 - Printer can't be installed twice
- //
- // First thing we want to do is make sure the printer isn't already installed.
- // If the printer name is found, we'll try and rename it until we
- // find a unique name
- //
- DWORD dwNeeded = 0, dwNumPrinters = 0;
-
- BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
-
- if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0))
- {
- try
- {
- buffer = new unsigned char[dwNeeded];
- }
- catch (...)
- {
- buffer = NULL;
- }
-
- require_action( buffer, exit, kNoMemoryErr );
- ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- for (DWORD index = 0; index < dwNumPrinters; index++)
- {
- PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
-
- m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName;
- }
- }
-
-exit:
-
- if (buffer != NULL)
- {
- delete [] buffer;
- }
-
- return err;
}
require_quiet( psheet, exit );
//
- // load the no rendezvous printers message until something shows up in the browse list
+ // load the no printers message until something shows up in the browse list
//
- text.LoadString(IDS_NO_RENDEZVOUS_PRINTERS);
+ text.LoadString(IDS_NO_PRINTERS);
LoadTextAndDisableWindow( text );
}
-OSStatus
-CSecondPage::StartOperation( DNSServiceRef ref )
-{
- OSStatus err;
-
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(ref), m_hWnd, WM_SERVICE_EVENT, FD_READ|FD_CLOSE);
- require_noerr( err, exit );
-
- m_serviceRefList.push_back( ref );
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopOperation( DNSServiceRef & ref )
-{
- OSStatus err = kNoErr;
-
- if ( ref )
- {
- m_serviceRefList.remove( ref );
-
- if ( IsWindow( m_hWnd ) )
- {
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 );
- require_noerr( err, exit );
- }
-
- DNSServiceRefDeallocate( ref );
- ref = NULL;
- }
-
-exit:
-
- return err;
-}
-
-
-Printer*
-CSecondPage::Lookup(const char * inName)
-{
- check( IsWindow( m_hWnd ) );
- check( inName );
-
- HTREEITEM item = m_browseList.GetChildItem( TVI_ROOT );\r
- while ( item )\r
- {\r
- Printer * printer;\r
- DWORD_PTR data;\r
-\r
- data = m_browseList.GetItemData( item );\r
- printer = reinterpret_cast<Printer*>(data);\r
-\r
- if ( printer && ( printer->name == inName ) )
- {
- return printer;
- }
-\r
- item = m_browseList.GetNextItem( item, TVGN_NEXT );
- }
-
- return NULL;
-}
-
-
-OSStatus
-CSecondPage::StartBrowse()
-{
- OSStatus err;
-
- //
- // setup the DNS-SD browsing
- //
- err = DNSServiceBrowse( &m_pdlBrowser, 0, 0, kPDLServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- err = StartOperation( m_pdlBrowser );
- require_noerr( err, exit );
-
- err = DNSServiceBrowse( &m_lprBrowser, 0, 0, kLPRServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- err = StartOperation( m_lprBrowser );
- require_noerr( err, exit );
-
- err = DNSServiceBrowse( &m_ippBrowser, 0, 0, kIPPServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- err = StartOperation( m_ippBrowser );
- require_noerr( err, exit );
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopBrowse()
-{
- OSStatus err;
-
- err = StopOperation( m_pdlBrowser );
- require_noerr( err, exit );
-
- err = StopOperation( m_lprBrowser );
- require_noerr( err, exit );
-
- err = StopOperation( m_ippBrowser );
- require_noerr( err, exit );
-
- while ( m_printers.size() > 0 )
- {
- Printer * printer = m_printers.front();
-
- m_printers.pop_front();
-
- if ( printer->resolving )
- {
- StopResolve( printer );
- }
-
- delete printer;
- }
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StartResolve( Printer * printer )
-{
- CPrinterSetupWizardSheet * psheet;
- OSStatus err = kNoErr;
- Services::iterator it;
-
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- check( printer );
-
- for ( it = printer->services.begin(); it != printer->services.end(); it++ )
- {
- if ( (*it)->serviceRef == NULL )
- {
- err = StartResolve( *it );
- require_noerr( err, exit );
- }
- }
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StartResolve( Service * service )
-{
- CPrinterSetupWizardSheet * psheet;
- OSStatus err = kNoErr;
-
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- check( service->serviceRef == NULL );
-
- //
- // clean out any queues that were collected during a previous
- // resolve
- //
-
- service->EmptyQueues();
-
- //
- // now start the new resolve
- //
-
- err = DNSServiceResolve( &service->serviceRef, 0, 0, service->printer->name.c_str(), service->type.c_str(), service->domain.c_str(), (DNSServiceResolveReply) OnResolve, service );
- require_noerr( err, exit );
-
- err = StartOperation( service->serviceRef );
- require_noerr( err, exit );
-
- //
- // If we're not currently resolving, then disable the next button
- // and set the cursor to hourglass
- //
-
- if ( !service->printer->resolving )
- {
- psheet->SetWizardButtons( PSWIZB_BACK );
-
- psheet->m_active = psheet->m_wait;
- SetCursor(psheet->m_active);
- }
-
- service->printer->resolving++;
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopResolve(Printer * printer)
-{
- OSStatus err = kNoErr;
-
- check( printer );
-
- Services::iterator it;
-
- for ( it = printer->services.begin(); it != printer->services.end(); it++ )
- {
- if ( (*it)->serviceRef )
- {
- err = StopResolve( *it );
- require_noerr( err, exit );
- }
- }
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopResolve( Service * service )
+void CSecondPage::DoDataExchange(CDataExchange* pDX)
{
- OSStatus err;
-
- check( service->serviceRef );
-
- err = StopOperation( service->serviceRef );
- require_noerr( err, exit );
+ CPropertyPage::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
+ DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);
- service->printer->resolving--;
+ DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);
-exit:
+ DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);
- return err;
-}
+ DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);
+ DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);
-void CSecondPage::DoDataExchange(CDataExchange* pDX)
-{
- CPropertyPage::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
- DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);\r
- DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);\r
- DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);\r
- DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);\r
- DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);\r
}
{
CPrinterSetupWizardSheet * psheet;
Printer * printer;
+ Printers::iterator it;
OSStatus err = kNoErr;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_action( psheet, exit, err = kUnknownErr );
- if ( ( printer = psheet->GetSelectedPrinter() ) != NULL )
- {
- psheet->SetSelectedPrinter( NULL );
- delete printer;
- }
-
- //
// initialize the browse list...this will remove everything currently
- // in it, and add the no rendezvous printers item
- //
- InitBrowseList();
-
- //
- // start browing
- //
- err = StartBrowse();
- require_noerr( err, exit );
-
-exit:
-
- if ( err != kNoErr )
- {
- if ( err == kDNSServiceErr_Firewall )
- {
- CString text, caption;
+ // in it, and add the no printers item
- text.LoadString( IDS_FIREWALL );
- caption.LoadString( IDS_FIREWALL_CAPTION );
-
- MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
- }
- else
- {
- CPrinterSetupWizardSheet::WizardException exc;
-
- exc.text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
- exc.caption.LoadString( IDS_ERROR_CAPTION );
-
- throw(exc);
- }
- }
-
- return CPropertyPage::OnSetActive();
-}
-
-
-BOOL
-CSecondPage::OnKillActive()
-{
- OSStatus err = kNoErr;
-
- if ( m_selected )
- {
- CPrinterSetupWizardSheet * psheet;
-
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- psheet->SetSelectedPrinter( m_selected );
- m_printers.remove( m_selected );
- m_selected = NULL;
- }
-
- err = StopBrowse();
- require_noerr( err, exit );
-
-exit:
-
- return CPropertyPage::OnKillActive();
-}
-
-
-void DNSSD_API
-CSecondPage::OnBrowse(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inName,
- const char * inType,
- const char * inDomain,
- void * inContext )
-{
- DEBUG_UNUSED(inRef);
-
- CSecondPage * self;
- bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
-
- require_noerr( inErrorCode, exit );
-
- self = reinterpret_cast <CSecondPage*>( inContext );
- require_quiet( self, exit );
-
- if ( inFlags & kDNSServiceFlagsAdd )
- {
- self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing );
- }
- else
- {
- self->OnRemovePrinter( inName, inType, inDomain, moreComing );
- }
-
-exit:
-
- return;
-}
-
-
-void DNSSD_API
-CSecondPage::OnResolve(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inFullName,
- const char * inHostName,
- uint16_t inPort,
- uint16_t inTXTSize,
- const char * inTXT,
- void * inContext )
-{
- DEBUG_UNUSED(inFullName);
- DEBUG_UNUSED(inInterfaceIndex);
- DEBUG_UNUSED(inFlags);
- DEBUG_UNUSED(inRef);
-
- CSecondPage * self;
- Service * service;
- Queue * q;
- bool qtotalDefined = false;
- uint32_t qpriority = kDefaultPriority;
- CString qname;
- int idx;
- OSStatus err;
-
- require_noerr( inErrorCode, exit );
-
- service = reinterpret_cast<Service*>( inContext );
- require_quiet( service, exit);
-
- check( service->refs != 0 );
-
- self = service->printer->window;
- require_quiet( self, exit );
-
- err = self->StopOperation( service->serviceRef );
- require_noerr( err, exit );
-
- //
- // hold on to the hostname...
- //
- err = UTF8StringToStringObject( inHostName, service->hostname );
- require_noerr( err, exit );
+ InitBrowseList();
- //
- // <rdar://problem/3739200> remove the trailing dot on hostname
- //
- idx = service->hostname.ReverseFind('.');
+ // And populate the list with any printers that we currently know about
- if ((idx > 1) && ((service->hostname.GetLength() - 1) == idx))
+ for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
{
- service->hostname.Delete(idx, 1);
+ OnAddPrinter( *it, false );
}
- //
- // hold on to the port
- //
- service->portNumber = ntohs(inPort);
-
- //
- // parse the text record.
- //
-
- err = self->ParseTextRecord( service, inTXTSize, inTXT, qtotalDefined, qname, qpriority );
- require_noerr( err, exit );
-
- if ( service->qtotal == 1 )
- {
- //
- // create a new queue
- //
- try
- {
- q = new Queue;
- }
- catch (...)
- {
- q = NULL;
- }
-
- require_action( q, exit, err = E_OUTOFMEMORY );
+ printer = psheet->GetSelectedPrinter();
- if ( qtotalDefined )
- {
- q->name = qname;
- }
-
- q->priority = qpriority;
-
- service->queues.push_back( q );
-
- //
- // we've completely resolved this service
- //
-
- self->OnResolveService( service );
- }
- else
+ if ( printer != NULL )
{
- //
- // if qtotal is more than 1, then we need to get additional
- // text records. if not, then this service is considered
- // resolved
- //
-
- err = DNSServiceQueryRecord(&service->serviceRef, 0, inInterfaceIndex, inFullName, kDNSServiceType_TXT, kDNSServiceClass_IN, OnQuery, (void*) service );
- require_noerr( err, exit );
-
- err = self->StartOperation( service->serviceRef );
- require_noerr( err, exit );
+ m_browseList.Select( printer->item, TVGN_FIRSTVISIBLE );
}
exit:
- return;
+ return CPropertyPage::OnSetActive();
}
-void DNSSD_API
-CSecondPage::OnQuery(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inFullName,
- uint16_t inRRType,
- uint16_t inRRClass,
- uint16_t inRDLen,
- const void * inRData,
- uint32_t inTTL,
- void * inContext)
+BOOL
+CSecondPage::OnKillActive()
{
- DEBUG_UNUSED( inTTL );
- DEBUG_UNUSED( inRRClass );
- DEBUG_UNUSED( inRRType );
- DEBUG_UNUSED( inFullName );
- DEBUG_UNUSED( inInterfaceIndex );
- DEBUG_UNUSED( inRef );
-
- Service * service = NULL;
- Queue * q;
- CSecondPage * self;
- bool qtotalDefined = false;
- bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
- OSStatus err = kNoErr;
-
- require_noerr( inErrorCode, exit );
-
- service = reinterpret_cast<Service*>( inContext );
- require_quiet( service, exit);
-
- self = service->printer->window;
- require_quiet( self, exit );
-
- if ( ( inFlags & kDNSServiceFlagsAdd ) && ( inRDLen > 0 ) && ( inRData != NULL ) )
- {
- const char * inTXT = ( const char * ) inRData;
-
- //
- // create a new queue
- //
- try
- {
- q = new Queue;
- }
- catch (...)
- {
- q = NULL;
- }
-
- require_action( q, exit, err = E_OUTOFMEMORY );
-
- err = service->printer->window->ParseTextRecord( service, inRDLen, inTXT, qtotalDefined, q->name, q->priority );
- require_noerr( err, exit );
-
- if ( !qtotalDefined )
- {
- q->name = L"";
- }
-
- //
- // add this queue
- //
-
- service->queues.push_back( q );
-
- if ( service->queues.size() == service->qtotal )
- {
- //
- // else if moreComing is not set, then we're going
- // to assume that we're done
- //
-
- self->StopOperation( service->serviceRef );
-
- //
- // sort the queues
- //
-
- service->queues.sort( OrderQueueFunc );
-
- //
- // we've completely resolved this service
- //
-
- self->OnResolveService( service );
- }
- }
-
-exit:
-
- if ( err && service && ( service->serviceRef != NULL ) )
- {
- service->printer->window->StopOperation( service->serviceRef );
- }
-
- return;
+ return CPropertyPage::OnKillActive();
}
BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
- ON_MESSAGE( WM_SERVICE_EVENT, OnServiceEvent )
ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
// Printer::EventHandler implementation
OSStatus
CSecondPage::OnAddPrinter(
- uint32_t inInterfaceIndex,
- const char * inName,
- const char * inType,
- const char * inDomain,
- bool moreComing)
+ Printer * printer,
+ bool moreComing )
{
- Printer * printer;
- Service * service;
CPrinterSetupWizardSheet * psheet;
- DWORD printerNameCount;
- bool newPrinter = false;
OSStatus err = kNoErr;
check( IsWindow( m_hWnd ) );
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
- printer = Lookup( inName );
+ printer->item = m_browseList.InsertItem(printer->displayName);
- if (printer == NULL)
- {
- try
- {
- printer = new Printer;
- }
- catch (...)
- {
- printer = NULL;
- }
-
- require_action( printer, exit, err = E_OUTOFMEMORY );
+ m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
- printer->window = this;
- printer->name = inName;
+ m_browseList.SortChildren(TVI_ROOT);
- err = UTF8StringToStringObject(inName, printer->displayName);
- check_noerr( err );
- printer->actualName = printer->displayName;
- printer->installed = false;
- printer->deflt = false;
- printer->resolving = 0;
-
- //
- // Compare this name against printers that are already installed
- // to avoid name clashes. Rename as necessary
- // to come up with a unique name.
- //
- printerNameCount = 2;
-
- for (;;)
- {
- PrinterNameMap::iterator it;
-
- it = m_printerNames.find(printer->actualName);
-
- if (it != m_printerNames.end())
- {
- printer->actualName.Format(L"%s (%d)", printer->displayName, printerNameCount);
- }
- else
- {
- break;
- }
-
- printerNameCount++;
- }
-
- newPrinter = true;
- }
-
- check( printer );
-
- service = printer->LookupService( inType );
-
- if ( service != NULL )
+ if ( printer->name == m_selectedName )
{
- service->refs++;
+ m_browseList.SelectItem( printer->item );
}
- else
- {
- try
- {
- service = new Service;
- }
- catch (...)
- {
- service = NULL;
- }
-
- require_action( service, exit, err = E_OUTOFMEMORY );
-
- service->printer = printer;
- service->ifi = inInterfaceIndex;
- service->type = inType;
- service->domain = inDomain;
- service->qtotal = 1;
- service->refs = 1;
- service->serviceRef = NULL;
-
- printer->services.push_back( service );
-
- //
- // if the printer is selected, then we'll want to start a
- // resolve on this guy
- //
- if ( m_selected == printer )
- {
- StartResolve( service );
- }
- }
-
- if ( newPrinter )
+ //
+ // if the searching item is still in the list
+ // get rid of it
+ //
+ // note that order is important here. Insert the printer
+ // item before removing the placeholder so we always have
+ // an item in the list to avoid experiencing the bug
+ // in Microsoft's implementation of CTreeCtrl
+ //
+ if (m_emptyListItem != NULL)
{
- printer->item = m_browseList.InsertItem(printer->displayName);
-
- m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
-
- m_printers.push_back( printer );
-
- m_browseList.SortChildren(TVI_ROOT);
-
- if ( printer->name == m_selectedName )
- {
- m_browseList.SelectItem( printer->item );
- }
-
- //
- // if the searching item is still in the list
- // get rid of it
- //
- // note that order is important here. Insert the printer
- // item before removing the placeholder so we always have
- // an item in the list to avoid experiencing the bug
- // in Microsoft's implementation of CTreeCtrl
- //
- if (m_emptyListItem != NULL)
- {
- m_browseList.DeleteItem(m_emptyListItem);
- m_emptyListItem = NULL;
- m_browseList.EnableWindow(TRUE);
- }
+ m_browseList.DeleteItem(m_emptyListItem);
+ m_emptyListItem = NULL;
+ m_browseList.EnableWindow(TRUE);
}
exit:
OSStatus
CSecondPage::OnRemovePrinter(
- const char * inName,
- const char * inType,
- const char * inDomain,
- bool moreComing)
+ Printer * printer,
+ bool moreComing)
{
- DEBUG_UNUSED( inDomain );
- DEBUG_UNUSED( inType );
-
- Printer * printer;
- OSStatus err = kNoErr;
+ CPrinterSetupWizardSheet * psheet;
+ OSStatus err = kNoErr;
check( IsWindow( m_hWnd ) );
+ check( printer );
- m_browseList.SetRedraw(FALSE);
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
- printer = Lookup( inName );
+ m_browseList.SetRedraw(FALSE);
- if ( printer )
+ //
+ // check to make sure if we're the only item in the control...i.e.
+ // the list size is 1.
+ //
+ if (m_browseList.GetCount() > 1)
{
- Service * service;
-
- service = printer->LookupService( inType );
-
- if ( service && ( --service->refs == 0 ) )
- {
- if ( service->serviceRef != NULL )
- {
- err = StopResolve( service );
- require_noerr( err, exit );
- }
-
- printer->services.remove( service );
-
- delete service;
- }
-
- if ( printer->services.size() == 0 )
- {
- //
- // check to make sure if we're the only item in the control...i.e.
- // the list size is 1.
- //
- if (m_browseList.GetCount() > 1)
- {
- //
- // if we're not the only thing in the list, then
- // simply remove it from the list
- //
- m_browseList.DeleteItem( printer->item );
- }
- else
- {
- //
- // if we're the only thing in the list, then redisplay
- // it with the no rendezvous printers message
- //
- InitBrowseList();
- }
-
- m_printers.remove( printer );
-
- if ( m_selected == printer )
- {
- m_selected = NULL;
- m_selectedName = "";
- }
-
- delete printer;
- }
+ //
+ // if we're not the only thing in the list, then
+ // simply remove it from the list
+ //
+ m_browseList.DeleteItem( printer->item );
+ }
+ else
+ {
+ //
+ // if we're the only thing in the list, then redisplay
+ // it with the no printers message
+ //
+ InitBrowseList();
}
exit:
- if (!moreComing)
+ if ( !moreComing )
{
m_browseList.SetRedraw(TRUE);
m_browseList.Invalidate();
check( service );
- if ( !--service->printer->resolving )
- {
- //
- // sort the services now. we want the service that
- // has the highest priority queue to be first in
- // the list.
- //
-
- service->printer->services.sort( OrderServiceFunc );
-
- //
- // and set it to selected
- //
-
- m_selected = service->printer;
- m_selectedName = service->printer->name;
+ //
+ // and set it to selected
+ //
- //
- // and update the printer information box
- //
- SetPrinterInformationState( TRUE );
+ m_selectedName = service->printer->name;
- m_descriptionField.SetWindowText( service->description );
- m_locationField.SetWindowText( service->location );
+ //
+ // and update the printer information box
+ //
+ SetPrinterInformationState( TRUE );
- psheet->SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
+ m_descriptionField.SetWindowText( service->description );
+ m_locationField.SetWindowText( service->location );
- //
- // reset the cursor
- //
+ //
+ // reset the cursor
+ //
- psheet->m_active = psheet->m_arrow;
- SetCursor(psheet->m_active);
- }
+ SetCursor(psheet->m_active);
exit:
}
-LONG
-CSecondPage::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
-{
- if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
- {
- dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
- }
- else
- {
- SOCKET sock = (SOCKET) inWParam;
-
- // iterate thru list
- ServiceRefList::iterator begin = m_serviceRefList.begin();
- ServiceRefList::iterator end = m_serviceRefList.end();
-
- while (begin != end)
- {
- DNSServiceRef ref = *begin++;
-
- check(ref != NULL);
-
- if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
- {
- DNSServiceProcessResult(ref);
- break;
- }
- }
- }
-
- return ( 0 );
-}
-
-
void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// this call will trigger a resolve. When the resolve is complete,
// our OnResolve will be called.
//
- err = StartResolve( printer );
+ err = psheet->StartResolve( printer );
require_noerr( err, exit );
//
}
-bool
-CSecondPage::OrderServiceFunc( const Service * a, const Service * b )
-{
- Queue * q1, * q2;
-
- q1 = (a->queues.size() > 0) ? a->queues.front() : NULL;
-
- q2 = (b->queues.size() > 0) ? b->queues.front() : NULL;
-
- if ( !q1 && !q2 )
- {
- return true;
- }
- else if ( q1 && !q2 )
- {
- return true;
- }
- else if ( !q1 && q2 )
- {
- return false;
- }
- else if ( q1->priority < q2->priority )
- {
- return true;
- }
- else if ( q1->priority > q2->priority )
- {
- return false;
- }
- else if ( ( a->type == kPDLServiceType ) || ( ( a->type == kLPRServiceType ) && ( b->type == kIPPServiceType ) ) )
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
-bool
-CSecondPage::OrderQueueFunc( const Queue * q1, const Queue * q2 )
-{
- return ( q1->priority <= q2->priority ) ? true : false;
-}
-
-
void
CSecondPage::LoadTextAndDisableWindow( CString & text )
{
void
CSecondPage::SetPrinterInformationState( BOOL state )
{
- m_printerInformation.EnableWindow( state );\r
- m_descriptionLabel.EnableWindow( state );\r
- m_descriptionField.EnableWindow( state );\r
- m_locationLabel.EnableWindow( state );\r
- m_locationField.EnableWindow( state );\r
-}\r
-\r
-\r
-OSStatus
-CSecondPage::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, bool & qtotalDefined, CString & qname, uint32_t & qpriority )
-{
- bool rpOnly = true;
- OSStatus err = kNoErr;
-
- while (inTXTSize)
- {
- char buf[256];
+ m_printerInformation.EnableWindow( state );
- unsigned char num = *inTXT;
- check( (int) num < inTXTSize );
+ m_descriptionLabel.EnableWindow( state );
- if ( num )
- {
- memset(buf, 0, sizeof(buf));
- memcpy(buf, inTXT + 1, num);
-
- CString elem;
-
- err = UTF8StringToStringObject( buf, elem );
- require_noerr( err, exit );
-
- int curPos = 0;
-
- CString key = elem.Tokenize(L"=", curPos);
- CString val = elem.Tokenize(L"=", curPos);
-
- key.MakeLower();
-
- if ( key == L"rp" )
- {
- qname = val;
- }
- else
- {
- rpOnly = false;
-
- if ((key == L"usb_mfg") || (key == L"usb_manufacturer"))
- {
- service->usb_MFG = val;
- }
- else if ((key == L"usb_mdl") || (key == L"usb_model"))
- {
- service->usb_MDL = val;
- }
- else if (key == L"ty")
- {
- service->description = val;
- }
- else if (key == L"product")
- {
- service->product = val;
- }
- else if (key == L"note")
- {
- service->location = val;
- }
- else if (key == L"qtotal")
- {
- service->qtotal = (unsigned short) _ttoi((LPCTSTR) val);
- qtotalDefined = true;
- }
- else if (key == L"priority")
- {
- qpriority = _ttoi((LPCTSTR) val);
- }
- }
- }
+ m_descriptionField.EnableWindow( state );
- inTXTSize -= (num + 1);
- inTXT += (num + 1);
- }
+ m_locationLabel.EnableWindow( state );
-exit:
+ m_locationField.EnableWindow( state );
- if ( rpOnly )
- {
- qtotalDefined = true;
- }
-
- return err;
}
+
Change History (most recent first):
$Log: SecondPage.h,v $
+Revision 1.7 2005/01/31 23:54:30 shersche
+<rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
+
Revision 1.6 2005/01/04 21:09:14 shersche
Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
// Dialog Data
enum { IDD = IDD_SECOND_PAGE };
- static void DNSSD_API
- OnBrowse(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inName,
- const char * inType,
- const char * inDomain,
- void * inContext );
-
- static void DNSSD_API
- OnResolve(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inFullName,
- const char * inHostName,
- uint16_t inPort,
- uint16_t inTXTSize,
- const char * inTXT,
- void * inContext );
-
- static void DNSSD_API
- OnQuery(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inFullName,
- uint16_t inRRType,
- uint16_t inRRClass,
- uint16_t inRDLen,
- const void * inRData,
- uint32_t inTTL,
- void * inContext);
-
protected:
void InitBrowseList();
HTREEITEM m_emptyListItem;
bool m_selectOkay;
CTreeCtrl m_browseList;
- DNSServiceRef m_resolver;
bool m_initialized;
bool m_waiting;
-
- LONG OnServiceEvent(WPARAM inWParam, LPARAM inLParam);
- afx_msg void OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
-
-private:
-
- OSStatus
- LoadPrinterNames();
- Printer*
- Lookup( const char * name );
-
- OSStatus
- StartOperation( DNSServiceRef ref );
-
- OSStatus
- StopOperation( DNSServiceRef & ref );
-
- OSStatus
- StartBrowse();
-
- OSStatus
- StopBrowse();
-
- OSStatus
- StartResolve( Printer * printer );
-
- OSStatus
- StartResolve( Service * service );
-
- OSStatus
- StopResolve( Printer * printer );
-
- OSStatus
- StopResolve( Service * service );
+ afx_msg void OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
OSStatus
OnAddPrinter(
- uint32_t inInterfaceIndex,
- const char * inName,
- const char * inType,
- const char * inDomain,
+ Printer * printer,
bool moreComing);
OSStatus
OnRemovePrinter(
- const char * inName,
- const char * inType,
- const char * inDomain,
+ Printer * printer,
bool moreComing);
void
OnResolveService( Service * service );
- static bool
- OrderServiceFunc( const Service * a, const Service * b );
-
- static bool
- OrderQueueFunc( const Queue * q1, const Queue * q2 );
+private:
void
LoadTextAndDisableWindow( CString & text );
void
SetPrinterInformationState( BOOL state );
- OSStatus
- ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, bool & qtotalDefined, CString & qname, uint32_t & qpriority );
-
- typedef std::map<CString,CString> PrinterNameMap;
- typedef std::list<DNSServiceRef> ServiceRefList;
- typedef std::list<Printer*> Printers;
-
-
- PrinterNameMap m_printerNames;
- Printers m_printers;
- ServiceRefList m_serviceRefList;
- DNSServiceRef m_pdlBrowser;
- DNSServiceRef m_lprBrowser;
- DNSServiceRef m_ippBrowser;
-
- Printer * m_selected;
std::string m_selectedName;
\r
private:\r
Change History (most recent first):
$Log: ThirdPage.cpp,v $
+Revision 1.20 2005/03/05 02:27:45 shersche
+<rdar://problem/4030388> Generic drivers don't do color
+
+Revision 1.19 2005/02/23 02:08:51 shersche
+<rdar://problem/4012275> If we can't match the manufacturer, and select a generic printer, then show all the manufacturers in the manufacturer pane, not just "Generic".
+
+Revision 1.18 2005/02/15 07:02:51 shersche
+<rdar://problem/4003724> Display different UI text when generic printer drivers are selected
+
+Revision 1.17 2005/02/08 21:45:06 shersche
+<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
+
+Revision 1.16 2005/02/08 18:56:03 shersche
+Fix generated IPP url so that it doesn't add "/printers" string
+
+Revision 1.15 2005/02/01 01:44:07 shersche
+Load ntprint.inf at startup. This will cause the wizard to take a second or two longer to come up, but will eliminate the pause when auto-selecting the print drivers.
+
Revision 1.14 2005/01/25 08:55:54 shersche
<rdar://problem/3911084> Load icons at run-time from resource DLL
Bug #: 3911084
//
// These are pre-defined names for Generic manufacturer and model
//
-#define kGenericManufacturer L"Generic"
-#define kGenericModel L"Generic / Text Only"
+#define kGenericManufacturer L"Generic"
+#define kGenericText L"Generic / Text Only"
+#define kGenericPostscript L"Generic / Postscript"
+#define kGenericPCL L"Generic / PCL"
+#define kPDLPostscriptKey L"application/postscript"
+#define kPDLPCLKey L"application/vnd.hp-pcl"
+#define kGenericPSColorDriver L"HP Color LaserJet 4550 PS"
+#define kGenericPSDriver L"HP LaserJet 4050 Series PS"
+#define kGenericPCLColorDriver L"HP Color LaserJet 4550 PCL"
+#define kGenericPCLDriver L"HP LaserJet 4050 Series PCL"
+
//
// states for parsing ntprint.inf
m_initialized(false),
m_printerImage( NULL )
{
+ static const int bufferSize = 32768;
+ TCHAR windowsDirectory[bufferSize];
+ CString header;
+ CString ntPrint;
+ OSStatus err;
+ BOOL ok;
+
m_psp.dwFlags &= ~(PSP_HASHELP);
m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_INSTALL_TITLE);
m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_INSTALL_SUBTITLE);
+
+ //
+ // load printers from ntprint.inf
+ //
+ ok = GetWindowsDirectory( windowsDirectory, bufferSize );
+ err = translate_errno( ok, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile);
+ err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false );
+ require_noerr(err, exit);
+
+ //
+ // load printer drivers that have been installed on this machine
+ //
+ err = LoadPrintDriverDefs( m_manufacturers );
+ require_noerr(err, exit);
+
+ //
+ // and lastly load our own special generic printer defs
+ //
+ err = LoadGenericPrintDriverDefs( m_manufacturers );
+ require_noerr( err, exit );
+
+exit:
+
+ return;
}
//
// ----------------------------------------------------
void
-CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
+CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturers & manufacturers, Manufacturer * manufacturer, Model * model)
{
LVFINDINFO info;
int nIndex;
check( manufacturer != NULL );
check( model != NULL );
- Manufacturers manufacturers;
- manufacturers[manufacturer->name] = manufacturer;
-
PopulateUI( manufacturers );
//
// select the model
//
info.flags = LVFI_STRING;
- info.psz = model->name;
+ info.psz = model->displayName;
nIndex = m_modelListCtrl.FindItem(&info);
CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufacturer * manufacturer, Model * model )
{
printer->manufacturer = manufacturer->name;
- printer->model = model->name;
+ printer->displayModelName = model->displayName;
+ printer->modelName = model->name;
printer->driverInstalled = model->driverInstalled;
printer->infFileName = model->infFileName;
if ( q->name.GetLength() > 0 )
{
- printer->portName.Format(L"http://%s:%d/printers/%s", static_cast<LPCTSTR>(service->hostname), service->portNumber, static_cast<LPCTSTR>(q->name) );
+ printer->portName.Format(L"http://%s:%d/%s", static_cast<LPCTSTR>(service->hostname), service->portNumber, static_cast<LPCTSTR>(q->name) );
}
else
{
require_action( model, exit, err = kNoMemoryErr );
model->infFileName = filename;
+ model->displayName = name;
model->name = name;
model->driverInstalled = false;
require_action( model, exit, err = kNoMemoryErr );
+ model->displayName = info[i].pName;
model->name = info[i].pName;
model->driverInstalled = true;
}
+// -------------------------------------------------------
+// LoadGenericPrintDriverDefs
+//
+// This function is responsible for loading polymorphic
+// generic print drivers defs. The UI will read
+// something like "Generic / Postscript" and we can map
+// that to any print driver we want.
+// -------------------------------------------------------
+OSStatus
+CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers )
+{
+ Manufacturer * manufacturer;
+ Model * model;
+ Manufacturers::iterator iter;
+ CString psDriverName;
+ CString pclDriverName;
+ OSStatus err = 0;
+
+ // <rdar://problem/4030388> Generic drivers don't do color
+
+ // First try and find our generic driver names
+
+ iter = manufacturers.find(L"HP");
+ require_action( iter != manufacturers.end(), exit, err = kUnknownErr );
+ manufacturer = iter->second;
+
+ // Look for Postscript
+
+ model = manufacturer->find( kGenericPSColorDriver );
+
+ if ( !model )
+ {
+ model = manufacturer->find( kGenericPSDriver );
+ }
+
+ if ( model )
+ {
+ psDriverName = model->name;
+
+ }
+
+ // Look for PCL
+
+ model = manufacturer->find( kGenericPCLColorDriver );
+
+ if ( !model )
+ {
+ model = manufacturer->find( kGenericPCLDriver );
+ }
+
+ if ( model )
+ {
+ pclDriverName = model->name;
+ }
+
+ // If we found either a generic PS driver, or a generic PCL driver,
+ // then add them to the list
+
+ if ( psDriverName.GetLength() || pclDriverName.GetLength() )
+ {
+ // Try and find generic manufacturer if there is one
+
+ iter = manufacturers.find(L"Generic");
+
+ if (iter != manufacturers.end())
+ {
+ manufacturer = iter->second;
+ }
+ else
+ {
+ try
+ {
+ manufacturer = new Manufacturer;
+ }
+ catch (...)
+ {
+ manufacturer = NULL;
+ }
+
+ require_action( manufacturer, exit, err = kNoMemoryErr );
+
+ manufacturer->name = "Generic";
+ manufacturers[manufacturer->name] = manufacturer;
+ }
+
+ if ( psDriverName.GetLength() > 0 )
+ {
+ try
+ {
+ m_genericPostscript = new Model;
+ }
+ catch (...)
+ {
+ m_genericPostscript = NULL;
+ }
+
+ require_action( m_genericPostscript, exit, err = kNoMemoryErr );
+
+ m_genericPostscript->displayName = kGenericPostscript;
+ m_genericPostscript->name = psDriverName;
+ m_genericPostscript->driverInstalled = false;
+
+ manufacturer->models.push_back( m_genericPostscript );
+ }
+
+ if ( pclDriverName.GetLength() > 0 )
+ {
+ try
+ {
+ m_genericPCL = new Model;
+ }
+ catch (...)
+ {
+ m_genericPCL = NULL;
+ }
+
+ require_action( m_genericPCL, exit, err = kNoMemoryErr );
+
+ m_genericPCL->displayName = kGenericPCL;
+ m_genericPCL->name = pclDriverName;
+ m_genericPCL->driverInstalled = false;
+
+ manufacturer->models.push_back( m_genericPCL );
+ }
+ }
+
+exit:
+
+ return err;
+}
+
// ------------------------------------------------------
// ConvertToManufacturerName
//
OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service)
{
CString normalizedProductName;
- Manufacturer * manufacturer = NULL;
- Model * model = NULL;
- bool found = false;
+ Manufacturer * manufacturer = NULL;
+ Manufacturer * genericManufacturer = NULL;
+ Model * model = NULL;
+ Model * genericModel = NULL;
+ bool found = false;
CString text;
- OSStatus err = kNoErr;
+ OSStatus err = kNoErr;
//
// first look to see if we have a usb_MFG descriptor
model = MatchModel ( manufacturer, ConvertToModelName ( service->usb_MDL ) );
}
- if ( model == NULL )
+ if ( ( model == NULL ) && ( service->product.GetLength() > 0 ) )
{
service->product.Remove('(');
service->product.Remove(')');
if ( model != NULL )
{
- SelectMatch(printer, service, manufacturer, model);
+ Manufacturers manufacturers;
+
+ manufacturers[manufacturer->name] = manufacturer;
+ SelectMatch(printer, service, manufacturers, manufacturer, model);
found = true;
}
}
{
text.LoadString(IDS_PRINTER_MATCH_GOOD);
}
+ else if ( MatchGeneric( printer, service, &genericManufacturer, &genericModel ) )
+ {
+ Manufacturers * pManufacturers;
+ Manufacturers manufacturers;
+
+ text.LoadString(IDS_PRINTER_MATCH_MAYBE);
+
+ if ( manufacturer )
+ {
+ manufacturers[genericManufacturer->name] = genericManufacturer;
+ manufacturers[manufacturer->name] = manufacturer;
+
+ pManufacturers = &manufacturers;
+ }
+ else
+ {
+ pManufacturers = &m_manufacturers;
+ }
+
+ SelectMatch( printer, service, *pManufacturers, genericManufacturer, genericModel );
+ }
else
{
text.LoadString(IDS_PRINTER_MATCH_BAD);
}
+// -------------------------------------------------------
+// MatchGeneric
+//
+// This function will attempt to find a generic printer
+// driver for a printer that we weren't able to match
+// specifically
+//
+BOOL
+CThirdPage::MatchGeneric( Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model )
+{
+ CString pdl;
+ BOOL ok = FALSE;
+
+ DEBUG_UNUSED( printer );
+
+ Manufacturers::iterator iter = m_manufacturers.find( kGenericManufacturer );
+ require_action_quiet( iter != m_manufacturers.end(), exit, ok = FALSE );
+
+ *manufacturer = iter->second;
+
+ pdl = service->pdl;
+ pdl.MakeLower();
+
+ if ( pdl.Find( kPDLPCLKey ) != -1 )
+ {
+ *model = m_genericPCL;
+ ok = TRUE;
+ }
+ else if ( pdl.Find( kPDLPostscriptKey ) != -1 )
+ {
+ *model = m_genericPostscript;
+ ok = TRUE;
+ }
+
+exit:
+
+ return ok;
+}
+
// -----------------------------------------------------------
// OnInitPage
OSStatus CThirdPage::OnInitPage()
{
- static const int bufferSize = 32768;
- TCHAR windowsDirectory[bufferSize];
- CString header;
- CString ntPrint;
- OSStatus err;
- BOOL ok;
+ CString header;
+ CString ntPrint;
+ OSStatus err = kNoErr;
+
+ // Load printer icon
+
+
- // Load printer icon\r
-\r
check( m_printerImage == NULL );
m_printerImage = (CStatic*) GetDlgItem( IDR_MANIFEST );
m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, 247);
m_modelSelected = NULL;
- //
- // load printers from ntprint.inf
- //
- ok = GetWindowsDirectory( windowsDirectory, bufferSize );
- err = translate_errno( ok, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile);
- err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false );
- require_noerr(err, exit);
-
- //
- // load printer drivers that have been installed on this machine
- //
- err = LoadPrintDriverDefs( m_manufacturers );
- require_noerr(err, exit);
-
-exit:
-
return (err);
}
DDX_Control(pDX, IDC_PRINTER_MODEL, m_modelListCtrl);
DDX_Control(pDX, IDC_PRINTER_NAME, m_printerName);
DDX_Control(pDX, IDC_DEFAULT_PRINTER, m_defaultPrinterCtrl);
- DDX_Control(pDX, IDC_PRINTER_SELECTION_TEXT, m_printerSelectionText);\r
+ DDX_Control(pDX, IDC_PRINTER_SELECTION_TEXT, m_printerSelectionText);
+
}
{
Model * model = *iter;
- int nItem = m_modelListCtrl.InsertItem(0, model->name);
+ int nItem = m_modelListCtrl.InsertItem( 0, model->displayName );
m_modelListCtrl.SetItemData(nItem, (DWORD_PTR) model);
}
Change History (most recent first):
$Log: ThirdPage.h,v $
+Revision 1.4 2005/02/08 21:45:06 shersche
+<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
+
Revision 1.3 2005/01/25 08:57:28 shersche
<rdar://problem/3911084> Add m_printerControl member for dynamic loading of icons from resource DLLs
Bug #: 3911084
//
OSStatus LoadPrintDriverDefs(Manufacturers & manufacturers);
+ //
+ // LoadGenericPrintDriversDefs
+ //
+ // Loads generic postscript and pcl print driver defs
+ //
+ OSStatus LoadGenericPrintDriverDefs( Manufacturers & manufacturers );
+
//
// PopulateUI
//
Manufacturer * MatchManufacturer( Manufacturers & manufacturer, const CString & name );
Model * MatchModel( Manufacturer * manufacturer, const CString & name );
- void SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
+ BOOL MatchGeneric( Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model );
+ void SelectMatch(Printer * printer, Service * service, Manufacturers & manufacturers, Manufacturer * manufacturer, Model * model);
void CopyPrinterSettings(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
Manufacturers m_manufacturers;
CListCtrl m_modelListCtrl;
Model * m_modelSelected;
+ Model * m_genericPostscript;
+ Model * m_genericPCL;
+
bool m_initialized;
public:
Change History (most recent first):
$Log: UtilTypes.h,v $
+Revision 1.11 2005/03/05 02:27:46 shersche
+<rdar://problem/4030388> Generic drivers don't do color
+
+Revision 1.10 2005/02/08 21:45:06 shersche
+<rdar://problem/3947490> Default to Generic PostScript or PCL if unable to match driver
+
+Revision 1.9 2005/02/01 01:16:12 shersche
+Change window owner from CSecondPage to CPrinterSetupWizardSheet
+
Revision 1.8 2005/01/06 08:18:26 shersche
Add protocol field to service, add EmptyQueues() function to service
#include <list>
#include <DebugServices.h>
-class CSecondPage;
+class CPrinterSetupWizardSheet;
#define kDefaultPriority 50
#define kDefaultQTotal 1
struct Model;
typedef std::list<Queue*> Queues;
+ typedef std::list<Printer*> Printers;
typedef std::list<Service*> Services;
typedef std::list<Model*> Models;
const std::string & type
);
- CSecondPage * window;
+ CPrinterSetupWizardSheet * window;
HTREEITEM item;
//
bool driverInstalled;
CString infFileName;
CString manufacturer;
- CString model;
+ CString displayModelName;
+ CString modelName;
CString portName;
bool deflt;
DNSServiceRef serviceRef;
CString hostname;
unsigned short portNumber;
+ CString pdl;
CString usb_MFG;
CString usb_MDL;
CString description;
CString name;
CString tag;
Models models;
+
+ Model*
+ find( const CString & name );
};
{
bool driverInstalled;
CString infFileName;
+ CString displayName;
CString name;
};
Queue::~Queue()
{
}
+
+ inline Model*
+ Manufacturer::find( const CString & name )
+ {
+ Models::iterator it;
+
+ for ( it = models.begin(); it != models.end(); it++ )
+ {
+ Model * model = *it;
+
+ if ( model->name = name )
+ {
+ return model;
+ }
+ }
+
+ return NULL;
+ }
}
#define IDS_INSTALL_ERROR_MESSAGE 115\r
#define IDS_MANUFACTURER_HEADING 116\r
#define IDS_MODEL_HEADING 117\r
-#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
+#define IDS_NO_PRINTERS 118\r
#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
#define IDS_PRINTER_MATCH_GOOD 121\r
#define IDS_INSTALL_ERROR_MESSAGE 115\r
#define IDS_MANUFACTURER_HEADING 116\r
#define IDS_MODEL_HEADING 117\r
-#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
+#define IDS_NO_PRINTERS 118\r
#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
#define IDS_PRINTER_MATCH_GOOD 121\r
#define IDS_PRINTER_MATCH_BAD 122\r
+#define IDS_PRINTER_MATCH_MAYBE 146\r
#define IDS_YES 123\r
#define IDS_NO 124\r
#define IDS_LARGE_FONT 125\r
#define IDS_REINSTALL 142\r
#define IDS_REINSTALL_CAPTION 143\r
#define IDC_INFO 144\r
+#define IDS_PRINTER_UNAVAILABLE 145\r
#define IDC_BUTTON1 1000\r
#define IDC_LIST1 1000\r
#define IDC_BROWSE_LIST 1000\r
#define IDS_INSTALL_ERROR_MESSAGE 115\r
#define IDS_MANUFACTURER_HEADING 116\r
#define IDS_MODEL_HEADING 117\r
-#define IDS_NO_RENDEZVOUS_PRINTERS 118\r
+#define IDS_NO_PRINTERS 118\r
#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119\r
#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120\r
#define IDS_PRINTER_MATCH_GOOD 121\r
typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
static int operation;
-static uint32_t interface = kDNSServiceInterfaceIndexAny;
+static uint32_t opinterface = kDNSServiceInterfaceIndexAny;
static DNSServiceRef client = NULL;
static DNSServiceRef client2 = NULL;
static int num_printed;
GetNextLabel(label[labels-1-depth], text);
printf("> %s\n", text);
}
+
+ fflush( stdout );
}
static void DNSSD_API browse_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-24s %-24s %s\n", "Domain", "Service Type", "Instance Name");
printtimestamp();
printf("%s%6X%3d %-24s %-24s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName);
+ fflush( stdout );
}
static void DNSSD_API resolve_reply(DNSServiceRef client, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
printf(" TXT %s", txtInfo);
}
printf("\n");
+ fflush( stdout );
}
static void myTimerCallBack(void)
}
if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5;
+ fflush( stdout );
}
static void DNSSD_API qr_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-30s%4s%4s Rdata\n", "Name", "T", "C");
printtimestamp();
printf("%s%6X%3d %-30s%4d%4d %s\n", op, flags, ifIndex, fullname, rrtype, rrclass, rdb);
+ fflush( stdout );
}
//*************************************************************************************************************
case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1);
default: printf("Error %d\n", errorCode); return;
}
+ fflush( stdout );
}
static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef *sdRef, const char *host, const char *ip)
{
uint16_t PortAsNumber = atoi(port);
Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } };
- char txt[2048] = "";
- char *ptr = txt;
+ unsigned char txt[2048] = "";
+ unsigned char *ptr = txt;
int i;
if (nam[0] == '.' && nam[1] == 0) nam = ""; // We allow '.' on the command line as a synonym for empty string
for (i = 0; i < argc; i++)
{
- char *len = ptr++;
+ unsigned char *len = ptr++;
*len = strlen(argv[i]);
- strcpy(ptr, argv[i]);
+ strcpy((char*)ptr, argv[i]);
ptr += *len;
}
printf("Registering Service %s.%s%s", nam, typ, dom);
if (host && *host) printf(" host %s", host);
printf(" port %s %s\n", port, txt);
- return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, interface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL));
+ return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, ptr-txt, txt, reg_reply, NULL));
}
int main(int argc, char **argv)
{
argc--;
argv++;
- interface = kDNSServiceInterfaceIndexLocalOnly;
+ opinterface = kDNSServiceInterfaceIndexLocalOnly;
printf("Using LocalOnly\n");
}
switch (operation)
{
case 'E': printf("Looking for recommended registration domains:\n");
- err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, interface, enum_reply, NULL);
+ err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, opinterface, enum_reply, NULL);
break;
case 'F': printf("Looking for recommended browsing domains:\n");
- err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, interface, enum_reply, NULL);
+ err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, opinterface, enum_reply, NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "nicta.com.au.", NULL);
- //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "rendezvous.nicta.com.au.", NULL);
+ //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "bonjour.nicta.com.au.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "ibm.com.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL);
break;
dom = (argc < optind+2) ? "" : argv[optind+1];
if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
printf("Browsing for %s%s\n", argv[optind+0], dom);
- err = DNSServiceBrowse(&client, 0, interface, argv[optind+0], dom, browse_reply, NULL);
+ err = DNSServiceBrowse(&client, 0, opinterface, argv[optind+0], dom, browse_reply, NULL);
break;
case 'L': if (argc < optind+2) goto Fail;
dom = (argc < optind+3) ? "local" : argv[optind+2];
if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local"
printf("Lookup %s.%s.%s\n", argv[optind+0], argv[optind+1], dom);
- err = DNSServiceResolve(&client, 0, interface, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL);
+ err = DNSServiceResolve(&client, 0, opinterface, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL);
break;
case 'R': if (argc < optind+4) goto Fail;
rrtype = (argc <= optind+1) ? kDNSServiceType_A : GetRRType(argv[optind+1]);
rrclass = (argc <= optind+2) ? kDNSServiceClass_IN : atoi(argv[optind+2]);
if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR) flags |= kDNSServiceFlagsLongLivedQuery;
- err = DNSServiceQueryRecord(&client, flags, interface, argv[optind+0], rrtype, rrclass, qr_reply, NULL);
+ err = DNSServiceQueryRecord(&client, flags, opinterface, argv[optind+0], rrtype, rrclass, qr_reply, NULL);
break;
}
Opaque16 registerPort = { { 0x12, 0x34 } };
static const char TXT[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
printf("Registering Service Test._testupdate._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, interface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
break;
}
for (i=0; i<sizeof(TXT); i++)
if ((i & 0x1F) == 0) TXT[i] = 0x1F; else TXT[i] = 'A' + (i >> 5);
printf("Registering Service Test._testlargetxt._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, interface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
break;
}
static const char TXT1[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
static const char TXT2[] = "\xD" "Fourth String" "\xC" "Fifth String" "\xC" "Sixth String";
printf("Registering Service Test._testdualtxt._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, interface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
if (!err) err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
break;
}
Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
static const char TXT[] = "\x09" "Test Data";
printf("Registering Service Test._testtxt._tcp.local.\n");
- err = DNSServiceRegister(&client, 0, interface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
+ err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
if (!err) err = DNSServiceUpdateRecord(client, NULL, 0, sizeof(TXT)-1, TXT, 0);
break;
}
include /Developer/Makefiles/pb_makefiles/platform.make
-MVERS = "mDNSResponder-98"
+MVERS = "mDNSResponder-107"
install:
cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS)
What is mDNSResponder?
----------------------
-The mDNSResponder project is a component of Rendezvous,
+The mDNSResponder project is a component of Bonjour,
Apple's ease-of-use IP networking initiative:
-<http://developer.apple.com/macosx/rendezvous/>
+<http://developer.apple.com/bonjour/>
-Apple's Rendezvous software derives from the ongoing standardization
+Apple's Bonjour software derives from the ongoing standardization
work of the IETF Zero Configuration Networking Working Group:
<http://zeroconf.org/>
About the mDNSResponder Code
----------------------------
-Because Apple benefits more from widespread adoption of Rendezvous than
-it would benefit from keeping Rendezvous proprietary, Apple is making
+Because Apple benefits more from widespread adoption of Bonjour than
+it would benefit from keeping Bonjour proprietary, Apple is making
this code open so that other developers can use it too.
Because Apple recognises that networks are hetrogenous environments
Change History (most recent first):
$Log: DNSCommon.c,v $
+Revision 1.87 2005/02/25 04:21:00 cheshire
+<rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing
+
+Revision 1.86 2005/02/18 00:43:12 cheshire
+<rdar://problem/4010245> mDNSResponder should auto-truncate service names that are too long
+
+Revision 1.85 2005/02/10 22:35:17 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.84 2005/02/03 00:44:38 cheshire
+<rdar://problem/3986663> DNSServiceUpdateRecord returns kDNSServiceErr_Invalid when rdlen=0, rdata=NULL
+
Revision 1.83 2005/01/27 22:57:55 cheshire
Fix compile errors on gcc4
<rdar://problem/3913653> Wide-Area Goodbyes broken
Revision 1.73 2004/12/07 22:49:06 cheshire
-<rdar://problem/3908850> BIND doesn't like zero-length rdata
+<rdar://problem/3908850> BIND doesn't allow zero-length TXT records
Revision 1.72 2004/12/06 21:15:20 ksekar
<rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
ustrcpy macro to DNSCommon.c using mDNSPlatformStrCopy().
Revision 1.42 2004/08/10 23:19:14 ksekar
-<rdar://problem/3722542>: DNS Extension daemon for Wide Area Rendezvous
+<rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
Moved routines/constants to allow extern access for garbage collection daemon
Revision 1.41 2004/08/10 01:10:01 cheshire
}
}
+// Note slight bug: this code uses the rdlength from the ResourceRecord object, to display
+// the rdata from the RDataBody object. Sometimes this could be the wrong length -- but as
+// long as this routine is only used for debugging messages, it probably isn't a big problem.
mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, char *buffer)
{
char *ptr = buffer;
for (i=0; i < (int)sizeof(SubTypeLabel); i++) *dst++ = SubTypeLabel[i];
type = (domainname *)s1;
- // Special support for queries done by older versions of "Rendezvous Browser"
+ // Special support for queries done by some third-party network monitoring software
// For these queries, we retract the "._sub" we just added between the subtype and the main type
if (SameDomainName((domainname*)s0, (domainname*)"\x09_services\x07_dns-sd\x04_udp") ||
SameDomainName((domainname*)s0, (domainname*)"\x09_services\x05_mdns\x04_udp"))
return(mDNStrue);
}
+// Notes on UTF-8:
+// 0xxxxxxx represents a 7-bit ASCII value from 0x00 to 0x7F
+// 10xxxxxx is a continuation byte of a multi-byte character
+// 110xxxxx is the first byte of a 2-byte character (11 effective bits; values 0x 80 - 0x 800-1)
+// 1110xxxx is the first byte of a 3-byte character (16 effective bits; values 0x 800 - 0x 10000-1)
+// 11110xxx is the first byte of a 4-byte character (21 effective bits; values 0x 10000 - 0x 200000-1)
+// 111110xx is the first byte of a 5-byte character (26 effective bits; values 0x 200000 - 0x 4000000-1)
+// 1111110x is the first byte of a 6-byte character (31 effective bits; values 0x4000000 - 0x80000000-1)
+//
+// UTF-16 surrogate pairs are used in UTF-16 to encode values larger than 0xFFFF.
+// Although UTF-16 surrogate pairs are not supposed to appear in legal UTF-8, we want to be defensive
+// about that too. (See <http://www.unicode.org/faq/utf_bom.html#34>, "What are surrogates?")
+// The first of pair is a UTF-16 value in the range 0xD800-0xDBFF (11101101 1010xxxx 10xxxxxx in UTF-8),
+// and the second is a UTF-16 value in the range 0xDC00-0xDFFF (11101101 1011xxxx 10xxxxxx in UTF-8).
+
+mDNSexport mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max)
+ {
+ if (length > max)
+ {
+ mDNSu8 c1 = string[max]; // First byte after cut point
+ mDNSu8 c2 = (max+1 < length) ? string[max+1] : 0xB0; // Second byte after cut point
+ length = max; // Trim length down
+ while (length > 0)
+ {
+ // Check if the byte right after the chop point is a UTF-8 continuation byte,
+ // or if the character right after the chop point is the second of a UTF-16 surrogate pair.
+ // If so, then we continue to chop more bytes until we get to a legal chop point.
+ mDNSBool continuation = ((c1 & 0xC0) == 0x80);
+ mDNSBool secondsurrogate = (c1 == 0xED && (c2 & 0xF0) == 0xB0);
+ if (!continuation && !secondsurrogate) break;
+ c2 = c1;
+ c1 = string[--length];
+ }
+ // Having truncated characters off the end of our string, also cut off any residual white space
+ while (length > 0 && string[length-1] <= ' ') length--;
+ }
+ return(length);
+ }
+
// Returns true if a rich text label ends in " (nnn)", or if an RFC 1034
// name ends in "-nnn", where n is some decimal number.
mDNSexport mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText)
while (val >= divisor * 10) { divisor *= 10; chars++; }
- if (name->c[0] > (mDNSu8)(MAX_DOMAIN_LABEL - chars))
- {
- name->c[0] = (mDNSu8)(MAX_DOMAIN_LABEL - chars);
- // If the following character is a UTF-8 continuation character,
- // we just chopped a multi-byte UTF-8 character in the middle, so strip back to a safe truncation point
- while (name->c[0] > 0 && (name->c[name->c[0]+1] & 0xC0) == 0x80) name->c[0]--;
- }
+ name->c[0] = TruncateUTF8ToLength(name->c+1, name->c[0], MAX_DOMAIN_LABEL - chars);
if (RichText) { name->c[++name->c[0]] = ' '; name->c[++name->c[0]] = '('; }
else { name->c[++name->c[0]] = '-'; }
mDNSexport mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2)
{
- if (r1->rrtype != r2->rrtype) return(mDNSfalse);
- if (r1->rdlength != r2->rdlength) return(mDNSfalse);
- if (r1->rdatahash != r2->rdatahash) return(mDNSfalse);
- if (r1->rdnamehash != r2->rdnamehash) return(mDNSfalse);
+ if (r1->rrtype != r2->rrtype) return(mDNSfalse);
+ if (r1->rdlength != r2->rdlength) return(mDNSfalse);
+ if (r1->rdatahash != r2->rdatahash) return(mDNSfalse);
switch(r1->rrtype)
{
case kDNSType_CNAME:// Same as PTR
mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd)
{
mDNSu16 len;
- // Some (or perhaps all) versions of BIND named (name daemon) don't allow updates
- // with zero-length rdata, so for consistency we don't allow them for mDNS either.
- // Otherwise we risk having applications that work with mDNS but not with uDNS.
- if (!rdlength) return(mDNSfalse);
switch(rrtype)
{
case kDNSType_MR: // Same as PTR
//case kDNSType_NULL not checked (no specified format, so always valid)
//case kDNSType_WKS not checked
- case kDNSType_PTR: len = DomainNameLength(&rd->u.name);
+ case kDNSType_PTR: if (!rdlength) return(mDNSfalse);
+ len = DomainNameLength(&rd->u.name);
return(len <= MAX_DOMAIN_NAME && rdlength == len);
case kDNSType_HINFO:// Same as TXT (roughly)
case kDNSType_MINFO:// Same as TXT (roughly)
- case kDNSType_TXT: {
+ case kDNSType_TXT: if (!rdlength) return(mDNSfalse); // TXT record has to be at least one byte (RFC 1035)
+ {
const mDNSu8 *ptr = rd->u.txt.c;
const mDNSu8 *end = rd->u.txt.c + rdlength;
while (ptr < end) ptr += 1 + ptr[0];
case kDNSType_AAAA: return(rdlength == sizeof(mDNSv6Addr));
- case kDNSType_MX: len = DomainNameLength(&rd->u.mx.exchange);
+ case kDNSType_MX: if (!rdlength) return(mDNSfalse);
+ len = DomainNameLength(&rd->u.mx.exchange);
return(len <= MAX_DOMAIN_NAME && rdlength == 2+len);
- case kDNSType_SRV: len = DomainNameLength(&rd->u.srv.target);
+ case kDNSType_SRV: if (!rdlength) return(mDNSfalse);
+ len = DomainNameLength(&rd->u.srv.target);
return(len <= MAX_DOMAIN_NAME && rdlength == 6+len);
default: return(mDNStrue); // Allow all other types without checking
target = GetRRDomainNameTarget(rr);
rr->rdlength = GetRDLength(rr, mDNSfalse);
rr->rdestimate = GetRDLength(rr, mDNStrue);
- rr->rdatahash = RDataHashValue(rr->rdlength, &rr->rdata->u);
- rr->rdnamehash = target ? DomainNameHashValue(target) : 0;
+ rr->rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(rr->rdlength, &rr->rdata->u);
}
mDNSexport const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end)
Change History (most recent first):
$Log: DNSCommon.h,v $
+Revision 1.31 2005/02/18 00:43:11 cheshire
+<rdar://problem/4010245> mDNSResponder should auto-truncate service names that are too long
+
Revision 1.30 2005/01/19 03:12:44 cheshire
Move LocalRecordReady() macro from mDNS.c to DNSCommon.h
"asyncronous" -> "asynchronous"
Revision 1.15 2004/08/10 23:19:14 ksekar
-<rdar://problem/3722542>: DNS Extension daemon for Wide Area Rendezvous
+<rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
Moved routines/constants to allow extern access for garbage collection daemon
Revision 1.14 2004/05/28 23:42:36 ksekar
extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent);
+extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max);
extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText);
extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText);
extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText);
Change History (most recent first):
$Log: mDNS.c,v $
+Revision 1.522 2005/03/04 21:48:12 cheshire
+<rdar://problem/4037283> Fractional time rounded down instead of up on platforms with coarse clock granularity
+
+Revision 1.521 2005/02/25 04:21:00 cheshire
+<rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing
+
+Revision 1.520 2005/02/16 01:14:11 cheshire
+Convert RR Cache LogOperation() calls to debugf()
+
+Revision 1.519 2005/02/15 01:57:20 cheshire
+When setting "q->LastQTxTime = m->timenow", must also clear q->RecentAnswerPkts to zero
+
+Revision 1.518 2005/02/10 22:35:17 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.517 2005/02/03 00:21:21 cheshire
+Update comments about BIND named and zero-length TXT records
+
Revision 1.516 2005/01/28 06:06:32 cheshire
Update comment
Call RecordProbeFailure even if there is no record callback
Revision 1.482 2004/12/07 22:49:06 cheshire
-<rdar://problem/3908850> BIND doesn't like zero-length rdata
+<rdar://problem/3908850> BIND doesn't allow zero-length TXT records
Revision 1.481 2004/12/07 21:26:04 ksekar
<rdar://problem/3908336> DNSServiceRegisterRecord() can crash on deregistration
Add explicit context parameter to mDNS_RemoveRecordFromService()
Revision 1.479 2004/12/07 17:50:49 ksekar
-<rdar://problem/3908850> BIND doesn't like zero-length rdata
+<rdar://problem/3908850> BIND doesn't allow zero-length TXT records
Revision 1.478 2004/12/06 21:15:22 ksekar
<rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
<rdar://problem/3514236> Registering service with port number 0 should create a "No Such Service" record
Revision 1.389 2004/08/10 23:19:14 ksekar
-<rdar://problem/3722542>: DNS Extension daemon for Wide Area Rendezvous
+<rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
Moved routines/constants to allow extern access for garbage collection daemon
Revision 1.388 2004/07/30 17:40:06 ksekar
if (!ValidateDomainName(rr->resrec.name))
{ LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
- // Some (or perhaps all) versions of BIND named (name daemon) don't allow updates with zero-length rdata. It's common for
- // existing mDNS clients to create empty TXT records, so we silently change those to a TXT record containing a single empty string.
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
// Don't do this until *after* we've set rr->resrec.rdlength
{ LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
- rr->resrec.rdatahash = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
- rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0;
+ rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
{
if (r)
{
- debugf("Adding %p %##s (%s) to duplicate list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ debugf("Adding to duplicate list %p %s", rr, ARDisplayString(m,rr));
*d = rr;
// If the previous copy of this record is already verified unique,
// then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
}
else
{
- debugf("Adding %p %##s (%s) to active record list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
+ debugf("Adding to active record list %p %s", rr, ARDisplayString(m,rr));
if (!m->NewLocalRecords) m->NewLocalRecords = rr;
*p = rr;
}
for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records
if (RRTypeIsAddressType(rr2->resrec.rrtype) && // For all address records (A/AAAA) ...
ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && // ... which are valid for answer ...
- rr->resrec.rdnamehash == rr2->resrec.namehash && // ... whose name is the name of the SRV target
+ rr->resrec.rdatahash == rr2->resrec.namehash && // ... whose name is the name of the SRV target
SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
AddRecordToResponseList(nrpp, rr2, rr);
}
if (RRTypeIsAddressType(r2->resrec.rrtype) && // For all address records (A/AAAA) ...
ResourceRecordIsValidAnswer(r2) && // ... which are valid for answer ...
rr->LastMCTime - r2->LastMCTime >= 0 && // ... which we have not sent recently ...
- rr->resrec.rdnamehash == r2->resrec.namehash && // ... whose name is the name of the SRV target
+ rr->resrec.rdatahash == r2->resrec.namehash && // ... whose name is the name of the SRV target
SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) &&
(rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID))
r2->ImmedAdditional = r2->resrec.InterfaceID; // ... then mark this address record for sending too
CacheRecord *rr;
domainname *target;
FORALL_CACHERECORDS(slot, cg, rr)
- if ((target = GetRRDomainNameTarget(&rr->resrec)) && rr->resrec.rdnamehash == q->qnamehash && SameDomainName(target, &q->qname))
+ if ((target = GetRRDomainNameTarget(&rr->resrec)) && rr->resrec.rdatahash == q->qnamehash && SameDomainName(target, &q->qname))
mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
}
m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID);
if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, &AllDNSLinkGroup_v4, MulticastDNSPort, -1, mDNSNULL);
if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, &AllDNSLinkGroup_v6, MulticastDNSPort, -1, mDNSNULL);
- if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + mDNSPlatformOneSecond/10);
+ if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
if (++pktcount >= 1000)
{ LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; }
// There might be more records left in the known answer list, or more questions to send
{
q->LastQTime = m->timenow;
q->LastQTxTime = m->timenow;
+ q->RecentAnswerPkts = 0;
q->ThisQInterval = MaxQuestionInterval;
q->RequestUnicast = mDNSfalse;
}
m->rrcache_free = e->next;
if (++m->rrcache_totalused >= m->rrcache_report)
{
- LogOperation("RR Cache now using %ld objects", m->rrcache_totalused);
+ debugf("RR Cache now using %ld objects", m->rrcache_totalused);
if (m->rrcache_report < 100) m->rrcache_report += 10;
else m->rrcache_report += 100;
}
// on platforms where the native clock rate is less than fifty ticks per second,
// we still guarantee that the final calculated delay is at least one platform tick.
// We want to make sure we don't ever allow the delay to be zero ticks,
- // because if that happens we'll fail the Rendezvous Conformance Test.
+ // because if that happens we'll fail the Bonjour Conformance Test.
// Our final computed delay is 20-120ms for normal delayed replies,
// or 400-500ms in the case of multi-packet known-answer lists.
m->SuppressSending = m->timenow + (delayresponse + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*5) + 49) / 50;
// else, the packet RR has different type or different rdata -- check to see if this is a conflict
else if (m->rec.r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &m->rec.r))
{
- debugf("mDNSCoreReceiveResponse: Our Record: %08lX %08lX %s", rr-> resrec.rdatahash, rr-> resrec.rdnamehash, ARDisplayString(m, rr));
- debugf("mDNSCoreReceiveResponse: Pkt Record: %08lX %08lX %s", m->rec.r.resrec.rdatahash, m->rec.r.resrec.rdnamehash, CRDisplayString(m, &m->rec.r));
+ debugf("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr-> resrec.rdatahash, ARDisplayString(m, rr));
+ debugf("mDNSCoreReceiveResponse: Pkt Record: %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
// If this record is marked DependentOn another record for conflict detection purposes,
// then *that* record has to be bumped back to probing state to resolve the conflict
}
}
- if (m->rec.r.resrec.rroriginalttl > 0)
+ if (!mDNSPlatformMemSame(m->rec.r.resrec.rdata->u.data, rr->resrec.rdata->u.data, m->rec.r.resrec.rdlength))
+ {
+ // If the rdata of the packet record differs in name capitalization from the record in our cache
+ // then mDNSPlatformMemSame will detect this. In this case, throw the old record away, so that clients get
+ // a 'remove' event for the record with the old capitalization, and then an 'add' event for the new one.
+ rr->resrec.rroriginalttl = 0;
+ rr->UnansweredQueries = MaxUnansweredQueries;
+ SetNextCacheCheckTime(m, rr);
+ // DO NOT break out here -- we want to continue as if we never found it
+ }
+ else if (m->rec.r.resrec.rroriginalttl > 0)
{
rr->resrec.rroriginalttl = m->rec.r.resrec.rroriginalttl;
rr->UnansweredQueries = 0;
rr->MPUnansweredQ = 0;
rr->MPUnansweredKA = 0;
rr->MPExpectingKA = mDNSfalse;
+ SetNextCacheCheckTime(m, rr);
+ break;
}
else
{
// lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth.
rr->resrec.rroriginalttl = 1;
rr->UnansweredQueries = MaxUnansweredQueries;
+ SetNextCacheCheckTime(m, rr);
+ break;
}
- SetNextCacheCheckTime(m, rr);
- break;
}
}
{
mStatus status;
mDNS_Lock(m);
- // Some (or perhaps all) versions of BIND named (name daemon) don't allow updates with zero-length rdata.
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
// (We have to duplicate this check here because uDNS_RegisterService() bypasses the usual mDNS_Register_internal() bottleneck)
if (!sr->RR_TXT.resrec.rdlength) { sr->RR_TXT.resrec.rdlength = 1; sr->RR_TXT.resrec.rdata->u.txt.c[0] = 0; }
status = uDNS_RegisterService(m, sr);
if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
{
mDNS_Lock(m);
- // Some (or perhaps all) versions of BIND named (name daemon) don't allow updates with zero-length rdata.
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
// (We have to duplicate this check here because uDNS_AddRecordToService() bypasses the usual mDNS_Register_internal() bottleneck)
if (extra->r.resrec.rrtype == kDNSType_TXT && extra->r.resrec.rdlength == 0)
{ extra->r.resrec.rdlength = 1; extra->r.resrec.rdata->u.txt.c[0] = 0; }
if (storage && numrecords)
{
mDNSu32 i;
- LogOperation("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity));
+ debugf("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity));
for (i=0; i<numrecords; i++) storage[i].next = &storage[i+1];
storage[numrecords-1].next = m->rrcache_free;
m->rrcache_free = storage;
Change History (most recent first):
$Log: mDNSEmbeddedAPI.h,v $
+Revision 1.281 2005/02/25 17:47:44 ksekar
+<rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
+
+Revision 1.280 2005/02/25 04:21:00 cheshire
+<rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing
+
+Revision 1.279 2005/02/17 01:56:14 cheshire
+Increase ifname field to 64 bytes
+
+Revision 1.278 2005/02/09 23:38:51 ksekar
+<rdar://problem/3993508> Reregister hostname when DNS server changes but IP address does not
+
+Revision 1.277 2005/02/09 23:31:12 ksekar
+<rdar://problem/3984374> NAT-PMP response callback should return a boolean indicating if the packet matched the request
+
+Revision 1.276 2005/02/01 19:33:29 ksekar
+<rdar://problem/3985239> Keychain format too restrictive
+
Revision 1.275 2005/01/27 22:57:55 cheshire
Fix compile errors on gcc4
<rdar://problem/3810596> mDNSResponder needs to return more specific TSIG errors
Revision 1.248 2004/12/02 20:03:48 ksekar
-<rdar://problem/3889647> Rendezvous still publishes wide-area domains even after switching to a local subnet
+<rdar://problem/3889647> Still publishes wide-area domains even after switching to a local subnet
Revision 1.247 2004/12/01 20:57:19 ksekar
-<rdar://problem/3873921> Wide Area Rendezvous must be split-DNS aware
+<rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
Revision 1.246 2004/11/29 23:26:32 cheshire
Added NonZeroTime() function, which usually returns the value given, with the exception
<rdar://problem/3854298> Unicast services don't disappear when you disable all networking
Revision 1.240 2004/11/19 02:32:43 ksekar
-Wide-Area Rendezvous Security: Add LLQ-ID to events
+Wide-Area Security: Add LLQ-ID to events
Revision 1.239 2004/11/15 20:09:23 ksekar
<rdar://problem/3719050> Wide Area support for Add/Remove record
Add comment clarifying the applicability of these APIs
Revision 1.183 2004/08/10 23:19:14 ksekar
-<rdar://problem/3722542>: DNS Extension daemon for Wide Area Rendezvous
+<rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
Moved routines/constants to allow extern access for garbage collection daemon
Revision 1.182 2004/07/30 17:40:06 ksekar
mStatus_BadTime = -65559,
mStatus_BadSig = -65560, // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
mStatus_BadKey = -65561,
-
- // -65562 to -65786 currently unused; available for allocation
+ mStatus_TransientErr = -65562, // transient failures, e.g. sending packets shortly after a network transition or wake from sleep
+ // -65563 to -65786 currently unused; available for allocation
// tcp connection status
mStatus_ConnPending = -65787,
#define StandardAuthRDSize 264
#define MaximumRDSize 8192
-// InlineCacheRDSize is 64
+// InlineCacheRDSize is 68
// Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
// Records received from the network with rdata larger than this have additional storage allocated for the rdata
// A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
// Only 69 records had rdata bigger than 64 bytes
// Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
// have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
-#define InlineCacheRDSize 64
+#define InlineCacheRDSize 68
#define InlineCacheGroupNameSize 144
mDNSu32 rroriginalttl; // In seconds
mDNSu16 rdlength; // Size of the raw rdata, in bytes
mDNSu16 rdestimate; // Upper bound on size of rdata after name compression
- mDNSu32 namehash; // Name-based (i.e. case insensitive) hash of name
- mDNSu32 rdatahash; // 32-bit hash of the raw rdata
- mDNSu32 rdnamehash; // Set if this rdata contains a domain name (e.g. PTR, SRV, CNAME etc.)
+ mDNSu32 namehash; // Name-based (i.e. case-insensitive) hash of name
+ mDNSu32 rdatahash; // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
+ // else, for all other rdata, 32-bit hash of the raw rdata
+ // Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
+ // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
+ // whether it's worth doing a full SameDomainName() call. If the rdatahash
+ // is not a correct case-insensitive name hash, they'll get false negatives.
RData *rdata; // Pointer to storage for this rdata
} ResourceRecord;
struct DNSServer *next;
mDNSAddr addr;
domainname domain; // name->server matching for "split dns"
+ int flag; // temporary marker for list intersection
} DNSServer;
typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
mDNSInterfaceID InterfaceID; // Identifies physical interface; MUST NOT be 0, -1, or -2
mDNSAddr ip; // The IPv4 or IPv6 address to advertise
mDNSAddr mask;
- char ifname[16];
+ char ifname[64]; // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
mDNSBool Advertise; // False if you are only searching on this interface
mDNSBool McastTxRx; // Send/Receive multicast on this { InterfaceID, address family } ?
};
} NATPortMapReply;
// Pass NULL for pkt on error (including timeout)
-typedef void (*NATResponseHndlr)(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len);
+typedef mDNSBool (*NATResponseHndlr)(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len);
struct NATTraversalInfo_struct
{
//
// mDNS_SetSecretForZone tells the core to authenticate (via TSIG with an HMAC_MD5 hash of the shared secret)
// when dynamically updating a given zone (and its subdomains). The key used in authentication must be in
-// domain name format. The shared secret must be a base64 encoded string with the base64 parameter set to
-// true, or binary data with the base64 parameter set to false. The length is the size of the secret in
-// bytes. (A minimum size of 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485).
+// domain name format. The shared secret must be a null-terminated base64 encoded string. A minimum size of
+// 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485.
// Calling this routine multiple times for a zone replaces previously entered values. Call with a NULL key
// to dissable authentication for the zone.
-extern mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret, mDNSu32 ssLen, mDNSBool base64);
+extern mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret);
// Hostname/Unicast Interface Configuration
Change History (most recent first):
$Log: uDNS.c,v $
+Revision 1.203 2005/03/04 03:00:03 ksekar
+<rdar://problem/4026546> Retransmissions happen too early, causing registrations to conflict with themselves
+
+Revision 1.202 2005/03/01 19:29:17 ksekar
+changed LogMsgs to debugfs
+
+Revision 1.201 2005/02/26 03:04:13 cheshire
+<rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
+Don't try to do updates to root name server. This ensures status dot turns red if user
+enters a bad host name such as just "fred" instead of a properly fully-qualified name.
+
+Revision 1.200 2005/02/25 17:47:45 ksekar
+<rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
+
+Revision 1.199 2005/02/25 04:21:00 cheshire
+<rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing
+
+Revision 1.198 2005/02/25 02:35:22 cheshire
+<rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
+If we get NXDomain error looking for the _dns-update._udp record,
+update status from 1 (in progress) to mStatus_NoSuchNameErr (failed)
+
+Revision 1.197 2005/02/24 21:56:59 ksekar
+Change LogMsgs to debugfs
+
+Revision 1.196 2005/02/24 21:52:28 ksekar
+<rdar://problem/3922768> Remove "deferred deregistration" logic for hostnames
+
+Revision 1.195 2005/02/22 17:53:08 ksekar
+Changed successful NAT Traversals from LogMsg to LogOperation
+
+Revision 1.194 2005/02/15 18:38:03 ksekar
+<rdar://problem/3967876> change expected/redundant log messages to debugfs.
+
+Revision 1.193 2005/02/15 01:17:48 ksekar
+Fixed build failure.
+
+Revision 1.192 2005/02/14 23:01:28 ksekar
+Refinement to previous checkin - don't log bad LLQ opcode if we had to send the request more than once.
+
+Revision 1.191 2005/02/14 18:26:51 ksekar
+<rdar://problem/4005569> mDNSResponder complains about bad LLQ Opcode 2
+
+Revision 1.190 2005/02/11 19:44:06 shersche
+Remove extra semicolon at end of line
+
+Revision 1.189 2005/02/10 21:07:02 ksekar
+Don't goto error in ReceiveNATAddrResponse if we receive a malformatted response
+
+Revision 1.188 2005/02/10 02:02:44 ksekar
+Remove double semi-colon
+
+Revision 1.187 2005/02/09 23:28:01 ksekar
+<rdar://problem/3984374> NAT-PMP response callback should return a
+boolean indicating if the packet matched the request
+
+Revision 1.186 2005/02/04 21:56:29 ksekar
+<rdar://problem/3984374> Simultaneous port map requests sometimes fail
+- Refinement to previous checkin.
+
+Revision 1.185 2005/02/03 23:48:22 ksekar
+<rdar://problem/3984374> Simultaneous port map requests sometimes fail
+
+Revision 1.184 2005/02/01 19:33:29 ksekar
+<rdar://problem/3985239> Keychain format too restrictive
+
Revision 1.183 2005/01/27 22:57:55 cheshire
Fix compile errors on gcc4
<rdar://problem/3810596> mDNSResponder needs to return more specific TSIG errors
Revision 1.134 2004/12/02 20:03:49 ksekar
-<rdar://problem/3889647> Rendezvous still publishes wide-area domains even after switching to a local subnet
+<rdar://problem/3889647> Still publishes wide-area domains even after switching to a local subnet
Revision 1.133 2004/12/02 18:37:52 ksekar
<rdar://problem/3758233> Registering with port number zero should not create a port mapping
Revision 1.132 2004/12/01 20:57:19 ksekar
-<rdar://problem/3873921> Wide Area Rendezvous must be split-DNS aware
+<rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
Revision 1.131 2004/12/01 19:59:27 cheshire
<rdar://problem/3882643> Crash in mDNSPlatformTCPConnect
<rdar://problem/3682609> Security: Enforce a "window" on one-shot wide-area queries
Revision 1.120 2004/11/19 02:32:43 ksekar
-<rdar://problem/3682608> Wide-Area Rendezvous Security: Add LLQ-ID to events
+<rdar://problem/3682608> Wide-Area Security: Add LLQ-ID to events
Revision 1.119 2004/11/18 23:21:24 ksekar
<rdar://problem/3764544> LLQ Security: Need to verify src port/address for LLQ handshake
<rdar://problem/3759567>: LLQ Refreshes never terminate if unanswered
Revision 1.62 2004/08/10 23:19:14 ksekar
-<rdar://problem/3722542>: DNS Extension daemon for Wide Area Rendezvous
+<rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
Moved routines/constants to allow extern access for garbage collection daemon
Revision 1.61 2004/07/30 17:40:06 ksekar
// set retry timestamp for record with exponential backoff
// (for service record sets, use RR_SRV as representative for time checks
-mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr)
+mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
{
rr->LastAPTime = mDNSPlatformTimeNow(m);
- if (rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL) { rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL; return; }
- if (rr->ThisAPInterval*2 <= MAX_UCAST_POLL_INTERVAL) { rr->ThisAPInterval *= 2; return; }
- if (rr->ThisAPInterval != MAX_UCAST_POLL_INTERVAL) { rr->ThisAPInterval = MAX_UCAST_POLL_INTERVAL; }
+ if (SendErr == mStatus_TransientErr || rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL) rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL;
+ else if (rr->ThisAPInterval*2 <= MAX_UCAST_POLL_INTERVAL) rr->ThisAPInterval *= 2;
+ else if (rr->ThisAPInterval != MAX_UCAST_POLL_INTERVAL) rr->ThisAPInterval = MAX_UCAST_POLL_INTERVAL;
}
#pragma mark - authorization management
#endif
-mDNSlocal uDNS_AuthInfo *GetAuthInfoForZone(const uDNS_GlobalInfo *u, const domainname *zone)
+mDNSlocal uDNS_AuthInfo *GetAuthInfoForName(const uDNS_GlobalInfo *u, const domainname *name)
{
uDNS_AuthInfo *ptr;
- while (zone->c[0])
+ while (name->c[0])
{
for (ptr = u->AuthInfoList; ptr; ptr = ptr->next)
- if (SameDomainName(&ptr->zone, zone)) return(ptr);
- zone = (const domainname *)(zone->c + 1 + zone->c[0]);
+ if (SameDomainName(&ptr->zone, name)) return(ptr);
+ name = (const domainname *)(name->c + 1 + name->c[0]);
}
return mDNSNULL;
}
}
}
-mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret, mDNSu32 ssLen, mDNSBool base64)
+mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const domainname *key, const char *sharedSecret)
{
uDNS_AuthInfo *info;
mDNSu8 keybuf[1024];
mDNS_Lock(m);
- if (GetAuthInfoForZone(u, zone)) DeleteAuthInfoForZone(u, zone);
+ if (GetAuthInfoForName(u, zone)) DeleteAuthInfoForZone(u, zone);
if (!key) goto exit;
- info = (uDNS_AuthInfo*)umalloc(sizeof(uDNS_AuthInfo) + ssLen);
+ info = (uDNS_AuthInfo*)umalloc(sizeof(*info));
if (!info) { LogMsg("ERROR: umalloc"); status = mStatus_NoMemoryErr; goto exit; }
- ubzero(info, sizeof(uDNS_AuthInfo));
+ ubzero(info, sizeof(*info));
AssignDomainName(&info->zone, zone);
AssignDomainName(&info->keyname, key);
- if (base64)
+ keylen = DNSDigest_Base64ToBin(sharedSecret, keybuf, 1024);
+ if (keylen < 0)
{
- keylen = DNSDigest_Base64ToBin(sharedSecret, keybuf, 1024);
- if (keylen < 0)
- {
- LogMsg("ERROR: mDNS_UpdateDomainRequiresAuthentication - could not convert shared secret from base64");
- ufree(info);
- status = mStatus_UnknownErr;
- goto exit;
- }
- DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen);
+ LogMsg("ERROR: mDNS_SetSecretForZone - could not convert shared secret %s from base64", sharedSecret);
+ ufree(info);
+ status = mStatus_UnknownErr;
+ goto exit;
}
- else DNSDigest_ConstructHMACKey(info, (mDNSu8*)sharedSecret, ssLen);
+ DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen);
// link into list
info->next = m->uDNS_info.AuthInfoList;
const mDNSu8 *end = (mDNSu8 *)&info->request;
if (info->op == NATOp_AddrRequest) end += sizeof(NATAddrRequest);
else end += sizeof(NATPortMapRequest);
-
+
dst.type = u->Router.type;
dst.ip.v4 = u->Router.ip.v4;
dstport = mDNSOpaque16fromIntVal(NATMAP_PORT);
info->retry = mDNSPlatformTimeNow(m) + info->RetryInterval;
}
-mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len)
+mDNSlocal mDNSBool ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len)
{
mStatus err = mStatus_NoError;
AuthRecord *rr = mDNSNULL;
if (n->state != NATState_Request)
{
LogMsg("ReceiveNATAddrResponse: bad state %d", n->state);
- err = mStatus_UnknownErr;
- goto end;
+ return mDNSfalse;
}
rr = n->reg.RecordRegistration;
if (!rr)
{
LogMsg("ReceiveNATAddrResponse: registration cancelled");
- err = mStatus_UnknownErr;
- goto end;
+ return mDNSfalse;
}
addr.type = mDNSAddrType_IPv4;
if (len < sizeof(*response))
{
LogMsg("ReceiveNATAddrResponse: response too short (%d bytes)", len);
- err = mStatus_NATTraversal;
- goto end;
+ return mDNSfalse;
}
if (response->vers != NATMAP_VERS)
{
LogMsg("ReceiveNATAddrResponse: received version %d (expect version %d)", pkt[0], NATMAP_VERS);
- err = mStatus_NATTraversal;
- goto end;
+ return mDNSfalse;
}
if (response->opcode != (NATOp_AddrRequest | NATMAP_RESPONSE_MASK))
{
LogMsg("ReceiveNATAddrResponse: bad response code %d", response->opcode);
- err = mStatus_NATTraversal;
- goto end;
+ return mDNSfalse;
}
if (response->err.NotAnInteger)
{ LogMsg("ReceiveAddrResponse: received error %d", mDNSVal16(response->err)); err = mStatus_NATTraversal; goto end; }
rr->RecordCallback(m, rr, mStatus_NATTraversal);
// note - unsafe to touch rr after callback
}
- return;
+ return mDNStrue;
}
- else LogMsg("Received public IP address %d.%d.%d.%d from NAT.", addr.ip.v4.b[0], addr.ip.v4.b[1], addr.ip.v4.b[2], addr.ip.v4.b[3]);
+ else LogOperation("Received public IP address %d.%d.%d.%d from NAT.", addr.ip.v4.b[0], addr.ip.v4.b[1], addr.ip.v4.b[2], addr.ip.v4.b[3]);
rr->resrec.rdata->u.ipv4 = addr.ip.v4; // replace rdata w/ public address
uDNS_RegisterRecord(m, rr);
+ return mDNStrue;
}
}
}
-mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len)
+mDNSlocal mDNSBool ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mDNSu16 len)
{
- ServiceRecordSet *srs;
- mDNSIPPort priv;
+ ServiceRecordSet *srs = n->reg.ServiceRegistration;
+ mDNSIPPort priv = srs ? srs->RR_SRV.resrec.rdata->u.srv.port : m->UnicastPort4;
mDNSu32 lease;
- mDNSBool deletion;
+ mDNSBool deletion = !n->request.PortReq.lease.NotAnInteger;
NATPortMapReply *reply = (NATPortMapReply *)pkt;
-
+ mDNSu8 *service = srs ? srs->RR_SRV.resrec.name->c : (mDNSu8 *)"\016LLQ event port";
+
if (n->state != NATState_Request && n->state != NATState_Refresh)
- { LogMsg("ReceivePortMapReply: bad state %d", n->state); return; }
-
- deletion = (!n->request.PortReq.lease.NotAnInteger);
- if (deletion) { n->state = NATState_Deleted; return; }
- // note that we explicitly ignore timeouts here
- // we keep the context struct around so that the SendServiceDeregistration code can reference
- // it to determine the public port to delete in the SRV record.
-
- srs = n->reg.ServiceRegistration;
- if (!srs && n != m->uDNS_info.LLQNatInfo)
- {
- debugf("ReceivePortMapReply: registration cancelled");
- FreeNATInfo(m, n);
- return;
- }
-
- priv = srs ? srs->RR_SRV.resrec.rdata->u.srv.port : m->UnicastPort4;
-
- if (!pkt) // timeout
+ { LogMsg("ReceivePortMapReply (%##s): bad state %d", service, n->state); return mDNSfalse; }
+
+ if (!pkt && !deletion) // timeout
{
#ifdef _LEGACY_NAT_TRAVERSAL_
mDNSIPPort pub;
#endif // _LEGACY_NAT_TRAVERSAL_
}
- if (len < sizeof(*reply)) { LogMsg("ReceivePortMapReply: response too short (%d bytes)", len); goto end; }
- if (reply->vers != NATMAP_VERS) { LogMsg("ReceivePortMapReply: received version %d (expect version %d)", pkt[0], NATMAP_VERS); goto end; }
- if (reply->opcode != (n->op | NATMAP_RESPONSE_MASK)) { LogMsg("ReceivePortMapReply: bad response code %d", pkt[1]); goto end; }
- if (reply->err.NotAnInteger) { LogMsg("ReceivePortMapReply: received error %d", mDNSVal16(reply->err)); goto end; }
- if (priv.NotAnInteger != reply->priv.NotAnInteger)
- { LogMsg("ReceivePortMapReply: reply private port does not match requested private port"); goto end; }
+ if (len < sizeof(*reply)) { LogMsg("ReceivePortMapReply: response too short (%d bytes)", len); return mDNSfalse; }
+ if (reply->vers != NATMAP_VERS) { LogMsg("ReceivePortMapReply: received version %d (expect version %d)", pkt[0], NATMAP_VERS); return mDNSfalse; }
+ if (reply->opcode != (n->op | NATMAP_RESPONSE_MASK)) { LogMsg("ReceivePortMapReply: bad response code %d", pkt[1]); return mDNSfalse; }
+ if (reply->err.NotAnInteger) { LogMsg("ReceivePortMapReply: received error %d", mDNSVal16(reply->err)); return mDNSfalse; }
+ if (priv.NotAnInteger != reply->priv.NotAnInteger) return mDNSfalse; // packet does not match this request
+ if (!srs && n != m->uDNS_info.LLQNatInfo)
+ {
+ LogMsg("ReceivePortMapReply: registration cancelled"); //!!!KRS change to debugf before checkin
+ FreeNATInfo(m, n);
+ return mDNStrue;
+ }
+
+ if (deletion) { n->state = NATState_Deleted; return mDNStrue; }
+
lease = (mDNSu32)mDNSVal32(reply->lease);
if (lease > 0x70000000UL / mDNSPlatformOneSecond) lease = 0x70000000UL / mDNSPlatformOneSecond;
- if (n->state == NATState_Refresh && reply->pub.NotAnInteger != n->PublicPort.NotAnInteger)
+ if (n->state == NATState_Refresh && reply->pub.NotAnInteger != n->PublicPort.NotAnInteger)
LogMsg("ReceivePortMapReply: NAT refresh changed public port from %d to %d", mDNSVal16(n->PublicPort), mDNSVal16(reply->pub));
- // !!!KRS we need to update the SRV here!
- n->PublicPort = reply->pub;
+ // this should never happen
+ n->PublicPort = reply->pub;
n->retry = mDNSPlatformTimeNow(m) + ((mDNSs32)lease * mDNSPlatformOneSecond / 2); // retry half way to expiration
-
- if (n->state == NATState_Refresh) { n->state = NATState_Established; return; }
+
+ if (n->state == NATState_Refresh) { n->state = NATState_Established; return mDNStrue; }
n->state = NATState_Established;
end:
if (n->state != NATState_Established && n->state != NATState_Legacy)
{
- LogMsg("NAT Port Mapping: timeout");
+ LogMsg("NAT Port Mapping (%##s): timeout", service);
+ if (pkt) LogMsg("!!! timeout with non-null packet");
n->state = NATState_Error;
if (srs) srs->uDNS_info.state = regState_NATError;
else LLQNatMapComplete(m);
- return; // note - unsafe to touch srs here
+ return mDNStrue; // note - unsafe to touch srs here
}
- LogMsg("Mapped private port %d to public port %d", mDNSVal16(priv), mDNSVal16(n->PublicPort));
- if (!srs) { LLQNatMapComplete(m); return; }
+ LogOperation("Mapped private port %d to public port %d", mDNSVal16(priv), mDNSVal16(n->PublicPort));
+ if (!srs) { LLQNatMapComplete(m); return mDNStrue; }
if (srs->uDNS_info.ns.ip.v4.NotAnInteger) SendServiceRegistration(m, srs); // non-zero server address means we already have necessary zone data to send update
else
srs->uDNS_info.state = regState_FetchingZoneData;
startGetZoneData(srs->RR_SRV.resrec.name, m, mDNStrue, mDNSfalse, serviceRegistrationCallback, srs);
}
+ return mDNStrue;
}
mDNSlocal void FormatPortMaprequest(NATTraversalInfo *info, mDNSIPPort port)
mDNSlocal void UpdateHostnameRegistrations(mDNS *m)
{
uDNS_GlobalInfo *u = &m->uDNS_info;
- AuthRecord *new;
uDNS_HostnameInfo *i;
for (i = u->Hostnames; i; i = i->next)
{
- // only allocate new record if existing record is actually registered (i.e. it wasn't pending the hostname or IP being set)
- if (i->ar->uDNS_info.state == regState_Unregistered) new = i->ar;
- else
- {
- new = umalloc(sizeof(AuthRecord));
- if (!new) { LogMsg("ERROR: UpdateHostnameRegistration - malloc"); return; }
- mDNS_SetupResourceRecord(new, mDNSNULL, 0, kDNSType_A, kWideAreaTTL, kDNSRecordTypeKnownUnique, HostnameCallback, i);
- }
-
- // setup new record
- AssignDomainName(new->resrec.name, i->ar->resrec.name);
- new->resrec.rdata->u.ipv4 = u->PrimaryIP.ip.v4;
+ // unlink and clear uDNS state (old registrations just get overwritten)
+ if (i->ar->uDNS_info.state != regState_Unregistered) unlinkAR(&u->RecordRegistrations, i->ar);
+ ubzero(&i->ar->uDNS_info, sizeof(i->ar->uDNS_info));
- if (i->ar->uDNS_info.state != regState_Unregistered)
- {
- // delete old record
- i->ar->RecordContext = mDNSNULL; // clear backpointer to HostnameInfo
- uDNS_DeregisterRecord(m, i->ar);
- i->ar = new;
- }
-
- // advertise new
- AdvertiseHostname(m, i);
+ // set rdata and register
+ i->ar->resrec.rdata->u.ipv4 = u->PrimaryIP.ip.v4;
+ AdvertiseHostname(m, i);
}
}
if (!rcode) return mStatus_NoError;
else if (rcode == kDNSFlag1_RC_YXDomain)
{
- LogMsg("name in use: %##s", displayname->c);
+ debugf("name in use: %##s", displayname->c);
return mStatus_NameConflict;
}
else if (rcode == kDNSFlag1_RC_Refused)
mDNSexport void uDNS_ReceiveNATMap(mDNS *m, mDNSu8 *pkt, mDNSu16 len)
{
uDNS_GlobalInfo *u = &m->uDNS_info;
- NATTraversalInfo *ptr, *cur;
+ NATTraversalInfo *ptr = u->NATTraversals;
NATOp_t op;
// check length, version, opcode
op = pkt[1];
if (!(op & NATMAP_RESPONSE_MASK)) { LogMsg("Received NAT Traversal message that is not a response (opcode %d)", op); return; }
- ptr = u->NATTraversals;
while (ptr)
{
- cur = ptr;
+ if ((ptr->state == NATState_Request || ptr->state == NATState_Refresh) && (ptr->op | NATMAP_RESPONSE_MASK) == op)
+ if (ptr->ReceiveResponse(ptr, m, pkt, len)) break; // note callback may invalidate ptr if it return value is non-zero
ptr = ptr->next;
- if ((cur->state == NATState_Request || cur->state == NATState_Refresh) &&
- (cur->op | NATMAP_RESPONSE_MASK) == op)
- cur->ReceiveResponse(cur, m, pkt, len); // callback may delete "cur"
- // specific request/reply matching logic handled by callback - we don't know if this was a match, so we don't break here
- }
+ }
}
mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
if (qptr->uDNS_info.id.NotAnInteger == msg->h.id.NotAnInteger)
{
if (timenow - (qptr->LastQTime + RESPONSE_WINDOW) > 0)
- { LogMsg("uDNS_ReceiveMsg - response received after maximum allowed window. Discarding"); return; }
+ { debugf("uDNS_ReceiveMsg - response received after maximum allowed window. Discarding"); return; }
if (msg->h.flags.b[0] & kDNSFlag0_TC)
{ hndlTruncatedAnswer(qptr, srcaddr, m); return; }
else
if (!end) { LogMsg("ERROR: sendLLQRefresh - putLLQ"); return; }
err = mDNSSendDNSMessage(m, &msg, end, mDNSInterface_Any, &info->servAddr, info->servPort, -1, mDNSNULL);
- if (err) LogMsg("ERROR: sendLLQRefresh - mDNSSendDNSMessage returned %ld", err);
+ if (err) debugf("ERROR: sendLLQRefresh - mDNSSendDNSMessage returned %ld", err);
if (info->state == LLQ_Established) info->ntries = 1;
else info->ntries++;
(void)InterfaceID; // unused
// find Opt RR, verify correct ID
- if (!getLLQAtIndex(m, msg, end, &opt, 0)) { debugf("Pkt does not contain LLQ Opt"); return mDNSfalse; }
- if (opt.llqOp != kLLQOp_Event) { LogMsg("recvLLQEvent - Bad LLQ Opcode %d", opt.llqOp); return mDNSfalse; }
- if (!q->uDNS_info.llq) { LogMsg("Error: recvLLQEvent - question object does not contain LLQ metadata"); return mDNSfalse; }
- if (!sameID(opt.id, q->uDNS_info.llq->id)) { return mDNSfalse; }
+ if (!getLLQAtIndex(m, msg, end, &opt, 0)) { debugf("Pkt does not contain LLQ Opt"); return mDNSfalse; }
+ if (!q->uDNS_info.llq) { LogMsg("Error: recvLLQEvent - question object does not contain LLQ metadata"); return mDNSfalse; }
+ if (!sameID(opt.id, q->uDNS_info.llq->id)) { return mDNSfalse; }
+ if (opt.llqOp != kLLQOp_Event) { if (!q->uDNS_info.llq->ntries) LogMsg("recvLLQEvent - Bad LLQ Opcode %d", opt.llqOp); return mDNSfalse; }
// invoke response handler
m->uDNS_info.CurrentQuery = q;
ackEnd = putQuestion(&ack, ack.data, ack.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
if (!ackEnd) { LogMsg("ERROR: recvLLQEvent - putQuestion"); return mDNSfalse; }
err = mDNSSendDNSMessage(m, &ack, ackEnd, mDNSInterface_Any, srcaddr, srcport, -1, mDNSNULL);
- if (err) LogMsg("ERROR: recvLLQEvent - mDNSSendDNSMessage returned %ld", err);
+ if (err) debugf("ERROR: recvLLQEvent - mDNSSendDNSMessage returned %ld", err);
return mDNStrue;
}
return;
}
-
if (!llq)
{
llq = &llqBuf;
if (!responsePtr) { LogMsg("ERROR: sendChallengeResponse - putLLQ"); goto error; }
err = mDNSSendDNSMessage(m, &response, responsePtr, mDNSInterface_Any, &info->servAddr, info->servPort, -1, mDNSNULL);
- if (err) LogMsg("ERROR: sendChallengeResponse - mDNSSendDNSMessage returned %ld", err);
+ if (err) debugf("ERROR: sendChallengeResponse - mDNSSendDNSMessage returned %ld", err);
// on error, we procede as normal and retry after the appropriate interval
return;
}
if (info->origLease != llq->lease)
- LogMsg("hndlRequestChallenge: requested lease %lu, granted lease %lu", info->origLease, llq->lease);
+ debugf("hndlRequestChallenge: requested lease %lu, granted lease %lu", info->origLease, llq->lease);
// cache expiration in case we go to sleep before finishing setup
info->origLease = llq->lease;
if (!defer) // if we are to defer, we simply set the retry timers so the request goes out in the future
{
err = mDNSSendDNSMessage(m, &msg, end, mDNSInterface_Any, &info->servAddr, info->servPort, -1, mDNSNULL);
- if (err) LogMsg("ERROR: startLLQHandshake - mDNSSendDNSMessage returned %ld", err);
+ if (err) debugf("ERROR: startLLQHandshake - mDNSSendDNSMessage returned %ld", err);
// on error, we procede as normal and retry after the appropriate interval
}
{
err = mDNSSendDNSMessage(m, &msg, endPtr, mDNSInterface_Any, &server, UnicastDNSPort, -1, mDNSNULL);
if (err) { debugf("ERROR: startQuery - %ld (keeping question in list for retransmission", err); }
+ if (err == mStatus_TransientErr) err = mStatus_NoError; // don't return transient errors to caller
}
-
- return mStatus_NoError; // don't return transient errors to caller
+ return err;
}
mDNSexport mStatus uDNS_StartQuery(mDNS *const m, DNSQuestion *const question)
return smContinue; // next routine will examine additionals section of A record
}
}
- LogMsg("ERROR: could not confirm existence of record %##s NS %##s", context->zone.c, context->ns.c);
+ debugf("ERROR: could not confirm existence of record %##s NS %##s", context->zone.c, context->ns.c);
return smError;
}
else { LogMsg("ERROR: confirmNS - bad state %d", context->state); return smError; }
if (err) { LogMsg("ERROR: conQueryCallback: constructQueryMsg - %ld", err); goto error; }
err = mDNSSendDNSMessage(m, msg, end, mDNSInterface_Any, &zeroAddr, zeroIPPort, sd, mDNSNULL);
question->LastQTime = mDNSPlatformTimeNow(m);
- if (err) { LogMsg("ERROR: conQueryCallback: mDNSSendDNSMessage_tcp - %ld", err); goto error; }
+ if (err) { debugf("ERROR: conQueryCallback: mDNSSendDNSMessage_tcp - %ld", err); goto error; }
}
else
{
if (rr->uDNS_info.lease)
{ ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
-
- err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, ®Info->ns, regInfo->port, -1, GetAuthInfoForZone(u, ®Info->zone));
- if (err) LogMsg("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err);
- SetRecordRetry(m, rr);
+ err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, ®Info->ns, regInfo->port, -1, GetAuthInfoForName(u, rr->resrec.name));
+ if (err) debugf("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err);
+
+ SetRecordRetry(m, rr, err);
if (regInfo->state != regState_Refresh && regInfo->state != regState_DeregDeferred) regInfo->state = regState_Pending;
return;
goto error;
}
+ // Don't try to do updates to the root name server.
+ // We might be tempted also to block updates to any single-label name server (e.g. com, edu, net, etc.) but some
+ // organizations use their own private pseudo-TLD, like ".home", etc, and we don't want to block that.
+ if (zoneData->zoneName.c[0] == 0)
+ {
+ LogMsg("ERROR: Only name server claiming responsibility for \"%##s\" is \"%##s\"!",
+ newRR->resrec.name->c, zoneData->zoneName.c);
+ err = mStatus_NoSuchNameErr;
+ goto error;
+ }
+
// cache zone data
AssignDomainName(&newRR->uDNS_info.zone, &zoneData->zoneName);
newRR->uDNS_info.ns.type = mDNSAddrType_IPv4;
if (srs->uDNS_info.lease)
{ ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
- err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rInfo->ns, rInfo->port, -1, GetAuthInfoForZone(u, &rInfo->zone));
- if (err) { LogMsg("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %ld", err); goto error; }
+ err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rInfo->ns, rInfo->port, -1, GetAuthInfoForName(u, srs->RR_SRV.resrec.name));
+ if (err) debugf("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %ld", err);
if (rInfo->state != regState_Refresh && rInfo->state != regState_DeregDeferred && srs->uDNS_info.state != regState_UpdatePending)
rInfo->state = regState_Pending;
- SetRecordRetry(m, &srs->RR_SRV);
+ SetRecordRetry(m, &srs->RR_SRV, err);
rInfo->id.NotAnInteger = id.NotAnInteger;
if (mapped) srv->resrec.rdata->u.srv.port = privport;
return;
}
rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
- rr->resrec.rdatahash = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
- rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0;
+ rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
rr->uDNS_info.state = regState_FetchingZoneData;
rr->next = m->uDNS_info.RecordRegistrations;
if (!ptr) goto error;
if (!(ptr = putDeletionRecord(&msg, ptr, &rr->resrec))) goto error;
- err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForZone(u, &rr->uDNS_info.zone));
- if (err) LogMsg("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err);
+ err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForName(u, rr->resrec.name));
+ if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err);
- SetRecordRetry(m, rr);
+ SetRecordRetry(m, rr, err);
rr->uDNS_info.state = regState_DeregPending;
return;
if (!GetServiceTarget(&m->uDNS_info, &srs->RR_SRV, &target))
{
// defer registration until we've got a target
- LogMsg("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c);
+ debugf("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c);
info->state = regState_NoTarget;
return mStatus_NoError;
}
if (!(ptr = putDeletionRecord(&msg, ptr, &srs->SubTypes[i].resrec))) goto error;
- err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForZone(u, &info->zone));
- if (err) { LogMsg("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %ld", err); goto error; }
+ err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForName(u, srs->RR_SRV.resrec.name));
+ if (err && err != mStatus_TransientErr) { debugf("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %ld", err); goto error; }
- SetRecordRetry(m, &srs->RR_SRV);
+ SetRecordRetry(m, &srs->RR_SRV, err);
info->id.NotAnInteger = id.NotAnInteger;
info->state = regState_DeregPending;
{ ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
// don't report send errors - retransmission will occurr if necessary
- err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForZone(u, &info->zone));
+ err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &info->ns, info->port, -1, GetAuthInfoForName(u, rr->resrec.name));
if (err) debugf("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err);
- //!!! Update this when we implement retransmission for services
- SetRecordRetry(m, rr);
+ SetRecordRetry(m, rr, err);
rr->uDNS_info.state = regState_UpdatePending;
if (&rr->uDNS_info != info) info->state = regState_UpdatePending; // set parent SRS
else
{
err = mDNSSendDNSMessage(m, &msg, end, mDNSInterface_Any, &server, UnicastDNSPort, -1, mDNSNULL);
- if (err) { debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %ld", err); } // surpress syslog messages if we have no network
q->LastQTime = timenow;
- if (q->ThisQInterval < MAX_UCAST_POLL_INTERVAL) q->ThisQInterval = q->ThisQInterval * 2;
+ if (err) debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %ld", err); // surpress syslog messages if we have no network
+ else if (q->ThisQInterval < MAX_UCAST_POLL_INTERVAL) q->ThisQInterval = q->ThisQInterval * 2; // don't increase interval if send failed
}
}
}
mDNS_Lock(m);
if (u->LLQNatInfo)
{
- NATTraversalInfo *nat = u->LLQNatInfo;
- u->LLQNatInfo = mDNSNULL;
- DeleteNATPortMapping(m, nat, mDNSNULL);
+ DeleteNATPortMapping(m, u->LLQNatInfo, mDNSNULL);
+ FreeNATInfo(m, u->LLQNatInfo); // routine clears u->LLQNatInfo ptr
}
SuspendLLQs(m, mDNStrue);
RestartQueries(m);
ptr = putDeletionRecord(&msg, ptr, &rr->resrec);
if (!ptr) { LogMsg("Error: SleepRecordRegistrations - could not put deletion record"); return; }
- mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForZone(&m->uDNS_info, &rr->uDNS_info.zone));
+ mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &rr->uDNS_info.ns, rr->uDNS_info.port, -1, GetAuthInfoForName(&m->uDNS_info, rr->resrec.name));
rr->uDNS_info.state = regState_Refresh;
rr->LastAPTime = timenow;
rr->ThisAPInterval = 300 * mDNSPlatformOneSecond;
Change History (most recent first):
$Log: uDNS.h,v $
+Revision 1.30 2005/03/04 03:00:03 ksekar
+<rdar://problem/4026546> Retransmissions happen too early, causing registrations to conflict with themselves
+
Revision 1.29 2005/01/11 22:50:53 ksekar
Fixed constant naming (was using kLLQ_DefLease for update leases)
extern "C" {
#endif
-#define RESTART_GOODBYE_DELAY (2 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up)
-#define MIN_UCAST_PERIODIC_EXEC (5 * mDNSPlatformOneSecond)
-#define INIT_UCAST_POLL_INTERVAL mDNSPlatformOneSecond // this interval is used after send failures on network transitions
- // which typically heal quickly, so we start agressively and exponentially back off
+#define RESTART_GOODBYE_DELAY (6 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up)
+#define MIN_UCAST_PERIODIC_EXEC (5 * mDNSPlatformOneSecond)
+#define INIT_UCAST_POLL_INTERVAL (3 * mDNSPlatformOneSecond) // this interval is used after send failures on network transitions
+ // which typically heal quickly, so we start agressively and exponentially back off
#define MAX_UCAST_POLL_INTERVAL (60 * 60 * mDNSPlatformOneSecond)
-#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request
+#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request
#define UPDATE_PORT_NAME "_dns-update._udp."
#define LLQ_PORT_NAME "_dns-llq._udp"
#define DEFAULT_UPDATE_LEASE 7200
Change History (most recent first):
$Log: mDNSLibraryResources.r,v $
+Revision 1.31 2005/03/15 02:14:14 cheshire
+mDNSResponder-107
+
+Revision 1.30 2005/03/10 01:32:37 cheshire
+mDNSResponder-105
+
+Revision 1.29 2005/02/26 05:20:13 cheshire
+mDNSResponder-102
+
+Revision 1.28 2005/02/19 00:42:58 cheshire
+mDNSResponder-101
+
+Revision 1.27 2005/02/10 21:56:38 cheshire
+mDNSResponder-100
+
+Revision 1.26 2005/02/04 03:25:10 cheshire
+mDNSResponder-99
+
Revision 1.25 2005/01/28 00:04:16 cheshire
mDNSResponder-98
resource 'vers' (1, purgeable)
{
- 0x01, 0x00, alpha, 98, verUS,
- "1.0a98",
- "Multicast DNS & DNS Service Discovery 1.0a98"
+ 0x01, 0x00, alpha, 107, verUS,
+ "1.0a107",
+ "Multicast DNS & DNS Service Discovery 1.0a107"
};
resource 'vers' (2, purgeable)
{
- 0x01, 0x00, alpha, 98, verUS,
- "1.0a98",
- "developer.apple.com/darwin/projects/rendezvous/"
+ 0x01, 0x00, alpha, 107, verUS,
+ "1.0a107",
+ "developer.apple.com/darwin/projects/bonjour/"
};
/* We need to load OT, so make sure the system heap has enough space for it */
--- /dev/null
+/*
+ File: ConfigurationAuthority.c
+
+ Abstract: Interface to system security framework that manages access
+ to protected resources like system configuration preferences.
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+
+$Log: ConfigurationAuthority.c,v $
+Revision 1.1 2005/02/05 02:28:22 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#include "ConfigurationAuthority.h"
+#include "ConfigurationRights.h"
+
+#include <AssertMacros.h>
+
+
+static AuthorizationRef gAuthRef = 0;
+
+static AuthorizationItem gAuthorizations[] = { { UPDATE_SC_RIGHT, 0, NULL, 0 },
+ { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 }};
+static AuthorizationRights gAuthSet = { sizeof gAuthorizations / sizeof gAuthorizations[0], gAuthorizations };
+
+static CFDictionaryRef CreateRightsDict( CFStringRef prompt)
+/* Create a CFDictionary decribing an auth right. See /etc/authorization for examples. */
+/* Specifies that the right requires admin authentication, which persists for 5 minutes. */
+{
+ CFMutableDictionaryRef dict = NULL, tmpDict;
+ CFMutableArrayRef mechanisms;
+ CFNumberRef timeout;
+ int val;
+
+ tmpDict = CFDictionaryCreateMutable( (CFAllocatorRef) NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ require( tmpDict != NULL, MakeDictFailed);
+
+ CFDictionaryAddValue(tmpDict, CFSTR("class"), CFSTR("user"));
+ CFDictionaryAddValue(tmpDict, CFSTR("comment"), prompt);
+ CFDictionaryAddValue(tmpDict, CFSTR("group"), CFSTR("admin"));
+
+ mechanisms = CFArrayCreateMutable((CFAllocatorRef) NULL, 1, &kCFTypeArrayCallBacks);
+ require( mechanisms != NULL, MakeArrayFailed);
+ CFArrayAppendValue( mechanisms, CFSTR("builtin:authenticate"));
+ CFDictionaryAddValue( tmpDict, CFSTR("mechanisms"), mechanisms);
+
+ val = 300; // seconds
+ timeout = CFNumberCreate((CFAllocatorRef) NULL, kCFNumberIntType, &val);
+ require( timeout != NULL, MakeIntFailed);
+ CFDictionaryAddValue( tmpDict, CFSTR("timeout"), timeout);
+ CFDictionaryAddValue( tmpDict, CFSTR("shared"), kCFBooleanTrue);
+
+ dict = tmpDict;
+ tmpDict = NULL;
+
+ CFRelease( timeout);
+MakeIntFailed:
+ CFRelease( mechanisms);
+MakeArrayFailed:
+ if ( tmpDict)
+ CFRelease( tmpDict);
+MakeDictFailed:
+ return dict;
+}
+
+OSStatus InitConfigAuthority(void)
+/* Initialize the authorization record-keeping */
+{
+ OSStatus err;
+ CFDictionaryRef dict;
+ CFStringRef rightInfo;
+
+ err = AuthorizationCreate((AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL,
+ (AuthorizationFlags) 0, &gAuthRef);
+ require_noerr( err, NewAuthFailed);
+
+ err = AuthorizationRightGet( UPDATE_SC_RIGHT, (CFDictionaryRef*) NULL);
+ if( err == errAuthorizationDenied)
+ {
+ rightInfo = CFCopyLocalizedString(CFSTR("Authentication required to set Dynamic DNS preferences."),
+ CFSTR("Describes operation that requires user authorization"));
+ require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
+ dict = CreateRightsDict(rightInfo);
+ require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
+
+ err = AuthorizationRightSet(gAuthRef, UPDATE_SC_RIGHT, dict, (CFStringRef) NULL,
+ (CFBundleRef) NULL, (CFStringRef) NULL);
+ CFRelease(rightInfo);
+ CFRelease(dict);
+ }
+ require_noerr( err, AuthSetFailed);
+
+ err = AuthorizationRightGet( EDIT_SYS_KEYCHAIN_RIGHT, (CFDictionaryRef*) NULL);
+ if( err == errAuthorizationDenied)
+ {
+ rightInfo = CFCopyLocalizedString( CFSTR("Authentication required to edit System Keychain."),
+ CFSTR("Describes operation that requires user authorization"));
+ require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
+ dict = CreateRightsDict( rightInfo);
+ require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
+
+ err = AuthorizationRightSet(gAuthRef, EDIT_SYS_KEYCHAIN_RIGHT, dict, (CFStringRef) NULL,
+ (CFBundleRef) NULL, (CFStringRef) NULL);
+ CFRelease( rightInfo);
+ CFRelease( dict);
+ }
+ require_noerr( err, AuthSetFailed);
+
+ (void) AttemptAcquireAuthority( false);
+
+AuthSetFailed:
+GetStrFailed:
+NewAuthFailed:
+ return err;
+}
+
+OSStatus AttemptAcquireAuthority( Boolean allowUI)
+/* Try to get permission for privileged ops, either implicitly or by asking the user for */
+/* authority to perform operations (if necessary) */
+{
+ AuthorizationFlags allowFlag = allowUI ? kAuthorizationFlagInteractionAllowed : 0;
+ OSStatus err;
+
+ err = AuthorizationCopyRights( gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL,
+ kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize |
+ allowFlag,
+ (AuthorizationRights**) NULL);
+ return err;
+}
+
+OSStatus ReleaseAuthority(void)
+/* Discard authority to perform operations */
+{
+ (void) AuthorizationFree( gAuthRef, kAuthorizationFlagDestroyRights);
+ gAuthRef = 0;
+ return AuthorizationCreate( (AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL,
+ (AuthorizationFlags) 0, &gAuthRef);
+}
+
+Boolean CurrentlyAuthorized(void)
+{
+ OSStatus err;
+
+ err = AuthorizationCopyRights(gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL,
+ (AuthorizationFlags) 0, (AuthorizationRights**) NULL);
+
+ return err == noErr;
+}
+
+
+OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth)
+/* Package up current authorizations for transfer to another process */
+{
+ return AuthorizationMakeExternalForm(gAuthRef, pAuth);
+}
--- /dev/null
+/*
+ File: ConfigurationAuthority.h
+
+ Abstract: Interface to system security framework that manages access
+ to protected resources like system configuration preferences.
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+
+$Log: ConfigurationAuthority.h,v $
+Revision 1.1 2005/02/05 02:32:30 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#include <CoreServices/CoreServices.h>
+#include <Security/Security.h>
+
+OSStatus InitConfigAuthority(void);
+Boolean CurrentlyAuthorized(void);
+OSStatus AttemptAcquireAuthority(Boolean allowUI);
+OSStatus ReleaseAuthority(void);
+OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth);
--- /dev/null
+/*
+ File: ConfigurationRights.h
+
+ Abstract: Defines the rights we need, namely, (i) the right to write to
+ the system configuration settings for Dynamic DNS and Wide-Area DNS-SD,
+ and (ii) the right to write to the system keychain to store Dynamic DNS
+ shared secrets used to perform authorized updates to DDNS servers.
+ Right now these are both actually the same right: "system.preferences"
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+$Log: ConfigurationRights.h,v $
+Revision 1.1 2005/02/05 01:59:19 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#define UPDATE_SC_RIGHT "system.preferences"
+#define EDIT_SYS_KEYCHAIN_RIGHT "system.preferences"
--- /dev/null
+/*
+ File: DNSServiceDiscoveryPref.h
+
+ Abstract: System Preference Pane for Dynamic DNS and Wide-Area DNS Service Discovery
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+$Log: DNSServiceDiscoveryPref.h,v $
+Revision 1.5 2005/02/26 00:44:24 cheshire
+Restore default reg domain if user deletes text and clicks "apply"
+
+Revision 1.4 2005/02/25 02:29:28 cheshire
+Show yellow dot for "update in progress"
+
+Revision 1.3 2005/02/10 22:35:19 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.2 2005/02/08 01:32:05 cheshire
+Add trimCharactersFromDomain routine to strip leading and trailing
+white space and punctuation from user-entered fields.
+
+Revision 1.1 2005/02/05 01:59:19 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#import <Cocoa/Cocoa.h>
+#import <PreferencePanes/PreferencePanes.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <SecurityInterface/SFAuthorizationView.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+#import <dns_sd.h>
+
+typedef struct MyDNSServiceState {
+ DNSServiceRef service;
+ CFRunLoopSourceRef source;
+ CFSocketRef socket;
+} MyDNSServiceState;
+
+
+@interface DNSServiceDiscoveryPref : NSPreferencePane
+{
+ IBOutlet NSTextField *hostName;
+ IBOutlet NSTextField *sharedSecretName;
+ IBOutlet NSSecureTextField *sharedSecretValue;
+ IBOutlet NSComboBox *browseDomainsComboBox;
+ IBOutlet NSComboBox *regDomainsComboBox;
+ IBOutlet NSButton *wideAreaCheckBox;
+ IBOutlet NSButton *hostNameSharedSecretButton;
+ IBOutlet NSButton *registrationSharedSecretButton;
+ IBOutlet NSButton *applyButton;
+ IBOutlet NSButton *revertButton;
+ IBOutlet NSWindow *sharedSecretWindow;
+ IBOutlet NSWindow *addBrowseDomainWindow;
+ IBOutlet NSButton *addBrowseDomainButton;
+ IBOutlet NSButton *removeBrowseDomainButton;
+ IBOutlet NSButton *browseOKButton;
+ IBOutlet NSButton *browseCancelButton;
+ IBOutlet NSButton *secretOKButton;
+ IBOutlet NSButton *secretCancelButton;
+ IBOutlet NSImageView *statusImageView;
+ IBOutlet NSTabView *tabView;
+ IBOutlet NSTableView *browseDomainList;
+ IBOutlet SFAuthorizationView *comboAuthButton;
+
+ NSWindow *mainWindow;
+ NSString *currentHostName;
+ NSString *currentRegDomain;
+ NSArray *currentBrowseDomainsArray;
+ NSMutableArray *browseDomainsArray;
+ NSMutableArray *defaultBrowseDomainsArray;
+ NSString *defaultRegDomain;
+
+ NSString *hostNameSharedSecretName;
+ NSString *hostNameSharedSecretValue;
+ NSString *regSharedSecretName;
+ NSString *regSharedSecretValue;
+ BOOL currentWideAreaState;
+ BOOL prefsNeedUpdating;
+ BOOL toolInstalled;
+ BOOL browseDomainListEnabled;
+ BOOL justStartedEditing;
+ NSImage *successImage;
+ NSImage *inprogressImage;
+ NSImage *failureImage;
+
+ MyDNSServiceState regQuery;
+ MyDNSServiceState browseQuery;
+ NSMutableArray *browseDataSource;
+ NSMutableArray *registrationDataSource;
+}
+
+- (IBAction)applyClicked:(id)sender;
+- (IBAction)enableBrowseDomainClicked:(id)sender;
+- (IBAction)addBrowseDomainClicked:(id)sender;
+- (IBAction)removeBrowseDomainClicked:(id)sender;
+- (IBAction)revertClicked:(id)sender;
+- (IBAction)changeButtonPressed:(id)sender;
+- (IBAction)closeMyCustomSheet:(id)sender;
+- (IBAction)comboAction:(id)sender;
+- (IBAction)wideAreaCheckBoxChanged:(id)sender;
+
+
+- (NSMutableArray *)browseDataSource;
+- (NSMutableArray *)registrationDataSource;
+- (NSComboBox *)browseDomainsComboBox;
+- (NSComboBox *)regDomainsComboBox;
+- (NSString *)currentRegDomain;
+- (NSMutableArray *)defaultBrowseDomainsArray;
+- (NSArray *)currentBrowseDomainsArray;
+- (NSString *)currentHostName;
+- (NSString *)defaultRegDomain;
+- (void)setDefaultRegDomain:(NSString *)domain;
+
+
+
+- (void)enableApplyButton;
+- (void)disableApplyButton;
+- (void)applyCurrentState;
+- (void)setBrowseDomainsComboBox;
+- (void)setupInitialValues;
+- (void)startDomainBrowsing;
+- (void)toggleWideAreaBonjour:(BOOL)state;
+- (void)updateApplyButtonState;
+- (void)enableControls;
+- (void)disableControls;
+- (void)validateTextFields;
+- (void)readPreferences;
+- (void)savePreferences;
+- (void)restorePreferences;
+- (void)watchForPreferenceChanges;
+- (void)updateStatusImageView;
+
+
+- (NSString *)sharedSecretKeyName:(NSString * )domain;
+- (NSString *)domainForHostName:(NSString *)hostNameString;
+- (int)statusForHostName:(NSString * )domain;
+- (NSData *)dataForDomainArray:(NSArray *)domainArray;
+- (NSData *)dataForDomain:(NSString *)domainName isEnabled:(BOOL)enabled;
+- (NSData *)dataForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName;
+- (BOOL)domainAlreadyInList:(NSString *)domainString;
+- (NSString *)trimCharactersFromDomain:(NSString *)domain;
+
+
+// Delegate methods
+- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view;
+- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view;
+- (void)mainViewDidLoad;
+- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox;
+- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index;
+- (void)controlTextDidChange:(NSNotification *) notification;
+
+@end
--- /dev/null
+/*
+ File: DNSServiceDiscoveryPref.m
+
+ Abstract: System Preference Pane for Dynamic DNS and Wide-Area DNS Service Discovery
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+$Log: DNSServiceDiscoveryPref.m,v $
+Revision 1.6 2005/02/26 00:44:24 cheshire
+Restore default reg domain if user deletes text and clicks "apply"
+
+Revision 1.5 2005/02/25 02:29:28 cheshire
+Show yellow dot for "update in progress"
+
+Revision 1.4 2005/02/16 00:18:33 cheshire
+Bunch o' fixes
+
+Revision 1.3 2005/02/10 22:35:20 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.2 2005/02/08 01:32:05 cheshire
+Add trimCharactersFromDomain routine to strip leading and trailing
+white space and punctuation from user-entered fields.
+
+Revision 1.1 2005/02/05 01:59:19 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#import "DNSServiceDiscoveryPref.h"
+#import "ConfigurationAuthority.h"
+#import "PrivilegedOperations.h"
+#import <unistd.h>
+
+@implementation DNSServiceDiscoveryPref
+
+static CFComparisonResult
+MyArrayCompareFunction(id val1, id val2, void *context)
+{
+ return CFStringCompare((CFStringRef)val1, (CFStringRef)val2, kCFCompareCaseInsensitive);
+}
+
+
+static CFComparisonResult
+MyDomainArrayCompareFunction(id val1, id val2, void *context)
+{
+ NSString *domain1 = [val1 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ NSString *domain2 = [val2 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ return CFStringCompare((CFStringRef)domain1, (CFStringRef)domain2, kCFCompareCaseInsensitive);
+}
+
+
+static const char *
+GetNextLabel(const char *cstr, char label[64])
+{
+ char *ptr = label;
+ while (*cstr && *cstr != '.') // While we have characters in the label...
+ {
+ char c = *cstr++;
+ if (c == '\\')
+ {
+ c = *cstr++;
+ if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
+ {
+ int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal
+ int v1 = cstr[ 0] - '0';
+ int v2 = cstr[ 1] - '0';
+ int val = v0 * 100 + v1 * 10 + v2;
+ if (val <= 255) { c = (char)val; cstr += 2; } // If valid three-digit decimal value, use it
+ }
+ }
+ *ptr++ = c;
+ if (ptr >= label+64) return(NULL);
+ }
+ if (*cstr) cstr++; // Skip over the trailing dot (if present)
+ *ptr++ = 0;
+ return(cstr);
+}
+
+
+static void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
+{
+ DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)context;
+ assert(me != NULL);
+
+ [me setupInitialValues];
+}
+
+
+static void ServiceDomainEnumReply( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *replyDomain, void *context, DNSServiceFlags enumType)
+{
+ if (strcmp(replyDomain, "local.") == 0) return; // local domain is not interesting
+
+ DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)context;
+ BOOL moreComing = (BOOL)(flags & kDNSServiceFlagsMoreComing);
+ NSMutableArray * domainArray;
+ NSMutableArray * defaultBrowseDomainsArray = nil;
+ NSComboBox * domainComboBox;
+ NSString * domainString;
+ NSString * currentDomain = nil;
+ char decodedDomainString[kDNSServiceMaxDomainName] = "\0";
+ char nextLabel[256] = "\0";
+ char * buffer = (char *)replyDomain;
+
+ while (*buffer) {
+ buffer = (char *)GetNextLabel(buffer, nextLabel);
+ strcat(decodedDomainString, nextLabel);
+ strcat(decodedDomainString, ".");
+ }
+
+ // Remove trailing dot from domain name.
+ decodedDomainString[strlen(decodedDomainString)-1] = '\0';
+
+ domainString = [[[NSString alloc] initWithUTF8String:(const char *)decodedDomainString] autorelease];
+
+ if (enumType & kDNSServiceFlagsRegistrationDomains) {
+ domainArray = [me registrationDataSource];
+ domainComboBox = [me regDomainsComboBox];
+ currentDomain = [me currentRegDomain];
+ } else {
+ domainArray = [me browseDataSource];
+ domainComboBox = [me browseDomainsComboBox];
+ defaultBrowseDomainsArray = [me defaultBrowseDomainsArray];
+ }
+
+ if (flags & kDNSServiceFlagsAdd) {
+ [domainArray removeObject:domainString]; // How can I check if an object is in the array?
+ [domainArray addObject:domainString];
+ if ((flags & kDNSServiceFlagsDefault) && (enumType & kDNSServiceFlagsRegistrationDomains)) {
+ [me setDefaultRegDomain:domainString];
+ if ([[domainComboBox stringValue] length] == 0) [domainComboBox setStringValue:domainString];
+ } else if ((flags & kDNSServiceFlagsDefault) && !(enumType & kDNSServiceFlagsRegistrationDomains)) {
+ [defaultBrowseDomainsArray removeObject:domainString];
+ [defaultBrowseDomainsArray addObject:domainString];
+ }
+ }
+
+ if (moreComing == NO) {
+ [domainArray sortUsingFunction:MyArrayCompareFunction context:nil];
+ [domainComboBox reloadData];
+ }
+}
+
+
+void
+browseDomainReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *replyDomain, void *context)
+{
+ ServiceDomainEnumReply(sdRef, flags, interfaceIndex, errorCode, replyDomain, context, kDNSServiceFlagsBrowseDomains);
+}
+
+
+void
+registrationDomainReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *replyDomain, void *context)
+{
+ ServiceDomainEnumReply(sdRef, flags, interfaceIndex, errorCode, replyDomain, context, kDNSServiceFlagsRegistrationDomains);
+}
+
+
+
+static void
+MyDNSServiceCleanUp(MyDNSServiceState * query)
+{
+ /* Remove the CFRunLoopSource from the current run loop. */
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), query->source, kCFRunLoopCommonModes);
+ CFRelease(query->source);
+
+ /* Invalidate the CFSocket. */
+ CFSocketInvalidate(query->socket);
+ CFRelease(query->socket);
+
+ /* Workaround that gives time to CFSocket's select thread so it can remove the socket from its FD set
+ before we close the socket by calling DNSServiceRefDeallocate. <rdar://problem/3585273> */
+ usleep(1000);
+
+ /* Terminate the connection with the mDNSResponder daemon, which cancels the query. */
+ DNSServiceRefDeallocate(query->service);
+}
+
+
+
+static void
+MySocketReadCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void * data, void * info)
+{
+ #pragma unused(s)
+ #pragma unused(type)
+ #pragma unused(address)
+ #pragma unused(data)
+
+ DNSServiceErrorType err;
+
+ MyDNSServiceState * query = (MyDNSServiceState *)info; // context passed in to CFSocketCreateWithNative().
+ assert(query != NULL);
+
+ /* Read a reply from the mDNSResponder. */
+ err= DNSServiceProcessResult(query->service);
+ if (err != kDNSServiceErr_NoError) {
+ fprintf(stderr, "DNSServiceProcessResult returned %d\n", err);
+
+ /* Terminate the query operation and release the CFRunLoopSource and CFSocket. */
+ MyDNSServiceCleanUp(query);
+ }
+}
+
+
+
+void
+MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
+{
+ CFSocketNativeHandle sock;
+ CFOptionFlags sockFlags;
+ CFSocketContext context = { 0, query, NULL, NULL, NULL }; // Use MyDNSServiceState as context data.
+
+ /* Access the underlying Unix domain socket to communicate with the mDNSResponder daemon. */
+ sock = DNSServiceRefSockFD(query->service);
+ assert(sock != -1);
+
+ /* Create a CFSocket using the Unix domain socket. */
+ query->socket = CFSocketCreateWithNative(NULL, sock, kCFSocketReadCallBack, MySocketReadCallback, &context);
+ assert(query->socket != NULL);
+
+ /* Prevent CFSocketInvalidate from closing DNSServiceRef's socket. */
+ sockFlags = CFSocketGetSocketFlags(query->socket);
+ CFSocketSetSocketFlags(query->socket, sockFlags & (~kCFSocketCloseOnInvalidate));
+
+ /* Create a CFRunLoopSource from the CFSocket. */
+ query->source = CFSocketCreateRunLoopSource(NULL, query->socket, 0);
+ assert(query->source != NULL);
+
+ /* Add the CFRunLoopSource to the current run loop. */
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), query->source, kCFRunLoopCommonModes);
+}
+
+
+
+-(void)updateStatusImageView
+{
+ int value = [self statusForHostName:currentHostName];
+ if (value == 0) [statusImageView setImage:successImage];
+ else if (value > 0) [statusImageView setImage:inprogressImage];
+ else [statusImageView setImage:failureImage];
+}
+
+
+- (void)watchForPreferenceChanges
+{
+ SCDynamicStoreContext context = { 0, self, NULL, NULL, NULL };
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("watchForPreferenceChanges"), NetworkChanged, &context);
+ CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFRunLoopSourceRef rls;
+
+ assert(store != NULL);
+ assert(keys != NULL);
+
+ CFArrayAppendValue(keys, SC_DYNDNS_STATE_KEY);
+ CFArrayAppendValue(keys, SC_DYNDNS_SETUP_KEY);
+
+ (void)SCDynamicStoreSetNotificationKeys(store, keys, NULL);
+
+ rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+ assert(rls != NULL);
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopCommonModes);
+
+ CFRelease(keys);
+ CFRelease(store);
+}
+
+
+-(int)statusForHostName:(NSString * )domain
+{
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("statusForHostName"), NULL, NULL);
+ NSString *lowercaseDomain = [domain lowercaseString];
+ int status = 1;
+
+ assert(store != NULL);
+
+ NSDictionary *dynamicDNS = (NSDictionary *)SCDynamicStoreCopyValue(store, SC_DYNDNS_STATE_KEY);
+ if (dynamicDNS) {
+ NSDictionary *hostNames = [dynamicDNS objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY];
+ NSDictionary *infoDict = [hostNames objectForKey:lowercaseDomain];
+ if (infoDict) status = [[infoDict objectForKey:(NSString*)SC_DYNDNS_STATUS_KEY] intValue];
+ CFRelease(dynamicDNS);
+ }
+ CFRelease(store);
+
+ return status;
+}
+
+
+- (void)startDomainBrowsing
+{
+ DNSServiceFlags flags;
+ OSStatus err = noErr;
+
+ flags = kDNSServiceFlagsRegistrationDomains;
+ err = DNSServiceEnumerateDomains(®Query.service, flags, 0, registrationDomainReply, (void *)self);
+ if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(®Query);
+
+ flags = kDNSServiceFlagsBrowseDomains;
+ err = DNSServiceEnumerateDomains(&browseQuery.service, flags, 0, browseDomainReply, (void *)self);
+ if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(&browseQuery);
+}
+
+
+-(void)readPreferences
+{
+ NSDictionary *origDict;
+ NSArray *regDomainArray;
+ NSArray *hostArray;
+
+ if (currentRegDomain) [currentRegDomain release];
+ if (currentBrowseDomainsArray) [currentBrowseDomainsArray release];
+ if (currentHostName) [currentHostName release];
+
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL, NULL);
+ origDict = (NSDictionary *)SCDynamicStoreCopyValue(store, SC_DYNDNS_SETUP_KEY);
+
+ regDomainArray = [origDict objectForKey:(NSString *)SC_DYNDNS_REGDOMAINS_KEY];
+ if (regDomainArray && [regDomainArray count] > 0) {
+ currentRegDomain = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy];
+ currentWideAreaState = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue];
+ } else {
+ currentRegDomain = [[NSString alloc] initWithString:@""];
+ currentWideAreaState = NO;
+ }
+
+ currentBrowseDomainsArray = [[origDict objectForKey:(NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY] retain];
+
+ hostArray = [origDict objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY];
+ if (hostArray && [hostArray count] > 0) {
+ currentHostName = [[[hostArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy];
+ } else {
+ currentHostName = [[NSString alloc] initWithString:@""];
+ }
+
+ [origDict release];
+ CFRelease(store);
+}
+
+
+- (void)tableViewSelectionDidChange:(NSNotification *)notification;
+{
+ [removeBrowseDomainButton setEnabled:[[notification object] numberOfSelectedRows]];
+}
+
+
+- (void)setBrowseDomainsComboBox;
+{
+ NSString * domain = nil;
+
+ if ([defaultBrowseDomainsArray count] > 0) {
+ NSEnumerator * arrayEnumerator = [defaultBrowseDomainsArray objectEnumerator];
+ while (domain = [arrayEnumerator nextObject]) {
+ if ([self domainAlreadyInList:domain] == NO) break;
+ }
+ }
+ if (domain) [browseDomainsComboBox setStringValue:domain];
+ else [browseDomainsComboBox setStringValue:@""];
+}
+
+
+- (IBAction)addBrowseDomainClicked:(id)sender;
+{
+ [self setBrowseDomainsComboBox];
+
+ [NSApp beginSheet:addBrowseDomainWindow modalForWindow:mainWindow modalDelegate:self
+ didEndSelector:@selector(addBrowseDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:sender];
+
+ [browseDomainList deselectAll:sender];
+ [self updateApplyButtonState];
+}
+
+
+- (IBAction)removeBrowseDomainClicked:(id)sender;
+{
+ int selectedBrowseDomain = [browseDomainList selectedRow];
+ [browseDomainsArray removeObjectAtIndex:selectedBrowseDomain];
+ [browseDomainList reloadData];
+ [self updateApplyButtonState];
+}
+
+
+- (IBAction)enableBrowseDomainClicked:(id)sender;
+{
+ NSTableView *tableView = sender;
+ NSMutableDictionary *browseDomainDict;
+ int value;
+
+ browseDomainDict = [[browseDomainsArray objectAtIndex:[tableView clickedRow]] mutableCopy];
+ value = [[browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue];
+ [browseDomainDict setObject:[[[NSNumber alloc] initWithInt:(!value)] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+ [browseDomainsArray replaceObjectAtIndex:[tableView clickedRow] withObject:browseDomainDict];
+ [tableView reloadData];
+ [self updateApplyButtonState];
+}
+
+
+
+- (int)numberOfRowsInTableView:(NSTableView *)tableView;
+{
+ int numberOfRows = 0;
+
+ if (browseDomainsArray) {
+ numberOfRows = [browseDomainsArray count];
+ }
+ return numberOfRows;
+}
+
+
+- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem;
+{
+ [browseDomainList deselectAll:self];
+ [mainWindow makeFirstResponder:nil];
+}
+
+
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row;
+{
+ NSDictionary *browseDomainDict;
+ id value = nil;
+
+ if (browseDomainsArray) {
+ browseDomainDict = [browseDomainsArray objectAtIndex:row];
+ if (browseDomainDict) {
+ if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_ENABLED_KEY]) {
+ value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+ } else if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_DOMAIN_KEY]) {
+ value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ }
+ }
+ }
+ return value;
+}
+
+
+- (void)setupInitialValues
+{
+ [self readPreferences];
+
+ if (currentHostName) {
+ [hostName setStringValue:currentHostName];
+ [self updateStatusImageView];
+ }
+
+ if (browseDomainsArray) {
+ [browseDomainsArray release];
+ browseDomainsArray = nil;
+ }
+
+ if (currentBrowseDomainsArray) {
+ browseDomainsArray = [currentBrowseDomainsArray mutableCopy];
+ if (browseDomainsArray) {
+ [browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil];
+ if ([browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) {
+ OSStatus err = WriteBrowseDomain((CFDataRef)[self dataForDomainArray:browseDomainsArray]);
+ if (err != noErr) NSLog(@"WriteBrowseDomain returned %d\n", err);
+ [currentBrowseDomainsArray release];
+ currentBrowseDomainsArray = [browseDomainsArray copy];
+ }
+ }
+ } else {
+ browseDomainsArray = nil;
+ }
+ [browseDomainList reloadData];
+
+ if (currentRegDomain && ([currentRegDomain length] > 0)) {
+ [regDomainsComboBox setStringValue:currentRegDomain];
+ [registrationDataSource removeObject:currentRegDomain];
+ [registrationDataSource addObject:currentRegDomain];
+ [registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil];
+ [regDomainsComboBox reloadData];
+ }
+
+ if (currentWideAreaState) {
+ [self toggleWideAreaBonjour:YES];
+ } else {
+ [self toggleWideAreaBonjour:NO];
+ }
+
+ if (hostNameSharedSecretValue) {
+ [hostNameSharedSecretValue release];
+ hostNameSharedSecretValue = nil;
+ }
+
+ if (regSharedSecretValue) {
+ [regSharedSecretValue release];
+ regSharedSecretValue = nil;
+ }
+
+ [self updateApplyButtonState];
+ [mainWindow makeFirstResponder:nil];
+ [browseDomainList deselectAll:self];
+ [removeBrowseDomainButton setEnabled:NO];
+}
+
+
+
+- (void)awakeFromNib
+{
+ OSStatus err;
+
+ prefsNeedUpdating = NO;
+ toolInstalled = NO;
+ browseDomainListEnabled = NO;
+ defaultRegDomain = nil;
+ currentRegDomain = nil;
+ currentBrowseDomainsArray = nil;
+ currentHostName = nil;
+ hostNameSharedSecretValue = nil;
+ regSharedSecretValue = nil;
+ browseDomainsArray = nil;
+ justStartedEditing = YES;
+ currentWideAreaState = NO;
+ NSString *successPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"success" ofType:@"tiff"];
+ NSString *inprogressPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"inprogress" ofType:@"tiff"];
+ NSString *failurePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"failure" ofType:@"tiff"];
+
+ registrationDataSource = [[NSMutableArray alloc] init];
+ browseDataSource = [[NSMutableArray alloc] init];
+ defaultBrowseDomainsArray = [[NSMutableArray alloc] init];
+ successImage = [[NSImage alloc] initWithContentsOfFile:successPath];
+ inprogressImage = [[NSImage alloc] initWithContentsOfFile:inprogressPath];
+ failureImage = [[NSImage alloc] initWithContentsOfFile:failurePath];
+
+ [tabView selectFirstTabViewItem:self];
+ [self setupInitialValues];
+ [self startDomainBrowsing];
+ [self watchForPreferenceChanges];
+
+ [tabView setDelegate:self];
+
+ InitConfigAuthority();
+ err = EnsureToolInstalled();
+ if (err == noErr) toolInstalled = YES;
+ else fprintf(stderr, "EnsureToolInstalled returned %ld\n", err);
+
+}
+
+
+- (IBAction)closeMyCustomSheet:(id)sender
+{
+ BOOL result = [sender isEqualTo:browseOKButton] || [sender isEqualTo:secretOKButton];
+
+ if (result) [NSApp endSheet:[sender window] returnCode:NSOKButton];
+ else [NSApp endSheet:[sender window] returnCode:NSCancelButton];
+}
+
+
+- (void)sharedSecretSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ NSButton * button = (NSButton *)contextInfo;
+ [sheet orderOut:self];
+ [self enableControls];
+
+ if (returnCode == NSOKButton) {
+ if ([button isEqualTo:hostNameSharedSecretButton]) {
+ hostNameSharedSecretName = [[NSString alloc] initWithString:[sharedSecretName stringValue]];
+ hostNameSharedSecretValue = [[NSString alloc] initWithString:[sharedSecretValue stringValue]];
+ } else {
+ regSharedSecretName = [[NSString alloc] initWithString:[sharedSecretName stringValue]];
+ regSharedSecretValue = [[NSString alloc] initWithString:[sharedSecretValue stringValue]];
+ }
+ [self updateApplyButtonState];
+ }
+ [sharedSecretValue setStringValue:@""];
+}
+
+
+- (BOOL)domainAlreadyInList:(NSString *)domainString
+{
+ if (browseDomainsArray) {
+ NSDictionary *domainDict;
+ NSString *domainName;
+ NSEnumerator *arrayEnumerator = [browseDomainsArray objectEnumerator];
+ while (domainDict = [arrayEnumerator nextObject]) {
+ domainName = [domainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ if ([domainString caseInsensitiveCompare:domainName] == NSOrderedSame) return YES;
+ }
+ }
+ return NO;
+}
+
+
+- (NSString *)trimCharactersFromDomain:(NSString *)domain
+{
+ NSMutableCharacterSet * trimSet = [[[NSCharacterSet whitespaceCharacterSet] mutableCopy] autorelease];
+ [trimSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
+ return [domain stringByTrimmingCharactersInSet:trimSet];
+}
+
+
+- (void)addBrowseDomainSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ [sheet orderOut:self];
+ [self enableControls];
+
+ if (returnCode == NSOKButton) {
+ NSString * newBrowseDomainString = [self trimCharactersFromDomain:[browseDomainsComboBox stringValue]];
+ NSMutableDictionary *newBrowseDomainDict;
+
+ if (browseDomainsArray == nil) browseDomainsArray = [[NSMutableArray alloc] initWithCapacity:0];
+ if ([self domainAlreadyInList:newBrowseDomainString] == NO) {
+ newBrowseDomainDict = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
+
+ [newBrowseDomainDict setObject:newBrowseDomainString forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ [newBrowseDomainDict setObject:[[[NSNumber alloc] initWithBool:YES] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+
+ [browseDomainsArray addObject:newBrowseDomainDict];
+ [browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil];
+ [browseDomainList reloadData];
+ [self updateApplyButtonState];
+ }
+ }
+}
+
+
+-(void)validateTextFields
+{
+ [hostName validateEditing];
+ [browseDomainsComboBox validateEditing];
+ [regDomainsComboBox validateEditing];
+}
+
+
+- (IBAction)changeButtonPressed:(id)sender
+{
+ NSString * keyName;
+
+ [self disableControls];
+ [self validateTextFields];
+ [mainWindow makeFirstResponder:nil];
+ [browseDomainList deselectAll:sender];
+
+ if ([sender isEqualTo:hostNameSharedSecretButton]) {
+ if (hostNameSharedSecretValue) {
+ [sharedSecretValue setStringValue:hostNameSharedSecretValue];
+ } else if (keyName = [self sharedSecretKeyName:[hostName stringValue]]) {
+ [sharedSecretName setStringValue:keyName];
+ [sharedSecretValue setStringValue:@"****************"];
+ } else {
+ [sharedSecretName setStringValue:[hostName stringValue]];
+ [sharedSecretValue setStringValue:@""];
+ }
+
+ } else {
+ if (regSharedSecretValue) {
+ [sharedSecretValue setStringValue:regSharedSecretValue];
+ } else if (keyName = [self sharedSecretKeyName:[regDomainsComboBox stringValue]]) {
+ [sharedSecretName setStringValue:keyName];
+ [sharedSecretValue setStringValue:@"****************"];
+ } else {
+ [sharedSecretName setStringValue:[regDomainsComboBox stringValue]];
+ [sharedSecretValue setStringValue:@""];
+ }
+ }
+
+ [sharedSecretWindow resignFirstResponder];
+
+ if ([[sharedSecretName stringValue] length] > 0) [sharedSecretWindow makeFirstResponder:sharedSecretValue];
+ else [sharedSecretWindow makeFirstResponder:sharedSecretName];
+
+ [NSApp beginSheet:sharedSecretWindow modalForWindow:mainWindow modalDelegate:self
+ didEndSelector:@selector(sharedSecretSheetDidEnd:returnCode:contextInfo:) contextInfo:sender];
+}
+
+
+- (IBAction)wideAreaCheckBoxChanged:(id)sender
+{
+ [self toggleWideAreaBonjour:[sender state]];
+ [self updateApplyButtonState];
+ [mainWindow makeFirstResponder:nil];
+}
+
+
+- (void)updateApplyButtonState
+{
+ NSString *hostNameString = [hostName stringValue];
+ NSString *regDomainString = [regDomainsComboBox stringValue];
+
+ NSComparisonResult hostNameResult = [hostNameString compare:currentHostName];
+ NSComparisonResult regDomainResult = [regDomainString compare:currentRegDomain];
+
+ if ((currentHostName && (hostNameResult != NSOrderedSame)) ||
+ (currentRegDomain && (regDomainResult != NSOrderedSame) && ([wideAreaCheckBox state])) ||
+ (currentHostName == nil && ([hostNameString length]) > 0) ||
+ (currentRegDomain == nil && ([regDomainString length]) > 0) ||
+ (currentWideAreaState != [wideAreaCheckBox state]) ||
+ (hostNameSharedSecretValue != nil) ||
+ (regSharedSecretValue != nil) ||
+ (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO))
+ {
+ [self enableApplyButton];
+ } else {
+ [self disableApplyButton];
+ }
+}
+
+
+
+- (void)controlTextDidChange:(NSNotification *)notification;
+{
+ [self updateApplyButtonState];
+}
+
+
+
+- (IBAction)comboAction:(id)sender;
+{
+ [self updateApplyButtonState];
+}
+
+
+- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index
+{
+ NSString *domain = nil;
+ if ([aComboBox isEqualTo:browseDomainsComboBox]) domain = [browseDataSource objectAtIndex:index];
+ else if ([aComboBox isEqualTo:regDomainsComboBox]) domain = [registrationDataSource objectAtIndex:index];
+ return domain;
+}
+
+
+
+- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
+{
+ int count = 0;
+ if ([aComboBox isEqualTo:browseDomainsComboBox]) count = [browseDataSource count];
+ else if ([aComboBox isEqualTo:regDomainsComboBox]) count = [registrationDataSource count];
+ return count;
+}
+
+
+- (NSMutableArray *)browseDataSource
+{
+ return browseDataSource;
+}
+
+
+- (NSMutableArray *)registrationDataSource
+{
+ return registrationDataSource;
+}
+
+
+- (NSComboBox *)browseDomainsComboBox
+{
+ return browseDomainsComboBox;
+}
+
+
+- (NSComboBox *)regDomainsComboBox
+{
+ return regDomainsComboBox;
+}
+
+
+- (NSString *)currentRegDomain
+{
+ return currentRegDomain;
+}
+
+
+- (NSMutableArray *)defaultBrowseDomainsArray
+{
+ return defaultBrowseDomainsArray;
+}
+
+
+- (NSArray *)currentBrowseDomainsArray
+{
+ return currentBrowseDomainsArray;
+}
+
+
+- (NSString *)currentHostName
+{
+ return currentHostName;
+}
+
+
+- (NSString *)defaultRegDomain
+{
+ return defaultRegDomain;
+}
+
+
+- (void)setDefaultRegDomain:(NSString *)domain
+{
+ [defaultRegDomain release];
+ defaultRegDomain = domain;
+ [defaultRegDomain retain];
+}
+
+
+- (void)didSelect
+{
+ [super didSelect];
+ mainWindow = [[self mainView] window];
+}
+
+
+- (void)mainViewDidLoad
+{
+ [comboAuthButton setString:"system.preferences"];
+ [comboAuthButton setDelegate:self];
+ [comboAuthButton updateStatus:nil];
+ [comboAuthButton setAutoupdate:YES];
+}
+
+
+
+- (IBAction)applyClicked:(id)sender
+{
+ [self applyCurrentState];
+}
+
+
+- (void)applyCurrentState
+{
+ [self validateTextFields];
+
+ if (toolInstalled == YES) {
+ [self savePreferences];
+ [self disableApplyButton];
+ [mainWindow makeFirstResponder:nil];
+ }
+}
+
+
+- (void)enableApplyButton
+{
+ [applyButton setEnabled:YES];
+ [revertButton setEnabled:YES];
+ prefsNeedUpdating = YES;
+}
+
+
+- (void)disableApplyButton
+{
+ [applyButton setEnabled:NO];
+ [revertButton setEnabled:NO];
+ prefsNeedUpdating = NO;
+}
+
+
+- (void)toggleWideAreaBonjour:(BOOL)state
+{
+ [wideAreaCheckBox setState:state];
+ [regDomainsComboBox setEnabled:state];
+ [registrationSharedSecretButton setEnabled:state];
+}
+
+
+- (IBAction)revertClicked:(id)sender;
+{
+ [self restorePreferences];
+ [browseDomainList deselectAll:sender];
+ [mainWindow makeFirstResponder:nil];
+}
+
+
+- (void)restorePreferences
+{
+ [self setupInitialValues];
+}
+
+
+- (void)savePanelWillClose:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)contextInfo;
+
+ if (returnCode == NSAlertDefaultReturn) {
+ [me applyCurrentState];
+ } else if (returnCode == NSAlertAlternateReturn ) {
+ [me restorePreferences];
+ }
+
+ [me enableControls];
+ [me replyToShouldUnselect:(returnCode != NSAlertOtherReturn)];
+}
+
+
+-(SecKeychainItemRef)copyKeychainItemforDomain:(NSString *)domain
+{
+ const char * serviceName = [domain UTF8String];
+ UInt32 type = 'ddns';
+ UInt32 typeLength = sizeof(type);
+
+ SecKeychainAttribute attrs[] = { { kSecServiceItemAttr, strlen(serviceName), (char *)serviceName },
+ { kSecTypeItemAttr, typeLength, (UInt32 *)&type } };
+
+ SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+ SecKeychainSearchRef searchRef;
+ SecKeychainItemRef itemRef = NULL;
+ OSStatus err;
+
+ err = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributes, &searchRef);
+ if (err == noErr) {
+ err = SecKeychainSearchCopyNext(searchRef, &itemRef);
+ if (err != noErr) itemRef = NULL;
+ }
+ return itemRef;
+}
+
+
+-(NSString *)sharedSecretKeyName:(NSString * )domain
+{
+ SecKeychainItemRef itemRef = NULL;
+ NSString *keyName = nil;
+ OSStatus err;
+
+ err = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+ assert(err == noErr);
+
+ itemRef = [self copyKeychainItemforDomain:[domain lowercaseString]];
+ if (itemRef) {
+ UInt32 tags[1];
+ SecKeychainAttributeInfo attrInfo;
+ SecKeychainAttributeList *attrList = NULL;
+ SecKeychainAttribute attribute;
+ int i;
+
+ tags[0] = kSecAccountItemAttr;
+ attrInfo.count = 1;
+ attrInfo.tag = tags;
+ attrInfo.format = NULL;
+
+ err = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrList, NULL, NULL);
+ if (err == noErr) {
+ for (i = 0; i < attrList->count; i++) {
+ attribute = attrList->attr[i];
+ if (attribute.tag == kSecAccountItemAttr) {
+ keyName = [[NSString alloc] initWithBytes:attribute.data length:attribute.length encoding:NSUTF8StringEncoding];
+ break;
+ }
+ }
+ if (attrList) (void)SecKeychainItemFreeAttributesAndData(attrList, NULL);
+ }
+ CFRelease(itemRef);
+ }
+ return keyName;
+}
+
+
+-(NSString *)domainForHostName:(NSString *)hostNameString
+{
+ NSString * domainName = nil;
+ char text[64];
+ char * ptr = NULL;
+
+ ptr = (char *)[hostNameString UTF8String];
+ if (ptr) {
+ ptr = (char *)GetNextLabel(ptr, text);
+ domainName = [[NSString alloc] initWithUTF8String:(const char *)ptr];
+ }
+ return ([domainName autorelease]);
+}
+
+
+- (NSData *)dataForDomain:(NSString *)domainName isEnabled:(BOOL)enabled
+{
+ NSMutableArray *domainsArray;
+ NSMutableDictionary *domainDict = nil;
+
+ if (domainName && [domainName length] > 0) {
+ domainDict= [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
+ [domainDict setObject:domainName forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ [domainDict setObject:[[[NSNumber alloc] initWithBool:enabled] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+ }
+ domainsArray = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
+ if (domainDict) [domainsArray addObject:domainDict];
+ return [NSArchiver archivedDataWithRootObject:domainsArray];
+}
+
+
+- (NSData *)dataForDomainArray:(NSArray *)domainArray
+{
+ return [NSArchiver archivedDataWithRootObject:domainArray];
+}
+
+
+- (NSData *)dataForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName
+{
+ NSMutableDictionary *sharedSecretDict = [[[NSMutableDictionary alloc] initWithCapacity:3] autorelease];
+ [sharedSecretDict setObject:secret forKey:(NSString *)SC_DYNDNS_SECRET_KEY];
+ [sharedSecretDict setObject:[domainName lowercaseString] forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ [sharedSecretDict setObject:keyName forKey:(NSString *)SC_DYNDNS_KEYNAME_KEY];
+ return [NSArchiver archivedDataWithRootObject:sharedSecretDict];
+}
+
+
+-(void)savePreferences
+{
+ NSString *hostNameString = [hostName stringValue];
+ NSString *browseDomainString = [browseDomainsComboBox stringValue];
+ NSString *regDomainString = [regDomainsComboBox stringValue];
+ NSString *tempHostNameSharedSecretName = hostNameSharedSecretName;
+ NSString *tempRegSharedSecretName = regSharedSecretName;
+ NSData *browseDomainData = nil;
+ BOOL regSecretWasSet = NO;
+ BOOL hostSecretWasSet = NO;
+ OSStatus err = noErr;
+
+ hostNameString = [self trimCharactersFromDomain:hostNameString];
+ browseDomainString = [self trimCharactersFromDomain:browseDomainString];
+ regDomainString = [self trimCharactersFromDomain:regDomainString];
+ tempHostNameSharedSecretName = [self trimCharactersFromDomain:tempHostNameSharedSecretName];
+ tempRegSharedSecretName = [self trimCharactersFromDomain:tempRegSharedSecretName];
+
+ [hostName setStringValue:hostNameString];
+ [regDomainsComboBox setStringValue:regDomainString];
+
+ // Convert Shared Secret account names to lowercase.
+ tempHostNameSharedSecretName = [tempHostNameSharedSecretName lowercaseString];
+ tempRegSharedSecretName = [tempRegSharedSecretName lowercaseString];
+
+ // Save hostname shared secret.
+ if ([hostNameSharedSecretName length] > 0 && ([hostNameSharedSecretValue length] > 0)) {
+ SetKeyForDomain((CFDataRef)[self dataForSharedSecret:hostNameSharedSecretValue domain:hostNameString key:tempHostNameSharedSecretName]);
+ [hostNameSharedSecretValue release];
+ hostNameSharedSecretValue = nil;
+ hostSecretWasSet = YES;
+ }
+
+ // Save registration domain shared secret.
+ if (([regSharedSecretName length] > 0) && ([regSharedSecretValue length] > 0)) {
+ SetKeyForDomain((CFDataRef)[self dataForSharedSecret:regSharedSecretValue domain:regDomainString key:tempRegSharedSecretName]);
+ [regSharedSecretValue release];
+ regSharedSecretValue = nil;
+ regSecretWasSet = YES;
+ }
+
+ // Save hostname.
+ if ((currentHostName == NULL) || [currentHostName compare:hostNameString] != NSOrderedSame) {
+ err = WriteHostname((CFDataRef)[self dataForDomain:hostNameString isEnabled:YES]);
+ if (err != noErr) NSLog(@"WriteHostname returned %d\n", err);
+ currentHostName = [hostNameString copy];
+ } else if (hostSecretWasSet) {
+ WriteHostname((CFDataRef)[self dataForDomain:@"" isEnabled:NO]);
+ usleep(200000); // Temporary hack
+ if ([currentHostName length] > 0) WriteHostname((CFDataRef)[self dataForDomain:(NSString *)currentHostName isEnabled:YES]);
+ }
+
+ // Save browse domain.
+ if (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) {
+ browseDomainData = [self dataForDomainArray:browseDomainsArray];
+ err = WriteBrowseDomain((CFDataRef)browseDomainData);
+ if (err != noErr) NSLog(@"WriteBrowseDomain returned %d\n", err);
+ currentBrowseDomainsArray = [browseDomainsArray copy];
+ }
+
+ // Save registration domain.
+ if ((currentRegDomain == NULL) || ([currentRegDomain compare:regDomainString] != NSOrderedSame) || (currentWideAreaState != [wideAreaCheckBox state])) {
+
+ err = WriteRegistrationDomain((CFDataRef)[self dataForDomain:regDomainString isEnabled:[wideAreaCheckBox state]]);
+ if (err != noErr) NSLog(@"WriteRegistrationDomain returned %d\n", err);
+
+ if (currentRegDomain) CFRelease(currentRegDomain);
+ currentRegDomain = [regDomainString copy];
+
+ if ([currentRegDomain length] > 0) {
+ currentWideAreaState = [wideAreaCheckBox state];
+ [registrationDataSource removeObject:regDomainString];
+ [registrationDataSource addObject:currentRegDomain];
+ [registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil];
+ [regDomainsComboBox reloadData];
+ } else {
+ currentWideAreaState = NO;
+ [self toggleWideAreaBonjour:NO];
+ if (defaultRegDomain != nil) [regDomainsComboBox setStringValue:defaultRegDomain];
+ }
+ } else if (regSecretWasSet) {
+ WriteRegistrationDomain((CFDataRef)[self dataForDomain:@"" isEnabled:NO]);
+ usleep(200000); // Temporary hack
+ if ([currentRegDomain length] > 0) WriteRegistrationDomain((CFDataRef)[self dataForDomain:currentRegDomain isEnabled:currentWideAreaState]);
+ }
+}
+
+
+- (NSPreferencePaneUnselectReply)shouldUnselect
+{
+#if 1
+ if (prefsNeedUpdating == YES) {
+
+ [self disableControls];
+
+ NSBeginAlertSheet(
+ @"Apply Configuration Changes?",
+ @"Apply",
+ @"Don't Apply",
+ @"Cancel",
+ mainWindow,
+ self,
+ @selector( savePanelWillClose:returnCode:contextInfo: ),
+ NULL,
+ (void *) self, // sender,
+ @"" );
+ return NSUnselectLater;
+ }
+#endif
+
+ return NSUnselectNow;
+}
+
+
+-(void)disableControls
+{
+ [hostName setEnabled:NO];
+ [hostNameSharedSecretButton setEnabled:NO];
+ [browseDomainsComboBox setEnabled:NO];
+ [applyButton setEnabled:NO];
+ [revertButton setEnabled:NO];
+ [wideAreaCheckBox setEnabled:NO];
+ [regDomainsComboBox setEnabled:NO];
+ [registrationSharedSecretButton setEnabled:NO];
+ [statusImageView setEnabled:NO];
+
+ browseDomainListEnabled = NO;
+ [browseDomainList deselectAll:self];
+ [browseDomainList setEnabled:NO];
+
+ [addBrowseDomainButton setEnabled:NO];
+ [removeBrowseDomainButton setEnabled:NO];
+}
+
+
+- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
+{
+ return browseDomainListEnabled;
+}
+
+
+-(void)enableControls
+{
+ [hostName setEnabled:YES];
+ [hostNameSharedSecretButton setEnabled:YES];
+ [browseDomainsComboBox setEnabled:YES];
+ [wideAreaCheckBox setEnabled:YES];
+ [registrationSharedSecretButton setEnabled:YES];
+ [self toggleWideAreaBonjour:[wideAreaCheckBox state]];
+ [statusImageView setEnabled:YES];
+ [addBrowseDomainButton setEnabled:YES];
+
+ [browseDomainList setEnabled:YES];
+ [browseDomainList deselectAll:self];
+ browseDomainListEnabled = YES;
+
+ [removeBrowseDomainButton setEnabled:[browseDomainList numberOfSelectedRows]];
+ [applyButton setEnabled:prefsNeedUpdating];
+ [revertButton setEnabled:prefsNeedUpdating];
+}
+
+
+- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view
+{
+ [self enableControls];
+}
+
+
+- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view
+{
+ [self disableControls];
+}
+
+
+@end
\ No newline at end of file
--- /dev/null
+{
+ IBClasses = (
+ {
+ ACTIONS = {
+ addBrowseDomainClicked = id;
+ applyClicked = id;
+ changeButtonPressed = id;
+ closeMyCustomSheet = id;
+ comboAction = id;
+ enableBrowseDomainClicked = id;
+ removeBrowseDomainClicked = id;
+ revertClicked = id;
+ wideAreaCheckBoxChanged = id;
+ };
+ CLASS = DNSServiceDiscoveryPref;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ addBrowseDomainButton = NSButton;
+ addBrowseDomainWindow = NSWindow;
+ applyButton = NSButton;
+ browseCancelButton = NSButton;
+ browseDomainList = NSTableView;
+ browseDomainsComboBox = NSComboBox;
+ browseOKButton = NSButton;
+ comboAuthButton = SFAuthorizationView;
+ hostName = NSTextField;
+ hostNameSharedSecretButton = NSButton;
+ regDomainsComboBox = NSComboBox;
+ registrationSharedSecretButton = NSButton;
+ removeBrowseDomainButton = NSButton;
+ revertButton = NSButton;
+ secretCancelButton = NSButton;
+ secretOKButton = NSButton;
+ sharedSecretName = NSTextField;
+ sharedSecretValue = NSSecureTextField;
+ sharedSecretWindow = NSWindow;
+ statusImageView = NSImageView;
+ tabView = NSTabView;
+ wideAreaCheckBox = NSButton;
+ };
+ SUPERCLASS = NSPreferencePane;
+ },
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ CLASS = NSPreferencePane;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ "_firstKeyView" = id;
+ "_initialKeyView" = id;
+ "_lastKeyView" = id;
+ "_window" = id;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {CLASS = NSSegmentedControl; LANGUAGE = ObjC; SUPERCLASS = NSControl; },
+ {CLASS = SFAuthorizationView; LANGUAGE = ObjC; SUPERCLASS = NSView; }
+ );
+ IBVersion = 1;
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>32 63 547 281 0 0 1024 746 </string>
+ <key>IBFramework Version</key>
+ <string>364.0</string>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>12</integer>
+ <integer>255</integer>
+ <integer>333</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>7U13</string>
+</dict>
+</plist>
--- /dev/null
+/*
+ File: PrivilegedOperations.c
+
+ Abstract: Interface to "ddnswriteconfig" setuid root tool.
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+$Log: PrivilegedOperations.c,v $
+Revision 1.2 2005/02/10 22:35:20 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.1 2005/02/05 01:59:19 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#include "PrivilegedOperations.h"
+#include "ConfigurationAuthority.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <AssertMacros.h>
+#include <Security/Security.h>
+
+Boolean gToolApproved = false;
+
+pid_t execTool(const char *args[])
+// fork/exec and return new pid
+{
+ pid_t child;
+
+ child = vfork();
+ if (child == 0)
+ {
+ execv(args[0], (char *const *)args);
+printf("exec of %s failed; errno = %d\n", args[0], errno);
+ _exit(-1); // exec failed
+ }
+ else
+ return child;
+}
+
+OSStatus EnsureToolInstalled(void)
+// Make sure that the tool is installed in the right place, with the right privs, and the right version.
+{
+ CFURLRef bundleURL;
+ pid_t toolPID;
+ int status;
+ OSStatus err = noErr;
+ const char *args[] = { kToolPath, "0", "V", NULL };
+ char toolPath[PATH_MAX] = {};
+
+ if (gToolApproved)
+ return noErr;
+
+ // Check version of installed tool
+ toolPID = execTool(args);
+ if (toolPID > 0)
+ {
+ waitpid(toolPID, &status, 0);
+ if (WIFEXITED(status) && WEXITSTATUS(status) == PRIV_OP_TOOL_VERS)
+ return noErr;
+ }
+
+ // Locate our in-bundle copy of privop tool
+ bundleURL = CFBundleCopyBundleURL(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.preference.bonjour")) );
+ if (bundleURL != NULL)
+ {
+ CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolPath, sizeof toolPath);
+ strcat(toolPath, "/Contents/Resources/" kToolName);
+ }
+ else
+ return coreFoundationUnknownErr;
+
+ // Obtain authorization and run in-bundle copy as root to install it
+ {
+ AuthorizationItem aewpRight = { kAuthorizationRightExecute, strlen(toolPath), toolPath, 0 };
+ AuthorizationItemSet rights = { 1, &aewpRight };
+ AuthorizationRef authRef;
+
+ err = AuthorizationCreate(&rights, (AuthorizationEnvironment*) NULL,
+ kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights |
+ kAuthorizationFlagPreAuthorize, &authRef);
+ if (err == noErr)
+ {
+ args[2] = "I";
+ err = AuthorizationExecuteWithPrivileges(authRef, toolPath, 0, (char * const *)&args[1], (FILE**) NULL);
+ if (err == noErr)
+ gToolApproved = true;
+ (void) AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
+ }
+ }
+
+ return err;
+}
+
+
+static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData)
+// Execute our privop tool with the supplied subCmd and parameter
+{
+ OSStatus err = noErr;
+ int commFD, dataLen;
+ u_int32_t len;
+ pid_t child;
+ char fileNum[16];
+ UInt8 *buff;
+ const char *args[] = { kToolPath, NULL, "A", NULL, NULL };
+ AuthorizationExternalForm authExt;
+
+ err = ExternalizeAuthority(&authExt);
+ require_noerr(err, AuthFailed);
+
+ dataLen = CFDataGetLength(paramData);
+ buff = (UInt8*) malloc(dataLen * sizeof(UInt8));
+ require_action(buff != NULL, AllocBuffFailed, err=memFullErr;);
+ {
+ CFRange all = { 0, dataLen };
+ CFDataGetBytes(paramData, all, buff);
+ }
+
+ commFD = fileno(tmpfile());
+ sprintf(fileNum, "%d", commFD);
+ args[1] = fileNum;
+ args[3] = subCmd;
+
+ // write authority to pipe
+ len = 0; // tag, unused
+ write(commFD, &len, sizeof len);
+ len = sizeof authExt; // len
+ write(commFD, &len, sizeof len);
+ write(commFD, &authExt, len);
+
+ // write parameter to pipe
+ len = 0; // tag, unused
+ write(commFD, &len, sizeof len);
+ len = dataLen; // len
+ write(commFD, &len, sizeof len);
+ write(commFD, buff, len);
+
+ child = execTool(args);
+ if (child > 0) {
+ int status;
+ waitpid(child, &status, 0);
+ if (WIFEXITED(status))
+ err = WEXITSTATUS(status);
+ //fprintf(stderr, "child exited; status = %d (%ld)\n", status, err);
+ }
+
+ close(commFD);
+
+ free(buff);
+AllocBuffFailed:
+AuthFailed:
+ return err;
+}
+
+OSStatus
+WriteBrowseDomain(CFDataRef domainArrayData)
+{
+ if (!CurrentlyAuthorized())
+ return authFailErr;
+ return ExecWithCmdAndParam("Wb", domainArrayData);
+}
+
+OSStatus
+WriteRegistrationDomain(CFDataRef domainArrayData)
+{
+ if (!CurrentlyAuthorized())
+ return authFailErr;
+ return ExecWithCmdAndParam("Wd", domainArrayData);
+}
+
+OSStatus
+WriteHostname(CFDataRef domainArrayData)
+{
+ if (!CurrentlyAuthorized())
+ return authFailErr;
+ return ExecWithCmdAndParam("Wh", domainArrayData);
+}
+
+OSStatus
+SetKeyForDomain(CFDataRef secretData)
+{
+ if (!CurrentlyAuthorized())
+ return authFailErr;
+ return ExecWithCmdAndParam("Wk", secretData);
+}
--- /dev/null
+/*
+ File: PrivilegedOperations.h
+
+ Abstract: Interface to "ddnswriteconfig" setuid root tool.
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+$Log: PrivilegedOperations.h,v $
+Revision 1.3 2005/02/16 00:17:35 cheshire
+Don't create empty arrays -- CFArrayGetValueAtIndex(array,0) returns an essentially random (non-null)
+result for empty arrays, which can lead to code crashing if it's not sufficiently defensive.
+
+Revision 1.2 2005/02/10 22:35:20 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.1 2005/02/05 01:59:19 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+#include <CoreServices/CoreServices.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#define PRIV_OP_TOOL_VERS 2
+
+#define kToolHome "/Library/Application Support/"
+#define kToolDir "Bonjour"
+#define kToolName "ddnswriteconfig"
+#define kToolPath kToolHome kToolDir "/" kToolName
+
+#define SC_DYNDNS_SETUP_KEY CFSTR("Setup:/Network/DynamicDNS")
+#define SC_DYNDNS_STATE_KEY CFSTR("State:/Network/DynamicDNS")
+#define SC_DYNDNS_REGDOMAINS_KEY CFSTR("RegistrationDomains")
+#define SC_DYNDNS_BROWSEDOMAINS_KEY CFSTR("BrowseDomains")
+#define SC_DYNDNS_HOSTNAMES_KEY CFSTR("HostNames")
+#define SC_DYNDNS_DOMAIN_KEY CFSTR("Domain")
+#define SC_DYNDNS_KEYNAME_KEY CFSTR("KeyName")
+#define SC_DYNDNS_SECRET_KEY CFSTR("Secret")
+#define SC_DYNDNS_ENABLED_KEY CFSTR("Enabled")
+#define SC_DYNDNS_STATUS_KEY CFSTR("Status")
+#define DYNDNS_KEYCHAIN_DESCRIPTION "Dynamic DNS Key"
+
+
+OSStatus EnsureToolInstalled(void);
+OSStatus WriteRegistrationDomain(CFDataRef domainArrayData);
+OSStatus WriteBrowseDomain(CFDataRef domainArrayData);
+OSStatus WriteHostname(CFDataRef domainArrayData);
+OSStatus SetKeyForDomain(CFDataRef secretData);
--- /dev/null
+/*
+ File: ddnswriteconfig.m
+
+ Abstract: Setuid root tool invoked by Preference Pane to perform
+ privileged accesses to system configuration preferences and the system keychain.
+ Invoked by PrivilegedOperations.c.
+
+ Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+$Log: ddnswriteconfig.m,v $
+Revision 1.3 2005/02/16 00:17:35 cheshire
+Don't create empty arrays -- CFArrayGetValueAtIndex(array,0) returns an essentially random (non-null)
+result for empty arrays, which can lead to code crashing if it's not sufficiently defensive.
+
+Revision 1.2 2005/02/10 22:35:20 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.1 2005/02/05 01:59:19 cheshire
+Add Preference Pane to facilitate testing of DDNS & wide-area features
+
+*/
+
+
+#import "PrivilegedOperations.h"
+#import "ConfigurationRights.h"
+
+#import <stdio.h>
+#import <stdint.h>
+#import <stdlib.h>
+#import <unistd.h>
+#import <fcntl.h>
+#import <errno.h>
+#import <sys/types.h>
+#import <sys/stat.h>
+#import <sys/mman.h>
+#import <mach-o/dyld.h>
+#import <AssertMacros.h>
+#import <Security/Security.h>
+#import <CoreServices/CoreServices.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+#import <Foundation/Foundation.h>
+
+
+static AuthorizationRef gAuthRef = 0;
+
+int
+CopySUIDTool(const char *srcPath, const char *dstPath)
+// Copy a tool from srcPath to dstPath and set its 'x' and SUID bits. Return 0 on success.
+{
+ int srcFD, dstFD, err = 0;
+ off_t len, written;
+ void *pSrc;
+
+ srcFD = open( srcPath, O_RDONLY, (mode_t) 0);
+ require_action( srcFD > 0, OpenSrcFailed, err=errno;);
+
+ len = lseek( srcFD, 0, SEEK_END);
+ require_action( len > 0, GetSrcLenFailed, err=errno;);
+ pSrc = mmap( NULL, len, PROT_READ, MAP_FILE, srcFD, 0);
+ require_action( pSrc != (void*)-1, MMapFailed, err=errno;);
+
+ dstFD = open( dstPath, O_RDWR | O_CREAT | O_TRUNC, (mode_t) 0);
+ require_action( dstFD > 0, OpenDstFailed, err=errno;);
+
+ written = write( dstFD, pSrc, len);
+ require_action( written == len, WriteFailed, err=errno;);
+
+ err = fchmod( dstFD, S_IRUSR | S_IXUSR | S_ISUID | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+
+WriteFailed:
+ close( dstFD);
+OpenDstFailed:
+ munmap( pSrc, len);
+MMapFailed:
+GetSrcLenFailed:
+ close( srcFD);
+OpenSrcFailed:
+ return err;
+}
+
+
+int
+InstallRootTool( const char *srcPath)
+{
+ if (geteuid() != 0)
+ return -1; // failure; not running as root
+
+ (void) mkdir(kToolHome kToolDir, S_IRUSR | S_IXUSR | S_IWUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+
+ return CopySUIDTool( srcPath, kToolPath);
+}
+
+
+OSStatus
+WriteArrayToDynDNS(CFStringRef arrayKey, CFArrayRef domainArray)
+{
+ SCPreferencesRef store;
+ OSStatus err = noErr;
+ CFDictionaryRef origDict;
+ CFMutableDictionaryRef dict = NULL;
+ Boolean result;
+ CFStringRef scKey = CFSTR("/System/Network/DynamicDNS");
+
+
+ // Add domain to the array member ("arrayKey") of the DynamicDNS dictionary
+ // Will replace duplicate, at head of list
+ // At this point, we only support a single-item list
+ store = SCPreferencesCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL);
+ require_action(store != NULL, SysConfigErr, err=paramErr;);
+ require_action(true == SCPreferencesLock( store, true), LockFailed, err=coreFoundationUnknownErr;);
+
+ origDict = SCPreferencesPathGetValue(store, scKey);
+ if (origDict) {
+ dict = CFDictionaryCreateMutableCopy(NULL, 0, origDict);
+ }
+
+ if (!dict) {
+ dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ }
+ require_action( dict != NULL, NoDict, err=memFullErr;);
+
+ if (CFArrayGetCount(domainArray) > 0) {
+ CFDictionarySetValue(dict, arrayKey, domainArray);
+ } else {
+ CFDictionaryRemoveValue(dict, arrayKey);
+ }
+
+ result = SCPreferencesPathSetValue(store, scKey, dict);
+ require_action(result, SCError, err=kernelPrivilegeErr;);
+
+ result = SCPreferencesCommitChanges(store);
+ require_action(result, SCError, err=kernelPrivilegeErr;);
+ result = SCPreferencesApplyChanges(store);
+ require_action(result, SCError, err=kernelPrivilegeErr;);
+
+SCError:
+ CFRelease(dict);
+NoDict:
+ SCPreferencesUnlock(store);
+LockFailed:
+ CFRelease(store);
+SysConfigErr:
+ return err;
+}
+
+
+static int
+readTaggedBlock(int fd, u_int32_t *pTag, u_int32_t *pLen, char **ppBuff)
+// Read tag, block len and block data from stream and return. Dealloc *ppBuff via free().
+{
+ ssize_t num;
+ u_int32_t tag, len;
+ int result = 0;
+
+ num = read(fd, &tag, sizeof tag);
+ require_action(num == sizeof tag, GetTagFailed, result = -1;);
+ num = read(fd, &len, sizeof len);
+ require_action(num == sizeof len, GetLenFailed, result = -1;);
+
+ *ppBuff = (char*) malloc( len);
+ require_action(*ppBuff != NULL, AllocFailed, result = -1;);
+
+ num = read(fd, *ppBuff, len);
+ if (num == len) {
+ *pTag = tag;
+ *pLen = len;
+ } else {
+ free(*ppBuff);
+ result = -1;
+ }
+
+AllocFailed:
+GetLenFailed:
+GetTagFailed:
+ return result;
+}
+
+
+
+int
+SetAuthInfo( int fd)
+{
+ int result = 0;
+ u_int32_t tag, len;
+ char *p;
+
+ result = readTaggedBlock( fd, &tag, &len, &p);
+ require( result == 0, ReadParamsFailed);
+
+ if (gAuthRef != 0) {
+ (void) AuthorizationFree(gAuthRef, kAuthorizationFlagDestroyRights);
+ gAuthRef = 0;
+ }
+
+ result = AuthorizationCreateFromExternalForm((AuthorizationExternalForm*) p, &gAuthRef);
+
+ free( p);
+ReadParamsFailed:
+ return result;
+}
+
+
+int
+HandleWriteDomain(int fd, int domainType)
+{
+ CFArrayRef domainArray;
+ CFDataRef domainData;
+ int result = 0;
+ u_int32_t tag, len;
+ char *p;
+
+ AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 };
+ AuthorizationRights authSet = { 1, &scAuth };
+
+ if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL)))
+ return result;
+
+ result = readTaggedBlock(fd, &tag, &len, &p);
+ require(result == 0, ReadParamsFailed);
+
+ domainData = CFDataCreate(NULL, (UInt8 *)p, len);
+ domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData];
+
+ if (domainType) {
+ result = WriteArrayToDynDNS(SC_DYNDNS_REGDOMAINS_KEY, domainArray);
+ } else {
+ result = WriteArrayToDynDNS(SC_DYNDNS_BROWSEDOMAINS_KEY, domainArray);
+ }
+
+ReadParamsFailed:
+ return result;
+}
+
+
+int
+HandleWriteHostname(int fd)
+{
+ CFArrayRef domainArray;
+ CFDataRef domainData;
+ int result = 0;
+ u_int32_t tag, len;
+ char *p;
+
+ AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 };
+ AuthorizationRights authSet = { 1, &scAuth };
+
+ if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags) 0, NULL)))
+ return result;
+
+ result = readTaggedBlock(fd, &tag, &len, &p);
+ require(result == 0, ReadParamsFailed);
+
+ domainData = CFDataCreate(NULL, (const UInt8 *)p, len);
+ domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData];
+ result = WriteArrayToDynDNS(SC_DYNDNS_HOSTNAMES_KEY, domainArray);
+
+ReadParamsFailed:
+ return result;
+}
+
+
+SecAccessRef
+MyMakeUidAccess(uid_t uid)
+{
+ // make the "uid/gid" ACL subject
+ // this is a CSSM_LIST_ELEMENT chain
+ CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
+ CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
+ CSSM_ACL_MATCH_UID, // set mask: match uids (only)
+ uid, // uid to match
+ 0 // gid (not matched here)
+ };
+ CSSM_LIST_ELEMENT subject2 = { NULL, 0 };
+ subject2.Element.Word.Data = (UInt8 *)&selector;
+ subject2.Element.Word.Length = sizeof(selector);
+ CSSM_LIST_ELEMENT subject1 = { &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID };
+
+
+ // rights granted (replace with individual list if desired)
+ CSSM_ACL_AUTHORIZATION_TAG rights[] = {
+ CSSM_ACL_AUTHORIZATION_ANY // everything
+ };
+ // owner component (right to change ACL)
+ CSSM_ACL_OWNER_PROTOTYPE owner = {
+ // TypedSubject
+ { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
+ // Delegate
+ false
+ };
+ // ACL entries (any number, just one here)
+ CSSM_ACL_ENTRY_INFO acls[] = {
+ {
+ // prototype
+ {
+ // TypedSubject
+ { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
+ false, // Delegate
+ // rights for this entry
+ { sizeof(rights) / sizeof(rights[0]), rights },
+ // rest is defaulted
+ }
+ }
+ };
+
+ SecAccessRef access = NULL;
+ (void) SecAccessCreateFromOwnerAndACL(&owner, sizeof(acls) / sizeof(acls[0]), acls, &access);
+ return access;
+}
+
+
+OSStatus
+MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef access, UInt32 serviceNameLength, const char *serviceName,
+ UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
+{
+ char * description = DYNDNS_KEYCHAIN_DESCRIPTION;
+ UInt32 descriptionLength = strlen(DYNDNS_KEYCHAIN_DESCRIPTION);
+ UInt32 type = 'ddns';
+ UInt32 creator = 'ddns';
+ UInt32 typeLength = sizeof(type);
+ UInt32 creatorLength = sizeof(creator);
+ OSStatus err;
+
+ // set up attribute vector (each attribute consists of {tag, length, pointer})
+ SecKeychainAttribute attrs[] = { { kSecLabelItemAttr, serviceNameLength, (char *)serviceName },
+ { kSecAccountItemAttr, accountNameLength, (char *)accountName },
+ { kSecServiceItemAttr, serviceNameLength, (char *)serviceName },
+ { kSecDescriptionItemAttr, descriptionLength, (char *)description },
+ { kSecTypeItemAttr, typeLength, (UInt32 *)&type },
+ { kSecCreatorItemAttr, creatorLength, (UInt32 *)&creator } };
+ SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+
+ err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, access, NULL);
+ return err;
+}
+
+
+int
+SetKeychainEntry(int fd)
+// Create a new entry in system keychain, or replace existing
+{
+ CFDataRef secretData;
+ CFDictionaryRef secretDictionary;
+ CFStringRef keyNameString;
+ CFStringRef domainString;
+ CFStringRef secretString;
+ SecKeychainItemRef item = NULL;
+ int result = 0;
+ u_int32_t tag, len;
+ char *p;
+ char keyname[1005];
+ char domain[1005];
+ char secret[1005];
+
+ AuthorizationItem kcAuth = { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 };
+ AuthorizationRights authSet = { 1, &kcAuth };
+
+ if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL)))
+ return result;
+
+ result = readTaggedBlock(fd, &tag, &len, &p);
+ require_noerr(result, ReadParamsFailed);
+
+ secretData = CFDataCreate(NULL, (UInt8 *)p, len);
+ secretDictionary = (CFDictionaryRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)secretData];
+
+ keyNameString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_KEYNAME_KEY);
+ assert(keyNameString != NULL);
+
+ domainString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_DOMAIN_KEY);
+ assert(domainString != NULL);
+
+ secretString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_SECRET_KEY);
+ assert(secretString != NULL);
+
+ CFStringGetCString(keyNameString, keyname, 1005, kCFStringEncodingUTF8);
+ CFStringGetCString(domainString, domain, 1005, kCFStringEncodingUTF8);
+ CFStringGetCString(secretString, secret, 1005, kCFStringEncodingUTF8);
+
+ result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+ if (result == noErr) {
+ result = SecKeychainFindGenericPassword(NULL, strlen(domain), domain, 0, NULL, 0, NULL, &item);
+ if (result == noErr) {
+ result = SecKeychainItemDelete(item);
+ if (result != noErr) fprintf(stderr, "SecKeychainItemDelete returned %d\n", result);
+ }
+
+ result = MyAddDynamicDNSPassword(NULL, MyMakeUidAccess(0), strlen(domain), domain, strlen(keyname)+1, keyname, strlen(secret)+1, secret);
+ if (result != noErr) fprintf(stderr, "MyAddDynamicDNSPassword returned %d\n", result);
+ if (item) CFRelease(item);
+ }
+
+ReadParamsFailed:
+ return result;
+}
+
+
+int main( int argc, char **argv)
+/* argv[0] is the exec path; argv[1] is a fd for input data; argv[2]... are operation codes.
+ The tool supports the following operations:
+ V -- exit with status PRIV_OP_TOOL_VERS
+ I -- install self as suid-root tool into system (must be run as root)
+ A -- read AuthInfo from input pipe
+ Wd -- write registration domain to dynamic store
+ Wb -- write browse domain to dynamic store
+ Wh -- write hostname to dynamic store
+ Wk -- write keychain entry for given account name
+*/
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ int commFD = -1, iArg, savedUID, result = 0;
+
+ if ( argc == 3 && 0 == strcmp( argv[2], "I")) {
+ return InstallRootTool( argv[0]);
+ }
+
+ savedUID = geteuid();
+#if 1
+ if ( 0 != seteuid( 0))
+ return -1;
+#else
+ sleep( 10);
+#endif
+
+ if ( argc == 3 && 0 == strcmp( argv[2], "V"))
+ return PRIV_OP_TOOL_VERS;
+
+ if ( argc >= 1)
+ {
+ commFD = strtol( argv[1], NULL, 0);
+ lseek( commFD, 0, SEEK_SET);
+ }
+ for ( iArg = 2; iArg < argc && result == 0; iArg++)
+ {
+ if ( 0 == strcmp( "A", argv[ iArg])) // get auth info
+ {
+ result = SetAuthInfo( commFD);
+ }
+ else if ( 0 == strcmp( "Wd", argv[ iArg])) // Write registration domain
+ {
+ result = HandleWriteDomain( commFD, 1);
+ }
+ else if ( 0 == strcmp( "Wb", argv[ iArg])) // Write browse domain
+ {
+ result = HandleWriteDomain( commFD, 0);
+ }
+ else if ( 0 == strcmp( "Wh", argv[ iArg])) // Write hostname
+ {
+ result = HandleWriteHostname( commFD);
+ }
+ else if ( 0 == strcmp( "Wk", argv[ iArg])) // Write keychain entry
+ {
+ result = SetKeychainEntry( commFD);
+ }
+ }
+ [pool release];
+ return result;
+}
Change History (most recent first):
$Log: daemon.c,v $
+Revision 1.255 2005/03/09 00:48:43 cheshire
+<rdar://problem/4015157> QU packets getting sent too early on wake from sleep
+Move "m->p->NetworkChanged = 0;" line from caller to callee
+
+Revision 1.254 2005/03/03 04:34:19 cheshire
+<rdar://problem/4025973> Bonjour name conflict dialog appears during MacBuddy
+
+Revision 1.253 2005/03/03 03:55:09 cheshire
+<rdar://problem/3862944> Name collision notifications should be localized
+
+Revision 1.252 2005/02/23 02:29:17 cheshire
+<rdar://problem/4005191> "Local Hostname is already in use..." dialogue shows for only 60 seconds before being removed
+Minor refinements, better variable names, improved comments
+
+Revision 1.251 2005/02/21 21:31:24 ksekar
+<rdar://problem/4015162> changed LogMsg to debugf
+
+Revision 1.250 2005/02/19 01:25:04 cheshire
+<rdar://problem/4005191> "Local Hostname is already in use..." dialogue shows for only 60 seconds before being removed
+Further refinements
+
+Revision 1.249 2005/02/19 00:28:45 cheshire
+<rdar://problem/4005191> "Local Hostname is already in use..." dialogue shows for only 60 seconds before being removed
+
+Revision 1.248 2005/02/19 00:18:34 cheshire
+Confusing variable name -- alertMessage should be called alertHeader
+
+Revision 1.247 2005/02/15 02:13:49 cheshire
+If we did registerBootstrapService() when starting, then we must do
+destroyBootstrapService() before exiting, or Mach init will keep restarting us.
+
+Revision 1.246 2005/02/03 00:44:37 cheshire
+<rdar://problem/3986663> DNSServiceUpdateRecord returns kDNSServiceErr_Invalid when rdlen=0, rdata=NULL
+
+Revision 1.245 2005/02/01 19:56:47 ksekar
+Moved LogMsg from daemon.c to uds_daemon.c, cleaned up wording
+
Revision 1.244 2005/01/28 00:34:49 cheshire
Turn off "Starting time value" log message
static int restarting_via_mach_init = 0;
static int started_via_launchdaemon = 0;
+static int OSXVers;
+
//*************************************************************************************************************
// Active client list structures
char _malloc_options[] = "AXZ";
-static void validatelists(mDNS *const m)
+mDNSlocal void validatelists(mDNS *const m)
{
DNSServiceDomainEnumeration *e;
DNSServiceBrowser *b;
{
DNSServiceRegistration *reg;
- LogMsg("%s default registration domain %##s", add ? "Adding" : "Removing", d->c);
for (reg = DNSServiceRegistrationList; reg; reg = reg->next)
{
if (reg->DefaultDomain)
prev = si;
si = si->next;
}
- if (!si) LogMsg("Requested removal of default domain %##s not in client %5d's list", d, reg->ClientMachPort);
+ if (!si) debugf("Requested removal of default domain %##s not in client %5d's list", d, reg->ClientMachPort); // normal if registration failed
}
}
}
return(err);
}
+mDNSlocal CFUserNotificationRef gNotification = NULL;
+mDNSlocal CFRunLoopSourceRef gNotificationRLS = NULL;
+mDNSlocal domainlabel gNotificationPrefHostLabel; // The prefs as they were the last time we saw them
+mDNSlocal domainlabel gNotificationPrefNiceLabel;
+mDNSlocal domainlabel gNotificationUserHostLabel; // The prefs as they were the last time the user changed them
+mDNSlocal domainlabel gNotificationUserNiceLabel;
+
+mDNSlocal void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
+ {
+ (void)responseFlags; // Unused
+ if (userNotification != gNotification) LogMsg("NotificationCallBackDismissed: Wrong CFUserNotificationRef");
+ if (gNotificationRLS)
+ {
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), gNotificationRLS, kCFRunLoopDefaultMode);
+ CFRelease(gNotificationRLS);
+ gNotificationRLS = NULL;
+ CFRelease(gNotification);
+ gNotification = NULL;
+ }
+ // By dismissing the alert, the user has conceptually acknowleged the rename.
+ // (e.g. the machine's name is now officially "computer-2.local", not "computer.local".)
+ // If we get *another* conflict, the new alert should refer to the 'old'.
+ // name as now being "computer-2.local", not "computer.local"
+ gNotificationUserHostLabel = gNotificationPrefHostLabel;
+ gNotificationUserNiceLabel = gNotificationPrefNiceLabel;
+ }
+
+mDNSlocal void ShowNameConflictNotification(CFStringRef header, CFStringRef subtext)
+ {
+ CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (!dictionary) return;
+ CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header);
+ CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext);
+
+ CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/CoreServices/mDNSResponder.bundle"), kCFURLPOSIXPathStyle, true);
+ if (urlRef) { CFDictionarySetValue(dictionary, kCFUserNotificationLocalizationURLKey, urlRef); CFRelease(urlRef); }
+
+ if (gNotification) // If notification already on-screen, update it in place
+ CFUserNotificationUpdate(gNotification, 0, kCFUserNotificationCautionAlertLevel, dictionary);
+ else // else, we need to create it
+ {
+ SInt32 error;
+ gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary);
+ if (!gNotification) { LogMsg("ShowNameConflictNotification: CFUserNotificationRef"); return; }
+ gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0);
+ if (!gNotificationRLS) { LogMsg("ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; }
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), gNotificationRLS, kCFRunLoopDefaultMode);
+ }
+
+ CFRelease(dictionary);
+ }
+
// This updates either the text of the field currently labelled "Local Hostname",
// or the text of the field currently labelled "Computer Name"
// in the Sharing Prefs Control Panel
-mDNSlocal void RecordUpdatedName(const mDNS *const m, domainlabel *n1, domainlabel *n2, char *msg, char *suffix, CFStringRef subtext)
+mDNSlocal void RecordUpdatedName(const mDNS *const m, const domainlabel *const olddl, const domainlabel *const newdl,
+ const char *const msg, const char *const suffix, const CFStringRef subtext)
{
char oldname[MAX_DOMAIN_LABEL+1];
char newname[MAX_DOMAIN_LABEL+1];
- ConvertDomainLabelToCString_unescaped(n1, oldname);
- ConvertDomainLabelToCString_unescaped(n2, newname);
- const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname, kCFStringEncodingUTF8);
- const CFStringRef cfnewname = CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8);
- const CFStringRef f1 = CFStringCreateWithCString(NULL, "“%@%s”", kCFStringEncodingUTF8);
- const CFStringRef f2 = CFStringCreateWithCString(NULL, "“%@%s”", kCFStringEncodingUTF8);
+ ConvertDomainLabelToCString_unescaped(olddl, oldname);
+ ConvertDomainLabelToCString_unescaped(newdl, newname);
+ const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname, kCFStringEncodingUTF8);
+ const CFStringRef cfnewname = CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8);
+ const CFStringRef f1 = CFStringCreateWithCString(NULL, " “%@%s” ", kCFStringEncodingUTF8);
+ const CFStringRef f2 = CFStringCreateWithCString(NULL, " “%@%s” ", kCFStringEncodingUTF8);
const SCPreferencesRef session = SCPreferencesCreate(NULL, CFSTR("mDNSResponder"), NULL);
- *n1 = *n2;
if (!cfoldname || !cfnewname || !f1 || !f2 || !session || !SCPreferencesLock(session, 0)) // If we can't get the lock don't wait
LogMsg("RecordUpdatedName: ERROR: Couldn't create SCPreferences session");
else
const CFStringRef s0 = CFStringCreateWithCString(NULL, msg, kCFStringEncodingUTF8);
const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, f1, cfoldname, suffix);
const CFStringRef s2 = CFStringCreateWithFormat(NULL, NULL, f2, cfnewname, suffix);
-// const CFMutableArrayRef alertMessage = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- const CFMutableStringRef alertMessage = CFStringCreateMutable(NULL, 0);
+ // On Tiger and later, if we pass an array instead of a string, CFUserNotification will translate each
+ // element of the array individually for us, and then concatenate the results to make the final message.
+ // This lets us have the relevant bits localized, but not the literal names, which should not be translated.
+ // On Panther this does not work, so we just build the string directly, and it will not be translated.
+ const CFMutableStringRef alertHeader =
+ (OSXVers < 8) ? CFStringCreateMutable(NULL, 0) : (CFMutableStringRef)CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
Boolean result;
- if (n2 == &m->hostlabel) result = SCPreferencesSetLocalHostName(session, cfnewname);
- else result = SCPreferencesSetComputerName(session, cfnewname, kCFStringEncodingUTF8);
- if (!result || !SCPreferencesCommitChanges(session) || !SCPreferencesApplyChanges(session) || !s0 || !s1 || !s2 || !alertMessage)
+ if (newdl == &gNotificationPrefHostLabel) result = SCPreferencesSetLocalHostName(session, cfnewname);
+ else result = SCPreferencesSetComputerName(session, cfnewname, kCFStringEncodingUTF8);
+ if (!result || !SCPreferencesCommitChanges(session) || !SCPreferencesApplyChanges(session) || !s0 || !s1 || !s2 || !alertHeader)
LogMsg("RecordUpdatedName: ERROR: Couldn't update SCPreferences");
else if (m->p->NotifyUser)
{
-// CFArrayAppendValue(alertMessage, s0);
- CFStringAppend(alertMessage, s0);
- CFStringAppend(alertMessage, s1);
- CFStringAppend(alertMessage, CFSTR(" is already in use on this network. The name has been changed to "));
- CFStringAppend(alertMessage, s2);
- CFStringAppend(alertMessage, CFSTR(" automatically."));
- CFUserNotificationDisplayNotice(60.0, // Auto-dismiss after 60 seconds
- kCFUserNotificationCautionAlertLevel,
- NULL, NULL, NULL, // iconURL, soundURL, localizationURL
- (CFStringRef)alertMessage, subtext, NULL); // alertHeader, alertMessage, defaultButtonTitle
+ uid_t uid;
+ gid_t gid;
+ CFStringRef userName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid);
+ if (userName)
+ {
+ CFRelease(userName);
+ typedef void CFStringAppendFN(CFMutableStringRef theString, CFStringRef appendedString);
+ CFStringAppendFN *const append = (OSXVers < 8) ? &CFStringAppend : (CFStringAppendFN*)&CFArrayAppendValue;
+ append(alertHeader, s0);
+ append(alertHeader, s1);
+ append(alertHeader, CFSTR("is already in use on this network."));
+ append(alertHeader, CFSTR(" "));
+ append(alertHeader, CFSTR("The name has been changed to"));
+ append(alertHeader, s2);
+ append(alertHeader, CFSTR("automatically."));
+ ShowNameConflictNotification(alertHeader, subtext);
+ }
}
- if (s0) CFRelease(s0);
- if (s1) CFRelease(s1);
- if (s2) CFRelease(s2);
- if (alertMessage) CFRelease(alertMessage);
+ if (s0) CFRelease(s0);
+ if (s1) CFRelease(s1);
+ if (s2) CFRelease(s2);
+ if (alertHeader) CFRelease(alertHeader);
SCPreferencesUnlock(session);
}
if (cfoldname) CFRelease(cfoldname);
(void)m; // Unused
if (result == mStatus_NoError)
{
- // Allow three seconds in case we get a Computer Name update too -- don't want to alert the user twice
- RecordUpdatedNiceLabel(m, mDNSPlatformOneSecond*3);
+ // One second pause in case we get a Computer Name update too -- don't want to alert the user twice
+ RecordUpdatedNiceLabel(m, mDNSPlatformOneSecond);
}
else if (result == mStatus_ConfigChanged)
{
+ // If the user-specified hostlabel from System Configuration has changed since the last time
+ // we saw it, and *we* didn't change it, then that implies that the user has changed it,
+ // so we auto-dismiss the name conflict alert.
+ if (!SameDomainLabel(m->p->userhostlabel.c, gNotificationPrefHostLabel.c) ||
+ !SameDomainLabel(m->p->usernicelabel.c, gNotificationPrefNiceLabel.c))
+ {
+ gNotificationUserHostLabel = gNotificationPrefHostLabel = m->p->userhostlabel;
+ gNotificationUserNiceLabel = gNotificationPrefNiceLabel = m->p->usernicelabel;
+ // If we're showing a name conflict notification, and the user has manually edited
+ // the name to remedy the conflict, we should now remove the notification window.
+ if (gNotificationRLS) CFUserNotificationCancel(gNotification);
+ }
+
DNSServiceRegistration *r;
for (r = DNSServiceRegistrationList; r; r=r->next)
if (r->autoname)
// Fill in new length, and data
newrdata->MaxRDLength = size;
memcpy(&newrdata->u, data, data_len);
+
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
+ if (rr->resrec.rrtype == kDNSType_TXT && data_len == 0) { data_len = 1; newrdata->u.txt.c[0] = 0; }
// Do the operation
LogOperation("%5d: DNSServiceRegistrationUpdateRecord(%##s, new length %d)",
}
}
+// On 10.2 the MachServerName is DNSServiceDiscoveryServer
+// On 10.3 and later, the MachServerName is com.apple.mDNSResponder
+
mDNSlocal kern_return_t mDNSDaemonInitialize(void)
{
mStatus err;
CFMachPortRef s_port = CFMachPortCreate(NULL, DNSserverCallback, NULL, NULL);
CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL);
mach_port_t m_port = CFMachPortGetPort(s_port);
- char *MachServerName = mDNSMacOSXSystemBuildNumber(NULL) < 7 ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder";
+ char *MachServerName = OSXVers < 7 ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder";
kern_return_t status = bootstrap_register(bootstrap_port, MachServerName, m_port);
CFRunLoopSourceRef d_rls = CFMachPortCreateRunLoopSource(NULL, d_port, 0);
CFRunLoopSourceRef s_rls = CFMachPortCreateRunLoopSource(NULL, s_port, 0);
if (err) { LogMsg("Daemon start: mDNS_Init failed %ld", err); return(err); }
+ gNotificationUserHostLabel = gNotificationPrefHostLabel = PlatformStorage.userhostlabel;
+ gNotificationUserNiceLabel = gNotificationPrefNiceLabel = PlatformStorage.usernicelabel;
+
client_death_port = CFMachPortGetPort(d_port);
signal_port = CFMachPortGetPort(i_port);
// mDNS_Execute() generates packets, including multicasts that are looped back to ourself.
// If we call mDNS_Execute() first, and generate packets, and then call mDNSMacOSXNetworkChanged() immediately afterwards
// we then systematically lose our own looped-back packets.
- if (m->p->NetworkChanged && now - m->p->NetworkChanged >= 0) { m->p->NetworkChanged = 0; mDNSMacOSXNetworkChanged(m); }
+ if (m->p->NetworkChanged && now - m->p->NetworkChanged >= 0) mDNSMacOSXNetworkChanged(m);
// 2. Call mDNS_Execute() to let mDNSCore do what it needs to do
mDNSs32 nextevent = mDNS_Execute(m);
if (!SameDomainLabel(m->p->usernicelabel.c, m->nicelabel.c))
{
LogMsg("Updating Computer Name from \"%#s\" to \"%#s\"", m->p->usernicelabel.c, m->nicelabel.c);
- RecordUpdatedName(m, &m->p->usernicelabel, &m->nicelabel, "The name of your computer ", "",
- CFSTR("To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field."));
- m->p->NotifyUser = 0; // Clear m->p->NotifyUser here -- even if the hostlabel has changed too, we don't want to bug the user with *two* alerts
+ gNotificationPrefNiceLabel = m->p->usernicelabel = m->nicelabel;
+ RecordUpdatedName(m, &gNotificationUserNiceLabel, &gNotificationPrefNiceLabel, "The name of your computer", "",
+ CFSTR("To change the name of your computer, open System Preferences and click Sharing. "
+ "Then type the name in the Computer Name field."));
+ // Clear m->p->NotifyUser here -- even if the hostlabel has changed too, we don't want to bug the user with *two* alerts
+ m->p->NotifyUser = 0;
}
if (!SameDomainLabel(m->p->userhostlabel.c, m->hostlabel.c))
{
LogMsg("Updating Local Hostname from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
- RecordUpdatedName(m, &m->p->userhostlabel, &m->hostlabel, "This computer's local hostname ", ".local",
- CFSTR("To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field."));
+ gNotificationPrefHostLabel = m->p->userhostlabel = m->hostlabel;
+ RecordUpdatedName(m, &gNotificationUserHostLabel, &gNotificationPrefHostLabel, "This computer’s local hostname", ".local",
+ CFSTR("To change the local hostname, open System Preferences and click Sharing. "
+ "Then click Edit and type the name in the Local Hostname field."));
}
m->p->NotifyUser = 0;
}
// Make our PID file and Unix Domain Socket first, because launchd waits for those before it starts launching other daemons.
// The sooner we do this, the faster the machine will boot.
status = udsserver_init();
- if (status) { LogMsg("Daemon start: udsserver_init failed"); return(status); }
+ if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; }
// First do the all the initialization we need root privilege for, before we change to user "nobody"
LogMsgIdent(mDNSResponderVersionString, "starting");
+ OSXVers = mDNSMacOSXSystemBuildNumber(NULL);
status = mDNSDaemonInitialize();
#if CAN_UPDATE_DYNAMIC_STORE_WITHOUT_BEING_ROOT
mDNS_Close(&mDNSStorage);
}
- if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService();
-
LogMsgIdent(mDNSResponderVersionString, "exiting");
+
+exit:
+ if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService();
return(status);
}
static GenLinkedList gEventSources; // linked list of CFSocketEventSource's
-static void cf_callback(CFSocketRef s, CFSocketCallBackType t, CFDataRef dr, const void *c, void *i)
+mDNSlocal void cf_callback(CFSocketRef s, CFSocketCallBackType t, CFDataRef dr, const void *c, void *i)
// Called by CFSocket when data appears on socket
{
(void)s; // Unused
Change History (most recent first):
$Log: mDNSMacOSX.c,v $
+Revision 1.308 2005/03/09 00:48:44 cheshire
+<rdar://problem/4015157> QU packets getting sent too early on wake from sleep
+Move "m->p->NetworkChanged = 0;" line from caller to callee
+
+Revision 1.307 2005/03/03 03:12:02 cheshire
+Add comment about mDNSMacOSXSystemBuildNumber()
+
+Revision 1.306 2005/03/02 22:18:00 cheshire
+<rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
+
+Revision 1.305 2005/02/26 05:08:28 cheshire
+<rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
+Added dnsinfo.h to project directory
+
+Revision 1.304 2005/02/25 23:51:22 cheshire
+<rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
+Return mStatus_UnknownErr instead of -1
+
+Revision 1.303 2005/02/25 17:47:45 ksekar
+<rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
+
+Revision 1.302 2005/02/25 02:34:14 cheshire
+<rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
+Show status as 1 (in progress) while we're trying
+
+Revision 1.301 2005/02/24 21:55:57 ksekar
+<rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
+
+Revision 1.300 2005/02/15 20:03:13 ksekar
+<rdar://problem/4005868> Crash when SCPreferences contains empty array
+
+Revision 1.299 2005/02/15 02:46:53 cheshire
+<rdar://problem/3967876> Don't log ENETUNREACH errors for unicast destinations
+
+Revision 1.298 2005/02/10 00:41:59 cheshire
+Fix compiler warning
+
+Revision 1.297 2005/02/09 23:38:51 ksekar
+<rdar://problem/3993508> Reregister hostname when DNS server changes but IP address does not
+
+Revision 1.296 2005/02/01 21:06:52 ksekar
+Avoid spurious log message
+
+Revision 1.295 2005/02/01 19:33:30 ksekar
+<rdar://problem/3985239> Keychain format too restrictive
+
Revision 1.294 2005/01/27 21:30:23 cheshire
<rdar://problem/3952067> "Can't assign requested address" message after AirPort turned off
Don't write syslog messages for EADDRNOTAVAIL if we know network configuration changes are happening
(When compiled on 10.3, code will not include split-DNS support.)
Revision 1.248 2004/12/01 20:57:20 ksekar
-<rdar://problem/3873921> Wide Area Rendezvous must be split-DNS aware
+<rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
Revision 1.247 2004/12/01 03:26:58 cheshire
Remove unused variables
instead of having to call through to the daemon via IPC to get this information.
Revision 1.235 2004/11/17 01:45:35 cheshire
-<rdar://problem/3847435> Rendezvous buddy list frequently becomes empty if you let the machine sleep
+<rdar://problem/3847435> mDNS buddy list frequently becomes empty if you let the machine sleep
Refresh our interface list on receiving kIOMessageSystemHasPoweredOn,
in case we get no System Configuration Framework "network changed" event.
#include <Security/Security.h>
-#include <AvailabilityMacros.h>
-#ifdef MAC_OS_X_VERSION_10_4
-#include <dnsinfo.h>
-#endif
+#include "dnsinfo.h"
// Code contributed by Dave Heller:
// Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
if (err < 0)
{
// Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
- if (!mDNSAddressIsAllDNSLinkGroup(dst) && (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH)) return(err);
+ if (!mDNSAddressIsAllDNSLinkGroup(dst))
+ if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
// Don't report EHOSTUNREACH in the first three minutes after boot
// This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
// but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
- if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(err);
+ if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
// Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
- if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(err);
+ if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
- return(err);
+ return(mStatus_UnknownErr);
}
return(mStatus_NoError);
if (dict)
{
CFArrayRef fqdnArray = CFDictionaryGetValue(dict, CFSTR("HostNames"));
- if (fqdnArray)
+ if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
{
CFDictionaryRef fqdnDict = CFArrayGetValueAtIndex(fqdnArray, 0); // for now, we only look at the first array element. if we ever support multiple configurations, we will walk the list
if (fqdnDict && DDNSSettingEnabled(fqdnDict))
}
CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("RegistrationDomains"));
- if (regArray)
+ if (regArray && CFArrayGetCount(regArray) > 0)
{
CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
if (regDict && DDNSSettingEnabled(regDict))
}
}
CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("BrowseDomains"));
- if (browseArray)
+ if (browseArray && CFArrayGetCount(browseArray) > 0)
{
CFRetain(browseArray);
*browseDomains = browseArray;
mDNSlocal mStatus GetDNSConfig(void **result)
{
-#ifndef MAC_OS_X_VERSION_10_4
+#if MDNS_NO_DNSINFO
static int MessageShown = 0;
- if (!MessageShown) { MessageShown = 1; LogMsg("Note: Compiled without Apple-specific split DNS support"); }
+ if (!MessageShown) { MessageShown = 1; LogMsg("Note: Compiled without Apple-specific Split-DNS support"); }
*result = NULL;
return mStatus_UnsupportedErr;
#else
return mStatus_UnknownErr;
}
return mStatus_NoError;
-#endif // MAC_OS_X_VERSION_10_4
+#endif // MDNS_NO_DNSINFO
}
-mDNSlocal mStatus RegisterSplitDNS(mDNS *m)
+mDNSlocal mStatus RegisterSplitDNS(mDNS *m, int *nAdditions, int *nDeletions)
{
(void)m; // unused on 10.3 systems
void *v;
+ *nAdditions = *nDeletions = 0;
mStatus err = GetDNSConfig(&v);
+
+#if !MDNS_NO_DNSINFO
if (!err && v)
{
-#ifdef MAC_OS_X_VERSION_10_4
int i;
+ DNSServer *p;
dns_config_t *config = v; // use void * to allow compilation on 10.3 systems
- mDNS_DeleteDNSServers(m);
+ mDNS_Lock(m);
+ p = m->uDNS_info.Servers;
+ while (p) { p->flag = -1; p = p->next; } // mark all for deletion
LogOperation("RegisterSplitDNS: Registering %d resolvers", config->n_resolver);
for (i = 0; i < config->n_resolver; i++)
mDNSAddr saddr;
if (SetupAddr(&saddr, r->nameserver[n])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
debugf("Adding dns server from slot %d %d.%d.%d.%d for domain %##s", i, saddr.ip.v4.b[0], saddr.ip.v4.b[1], saddr.ip.v4.b[2], saddr.ip.v4.b[3], d.c);
- mDNS_AddDNSServer(m, &saddr, &d);
+ p = m->uDNS_info.Servers;
+ while (p)
+ {
+ if (mDNSSameAddress(&p->addr, &saddr) && SameDomainName(&p->domain, &d)) { p->flag = 0; break; }
+ else p = p->next;
+ }
+ if (!p)
+ {
+ p = mallocL("DNSServer", sizeof(*p));
+ if (!p) { LogMsg("Error: malloc"); mDNS_Unlock(m); return mStatus_UnknownErr; }
+ p->addr = saddr;
+ AssignDomainName(&p->domain, &d);
+ p->flag = 0;
+ p->next = m->uDNS_info.Servers;
+ m->uDNS_info.Servers = p;
+ (*nAdditions)++;
+ }
break; // !!!KRS if we ever support round-robin servers, don't break here
}
}
}
+
+ // remove all servers marked for deletion
+ DNSServer **s = &m->uDNS_info.Servers;
+ while (*s)
+ {
+ if ((*s)->flag < 0)
+ {
+ p = *s;
+ *s = (*s)->next;
+ freeL("DNSServer", p);
+ (*nDeletions)--;
+ }
+ else s = &(*s)->next;
+ }
+ mDNS_Unlock(m);
dns_configuration_free(config);
-#endif
}
- return err;
+#endif
+
+ return err;
}
mDNSlocal mStatus RegisterNameServers(mDNS *const m, CFDictionaryRef dict)
{
void *v;
mStatus err = GetDNSConfig(&v);
+
+#if !MDNS_NO_DNSINFO
if (!err && v)
{
-#ifdef MAC_OS_X_VERSION_10_4
int i;
dns_config_t *config = v;
if (!config->n_resolver) return err;
for (i = 0; i < resolv->n_search; i++) MarkSearchListElem(resolv->search[i]);
if (resolv->domain) MarkSearchListElem(resolv->domain);
dns_configuration_free(config);
-#endif
}
+#endif
+
return err;
}
mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain)
{
OSStatus err = 0;
- SecKeychainRef SysKeychain = NULL;
- SecKeychainItemRef KeychainItem;
char dstring[MAX_ESCAPED_DOMAIN_NAME];
mDNSu32 secretlen;
void *secret = NULL;
domainname *d, canon;
int i, dlen;
-
+ mDNSu32 type = 'ddns';
+ mDNSu32 typelen = sizeof(type);
+ char *failedfn = "(none)";
+ SecKeychainAttributeList *attrList = NULL;
+ SecKeychainItemRef itemRef = NULL;
+
+ err = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+ if (err) { failedfn = "SecKeychainSetPreferenceDomain"; goto cleanup; }
+
// canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
ConvertDomainNameToCString(domain, dstring);
dlen = strlen(dstring);
MakeDomainNameFromDNSNameString(&canon, dstring);
d = &canon;
- err = SecKeychainOpen(SYS_KEYCHAIN_PATH, &SysKeychain);
- if (err) { LogMsg("SetSecretForDomain: couldn't open system keychain (error %d)", err); return; }
- // find longest-match key ("account") name, excluding last label (e.g. excluding ".com")
+ // find longest-match key, excluding last label (e.g. excluding ".com")
while (d->c[0] && *(d->c + d->c[0] + 1))
{
if (!ConvertDomainNameToCString(d, dstring)) { LogMsg("SetSecretForDomain: bad domain %##s", d->c); return; }
dlen = strlen(dstring);
if (dstring[dlen-1] == '.') { dstring[dlen-1] = '\0'; dlen--; } // chop trailing dot
- err = SecKeychainFindGenericPassword(SysKeychain, strlen(DYNDNS_KEYCHAIN_SERVICE), DYNDNS_KEYCHAIN_SERVICE, dlen, dstring, &secretlen, &secret, &KeychainItem);
+ SecKeychainAttribute attrs[] = { { kSecServiceItemAttr, strlen(dstring), dstring },
+ { kSecTypeItemAttr, typelen, (UInt32 *)&type } };
+ SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+ SecKeychainSearchRef searchRef;
+
+ err = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributes, &searchRef);
+ if (err) { failedfn = "SecKeychainSearchCreateFromAttributes"; goto cleanup; }
+
+ err = SecKeychainSearchCopyNext(searchRef, &itemRef);
if (!err)
{
- debugf("Setting shared secret for zone %s with key %##s", dstring, d->c);
- mDNS_SetSecretForZone(m, d, d, secret, secretlen, mDNStrue);
- free(secret);
- return;
- }
- if (err == errSecItemNotFound) d = (domainname *)(d->c + d->c[0] + 1);
- else
- {
- if (err == errSecNoSuchKeychain) debugf("SetSecretForDomain: keychain not found");
- else LogMsg("SetSecretForDomain: SecKeychainFindGenericPassword returned error %d", err);
- return;
+ mDNSu32 tags[1];
+ SecKeychainAttributeInfo attrInfo;
+ mDNSu32 i;
+ char keybuf[MAX_ESCAPED_DOMAIN_NAME+1];
+ domainname keyname;
+
+ tags[0] = kSecAccountItemAttr;
+ attrInfo.count = 1;
+ attrInfo.tag = tags;
+ attrInfo.format = NULL;
+
+ err = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrList, &secretlen, &secret);
+ if (err || !attrList) { failedfn = "SecKeychainItemCopyAttributesAndData"; goto cleanup; }
+ if (!secretlen || !secret) { LogMsg("SetSecretForDomain - bad shared secret"); return; }
+ if (((char *)secret)[secretlen-1]) { LogMsg("SetSecretForDomain - Shared secret not NULL-terminated"); goto cleanup; }
+
+ for (i = 0; i < attrList->count; i++)
+ {
+ SecKeychainAttribute attr = attrList->attr[i];
+ if (attr.tag == kSecAccountItemAttr)
+ {
+ if (!attr.length || attr.length > MAX_ESCAPED_DOMAIN_NAME) { LogMsg("SetSecretForDomain - Bad key length %d", attr.length); goto cleanup; }
+ strncpy(keybuf, attr.data, attr.length);
+ if (!MakeDomainNameFromDNSNameString(&keyname, keybuf)) { LogMsg("SetSecretForDomain - bad key %s", keybuf); goto cleanup; }
+ debugf("Setting shared secret for zone %s with key %##s", dstring, keyname.c);
+ mDNS_SetSecretForZone(m, d, &keyname, secret);
+ break;
+ }
+ }
+ if (i == attrList->count) LogMsg("SetSecretForDomain - no key name set");
+ goto cleanup;
}
+ else if (err == errSecItemNotFound) d = (domainname *)(d->c + d->c[0] + 1);
+ else { failedfn = "SecKeychainSearchCopyNext"; goto cleanup; }
}
+
+ cleanup:
+ if (err && err != errSecItemNotFound) LogMsg("Error: SetSecretForDomain - %s failed with error code %d", failedfn, err);
+ if (attrList) SecKeychainItemFreeAttributesAndData(attrList, secret);
+ if (itemRef) CFRelease(itemRef);
}
mDNSlocal void SetSCPrefsBrowseDomainsFromCFArray(mDNS *m, CFArrayRef browseDomains, mDNSBool add)
CFStringRef key;
domainname RegDomain, fqdn;
CFArrayRef NewBrowseDomains = NULL;
+ int nAdditions = 0, nDeletions = 0;
// get fqdn, zone from SCPrefs
GetUserSpecifiedDDNSConfig(&fqdn, &RegDomain, &NewBrowseDomains);
if (DynDNSHostname.c[0])
{
SetSecretForDomain(m, &fqdn); // no-op if "zone" secret, above, is to be used for hostname
+ SetDDNSNameStatus(&DynDNSHostname, 1); // Set status to 1 to indicate "in progress"
mDNS_AddDynDNSHostName(m, &DynDNSHostname, SCPrefsDynDNSCallback, NULL);
- SetDDNSNameStatus(&DynDNSHostname, 1);
}
}
CFRelease(key);
// handle any changes to search domains and DNS server addresses
- if (RegisterSplitDNS(m) != mStatus_NoError)
+ if (RegisterSplitDNS(m, &nAdditions, &nDeletions) != mStatus_NoError)
if (dict) RegisterNameServers(m, dict); // fall back to non-split DNS aware configuration on failure
RegisterSearchDomains(m, dict); // note that we register name servers *before* search domains
if (dict) CFRelease(dict);
dict = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
CFRelease(store);
- if (!dict)
- { mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL); return; } // lost v4
+ if (!dict) // lost v4
+ {
+ mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL);
+ if (DynDNSHostname.c[0]) SetDDNSNameStatus(&DynDNSHostname, 1); // Set status to 1 to indicate temporary failure
+ return;
+ }
// handle router changes
mDNSAddr r;
}
// handle primary interface changes
+ // if we gained or lost DNS servers (e.g. logged into VPN) "toggle" primary address so it gets re-registered even if it is unchanged
+ if (nAdditions || nDeletions) mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL);
CFStringRef primary = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
if (primary)
{
mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
{
LogOperation("*** Network Configuration Change ***");
+ m->p->NetworkChanged = 0; // If we received a network change event and deferred processing, we're now dealing with it
mDNSs32 utc = mDNSPlatformUTC();
MarkAllInterfacesInactive(m, utc);
UpdateInterfaceList(m, utc);
(void)service; // Parameter not used
switch(messageType)
{
- case kIOMessageCanSystemPowerOff: debugf("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
- case kIOMessageSystemWillPowerOff: debugf("PowerChanged kIOMessageSystemWillPowerOff");
- mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000250
- case kIOMessageSystemWillNotPowerOff: debugf("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
- case kIOMessageCanSystemSleep: debugf("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
- case kIOMessageSystemWillSleep: debugf("PowerChanged kIOMessageSystemWillSleep");
- mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000280
- case kIOMessageSystemWillNotSleep: debugf("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
- case kIOMessageSystemHasPoweredOn: debugf("PowerChanged kIOMessageSystemHasPoweredOn");
+ case kIOMessageCanSystemPowerOff: debugf ("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
+ case kIOMessageSystemWillPowerOff: LogOperation("PowerChanged kIOMessageSystemWillPowerOff");
+ mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000250
+ case kIOMessageSystemWillNotPowerOff: debugf ("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
+ case kIOMessageCanSystemSleep: debugf ("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
+ case kIOMessageSystemWillSleep: LogOperation("PowerChanged kIOMessageSystemWillSleep");
+ mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000280
+ case kIOMessageSystemWillNotSleep: debugf ("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
+ case kIOMessageSystemHasPoweredOn: LogOperation("PowerChanged kIOMessageSystemHasPoweredOn");
// If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
if (m->SleepState) mDNSCoreMachineSleep(m, false);
// Just to be safe, also make sure our interface list is fully up to date, in case we
// haven't yet received the System Configuration Framework "network changed" event that
// we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message
- mDNSMacOSXNetworkChanged(m); break; // E0000300
- case kIOMessageSystemWillRestart: debugf("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
- case kIOMessageSystemWillPowerOn: debugf("PowerChanged kIOMessageSystemWillPowerOn");
+ mDNSMacOSXNetworkChanged(m); break; // E0000300
+ case kIOMessageSystemWillRestart: debugf ("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
+ case kIOMessageSystemWillPowerOn: LogOperation("PowerChanged kIOMessageSystemWillPowerOn");
// Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
- mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false); break; // E0000320
- default: debugf("PowerChanged unknown message %X", messageType); break;
+ mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false); break; // E0000320
+ default: LogOperation("PowerChanged unknown message %X", messageType); break;
}
IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
}
CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
+// Major version 6 is 10.2.x (Jaguar)
+// Major version 7 is 10.3.x (Panther)
+// Major version 8 is 10.4.x (Tiger)
mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
{
int major = 0, minor = 0;
LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time);
// Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
last_mach_absolute_time = this_mach_absolute_time;
- // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
+ // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later
if (mDNSMacOSXSystemBuildNumber(NULL) >= 8)
NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
}
Change History (most recent first):
$Log: mDNSMacOSX.h,v $
+Revision 1.50 2005/02/19 00:04:18 cheshire
+Add comments
+
Revision 1.49 2004/12/17 23:37:47 cheshire
<rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
(and other repetitive configuration changes)
{
NetworkInterfaceInfoOSX *InterfaceList;
CFSocketSet unicastsockets;
- domainlabel userhostlabel;
- domainlabel usernicelabel;
+ domainlabel userhostlabel; // The hostlabel as it was set in System Preferences the last time we looked
+ domainlabel usernicelabel; // The nicelabel as it was set in System Preferences the last time we looked
mDNSs32 NotifyUser;
mDNSs32 NetworkChanged;
SCDynamicStoreRef Store;
--- /dev/null
+"The name of your computer" = "The name of your computer";
+"This computer’s local hostname" = "This computer’s local hostname";
+"is already in use on this network." = "is already in use on this network.";
+
+"The name has been changed to" = "The name has been changed to";
+"automatically." = "automatically.";
+
+"To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field." = "To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field.";
+
+"To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field." = "To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field.";
--- /dev/null
+"The name of your computer" = "Le nom de l’ordinateur";
+"This computer’s local hostname" = "Le nom d’hôte local de cet ordinateur";
+"is already in use on this network." = "est déjà utilié sur ce réseau.";
+
+"The name has been changed to" = "Le non a été changé par";
+"automatically." = "automatiquement.";
+
+"To change the name of your computer, open System Preferences and click Sharing. Then type the name in the Computer Name field." = "Pour changer le nom de votre ordinateur, ouvrez Préférences Systèmes et cliquer Partage. Ensuite entrez le nom dans le champ Nom de l’ordinateur.";
+
+"To change the local hostname, open System Preferences and click Sharing. Then click Edit and type the name in the Local Hostname field." = "Pour changer le nom d’hôte local, ouvrez Préférences Systèmes et cliquer Partage. Ensuite cliquer Modifier et entrez le nom dans le champ Nom local de l’ordinateur.";
FRAMEWORK_SEARCH_PATHS = "";
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = 3.3;
- HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\"";
+ HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\" \"$(OBJROOT)\"";
LIBRARY_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.2;
OPTIMIZATION_CFLAGS = "-O0";
FF16238F07023BD2001AB7D7,
FFD41DDB0664169900F0C438,
FFD41DDC0664169B00F0C438,
+ FF2A870707B4481500B14068,
);
isa = PBXAggregateTarget;
name = "Build All";
DB2CC4530662DD6800335AB3,
DB2CC4660662DF5C00335AB3,
FF25792906C9A70800376F7B,
+ FFFB0DA907B43C9100B88D48,
+ FF2609E107B440DD00CE10E5,
);
};
08FB7794FE84155DC02AAC07 = {
6575FC1F022EB78C00000109,
6575FBFE022EAFA800000109,
DB2CC4420662DCE500335AB3,
+ FFFB0DA407B43BED00B88D48,
08FB779DFE84155DC02AAC07,
19C28FBDFE9D53C911CA2CBB,
);
08FB779DFE84155DC02AAC07 = {
children = (
7F869685066EE02400D2A2DC,
+ FFFB0DB407B43D2700B88D48,
09AB6884FE841BABC02AAC07,
65713D46025A293200000109,
00CA213D02786FC30CCA2C71,
DB2CC4680662DFF500335AB3,
+ FF2609FA07B4433800CE10E5,
+ FF260A1F07B4436900CE10E5,
);
isa = PBXGroup;
name = "External Frameworks and Libraries";
FRAMEWORK_SEARCH_PATHS = "";
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = 3.3;
- HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\"";
+ HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\" \"$(OBJROOT)\"";
INSTALL_PATH = /usr/sbin;
LIBRARY_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.2;
FFD41DDA0664157900F0C438,
FF25794406C9A70800376F7B,
FF1C919B07021C84001048AB,
+ FFFB0DAA07B43C9100B88D48,
+ FF2609E207B440DD00CE10E5,
);
isa = PBXGroup;
name = Products;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
GCC_VERSION = 3.3;
- INSTALL_PATH = /System/Library/Java/Extensions;
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Java/Extensions";
JAVA_ARCHIVE_CLASSES = YES;
JAVA_ARCHIVE_COMPRESSION = YES;
JAVA_ARCHIVE_TYPE = JAR;
JAVA_COMPILER_TARGET_VM_VERSION = 1.2;
JAVA_SOURCE_SUBDIR = .;
LIBRARY_STYLE = STATIC;
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_LIBTOOL_FLAGS = "";
HEADER_SEARCH_PATHS = "../mDNSShared \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/A/Headers\" \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"$(OBJROOT)/mDNSResponder.build/dns_sd.jar.build\"";
INSTALL_PATH = /usr/lib/java;
LIBRARY_STYLE = DYNAMIC;
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
OTHER_CFLAGS = "";
OTHER_LIBTOOL_FLAGS = "";
OTHER_REZFLAGS = "";
//FF2
//FF3
//FF4
+ FF08480607CEB8E800AE6769 = {
+ isa = PBXFileReference;
+ name = inprogress.tiff;
+ path = PreferencePane/Artwork/inprogress.tiff;
+ refType = 2;
+ };
+ FF08480707CEB8E800AE6769 = {
+ fileRef = FF08480607CEB8E800AE6769;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
FF0E0B5D065ADC7600FE4D9C = {
fileEncoding = 4;
isa = PBXFileReference;
isa = PBXTargetDependency;
target = FF25792906C9A70800376F7B;
};
+ FF2609DC07B440DD00CE10E5 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FF2609DD07B440DD00CE10E5 = {
+ buildActionMask = 2147483647;
+ files = (
+ FF260A2B07B4464B00CE10E5,
+ FF260A2C07B4464B00CE10E5,
+ FF260A2D07B4464B00CE10E5,
+ FF260A2E07B4464B00CE10E5,
+ FF260A2F07B4464B00CE10E5,
+ FF260A3007B4464B00CE10E5,
+ FF260A3107B4464B00CE10E5,
+ FF260A3407B4466900CE10E5,
+ FF260A3507B4466900CE10E5,
+ FF260A4A07B4475600CE10E5,
+ FF260A4D07B4477F00CE10E5,
+ FF2A870607B447EF00B14068,
+ FF08480707CEB8E800AE6769,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FF2609DE07B440DD00CE10E5 = {
+ buildActionMask = 2147483647;
+ files = (
+ FF2609E407B441D400CE10E5,
+ FF2609E507B441D700CE10E5,
+ FF2609E607B441DB00CE10E5,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FF2609DF07B440DD00CE10E5 = {
+ buildActionMask = 2147483647;
+ files = (
+ FF2609F607B442BA00CE10E5,
+ FF2609F707B442C000CE10E5,
+ FF2609FB07B4433800CE10E5,
+ FF260A2007B4436900CE10E5,
+ FF260A2107B443B500CE10E5,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FF2609E007B440DD00CE10E5 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FF2609E107B440DD00CE10E5 = {
+ buildPhases = (
+ FF2609DC07B440DD00CE10E5,
+ FF2609DD07B440DD00CE10E5,
+ FF2609DE07B440DD00CE10E5,
+ FF2609DF07B440DD00CE10E5,
+ FF2609E007B440DD00CE10E5,
+ );
+ buildSettings = {
+ EXPORTED_SYMBOLS_FILE = "";
+ GCC_VERSION = 3.3;
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PreferencePanes";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "-twolevel_namespace";
+ OTHER_REZFLAGS = "";
+ PREBINDING = NO;
+ PRODUCT_NAME = Bonjour;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = prefPane;
+ };
+ dependencies = (
+ FF2609E307B440EC00CE10E5,
+ );
+ isa = PBXBundleTarget;
+ name = PreferencePane;
+ productInstallPath = "$(SYSTEM_LIBRARY_DIR)/PreferencePanes";
+ productName = PreferencePane;
+ productReference = FF2609E207B440DD00CE10E5;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>Bonjour</string>
+ <key>CFBundleGetInfoString</key>
+ <string></string>
+ <key>CFBundleIconFile</key>
+ <string>DNSServiceDiscoveryPref</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.preference.bonjour</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string></string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string></string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSMainNibFile</key>
+ <string>DNSServiceDiscoveryPref</string>
+ <key>NSPrefPaneIconFile</key>
+ <string>DNSServiceDiscoveryPref.tiff</string>
+ <key>NSPrefPaneIconLabel</key>
+ <string>Bonjour</string>
+ <key>NSPrincipalClass</key>
+ <string>DNSServiceDiscoveryPref</string>
+</dict>
+</plist>
+";
+ };
+ FF2609E207B440DD00CE10E5 = {
+ isa = PBXBundleReference;
+ path = Bonjour.prefPane;
+ refType = 3;
+ };
+ FF2609E307B440EC00CE10E5 = {
+ isa = PBXTargetDependency;
+ target = FFFB0DA907B43C9100B88D48;
+ };
+ FF2609E407B441D400CE10E5 = {
+ fileRef = FFFB0DAC07B43CBA00B88D48;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2609E507B441D700CE10E5 = {
+ fileRef = FFFB0DAD07B43CBA00B88D48;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2609E607B441DB00CE10E5 = {
+ fileRef = FFFB0DAE07B43CBA00B88D48;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2609F607B442BA00CE10E5 = {
+ fileRef = 65713D46025A293200000109;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2609F707B442C000CE10E5 = {
+ fileRef = 7F869685066EE02400D2A2DC;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2609FA07B4433800CE10E5 = {
+ isa = PBXFrameworkReference;
+ name = Cocoa.framework;
+ path = /System/Library/Frameworks/Cocoa.framework;
+ refType = 0;
+ };
+ FF2609FB07B4433800CE10E5 = {
+ fileRef = FF2609FA07B4433800CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A1F07B4436900CE10E5 = {
+ isa = PBXFrameworkReference;
+ name = PreferencePanes.framework;
+ path = /System/Library/Frameworks/PreferencePanes.framework;
+ refType = 0;
+ };
+ FF260A2007B4436900CE10E5 = {
+ fileRef = FF260A1F07B4436900CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2107B443B500CE10E5 = {
+ fileRef = 09AB6884FE841BABC02AAC07;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2207B443C500CE10E5 = {
+ fileRef = 09AB6884FE841BABC02AAC07;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2307B4463400CE10E5 = {
+ children = (
+ FF260A2407B4464B00CE10E5,
+ FF260A2507B4464B00CE10E5,
+ FF260A2607B4464B00CE10E5,
+ FF260A2707B4464B00CE10E5,
+ FF260A2907B4464B00CE10E5,
+ FF260A2807B4464B00CE10E5,
+ FF08480607CEB8E800AE6769,
+ FF260A2A07B4464B00CE10E5,
+ FF260A3207B4466900CE10E5,
+ FF260A3307B4466900CE10E5,
+ FF260A4807B4475600CE10E5,
+ FF260A4B07B4477F00CE10E5,
+ );
+ isa = PBXGroup;
+ name = Resources;
+ refType = 4;
+ };
+ FF260A2407B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = remove_idle.tiff;
+ path = PreferencePane/Artwork/remove_idle.tiff;
+ refType = 2;
+ };
+ FF260A2507B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = add_pressed.tiff;
+ path = PreferencePane/Artwork/add_pressed.tiff;
+ refType = 2;
+ };
+ FF260A2607B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = remove_disabled.tiff;
+ path = PreferencePane/Artwork/remove_disabled.tiff;
+ refType = 2;
+ };
+ FF260A2707B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = add_idle.tiff;
+ path = PreferencePane/Artwork/add_idle.tiff;
+ refType = 2;
+ };
+ FF260A2807B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = success.tiff;
+ path = PreferencePane/Artwork/success.tiff;
+ refType = 2;
+ };
+ FF260A2907B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = remove_pressed.tiff;
+ path = PreferencePane/Artwork/remove_pressed.tiff;
+ refType = 2;
+ };
+ FF260A2A07B4464B00CE10E5 = {
+ isa = PBXFileReference;
+ name = failure.tiff;
+ path = PreferencePane/Artwork/failure.tiff;
+ refType = 2;
+ };
+ FF260A2B07B4464B00CE10E5 = {
+ fileRef = FF260A2407B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2C07B4464B00CE10E5 = {
+ fileRef = FF260A2507B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2D07B4464B00CE10E5 = {
+ fileRef = FF260A2607B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2E07B4464B00CE10E5 = {
+ fileRef = FF260A2707B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A2F07B4464B00CE10E5 = {
+ fileRef = FF260A2807B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A3007B4464B00CE10E5 = {
+ fileRef = FF260A2907B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A3107B4464B00CE10E5 = {
+ fileRef = FF260A2A07B4464B00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A3207B4466900CE10E5 = {
+ isa = PBXFileReference;
+ name = DNSServiceDiscoveryPref.icns;
+ path = PreferencePane/DNSServiceDiscoveryPref.icns;
+ refType = 2;
+ };
+ FF260A3307B4466900CE10E5 = {
+ isa = PBXFileReference;
+ name = DNSServiceDiscoveryPref.tiff;
+ path = PreferencePane/DNSServiceDiscoveryPref.tiff;
+ refType = 2;
+ };
+ FF260A3407B4466900CE10E5 = {
+ fileRef = FF260A3207B4466900CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A3507B4466900CE10E5 = {
+ fileRef = FF260A3307B4466900CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A4807B4475600CE10E5 = {
+ children = (
+ FF260A4907B4475600CE10E5,
+ );
+ isa = PBXVariantGroup;
+ name = DNSServiceDiscoveryPref.nib;
+ path = PreferencePane;
+ refType = 2;
+ };
+ FF260A4907B4475600CE10E5 = {
+ isa = PBXFileReference;
+ name = English;
+ path = PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib;
+ refType = 2;
+ };
+ FF260A4A07B4475600CE10E5 = {
+ fileRef = FF260A4807B4475600CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF260A4B07B4477F00CE10E5 = {
+ children = (
+ FF260A4C07B4477F00CE10E5,
+ );
+ isa = PBXVariantGroup;
+ name = InfoPlist.strings;
+ path = PreferencePane;
+ refType = 2;
+ };
+ FF260A4C07B4477F00CE10E5 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ name = English;
+ path = PreferencePane/English.lproj/InfoPlist.strings;
+ refType = 2;
+ };
+ FF260A4D07B4477F00CE10E5 = {
+ fileRef = FF260A4B07B4477F00CE10E5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2A870607B447EF00B14068 = {
+ fileRef = FFFB0DAA07B43C9100B88D48;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FF2A870707B4481500B14068 = {
+ isa = PBXTargetDependency;
+ target = FF2609E107B440DD00CE10E5;
+ };
FF37BE9207614059003C0420 = {
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if [ -e /usr/local/lib/libdnsinfo.a ]\nthen\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi";
+ shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/dnsinfo.h\"\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/dnsinfo.h\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi";
};
FF485D5105632E0000130380 = {
fileEncoding = 4;
neededFileNames = (
);
runOnlyForDeploymentPostprocessing = 1;
- shellPath = /bin/sh;
- shellScript = "mkdir -p ${DSTROOT}/System/Library/LaunchDaemons\ncp ${SRCROOT}/LaunchDaemonInfo.plist ${DSTROOT}/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist";
+ shellPath = /bin/tcsh;
+ shellScript = "# Install plist to tell launchd to start mDNSResponder\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\ncp ${SRCROOT}/LaunchDaemonInfo.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\n\n# Install mDNSResponder.bundle containing language localizations\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices\ncp -R ${SRCROOT}/mDNSResponder-bundle ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle\n\n# Remove unwanted CVS directories\nfind ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -depth -name CVS -exec rm -rf {} \\;\n\n# Expand UTF-8 files to UTF-16 (not necessary, but required by B&I policy)\nforeach file (`find ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -name Localizable.strings`)\niconv -f utf-8 -t utf-16 ${file} > ${file}.new\nmv -f ${file}.new ${file}\nend\n\n# Remove French localization (not wanted for Apple B&I builds)\nrm -rf ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle/Resources/French.lproj\n";
};
FF5A0AE705632EA600743C27 = {
buildActionMask = 8;
isa = PBXTargetDependency;
target = DB2CC4530662DD6800335AB3;
};
+ FFE6935007C2CA7F00283007 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ name = ConfigurationAuthority.h;
+ path = PreferencePane/ConfigurationAuthority.h;
+ refType = 2;
+ };
+ FFE6935207C2CAA400283007 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ name = DNSServiceDiscoveryPref.h;
+ path = PreferencePane/DNSServiceDiscoveryPref.h;
+ refType = 2;
+ };
+ FFE6935407C2CABD00283007 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ name = PrivilegedOperations.h;
+ path = PreferencePane/PrivilegedOperations.h;
+ refType = 2;
+ };
FFF4F63A06CFE4DD00459EFD = {
fileEncoding = 4;
isa = PBXFileReference;
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if [ -e /usr/local/lib/libdnsinfo.a ]\nthen\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi";
+ shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/dnsinfo.h\"\nrm -f \"${OBJROOT}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/dnsinfo.h\ntouch ${OBJROOT}/empty.c\ncc ${OBJROOT}/empty.c -c -o \"${OBJROOT}/libdnsinfo.a\"\nrm -f ${OBJROOT}/empty.c\nfi";
+ };
+ FFFB0DA407B43BED00B88D48 = {
+ children = (
+ FFE6935007C2CA7F00283007,
+ FFFB0DAE07B43CBA00B88D48,
+ FFE6935207C2CAA400283007,
+ FFFB0DAC07B43CBA00B88D48,
+ FFE6935407C2CABD00283007,
+ FFFB0DAD07B43CBA00B88D48,
+ FFFB0DAF07B43CBA00B88D48,
+ FF260A2307B4463400CE10E5,
+ );
+ isa = PBXGroup;
+ path = PreferencePane;
+ refType = 2;
+ };
+ FFFB0DA507B43C9100B88D48 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FFFB0DA607B43C9100B88D48 = {
+ buildActionMask = 2147483647;
+ files = (
+ FFFB0DB307B43CBA00B88D48,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FFFB0DA707B43C9100B88D48 = {
+ buildActionMask = 2147483647;
+ files = (
+ FFFB0DB507B43D2700B88D48,
+ FFFB0DB907B43D5F00B88D48,
+ FFFB0DBD07B43D7400B88D48,
+ FF260A2207B443C500CE10E5,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FFFB0DA807B43C9100B88D48 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FFFB0DA907B43C9100B88D48 = {
+ buildPhases = (
+ FFFB0DA507B43C9100B88D48,
+ FFFB0DA607B43C9100B88D48,
+ FFFB0DA707B43C9100B88D48,
+ FFFB0DA807B43C9100B88D48,
+ );
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = ddnswriteconfig;
+ REZ_EXECUTABLE = YES;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXToolTarget;
+ name = ddnswriteconfig;
+ productInstallPath = /usr/local/bin;
+ productName = ddnswriteconfig;
+ productReference = FFFB0DAA07B43C9100B88D48;
+ };
+ FFFB0DAA07B43C9100B88D48 = {
+ isa = PBXExecutableFileReference;
+ path = ddnswriteconfig;
+ refType = 3;
+ };
+ FFFB0DAC07B43CBA00B88D48 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ path = DNSServiceDiscoveryPref.m;
+ refType = 4;
+ };
+ FFFB0DAD07B43CBA00B88D48 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ path = PrivilegedOperations.c;
+ refType = 4;
+ };
+ FFFB0DAE07B43CBA00B88D48 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ path = ConfigurationAuthority.c;
+ refType = 4;
+ };
+ FFFB0DAF07B43CBA00B88D48 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ path = ddnswriteconfig.m;
+ refType = 4;
+ };
+ FFFB0DB307B43CBA00B88D48 = {
+ fileRef = FFFB0DAF07B43CBA00B88D48;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FFFB0DB407B43D2700B88D48 = {
+ isa = PBXFrameworkReference;
+ name = Foundation.framework;
+ path = /System/Library/Frameworks/Foundation.framework;
+ refType = 0;
+ };
+ FFFB0DB507B43D2700B88D48 = {
+ fileRef = FFFB0DB407B43D2700B88D48;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FFFB0DB907B43D5F00B88D48 = {
+ fileRef = 7F869685066EE02400D2A2DC;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ FFFB0DBD07B43D7400B88D48 = {
+ fileRef = 65713D46025A293200000109;
+ isa = PBXBuildFile;
+ settings = {
+ };
};
};
rootObject = 08FB7793FE84155DC02AAC07;
Change History (most recent first):
$Log: Client.c,v $
+Revision 1.16 2005/02/04 01:00:53 cheshire
+Add '-d' command-line option to specify domain to browse
+
Revision 1.15 2004/12/16 20:17:11 cheshire
<rdar://problem/3324626> Cache memory management improvements
return result;
}
-static const char kDefaultServiceType[] = "_afpovertcp._tcp.";
+static const char kDefaultServiceType[] = "_afpovertcp._tcp";
+static const char kDefaultDomain[] = "local.";
static void PrintUsage()
{
fprintf(stderr,
- "Usage: %s [-v level] [-t type]\n",
+ "Usage: %s [-v level] [-t type] [-d domain]\n",
gProgramName);
fprintf(stderr, " -v verbose mode, level is a number from 0 to 2\n");
fprintf(stderr, " 0 = no debugging info (default)\n");
fprintf(stderr, " 1 = standard debugging info\n");
fprintf(stderr, " 2 = intense debugging info\n");
fprintf(stderr, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType);
+ fprintf(stderr, " -d uses 'domain' as the domain to browse (default is '%s')\n", kDefaultDomain);
}
static const char *gServiceType = kDefaultServiceType;
+static const char *gServiceDomain = kDefaultDomain;
static void ParseArguments(int argc, char **argv)
// Parses our command line arguments into the global variables
// Parse command line options using getopt.
do {
- ch = getopt(argc, argv, "v:t:");
+ ch = getopt(argc, argv, "v:t:d:");
if (ch != -1) {
switch (ch) {
case 'v':
exit(1);
}
break;
+ case 'd':
+ gServiceDomain = optarg;
+ break;
case '?':
default:
PrintUsage();
// Construct and start the query.
MakeDomainNameFromDNSNameString(&type, gServiceType);
- MakeDomainNameFromDNSNameString(&domain, "local.");
+ MakeDomainNameFromDNSNameString(&domain, gServiceDomain);
status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, BrowseCallback, NULL);
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Log: Makefile,v $
+# Revision 1.56 2005/02/02 02:25:21 cheshire
+# <rdar://problem/3980388> /var/run/mDNSResponder should be /var/run/mdnsd on Linux
+#
# Revision 1.55 2005/01/27 22:55:00 cheshire
# Add "make os=tiger" target which uses gcc4 and "-Wdeclaration-after-statement"
#
CP = cp
RM = rm
LN = ln -s -f
-CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\"
+CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" -DMDNS_UDS_SERVERPATH=\"/var/run/mdnsd\"
LIBFLAGS =
DNSEXT_FLAGS = -D_REENTRANT -g -Wall -lpthread
LDSUFFIX = so
Change History (most recent first):
$Log: PosixDaemon.c,v $
+Revision 1.27 2005/02/04 00:39:59 cheshire
+Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
+
+Revision 1.26 2005/02/02 02:21:30 cheshire
+Update references to "mDNSResponder" to say "mdnsd" instead
+
Revision 1.25 2005/01/27 20:01:50 cheshire
udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
Revision 1.21 2004/12/01 20:57:20 ksekar
-<rdar://problem/3873921> Wide Area Rendezvous must be split-DNS aware
+<rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
Revision 1.20 2004/12/01 04:28:43 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
#include <fcntl.h>
#include <pwd.h>
#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include "mDNSEmbeddedAPI.h"
#include "mDNSDebug.h"
#include "uds_daemon.h"
#include "PlatformCommon.h"
-#define uDNS_SERVERS_FILE "/etc/resolv.conf"
-
#define CONFIG_FILE "/etc/mdnsd.conf"
static domainname DynDNSZone; // Default wide-area zone for service registration
static domainname DynDNSHostname;
extern const char mDNSResponderVersionString[];
-static int ParseDNSServers(mDNS *m, const char *filePath)
- {
- char line[256];
- char nameserver[16];
- char keyword[10];
- int numOfServers = 0;
- FILE *fp = fopen(filePath, "r");
- if (fp == NULL) return -1;
- while (fgets(line,sizeof(line),fp))
- {
- struct in_addr ina;
- line[255]='\0'; // just to be safe
- if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue; // it will skip whitespaces
- if (strncmp(keyword,"nameserver",10)) continue;
- if (inet_aton(nameserver, (struct in_addr *)&ina) != 0)
- {
- mDNSAddr DNSAddr;
- DNSAddr.type = mDNSAddrType_IPv4;
- DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
- mDNS_AddDNSServer(m, &DNSAddr, NULL);
- numOfServers++;
- }
- }
- return (numOfServers > 0) ? 0 : -1;
- }
-
static void Reconfigure(mDNS *m)
{
mDNSAddr DynDNSIP;
if (argc > 1)
{
if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
- else printf("Usage: mDNSResponder [-debug]\n");
+ else printf("Usage: %s [-debug]\n", argv[0]);
}
if (!mDNS_DebugMode)
int result = daemon(0, 0);
if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
#if __APPLE__
- LogMsg("The POSIX mDNSResponder should only be used on OS X for testing - exiting");
+ LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
exit(-1);
#endif
}
ParseCmdLinArgs(argc, argv);
+ LogMsgIdent(mDNSResponderVersionString, "starting");
+
err = mDNS_Init(&mDNSRecord, &platformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
if (mStatus_NoError == err)
err = MainLoop(&mDNSRecord);
+ LogMsgIdent(mDNSResponderVersionString, "stopping");
+
mDNS_Close(&mDNSRecord);
if (udsserver_exit() < 0)
<http://www.zeroconf.org/>
-Apple uses the brand name "Rendezvous" to describe our implementation of
+Apple uses the trade mark "Bonjour" to describe our implementation of
zeroconf technologies. This sample is designed to show how easy it is
-to make a device "Rendezvous compatible".
+to make a device "Bonjour compatible".
The code in this sample was compiled and tested on Mac OS X (10.1.x,
10.2, 10.3), Solaris (SunOS 5.8), Linux (Redhat 2.4.9-21, Fedora Core 1),
Change History (most recent first):
$Log: Responder.c,v $
+Revision 1.29 2005/03/04 21:35:33 cheshire
+<rdar://problem/4037201> Services.txt file not parsed properly when it contains more than one service
+
Revision 1.28 2005/01/11 01:55:26 ksekar
Fix compile errors in Posix debug build
#pragma mark ***** Parameter Checking
#endif
-static mDNSBool CheckThatRichTextHostNameIsUsable(const char *richTextHostName, mDNSBool printExplanation)
- // Checks that richTextHostName is a reasonable host name
+static mDNSBool CheckThatRichTextNameIsUsable(const char *richTextName, mDNSBool printExplanation)
+ // Checks that richTextName is reasonable
// label and, if it isn't and printExplanation is true, prints
// an explanation of why not.
{
- mDNSBool result;
- domainlabel richLabel;
- domainlabel poorLabel;
-
- result = mDNStrue;
- if (result && strlen(richTextHostName) > 63) {
+ mDNSBool result = mDNStrue;
+ if (result && strlen(richTextName) > 63) {
if (printExplanation) {
fprintf(stderr,
- "%s: Host name is too long (must be 63 characters or less)\n",
+ "%s: Service name is too long (must be 63 characters or less)\n",
gProgramName);
}
result = mDNSfalse;
}
- if (result && richTextHostName[0] == 0) {
+ if (result && richTextName[0] == 0) {
if (printExplanation) {
- fprintf(stderr, "%s: Host name can't be empty\n", gProgramName);
+ fprintf(stderr, "%s: Service name can't be empty\n", gProgramName);
}
result = mDNSfalse;
}
- if (result) {
- MakeDomainLabelFromLiteralString(&richLabel, richTextHostName);
- ConvertUTF8PstringToRFC1034HostLabel(richLabel.c, &poorLabel);
- if (poorLabel.c[0] == 0) {
- if (printExplanation) {
- fprintf(stderr,
- "%s: Host name doesn't produce a usable RFC-1034 name\n",
- gProgramName);
- }
- result = mDNSfalse;
- }
- }
return result;
}
fprintf(stderr, " 2 = intense debugging info\n");
fprintf(stderr, " can be cycled kill -USR1\n");
fprintf(stderr, " -r also bind to port 53 (port 5353 is always bound)\n");
- fprintf(stderr, " -n uses 'name' as the host name (default is none)\n");
+ fprintf(stderr, " -n uses 'name' as the service name (required)\n");
fprintf(stderr, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType);
fprintf(stderr, " -d uses 'domain' as the service domain (default is '%s')\n", kDefaultServiceDomain);
fprintf(stderr, " -p uses 'port' as the port number (default is '%d')\n", kDefaultPortNumber);
}
static mDNSBool gAvoidPort53 = mDNStrue;
-static const char *gRichTextHostName = "";
+static const char *gServiceName = "";
static const char *gServiceType = kDefaultServiceType;
static const char *gServiceDomain = kDefaultServiceDomain;
static mDNSu8 gServiceText[sizeof(RDataBody)];
gAvoidPort53 = mDNSfalse;
break;
case 'n':
- gRichTextHostName = optarg;
- if ( ! CheckThatRichTextHostNameIsUsable(gRichTextHostName, mDNStrue) ) {
+ gServiceName = optarg;
+ if ( ! CheckThatRichTextNameIsUsable(gServiceName, mDNStrue) ) {
exit(1);
}
break;
// Check for inconsistency between the arguments.
- if ( (gRichTextHostName[0] == 0) && (gServiceFile[0] == 0) ) {
+ if ( (gServiceName[0] == 0) && (gServiceFile[0] == 0) ) {
PrintUsage();
- fprintf(stderr, "%s: You must specify a service to register (-n) or a service file (-f).\n", gProgramName);
+ fprintf(stderr, "%s: You must specify a service name to register (-n) or a service file (-f).\n", gProgramName);
exit(1);
}
}
static int gServiceID = 0;
-static mStatus RegisterOneService(const char * richTextHostName,
+static mStatus RegisterOneService(const char * richTextName,
const char * serviceType,
const char * serviceDomain,
const mDNSu8 text[],
status = mStatus_NoMemoryErr;
}
if (status == mStatus_NoError) {
- MakeDomainLabelFromLiteralString(&name, richTextHostName);
+ MakeDomainLabelFromLiteralString(&name, richTextName);
MakeDomainNameFromDNSNameString(&type, serviceType);
MakeDomainNameFromDNSNameString(&domain, serviceDomain);
status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ,
"%s: Registered service %d, name '%s', type '%s', port %ld\n",
gProgramName,
thisServ->serviceID,
- richTextHostName,
+ richTextName,
serviceType,
portNumber);
}
mDNSBool good, skip;
do {
good = (fgets(buf, bufSize, fp) != NULL);
- skip = (good && (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n'));
+ skip = (good && (buf[0] == '#'));
} while (good && skip);
if (good)
{
if (status == mStatus_NoError) {
mDNSBool good = mDNStrue;
do {
+ int ch;
char name[256];
char type[256];
const char *dom = kDefaultServiceDomain;
mDNSu8 text[sizeof(RDataBody)];
mDNSu16 textLen = 0;
char port[256];
+
+ // Skip over any blank lines.
+ do ch = fgetc(fp); while ( ch == '\n' || ch == '\r' );
+ if (ch != EOF) good = (ungetc(ch, fp) == ch);
// Read three lines, check them for validity, and register the service.
good = ReadALine(name, sizeof(name), fp);
good = ReadALine(port, sizeof(port), fp);
}
if (good) {
- good = CheckThatRichTextHostNameIsUsable(name, mDNSfalse)
+ good = CheckThatRichTextNameIsUsable(name, mDNSfalse)
&& CheckThatServiceTypeIsUsable(type, mDNSfalse)
&& CheckThatPortNumberIsUsable(atol(port), mDNSfalse);
}
if (good) {
while (1) {
+ int len;
if (!ReadALine(rawText, sizeof(rawText), fp)) break;
- text[textLen] = strlen(rawText);
- if (text[textLen] == 0) break;
- memcpy(text + textLen + 1, rawText, text[textLen]);
- textLen += 1 + text[textLen];
+ len = strlen(rawText);
+ if (len <= 255)
+ {
+ text[textLen] = len;
+ if (text[textLen] == 0) break;
+ memcpy(text + textLen + 1, rawText, text[textLen]);
+ textLen += 1 + text[textLen];
+ }
+ else
+ fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n",
+ gProgramName, name, type, port);
}
}
if (good) {
status = RegisterOneService(name, type, dom, text, textLen, atol(port));
if (status != mStatus_NoError) {
- fprintf(stderr,
- "%s: Failed to register service, name = %s, type = %s, port = %s\n",
- gProgramName,
- name,
- type,
- port);
+ fprintf(stderr, "%s: Failed to register service, name = %s, type = %s, port = %s\n",
+ gProgramName, name, type, port);
status = mStatus_NoError; // keep reading
}
}
mStatus status;
status = mStatus_NoError;
- if (gRichTextHostName[0] != 0) {
- status = RegisterOneService(gRichTextHostName,
+ if (gServiceName[0] != 0) {
+ status = RegisterOneService(gServiceName,
gServiceType,
gServiceDomain,
gServiceText, gServiceTextLen,
Change History (most recent first):
$Log: dnsextd.c,v $
+Revision 1.33 2005/03/11 19:09:02 ksekar
+Fixed ZERO_LLQID macro
+
+Revision 1.32 2005/03/10 22:54:33 ksekar
+<rdar://problem/4046285> dnsextd leaks memory/ports
+
+Revision 1.31 2005/02/24 02:37:57 ksekar
+<rdar://problem/4021977> dnsextd memory management improvements
+
Revision 1.30 2005/01/27 22:57:56 cheshire
Fix compile errors on gcc4
Fixed verbose log message argument
Revision 1.15 2004/11/19 02:35:02 ksekar
-<rdar://problem/3886317> Wide Area Rendezvous Security: Add LLQ-ID to events
+<rdar://problem/3886317> Wide Area Security: Add LLQ-ID to events
Revision 1.14 2004/11/17 06:17:58 cheshire
Update comments to show correct SRV names: _dns-update._udp.<zone>. and _dns-llq._udp.<zone>.
#endif
#define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y))
-#define ZERO_LLQID(x) (!memcmp(x, "\x0\x0\x0\x0", 8))
+#define ZERO_LLQID(x) (!memcmp(x, "\x0\x0\x0\x0\x0\x0\x0\x0", 8))
//
// Data Structures
Established = 2
} LLQState;
+typedef struct AnswerListElem
+ {
+ struct AnswerListElem *next;
+ domainname name;
+ mDNSu16 type;
+ CacheRecord *KnownAnswers; // All valid answers delivered to client
+ CacheRecord *EventList; // New answers (adds/removes) to be sent to client
+ int refcount;
+ } AnswerListElem;
+
// llq table entry
typedef struct LLQEntry
{
LLQState state;
mDNSu32 lease; // original lease, in seconds
mDNSs32 expire; // expiration, absolute, in seconds since epoch
- CacheRecord *KnownAnswers;// !!!KRS this should be shared amongst identical questions
+ AnswerListElem *AnswerList;
} LLQEntry;
// daemon-wide information
// LLQ table variables
LLQEntry *LLQTable[LLQ_TABLESIZE]; // !!!KRS change this and RRTable to use a common data structure
+ AnswerListElem *AnswerTable[LLQ_TABLESIZE];
int LLQEventListenSock; // Unix domain socket pair - polling thread writes to ServPollSock, which wakes
int LLQServPollSock; // the main thread listening on EventListenSock, indicating that the zone has changed
} DaemonInfo;
RRTableElem *ptr, *tmp, **new;
int i, bucket, newnbuckets = d->nbuckets * 2;
+ VLog("Rehashing lease table (new size %d buckets)", newnbuckets);
new = malloc(sizeof(RRTableElem *) * newnbuckets);
if (!new) { LogErr("RehashTable", "malloc"); return; }
bzero(new, newnbuckets * sizeof(RRTableElem *));
}
}
d->nbuckets = newnbuckets;
+ free(d->table);
+ d->table = new;
}
// print entire contents of hashtable, invoked via SIGINFO
// Add, delete, or refresh records in table based on contents of a successfully completed dynamic update
mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
{
- RRTableElem *prev, *rptr, *new = NULL;
- int i, bucket;
+ RRTableElem **rptr, *tmp;
+ int i, allocsize, bucket;
LargeCacheRecord lcr;
+ ResourceRecord *rr = &lcr.r.resrec;
const mDNSu8 *ptr, *end;
struct timeval time;
DNSQuestion zone;
for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++)
{
+ mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse;
+
ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
if (!ptr) { Log("UpdateLeaseTable: GetLargeResourceRecord returned NULL"); goto cleanup; }
- //!!!KRS we should include rdata in hash here
- bucket = lcr.r.resrec.namehash % d->nbuckets;
-
- // look for RR in table
- prev = NULL;
- rptr = d->table[bucket];
- while (rptr)
+ bucket = rr->namehash % d->nbuckets;
+ rptr = &d->table[bucket];
+
+ // handle deletions
+ if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength)
+ DeleteAllRRSets = mDNStrue; // delete all rrsets for a name
+ else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength)
+ DeleteOneRRSet = mDNStrue;
+ else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE)
+ DeleteOneRR = mDNStrue;
+
+ if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR)
{
- if (SameResourceRecord(&rptr->rr.resrec, &lcr.r.resrec)) break;
- prev = rptr;
- rptr = rptr->next;
+ while (*rptr)
+ {
+ if (SameDomainName((*rptr)->rr.resrec.name, rr->name) &&
+ (DeleteAllRRSets ||
+ (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) ||
+ (DeleteOneRR && SameResourceRecord(&(*rptr)->rr.resrec, rr))))
+ {
+ tmp = *rptr;
+ VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf));
+ *rptr = (*rptr)->next;
+ free(tmp);
+ d->nelems--;
+ }
+ else rptr = &(*rptr)->next;
+ }
}
-
- if (rptr)
+ else if (lease > 0)
{
- // Record is already in table
- if (!lcr.r.resrec.rroriginalttl && lcr.r.resrec.rrclass == kDNSClass_NONE)
+ // see if add or refresh
+ while (*rptr && !SameResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next;
+ if (*rptr)
{
- // deletion record
- VLog("Received deletion update for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
- if (prev) prev->next = rptr->next;
- else d->table[bucket] = rptr->next;
- free(rptr);
- d->nelems--;
+ // refresh
+ if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
+ (*rptr)->expire = time.tv_sec + (unsigned)lease;
+ VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
}
else
{
- // refresh
- if (lease < 0)
+ // New record - add to table
+ if (d->nelems > d->nbuckets)
{
- Log("Update for record %s already in lease table with no refresh lease specified",
- GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
- }
- else
- {
- if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
- rptr->expire = time.tv_sec + (unsigned)lease;
- VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
+ RehashTable(d);
+ bucket = rr->namehash % d->nbuckets;
+ rptr = &d->table[bucket];
}
+ if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
+ allocsize = sizeof(RRTableElem);
+ if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize);
+ tmp = malloc(allocsize);
+ if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; }
+ memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize);
+ tmp->rr.resrec.rdata = (RData *)&tmp->rr.rdatastorage;
+ AssignDomainName(&tmp->name, rr->name);
+ tmp->rr.resrec.name = &tmp->name;
+ tmp->expire = time.tv_sec + (unsigned)lease;
+ tmp->cli.sin_addr = pkt->src.sin_addr;
+ AssignDomainName(&tmp->zone, &zone.qname);
+ tmp->next = d->table[bucket];
+ d->table[bucket] = tmp;
+ d->nelems++;
+ VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
}
}
- else if (lease > 0)
- {
- // New record - add to table
- if (d->nelems > d->nbuckets) RehashTable(d);
- if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
- new = malloc(sizeof(RRTableElem) + lcr.r.resrec.rdlength - InlineCacheRDSize);
- if (!new) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; }
- memcpy(&new->rr, &lcr.r, sizeof(CacheRecord) + lcr.r.resrec.rdlength - InlineCacheRDSize);
- new->rr.resrec.rdata = (RData *)&new->rr.rdatastorage;
- AssignDomainName(&new->name, lcr.r.resrec.name);
- new->rr.resrec.name = &new->name;
- new->expire = time.tv_sec + (unsigned)lease;
- new->cli.sin_addr = pkt->src.sin_addr;
- AssignDomainName(&new->zone, &zone.qname);
- new->next = d->table[bucket];
- d->table[bucket] = new;
- d->nelems++;
- VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
- }
}
cleanup:
else return e->expire - t.tv_sec;
}
-mDNSlocal void FreeKnownAnswers(LLQEntry *e)
- {
- CacheRecord *tmp;
-
- while(e->KnownAnswers)
- {
- tmp = e->KnownAnswers;
- e->KnownAnswers = e->KnownAnswers->next;
- free(tmp);
- }
- }
-
mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e)
{
- int bucket = bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
- LLQEntry *prev = NULL, *ptr = d->LLQTable[bucket];
+ int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
+ LLQEntry **ptr = &d->LLQTable[bucket];
+ AnswerListElem *a = e->AnswerList;
char addr[32];
inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr);
- FreeKnownAnswers(e);
- while(ptr)
+ // free shared answer structure if ref count drops to zero
+ if (a && !(--a->refcount))
{
- if (ptr == e)
+ CacheRecord *cr = a->KnownAnswers, *tmp;
+ AnswerListElem **tbl = &d->AnswerTable[bucket];
+
+ while (cr)
{
- if (prev) prev->next = ptr->next;
- else d->LLQTable[bucket] = ptr->next;
- free(e);
- return;
+ tmp = cr;
+ cr = cr->next;
+ free(tmp);
}
- prev = ptr;
- ptr = ptr->next;
+
+ while (*tbl && *tbl != a) tbl = &(*tbl)->next;
+ if (*tbl) { *tbl = (*tbl)->next; free(a); }
+ else Log("Error: DeleteLLQ - AnswerList not found in table");
}
- Log("Error: DeleteLLQ - LLQ not in table");
+
+ // remove LLQ from table, free memory
+ while(*ptr && *ptr != e) ptr = &(*ptr)->next;
+ if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; }
+ *ptr = (*ptr)->next;
+ free(e);
}
mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst)
// if non-negative, sd is a TCP socket connected to the nameserver
// otherwise, this routine creates and closes its own socket
-mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd)
+mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd)
{
PktMsg q;
int i;
mDNSu8 rcode;
mDNSBool CloseSDOnExit = sd < 0;
- VLog("Querying server for %##s type %d", e->qname.c, e->qtype);
+ VLog("Querying server for %##s type %d", e->name.c, e->type);
flags.b[0] |= kDNSFlag0_RD; // recursion desired
id.NotAnInteger = 0;
InitializeDNSMessage(&q.msg.h, id, flags);
- end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
+ end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN);
if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; }
q.len = (int)(end - (mDNSu8 *)&q.msg);
if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery))
{ Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; }
rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC);
- if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->qname.c, e->qtype, rcode); goto end; }
+ if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; }
end = (mDNSu8 *)&reply->msg + reply->len;
ansptr = LocateAnswers(&reply->msg, end);
for (i = 0; i < reply->msg.h.numAnswers; i++)
{
- //rr = malloc(sizeof(*rr));
- //if (!rr) { LogErr("AnswerQuestion", "malloc"); goto end; }
ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr);
if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; }
- if (lcr.r.resrec.rrtype != e->qtype || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->qname))
+ if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name))
{
Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding",
- lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->qname.c, e->qtype);
+ lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type);
}
else
{
- CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->qname);
+ CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name);
if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; }
cr->next = AnswerList;
AnswerList = cr;
end:
if (sd > -1 && CloseSDOnExit) close(sd);
if (reply) free(reply);
- e->state = Established;
return AnswerList;
}
-mDNSlocal void UpdateAnswerList(DaemonInfo *d, LLQEntry *e, CacheRecord *answers)
+// Routine sets EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list
+mDNSlocal void UpdateAnswerList(DaemonInfo *d, AnswerListElem *a, int sd)
{
- CacheRecord *prev = NULL, *na, *ka; // "new answer", "known answer"
- PktMsg response;
- mDNSu8 *end = (mDNSu8 *)&response.msg.data;
- mDNSOpaque16 msgID;
- char rrbuf[80], addrbuf[32];
- AuthRecord opt;
+ CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer"
+
+ // get up to date answers
+ NewAnswers = AnswerQuestion(d, a, sd);
// first pass - mark all answers for deletion
- for (ka = e->KnownAnswers; ka; ka = ka->next)
- ka->resrec.rroriginalttl = -1; // -1 means delete
+ for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
+ (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete
// second pass - mark answers pre-existent
- for (ka = e->KnownAnswers; ka; ka = ka->next)
+ for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
{
- for (na = answers; na; na = na->next)
+ for (na = &NewAnswers; *na; na = &(*na)->next)
{
- if (SameResourceRecord(&ka->resrec, &na->resrec))
- { ka->resrec.rroriginalttl = 0; break; } // 0 means no change
+ if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec))
+ { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change
}
}
- // third pass - add new records
- for (na = answers; na; na = na->next)
+ // third pass - add new records to Event list
+ na = &NewAnswers;
+ while (*na)
{
- for (ka = e->KnownAnswers; ka; ka = ka->next)
- if (SameResourceRecord(&ka->resrec, &na->resrec)) break;
- if (!ka)
+ for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
+ if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break;
+ if (!*ka)
{
- // answer is not in KA list
- CacheRecord *cr = CopyCacheRecord(na, &e->qname);
- if (!cr) { Log("Error: UpdateAnswerList - CopyCacheRecord returned NULL"); return; }
+ // answer is not in list - splice from NewAnswers list, add to Event list
+ cr = *na;
+ *na = (*na)->next; // splice from list
+ cr->next = a->EventList; // add spliced record to event list
+ a->EventList = cr;
cr->resrec.rroriginalttl = 1; // 1 means add
- cr->next = e->KnownAnswers;
- e->KnownAnswers = cr;
}
+ else na = &(*na)->next;
}
-
- // now send the update
- msgID.NotAnInteger = random();
- InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags);
- end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
- if (!end) { Log("Error: UpdateAnswerList - putQuestion returned NULL"); return; }
-
- if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
- // put adds/removes in packet
- for (ka = e->KnownAnswers; ka; ka = ka->next)
+
+ // move all the removes from the answer list to the event list
+ ka = &a->KnownAnswers;
+ while (*ka)
{
- if (ka->resrec.rroriginalttl)
+ if ((*ka)->resrec.rroriginalttl == (unsigned)-1)
{
- if (verbose) GetRRDisplayString_rdb(&ka->resrec, &ka->resrec.rdata->u, rrbuf);
- VLog("%s (%s): %s", addrbuf, (mDNSs32)ka->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf);
- end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl);
- if (!end) { Log("Error: UpdateAnswerList - UpdateAnswerList returned NULL"); return; }
+ cr = *ka;
+ *ka = (*ka)->next;
+ cr->next = a->EventList;
+ a->EventList = cr;
}
+ else ka = &(*ka)->next;
}
+
+ // lastly, free the remaining records (known answers) in NewAnswers list
+ while (NewAnswers)
+ {
+ cr = NewAnswers;
+ NewAnswers = NewAnswers->next;
+ free(cr);
+ }
+ }
- // delete removes from list
- ka = e->KnownAnswers;
- while (ka)
+mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e)
+ {
+ PktMsg response;
+ CacheRecord *cr;
+ mDNSu8 *end = (mDNSu8 *)&response.msg.data;
+ mDNSOpaque16 msgID;
+ char rrbuf[80], addrbuf[32];
+ AuthRecord opt;
+
+ msgID.NotAnInteger = random();
+ if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
+ InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags);
+ end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
+ if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; }
+
+ // put adds/removes in packet
+ for (cr = e->AnswerList->EventList; cr; cr = cr->next)
{
- if ((mDNSs32)ka->resrec.rroriginalttl < 0)
- {
- CacheRecord *fptr = ka;
- if (prev) prev->next = ka->next;
- else e->KnownAnswers = ka->next;
- ka = ka->next;
- free(fptr);
- }
- else
- {
- prev = ka;
- ka = ka->next;
- }
+ if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf);
+ VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf);
+ end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl);
+ if (!end) { Log("Error: SendEvents - UpdateAnswerList returned NULL"); return; }
}
FormatLLQOpt(&opt, kLLQOp_Event, e->id, LLQLease(e));
end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0);
- if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
+ if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; }
response.len = (int)(end - (mDNSu8 *)&response.msg);
- if (response.msg.h.numAnswers)
- if (SendLLQ(d, &response, e->cli) < 0) LogErr("UpdateAnswerList", "SendLLQ");
+ if (SendLLQ(d, &response, e->cli) < 0) LogMsg("Error: SendEvents - SendLLQ");
}
mDNSlocal void PrintLLQTable(DaemonInfo *d)
// Send events to clients as a result of a change in the zone
mDNSlocal void GenLLQEvents(DaemonInfo *d)
{
- LLQEntry *e, *tmp;
+ LLQEntry **e;
int i, sd;
struct timeval t;
- char addr[32];
+
VLog("Generating LLQ Events");
gettimeofday(&t, NULL);
sd = ConnectToServer(d);
if (sd < 0) { Log("GenLLQEvents: ConnectToServer failed"); return; }
-
+
+ // get all answers up to date
for (i = 0; i < LLQ_TABLESIZE; i++)
{
- e = d->LLQTable[i];
- while(e)
+ AnswerListElem *a = d->AnswerTable[i];
+ while(a)
{
- if (e->expire < t.tv_sec)
- {
- inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
- VLog("Expiring LLQ %##s from %s", e->qname.c, addr);
- tmp = e;
- e = e->next;
- DeleteLLQ(d, tmp);
- }
+ UpdateAnswerList(d, a, sd);
+ a = a->next;
+ }
+ }
+
+ // for each established LLQ, send events
+ for (i = 0; i < LLQ_TABLESIZE; i++)
+ {
+ e = &d->LLQTable[i];
+ while(*e)
+ {
+ if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e);
else
{
- CacheRecord *tmp, *answers = AnswerQuestion(d, e, sd);
- UpdateAnswerList(d, e, answers);
- while (answers) { tmp = answers; answers = answers->next; free(tmp); }
- e = e->next;
+ if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e);
+ e = &(*e)->next;
}
- }
+ }
}
+
+ // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes
+ for (i = 0; i < LLQ_TABLESIZE; i++)
+ {
+ AnswerListElem *a = d->AnswerTable[i];
+ while(a)
+ {
+ if (a->EventList)
+ {
+ CacheRecord *cr = a->EventList, *tmp;
+ while (cr)
+ {
+ tmp = cr;
+ cr = cr->next;
+ if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp);
+ else
+ {
+ tmp->next = a->KnownAnswers;
+ a->KnownAnswers = tmp;
+ tmp->resrec.rroriginalttl = 0;
+ }
+ }
+ a->EventList = NULL;
+ }
+ a = a->next;
+ }
+ }
+
close(sd);
}
if (!ptr) Log("LLQEventMonitor: response to query did not contain SOA");
}
}
-
+
+mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e)
+ {
+ int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
+ AnswerListElem *a = d->AnswerTable[bucket];
+ while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next;
+ if (!a)
+ {
+ a = malloc(sizeof(*a));
+ if (!a) { LogErr("SetAnswerList", "malloc"); return; }
+ AssignDomainName(&a->name, &e->qname);
+ a->type = e->qtype;
+ a->refcount = 0;
+ a->KnownAnswers = NULL;
+ a->EventList = NULL;
+ a->next = d->AnswerTable[bucket];
+ d->AnswerTable[bucket] = a;
+
+ // to get initial answer list, call UpdateAnswerList and move cache records from EventList to KnownAnswers
+ UpdateAnswerList(d, a, -1);
+ a->KnownAnswers = a->EventList;
+ a->EventList = NULL;
+ }
+
+ e->AnswerList = a;
+ a->refcount ++;
+ }
+
// Allocate LLQ entry, insert into table
mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease)
{
char addr[32];
struct timeval t;
- int bucket;
- LLQEntry *e = malloc(sizeof(*e));
+ int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
+ LLQEntry *e;
+
+ e = malloc(sizeof(*e));
if (!e) { LogErr("NewLLQ", "malloc"); return NULL; }
inet_ntop(AF_INET, &cli.sin_addr, addr, 32);
e->qtype = qtype;
memset(e->id, 0, 8);
e->state = RequestReceived;
- e->KnownAnswers = NULL;
+ e->AnswerList = NULL;
if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE;
else if (lease > LLQ_MAX_LEASE) lease = LLQ_MIN_LEASE;
e->lease = lease;
// add to table
- bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
e->next = d->LLQTable[bucket];
d->LLQTable[bucket] = e;
end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
if (!end) { Log("Error: putQuestion"); return; }
- if (e->state != Established) e->KnownAnswers = AnswerQuestion(d, e, -1); // only fetch KA list the first time through
+ if (e->state != Established) { SetAnswerList(d, e); e->state = Established; }
+
if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
- for (ptr = e->KnownAnswers; ptr; ptr = ptr->next)
+ for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next)
{
if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf);
VLog("%s Intitial Answer - %s", addr, rrbuf);
if (reply) free(reply);
free(req);
- return NULL;
+ pthread_exit(NULL);
}
//!!!KRS this needs to be changed to use non-blocking sockets
return err;
}
- if (IsLLQAck(&req->pkt)) return 0; // !!!KRS need to do acks + retrans
+ if (IsLLQAck(&req->pkt)) { free(req); return 0; } // !!!KRS need to do acks + retrans
if (pthread_create(&tid, NULL, UDPUpdateRequestForkFn, req)) { LogErr("RecvUDPRequest", "pthread_create"); free(req); return -1; }
+ pthread_detach(tid);
return 0;
}
free(req);
if (in) free(in);
if (out) free(out);
- return NULL;
+ pthread_exit(NULL);
}
mDNSlocal int RecvTCPRequest(int sd, DaemonInfo *d)
if (req->sd < 0) { LogErr("RecvTCPRequest", "accept"); return -1; }
if (clilen != sizeof(req->cliaddr)) { Log("Client address of unknown size %d", clilen); free(req); return -1; }
if (pthread_create(&tid, NULL, TCPRequestForkFn, req)) { LogErr("RecvTCPRequest", "pthread_create"); free(req); return -1; }
+ pthread_detach(tid);
return 0;
}
int main(int argc, char *argv[])
{
pthread_t LLQtid;
- DaemonInfo d;
- bzero(&d, sizeof(DaemonInfo));
+ DaemonInfo *d;
+
+ d = malloc(sizeof(*d));
+ if (!d) { LogErr("main", "malloc"); exit(1); }
+ bzero(d, sizeof(DaemonInfo));
if (signal(SIGTERM, HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM");
if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO");
if (signal(SIGINT, HndlSignal) == SIG_ERR) perror("Can't catch SIGINT");
if (signal(SIGPIPE, SIG_IGN ) == SIG_ERR) perror("Can't ignore SIGPIPE");
- if (ProcessArgs(argc, argv, &d) < 0) exit(1);
+ if (ProcessArgs(argc, argv, d) < 0) exit(1);
if (!foreground)
{
}
}
- if (InitLeaseTable(&d) < 0) exit(1);
- if (SetupSockets(&d) < 0) exit(1);
- if (SetUpdateSRV(&d) < 0) exit(1);
+ if (InitLeaseTable(d) < 0) exit(1);
+ if (SetupSockets(d) < 0) exit(1);
+ if (SetUpdateSRV(d) < 0) exit(1);
- if (pthread_create(&LLQtid, NULL, LLQEventMonitor, &d)) { LogErr("main", "pthread_create"); }
- else ListenForUpdates(&d);
+ if (pthread_create(&LLQtid, NULL, LLQEventMonitor, d)) { LogErr("main", "pthread_create"); }
+ else
+ {
+ pthread_detach(LLQtid);
+ ListenForUpdates(d);
+ }
- if (ClearUpdateSRV(&d) < 0) exit(1); // clear update srv's even if ListenForUpdates or pthread_create returns an error
+ if (ClearUpdateSRV(d) < 0) exit(1); // clear update srv's even if ListenForUpdates or pthread_create returns an error
+ free(d);
exit(0);
+
}
-
Change History (most recent first):
$Log: mDNSPosix.c,v $
+Revision 1.71 2005/02/26 01:29:12 cheshire
+Ignore multicasts accidentally delivered to our unicast receiving socket
+
+Revision 1.70 2005/02/04 00:39:59 cheshire
+Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
+
Revision 1.69 2004/12/18 02:03:28 cheshire
Need to #include "dns_sd.h"
#include <sys/uio.h>
#include <sys/select.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <time.h> // platform support for UTC time
#if USES_NETLINK
// different capabilities of our target platforms.
reject = mDNSfalse;
- if (intf)
+ if (!intf)
+ {
+ // Ignore multicasts accidentally delivered to our unicast receiving socket
+ if (mDNSAddrIsDNSMulticast(&destAddr)) packetLen = -1;
+ }
+ else
{
if ( packetInfo.ipi_ifname[0] != 0 ) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0);
else if ( packetInfo.ipi_ifindex != -1 ) reject = (packetInfo.ipi_ifindex != intf->index);
if (reject)
{
- verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d",
+ verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d/%d",
&senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex,
- &intf->coreIntf.ip, intf->intfName, intf->index);
+ &intf->coreIntf.ip, intf->intfName, intf->index, skt);
packetLen = -1;
num_pkts_rejected++;
if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2)
}
else
{
- verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d",
- &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index);
+ verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d/%d",
+ &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index, skt);
num_pkts_accepted++;
}
}
GetUserSpecifiedRFC1034ComputerName( namelabel);
}
+mDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
+ {
+ char line[256];
+ char nameserver[16];
+ char keyword[10];
+ int numOfServers = 0;
+ FILE *fp = fopen(filePath, "r");
+ if (fp == NULL) return -1;
+ while (fgets(line,sizeof(line),fp))
+ {
+ struct in_addr ina;
+ line[255]='\0'; // just to be safe
+ if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue; // it will skip whitespaces
+ if (strncmp(keyword,"nameserver",10)) continue;
+ if (inet_aton(nameserver, (struct in_addr *)&ina) != 0)
+ {
+ mDNSAddr DNSAddr;
+ DNSAddr.type = mDNSAddrType_IPv4;
+ DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
+ mDNS_AddDNSServer(m, &DNSAddr, NULL);
+ numOfServers++;
+ }
+ }
+ return (numOfServers > 0) ? 0 : -1;
+ }
+
// Searches the interface list looking for the named interface.
// Returns a pointer to if it found, or NULL otherwise.
mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const char *intfName)
return intf;
}
-extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
+mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
{
PosixNetworkInterface *intf;
assert(*sktPtr == -1);
// Open the socket...
- if (intfAddr->sa_family == AF_INET) *sktPtr = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (intfAddr->sa_family == AF_INET ) *sktPtr = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#if HAVE_IPV6
else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
#endif
// Tell mDNS core about the network interfaces on this machine.
if (err == mStatus_NoError) err = SetupInterfaceList(m);
+ // Tell mDNS core about DNS Servers
+ if (err == mStatus_NoError) ParseDNSServers(m, uDNS_SERVERS_FILE);
+
if (err == mStatus_NoError)
{
err = WatchForInterfaceChange(m);
#endif
}
-extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
+mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
{
int err;
ClearInterfaceList(m);
Change History (most recent first):
$Log: mDNSPosix.h,v $
+Revision 1.17 2005/02/04 00:39:59 cheshire
+Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
+
Revision 1.16 2004/11/30 22:37:01 cheshire
Update copyright dates and add "Mode: C; tab-width: 4" headers
#endif
};
+#define uDNS_SERVERS_FILE "/etc/resolv.conf"
+extern int ParseDNSServers(mDNS *m, const char *filePath);
extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m);
// See comment in implementation.
--- /dev/null
+Microsoft Visual Studio Solution File, Format Version 7.00\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL", "mDNSWindows\DLL\dnssd.vcproj", "{AB581101-18F0-46F6-B56A-83A6B1EA657E}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mDNSResponder", "mDNSWindows\SystemService\Service.vcproj", "{C1D98254-BA27-4427-A3BE-A68CA2CC5F69}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NSPTool", "mDNSWindows\NSPTool\NSPTool.vcproj", "{208B3A9F-1CA0-4D1D-9D6C-C61616F94705}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdnsNSP", "mDNSWindows\mdnsNSP\mdnsNSP.vcproj", "{F4F15529-F0EB-402F-8662-73C5797EE557}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPlugin", "Clients\ExplorerPlugin\ExplorerPlugin.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizard", "Clients\PrinterSetupWizard\PrinterSetupWizard.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL.NET", "mDNSWindows\DLL.NET\dnssd_NET.vcproj", "{9C6701E2-82B7-44B7-9B5E-3897D9153F79}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ControlPanel", "mDNSWindows\ControlPanel\ControlPanel.vcproj", "{F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardLocRes", "Clients\PrinterSetupWizard\PrinterSetupWizardLocRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrinterSetupWizardRes", "Clients\PrinterSetupWizard\PrinterSetupWizardRes.vcproj", "{B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginLocRes", "Clients\ExplorerPlugin\ExplorerPluginLocRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExplorerPluginRes", "Clients\ExplorerPlugin\ExplorerPluginRes.vcproj", "{BB8AC1B5-6587-4163-BDC6-788B157705CA}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dns-sd", "Clients\DNS-SD.VisualStudio\dns-sd.vcproj", "{AA230639-E115-4A44-AA5A-44A61235BA50}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfiguration) = preSolution\r
+ ConfigName.0 = Debug\r
+ ConfigName.1 = Release\r
+ EndGlobalSection\r
+ GlobalSection(ProjectDependencies) = postSolution\r
+ {F4F15529-F0EB-402F-8662-73C5797EE557}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.0 = {AB581101-18F0-46F6-B56A-83A6B1EA657E}\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfiguration) = postSolution\r
+ {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.ActiveCfg = Debug|Win32\r
+ {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Debug.Build.0 = Debug|Win32\r
+ {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release.ActiveCfg = Release|Win32\r
+ {AB581101-18F0-46F6-B56A-83A6B1EA657E}.Release.Build.0 = Release|Win32\r
+ {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug.ActiveCfg = Debug|Win32\r
+ {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Debug.Build.0 = Debug|Win32\r
+ {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release.ActiveCfg = Release|Win32\r
+ {C1D98254-BA27-4427-A3BE-A68CA2CC5F69}.Release.Build.0 = Release|Win32\r
+ {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug.ActiveCfg = Debug|Win32\r
+ {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Debug.Build.0 = Debug|Win32\r
+ {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release.ActiveCfg = Release|Win32\r
+ {208B3A9F-1CA0-4D1D-9D6C-C61616F94705}.Release.Build.0 = Release|Win32\r
+ {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug.ActiveCfg = Debug|Win32\r
+ {F4F15529-F0EB-402F-8662-73C5797EE557}.Debug.Build.0 = Debug|Win32\r
+ {F4F15529-F0EB-402F-8662-73C5797EE557}.Release.ActiveCfg = Release|Win32\r
+ {F4F15529-F0EB-402F-8662-73C5797EE557}.Release.Build.0 = Release|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32\r
+ {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Debug.ActiveCfg = Debug|Win32\r
+ {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Debug.Build.0 = Debug|Win32\r
+ {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Release.ActiveCfg = Release|Win32\r
+ {9C6701E2-82B7-44B7-9B5E-3897D9153F79}.Release.Build.0 = Release|Win32\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug.ActiveCfg = Debug|Win32\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Debug.Build.0 = Debug|Win32\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release.ActiveCfg = Release|Win32\r
+ {F5D703B6-5612-4381-8BE2-2B7AEBAE58FC}.Release.Build.0 = Release|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.ActiveCfg = Debug|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Debug.Build.0 = Debug|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.ActiveCfg = Release|Win32\r
+ {B1D2CDA2-CC8F-45D5-A694-2EE45B0308CF}.Release.Build.0 = Release|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.ActiveCfg = Debug|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Debug.Build.0 = Debug|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.ActiveCfg = Release|Win32\r
+ {BB8AC1B5-6587-4163-BDC6-788B157705CA}.Release.Build.0 = Release|Win32\r
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.ActiveCfg = Debug|Win32\r
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug.Build.0 = Debug|Win32\r
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.ActiveCfg = Release|Win32\r
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Release.Build.0 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(ExtensibilityGlobals) = postSolution\r
+ EndGlobalSection\r
+ GlobalSection(ExtensibilityAddIns) = postSolution\r
+ EndGlobalSection\r
+EndGlobal\r
Change History (most recent first):
$Log: PlatformCommon.c,v $
+Revision 1.5 2005/02/01 19:33:30 ksekar
+<rdar://problem/3985239> Keychain format too restrictive
+
Revision 1.4 2005/01/19 19:19:21 ksekar
<rdar://problem/3960191> Need a way to turn off domain discovery
{
char buf [MAX_ESCAPED_DOMAIN_NAME];
char secret[MAX_ESCAPED_DOMAIN_NAME] = "";
- int slen;
mStatus err;
FILE *f = fopen(filename, "r");
if (domain && domain->c[0] && secret[0])
{
// for now we assume keyname = service reg domain and we use same key for service and hostname registration
- slen = strlen(secret);
- err = mDNS_SetSecretForZone(m, domain, domain, secret, slen, mDNStrue);
+ err = mDNS_SetSecretForZone(m, domain, domain, secret);
if (err) LogMsg("ERROR: mDNS_SetSecretForZone returned %d for domain %##s", err, domain->c);
}
.\" @APPLE_LICENSE_HEADER_END@
.\"
.\" $Log: dns-sd.1,v $
+.\" Revision 1.4 2005/02/16 02:29:32 cheshire
+.\" Update terminology
+.\"
+.\" Revision 1.3 2005/02/10 22:35:28 cheshire
+.\" <rdar://problem/3727944> Update name
+.\"
.\" Revision 1.2 2004/09/24 18:33:05 cheshire
.\" <rdar://problem/3561780> Update man pages to clarify that mDNS and dns-sd are not intended for script use
.\"
.\"
.Sh NAME
.Nm dns-sd
-.Nd Multicast DNS Service Discovery (mDNS-SD) Test Tool \" For whatis
+.Nd Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool \" For whatis
.\"
.Sh SYNOPSIS
.Nm Fl R Ar name type domain port Op Ar key=value ...
.Pp
To advertise the existence of LPR printing service on port 515 on this
machine, such that it will be discovered by the Mac OS X printing software
-and other mDNS-SD compatible printing clients, use:
+and other DNS-SD compatible printing clients, use:
.Pp
.Dl Nm Fl R Ns \ \&"My Test\&" _printer._tcp. \&. 515 pdl=application/postscript
.Pp
.Pp
Similarly, to advertise a web page being served by an HTTP
server on port 80 on this machine, such that it will show up in the
-Rendezvous list in Safari and other mDNS-SD compatible Web clients, use:
+Bonjour list in Safari and other DNS-SD compatible Web clients, use:
.Pp
.Dl Nm Fl R Ns \ \&"My Test\&" _http._tcp \&. 80 path=/path-to-page.html
.Pp
kDNSServiceType_HINFO = 13, /* Host information. */
kDNSServiceType_MINFO = 14, /* Mailbox information. */
kDNSServiceType_MX = 15, /* Mail routing information. */
- kDNSServiceType_TXT = 16, /* Text strings. */
+ kDNSServiceType_TXT = 16, /* One or more text strings. */
kDNSServiceType_RP = 17, /* Responsible person. */
kDNSServiceType_AFSDB = 18, /* AFS cell database. */
kDNSServiceType_X25 = 19, /* X_25 calling address. */
};
-/* Maximum length, in bytes, of a domain name represented as an escaped C-String */
-/* including the final trailing dot, and the C-String terminating NULL at the end */
+/* Maximum length, in bytes, of a service name represented as a */
+/* literal C-String, including the terminating NULL at the end. */
+
+#define kDNSServiceMaxServiceName 64
+
+/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
+/* including the final trailing dot, and the C-String terminating NULL at the end. */
#define kDNSServiceMaxDomainName 1005
* it is, by definition, just a single literal string. Any characters in that string
* represent exactly what they are. The "regtype" portion is, technically speaking,
* escaped, but since legal regtypes are only allowed to contain letters, digits,
- * and hyphens, the issue is moot. The "domain" portion is also escaped, though
- * most domains in use on the public Internet today, like regtypes, don't contain
- * any characters that need to be escaped. As DNS-SD becomes more popular, rich-text
- * domains for service discovery will become common, so software should be written
- * to cope with domains with escaping.
+ * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
+ * portion is also escaped, though most domains in use on the public Internet
+ * today, like regtypes, don't contain any characters that need to be escaped.
+ * As DNS-SD becomes more popular, rich-text domains for service discovery will
+ * become common, so software should be written to cope with domains with escaping.
+ *
+ * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
+ * terminating NULL at the end). The regtype is of the form _service._tcp or
+ * _service._udp, where the "service" part is 1-14 characters, which may be
+ * letters, digits, or hyphens. The domain part of the three-part name may be
+ * any legal domain, providing that the resulting servicename+regtype+domain
+ * name does not exceed 255 bytes.
*
* For most software, these issues are transparent. When browsing, the discovered
* servicenames should simply be displayed as-is. When resolving, the discovered
* flags: Currently unused, reserved for future use.
*
* errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
- * indicate the failure that occurred (including name conflicts, if the
- * kDNSServiceFlagsNoAutoRename flag was passed to the
- * callout.) Other parameters are undefined if errorCode is nonzero.
+ * indicate the failure that occurred (including name conflicts,
+ * if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
+ * Other parameters are undefined if errorCode is nonzero.
*
* name: The service name registered (if the application did not specify a name in
* DNSServiceRegister(), this indicates what name was automatically chosen).
* will pass 0). See flag definitions above for details.
*
* name: If non-NULL, specifies the service name to be registered.
- * Most applications will not specify a name, in which case the
- * computer name is used (this name is communicated to the client via
- * the callback).
+ * Most applications will not specify a name, in which case the computer
+ * name is used (this name is communicated to the client via the callback).
+ * If a name is specified, it must be 1-63 bytes of UTF-8 text.
+ * If the name is longer than 63 bytes it will be automatically truncated
+ * to a legal length, unless the NoAutoRename flag is set,
+ * in which case kDNSServiceErr_BadParam will be returned.
*
* regtype: The service type followed by the protocol, separated by a dot
- * (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
- * New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html.
+ * (e.g. "_ftp._tcp"). The service type must be an underscore, followed
+ * by 1-14 characters, which may be letters, digits, or hyphens.
+ * The transport protocol must be "_tcp" or "_udp". New service types
+ * should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
*
* domain: If non-NULL, specifies the domain on which to advertise the service.
* Most applications will not specify a domain, instead automatically
*
* txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
*
- * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord
- * MUST be a properly formatted DNS TXT record, i.e. <length byte> <data>
- * <length byte> <data> ...
+ * txtRecord: The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
+ * TXT record, i.e. <length byte> <data> <length byte> <data> ...
+ * Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
+ * i.e. it creates a TXT record of length one containing a single empty string.
+ * RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
+ * string is the smallest legal DNS TXT record.
*
* callBack: The function to be called when the registration completes or asynchronously
* fails. The client MAY pass NULL for the callback - The client will NOT be notified
* Note: When the desired results have been returned, the client MUST terminate the resolve by calling
* DNSServiceRefDeallocate().
*
- * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record and
- * a single TXT record (the TXT record may be empty.) To resolve non-standard services with multiple
- * SRV or TXT records, DNSServiceQueryRecord() should be used.
+ * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
+ * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
+ * DNSServiceQueryRecord() should be used.
*
* DNSServiceResolveReply Callback Parameters:
*
*
* bufferLen: The size of the storage provided in the "buffer" parameter.
*
- * buffer: The storage used to hold the TXTRecord data.
+ * buffer: Optional caller-supplied storage used to hold the TXTRecord data.
* This storage must remain valid for as long as
* the TXTRecordRef.
*/
Change History (most recent first):
$Log: dnssd_clientstub.c,v $
+Revision 1.45 2005/02/01 01:25:06 shersche
+Define sleep() to be Sleep() for Windows compatibility
+
Revision 1.44 2005/01/27 22:57:56 cheshire
Fix compile errors on gcc4
Use dnssd_close() rather than close() for Windows compatibility
Revision 1.41 2004/12/23 17:34:26 ksekar
-<rdar://problem/3931319> Rendevzous calls leak sockets if mDNSResponder is not running
+<rdar://problem/3931319> Calls leak sockets if mDNSResponder is not running
Revision 1.40 2004/11/23 03:39:47 cheshire
Let interface name/index mapping capability live directly in JNISupport.c,
Changes for Windows compatibility
Revision 1.29 2004/09/16 21:46:38 ksekar
-<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area Rendezvous domain
+<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
Revision 1.28 2004/08/11 17:10:04 cheshire
Fix signed/unsigned warnings
// conversion in expression"
#pragma warning(disable:4152)
+#define sleep(X) Sleep((X) * 1000)
+
static int g_initWinsock = 0;
#endif
Change History (most recent first):
$Log: dnssd_ipc.h,v $
+Revision 1.19 2005/02/02 02:25:22 cheshire
+<rdar://problem/3980388> /var/run/mDNSResponder should be /var/run/mdnsd on Linux
+
Revision 1.18 2005/01/27 22:57:56 cheshire
Fix compile errors on gcc4
Changes for Windows compatibility
Revision 1.12 2004/09/16 21:46:38 ksekar
-<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area Rendezvous domain
+<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
Revision 1.11 2004/08/10 06:24:56 cheshire
Use types with precisely defined sizes for 'op' and 'reg_index', for better
# define dnssd_sockaddr_t struct sockaddr_in
#else
# define AF_DNSSD AF_LOCAL
-# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder"
+# ifndef MDNS_UDS_SERVERPATH
+# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder"
+# endif
# define LISTENQ 100
// longest legal control path length
# define MAX_CTLPATH 256
.\" @APPLE_LICENSE_HEADER_END@
.\"
.\" $Log: mDNS.1,v $
+.\" Revision 1.7 2005/02/16 02:29:32 cheshire
+.\" Update terminology
+.\"
+.\" Revision 1.6 2005/02/10 22:35:28 cheshire
+.\" <rdar://problem/3727944> Update name
+.\"
.\" Revision 1.5 2004/09/24 18:33:05 cheshire
.\" <rdar://problem/3561780> Update man pages to clarify that mDNS and dns-sd are not intended for script use
.\"
.\"
.Sh NAME
.Nm mDNS
-.Nd Multicast DNS Service Discovery (mDNS-SD) Test Tool \" For whatis
+.Nd Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool \" For whatis
.\"
.Sh SYNOPSIS
.Nm Fl R Ar name type domain port Op Ar key=value ...
.Pp
To advertise the existence of LPR printing service on port 515 on this
machine, such that it will be discovered by the Mac OS X printing software
-and other mDNS-SD compatible printing clients, use:
+and other DNS-SD compatible printing clients, use:
.Pp
.Dl Nm Fl R Ns \ \&"My Test\&" _printer._tcp. \&. 515 pdl=application/postscript
.Pp
.Pp
Similarly, to advertise a web page being served by an HTTP
server on port 80 on this machine, such that it will show up in the
-Rendezvous list in Safari and other mDNS-SD compatible Web clients, use:
+Bonjour list in Safari and other DNS-SD compatible Web clients, use:
.Pp
.Dl Nm Fl R Ns \ \&"My Test\&" _http._tcp \&. 80 path=/path-to-page.html
.Pp
.\" @APPLE_LICENSE_HEADER_END@
.\"
.\" $Log: mDNSResponder.8,v $
+.\" Revision 1.6 2005/02/10 22:35:28 cheshire
+.\" <rdar://problem/3727944> Update name
+.\"
.\" Revision 1.5 2004/06/29 02:41:38 cheshire
.\" Add note that mDNSResponder is called mdnsd on some systems
.\"
.Pp
For information on how to use the Multicast DNS and the
DNS Service Discovery APIs on Mac OS X and other platforms, see
-.Pa http://developer.apple.com/macosx/rendezvous/
+.Pa http://developer.apple.com/bonjour/
.Pp
For the source code to
.Nm , see
-.Pa http://developer.apple.com/darwin/projects/rendezvous/
+.Pa http://developer.apple.com/darwin/projects/bonjour/
.\"
.Sh BUGS
.Nm
Change History (most recent first):
$Log: uds_daemon.c,v $
+Revision 1.180 2005/03/10 00:13:12 cheshire
+<rdar://problem/4043098> DNSServiceBrowse no longer returning error codes for invalid types
+In handle_browse_request(), mStatus err was being set correctly if an error occurred,
+but the end of the function returned mStatus_NoError intead of err.
+
+Revision 1.179 2005/03/04 02:47:26 ksekar
+<rdar://problem/4026393> SCPreference domains disappear from enumeration when moving out from firewall
+
+Revision 1.178 2005/02/25 19:35:38 ksekar
+<rdar://problem/4023750> Non-local empty string registration failures should not return errors to caller
+
+Revision 1.177 2005/02/25 03:05:41 cheshire
+Change "broken pipe" message to debugf()
+
+Revision 1.176 2005/02/24 18:44:45 ksekar
+<rdar://problem/4018516> Printer Sharing does not get re-registered with wide-area
+
+Revision 1.175 2005/02/21 21:31:25 ksekar
+<rdar://problem/4015162> changed LogMsg to debugf
+
+Revision 1.174 2005/02/20 01:41:17 cheshire
+Fix compiler signed/unsigned warning
+
+Revision 1.173 2005/02/18 01:26:42 cheshire
+<rdar://problem/4012162> "Could not write data to client after 60 seconds" message could be more helpful
+Log additional information about failed client
+
+Revision 1.172 2005/02/18 00:58:35 cheshire
+<rdar://problem/4012162> "Could not write data to client after 60 seconds" message could be more helpful
+
+Revision 1.171 2005/02/18 00:43:12 cheshire
+<rdar://problem/4010245> mDNSResponder should auto-truncate service names that are too long
+
+Revision 1.170 2005/02/16 01:15:02 cheshire
+Improve LogOperation() debugging messages for DNSServiceBrowse and DNSServiceRegister
+
+Revision 1.169 2005/02/08 01:57:14 cheshire
+More detailed error reporting in udsserver_init()
+
+Revision 1.168 2005/02/03 00:44:37 cheshire
+<rdar://problem/3986663> DNSServiceUpdateRecord returns kDNSServiceErr_Invalid when rdlen=0, rdata=NULL
+
+Revision 1.167 2005/02/02 02:19:32 cheshire
+Add comment explaining why unlink(MDNS_UDS_SERVERPATH); fails
+
+Revision 1.166 2005/02/01 19:58:52 ksekar
+Shortened cryptic "broken pipe" syslog message
+
+Revision 1.165 2005/02/01 19:56:47 ksekar
+Moved LogMsg from daemon.c to uds_daemon.c, cleaned up wording
+
Revision 1.164 2005/01/28 06:07:55 cheshire
Don't use deliver_error() from within handle_regrecord_request()
Changes for Windows compatibility
Revision 1.81 2004/09/16 21:46:38 ksekar
-<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area Rendezvous domain
+<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
Revision 1.80 2004/09/16 01:58:23 cheshire
Fix compiler warnings
static void browse_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
static void handle_regservice_request(request_state *request);
static void regservice_termination_callback(void *context);
-static void process_service_registration(ServiceRecordSet *const srs);
+static void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError);
static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
static mStatus handle_add_request(request_state *rstate);
static mStatus handle_update_request(request_state *rstate);
#define PID_FILE "/var/run/mDNSResponder.pid"
#endif
+mDNSlocal void LogClientInfo(request_state *req)
+ {
+ void *t = req->termination_context;
+ if (t)
+ {
+ if (req->terminate == regservice_termination_callback)
+ {
+ service_instance *ptr;
+ for (ptr = ((service_info *)t)->instances; ptr; ptr = ptr->next)
+ LogMsgNoIdent("%3d: DNSServiceRegister %##s %u", req->sd, ptr->srs.RR_SRV.resrec.name->c, SRS_PORT(&ptr->srs));
+ }
+ else if (req->terminate == browse_termination_callback)
+ {
+ browser_t *blist;
+ for (blist = req->browser_info->browsers; blist; blist = blist->next)
+ LogMsgNoIdent("%3d: DNSServiceBrowse %##s", req->sd, blist->q.qname.c);
+ }
+ else if (req->terminate == resolve_termination_callback)
+ LogMsgNoIdent("%3d: DNSServiceResolve %##s", req->sd, ((resolve_termination_t *)t)->qsrv.qname.c);
+ else if (req->terminate == question_termination_callback)
+ LogMsgNoIdent("%3d: DNSServiceQueryRecord %##s", req->sd, ((DNSQuestion *) t)->qname.c);
+ else if (req->terminate == enum_termination_callback)
+ LogMsgNoIdent("%3d: DNSServiceEnumerateDomains %##s", req->sd, ((enum_termination_t *) t)->all->question.qname.c);
+ }
+ }
+
static void FatalError(char *errmsg)
{
LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno()));
}
if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) == dnssd_InvalidSocket)
+ {
+ my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed");
goto error;
+ }
bzero(&laddr, sizeof(laddr));
laddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
if (ret < 0)
+ {
+ my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
goto error;
+ }
}
#else
{
ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
umask(mask);
if (ret < 0)
+ {
+ my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
goto error;
+ }
}
#endif
#else
if (fcntl(listenfd, F_SETFL, O_NONBLOCK) != 0)
#endif
- {
+ {
my_perror("ERROR: could not set listen socket to non-blocking mode");
goto error;
- }
+ }
if (listen(listenfd, LISTENQ) != 0)
{
dnssd_close(listenfd);
#if !defined(USE_TCP_LOOPBACK)
- unlink(MDNS_UDS_SERVERPATH);
+ // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody"
+ // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket.
+ // It would be nice if we could find a solution to this problem
+ if (unlink(MDNS_UDS_SERVERPATH))
+ debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
#endif
return 0;
}
}
if (result == t_morecoming)
- {
- if (!req->time_blocked) req->time_blocked = now;
- debugf("udsserver_idle: client has been blocked for %ld seconds", (now - req->time_blocked) / mDNSPlatformOneSecond);
- if (now - req->time_blocked >= MAX_TIME_BLOCKED)
- {
- LogMsg("Could not write data to client after %ld seconds - aborting connection", MAX_TIME_BLOCKED / mDNSPlatformOneSecond);
- abort_request(req);
- result = t_terminated;
- }
- else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond; // try again in a second
- }
+ {
+ if (!req->time_blocked) req->time_blocked = now;
+ debugf("udsserver_idle: client has been blocked for %ld seconds", (now - req->time_blocked) / mDNSPlatformOneSecond);
+ if (now - req->time_blocked >= MAX_TIME_BLOCKED)
+ {
+ LogMsg("Could not write data to client %d after %ld seconds - aborting connection", req->sd, MAX_TIME_BLOCKED / mDNSPlatformOneSecond);
+ LogClientInfo(req);
+ abort_request(req);
+ result = t_terminated;
+ }
+ else if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond; // try again in a second
+ }
if (result == t_terminated || result == t_error)
//since we're already doing a list traversal, we unlink the request manunally instead of calling unlink_request()
{
LogMsgNoIdent("Cache currently contains %lu records; %lu referenced by active questions", CacheUsed, CacheActive);
for (req = all_requests; req; req=req->next)
- {
- void *t = req->termination_context;
- if (!t) continue;
- if (req->terminate == regservice_termination_callback)
- {
- service_instance *ptr;
- for (ptr = ((service_info *)t)->instances; ptr; ptr = ptr->next)
- LogMsgNoIdent("%3d: DNSServiceRegister %##s %u", req->sd, ptr->srs.RR_SRV.resrec.name->c, SRS_PORT(&ptr->srs));
- }
- else if (req->terminate == browse_termination_callback)
- {
- browser_t *blist;
- for (blist = req->browser_info->browsers; blist; blist = blist->next)
- LogMsgNoIdent("%3d: DNSServiceBrowse %##s", req->sd, blist->q.qname.c);
- }
- else if (req->terminate == resolve_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceResolve %##s", req->sd, ((resolve_termination_t *)t)->qsrv.qname.c);
- else if (req->terminate == question_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceQueryRecord %##s", req->sd, ((DNSQuestion *) t)->qname.c);
- else if (req->terminate == enum_termination_callback)
- LogMsgNoIdent("%3d: DNSServiceEnumerateDomains %##s", req->sd, ((enum_termination_t *) t)->all->question.qname.c);
- }
+ LogClientInfo(req);
now = mDNS_TimeNow(m);
LogMsgNoIdent("Timenow 0x%08lX (%ld)", (mDNSu32)now, now);
domainname typedn, d, temp;
mDNSs32 NumSubTypes;
char *ptr;
- mStatus err;
+ mStatus err = mStatus_NoError;
DNameListElem *search_domain_list, *sdom;
browser_info_t *info = NULL;
request->termination_context = info;
request->terminate = browse_termination_callback;
- LogOperation("%3d: DNSServiceBrowse(%##s%s) START", request->sd, info->regtype.c, domain);
+ LogOperation("%3d: DNSServiceBrowse(\"%##s\", \"%s\") START", request->sd, info->regtype.c, domain);
if (domain[0])
{
if (!MakeDomainNameFromDNSNameString(&d, domain)) { err = mStatus_BadParamErr; goto error; }
mDNS_FreeDNameList(search_domain_list);
}
- deliver_error(request, mStatus_NoError);
+ deliver_error(request, err);
return;
error:
{
request_state *rstate;
service_info *info;
-
+
+ LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->c);
for (rstate = all_requests; rstate; rstate = rstate->next)
{
if (rstate->terminate != regservice_termination_callback) continue;
prev = si;
si = si->next;
}
- if (!si) LogMsg("udsserver_default_reg_domain_changed - domain %##s not registered", d->c);
+ if (!si) debugf("udsserver_default_reg_domain_changed - domain %##s not registered", d->c); // normal if registration failed
}
}
}
{
DNSServiceFlags flags;
uint32_t ifi;
- char name[256], domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME];
+ char name[1024]; // Lots of spare space for extra-long names that we'll auto-truncate down to 63 bytes
+ char domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME];
char *ptr;
domainname d, srv;
mStatus result;
service->InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(gmDNS, ifi);
if (ifi && !service->InterfaceID)
{ LogMsg("ERROR: handle_regservice_request - Couldn't find InterfaceID for interfaceIndex %d", ifi); goto bad_param; }
- if (get_string(&ptr, name, 256) < 0 ||
+ if (get_string(&ptr, name, sizeof(name)) < 0 ||
get_string(&ptr, service->type_as_string, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
get_string(&ptr, domain, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
get_string(&ptr, host, MAX_ESCAPED_DOMAIN_NAME) < 0)
service->port.b[1] = *ptr++;
service->txtlen = get_short(&ptr);
- service->txtdata = get_rdata(&ptr, service->txtlen);
+ if (service->txtlen)
+ {
+ service->txtdata = mallocL("txtdata", service->txtlen);
+ if (!service->txtdata) { my_perror("ERROR: malloc"); result = mStatus_NoMemoryErr; goto finish; }
+ memcpy(service->txtdata, get_rdata(&ptr, service->txtlen), service->txtlen);
+ }
+ else service->txtdata = NULL;
// Check for sub-types after the service type
service->num_subtypes = ChopSubTypes(service->type_as_string); // Note: Modifies regtype string to remove trailing subtypes
}
else
{
+ // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel
+ if ((flags & kDNSServiceFlagsNoAutoRename) == 0)
+ {
+ int newlen = TruncateUTF8ToLength((mDNSu8*)name, mDNSPlatformStrLen(name), MAX_DOMAIN_LABEL);
+ name[newlen] = 0;
+ }
if (!MakeDomainLabelFromLiteralString(&service->name, name))
{ LogMsg("ERROR: handle_regservice_request - name bad %s", name); goto bad_param; }
service->autoname = mDNSfalse;
count+1, srv.c, mDNSVal16(service->port));
}
- LogOperation("%3d: DNSServiceRegister(%##s, %u) START", request->sd, srv.c, mDNSVal16(service->port));
+ LogOperation("%3d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", \"%s\", %u) START",
+ request->sd, name, service->type_as_string, domain, host, mDNSVal16(service->port));
result = register_service_instance(request, &d);
if (!result && !*domain)
static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
{
mStatus err;
+ mDNSBool SuppressError = mDNSfalse;
service_instance *instance = srs->ServiceContext;
(void)m; // Unused
if (!srs) { LogMsg("regservice_callback: srs is NULL %d", result); return; }
if (!instance) { LogMsg("regservice_callback: srs->ServiceContext is NULL %d", result); return; }
+ if (instance->request && instance->request->service_registration)
+ {
+ service_info *info = instance->request->service_registration;
+ if (info->default_domain && !instance->default_local) SuppressError = mDNStrue;
+ // don't send errors up to client for wide-area, empty-string registrations
+ }
+
if (result == mStatus_NoError)
LogOperation("%3d: DNSServiceRegister(%##s, %u) REGISTERED ", instance->sd, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port));
else if (result == mStatus_MemFree)
srs->RR_TXT.AllowRemoteQuery = mDNStrue;
for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue;
}
- process_service_registration(srs);
+ process_service_registration(srs, SuppressError);
if (instance->autoname && CountPeerRegistrations(m, srs) == 0)
RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately
return;
request_state *rs = instance->request;
if (!rs) { LogMsg("ERROR: regservice_callback: received result %ld with a NULL request pointer", result); return; }
free_service_instance(instance);
- if (deliver_async_error(rs, reg_service_reply, result) < 0)
+ if (!SuppressError && deliver_async_error(rs, reg_service_reply, result) < 0)
{
abort_request(rs);
unlink_request(rs);
if (!rs) { LogMsg("ERROR: regservice_callback: received result %ld with a NULL request pointer", result); return; }
if (result != mStatus_NATTraversal) LogMsg("ERROR: unknown result in regservice_callback: %ld", result);
free_service_instance(instance);
- if (deliver_async_error(rs, reg_service_reply, result) < 0)
+ if (!SuppressError && deliver_async_error(rs, reg_service_reply, result) < 0)
{
abort_request(rs);
unlink_request(rs);
if (!newrd) FatalError("ERROR: malloc");
newrd->MaxRDLength = (mDNSu16) rdsize;
memcpy(&newrd->u, rdata, rdlen);
+
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
+ if (rr->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
+
result = mDNS_Update(gmDNS, rr, ttl, rdlen, newrd, update_callback);
if (result) { LogMsg("ERROR: mDNS_Update - %ld", result); freeL("handle_update_request", newrd); }
return result;
if (oldrd != &rr->rdatastorage) freeL("update_callback", oldrd);
}
-static void process_service_registration(ServiceRecordSet *const srs)
+static void process_service_registration(ServiceRecordSet *const srs, mDNSBool SuppressError)
{
reply_state *rep;
transfer_state send_result;
err = gen_rr_response(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, req, &rep);
if (err)
{
- if (deliver_async_error(req, reg_service_reply, err) < 0)
+ if (SuppressError && deliver_async_error(req, reg_service_reply, err) < 0)
{
abort_request(req);
unlink_request(req);
if (mDNS_DeregisterService(gmDNS, &p->srs)) free_service_instance(p);
}
info->request->service_registration = NULL; // clear pointer from request back to info
+ if (info->txtdata) { freeL("txtdata", info->txtdata); info->txtdata = NULL; }
freeL("service_info", info);
}
(void)m; // Unused
if (answer->rrtype != kDNSType_PTR) return;
+ if (!AddRecord && de->type != mDNS_DomainTypeBrowse) return;
+
if (AddRecord)
{
flags |= kDNSServiceFlagsAdd;
if (de->type == mDNS_DomainTypeRegistrationDefault || de->type == mDNS_DomainTypeBrowseDefault)
flags |= kDNSServiceFlagsDefault;
- }
+ }
ConvertDomainNameToCString(&answer->rdata->u.name, domain);
// note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from
// a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the
#if !defined(PLATFORM_NO_EPIPE)
if (dnssd_errno() == EPIPE)
{
- LogMsg("%3d: broken pipe - cleanup will be handled by run-loop read wakeup", rs->sd);
+ debugf("%3d: broken pipe", rs->sd);
rs->ts = t_terminated;
rs->request->ts = t_terminated;
return t_terminated;
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: ConfigDialog.cpp,v $
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+
+#include "ConfigDialog.h"
+#include "ControlPanel.h"
+
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+IMPLEMENT_DYNCREATE(CConfigDialog, CDialog)
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigDialog::CConfigDialog
+//---------------------------------------------------------------------------------------------------------------------------
+
+CConfigDialog::CConfigDialog()
+ : CDialog(CConfigDialog::IDD, NULL)
+{
+ //{{AFX_DATA_INIT(CConfigDialog)
+ //}}AFX_DATA_INIT
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigDialog::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CConfigDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CConfigDialog)
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CConfigDialog, CDialog)
+ //{{AFX_MSG_MAP(CConfigDialog)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
--- /dev/null
+/*\r
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.\r
+ *\r
+ * @APPLE_LICENSE_HEADER_START@\r
+ * \r
+ * This file contains Original Code and/or Modifications of Original Code\r
+ * as defined in and that are subject to the Apple Public Source License\r
+ * Version 2.0 (the 'License'). You may not use this file except in\r
+ * compliance with the License. Please obtain a copy of the License at\r
+ * http://www.opensource.apple.com/apsl/ and read it before using this\r
+ * file.\r
+ * \r
+ * The Original Code and all software distributed under the License are\r
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
+ * Please see the License for the specific language governing rights and\r
+ * limitations under the License.\r
+ * \r
+ * @APPLE_LICENSE_HEADER_END@\r
+\r
+ Change History (most recent first):\r
+\r
+$Log: ConfigDialog.h,v $
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+\r
+\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "stdafx.h"\r
+#include "resource.h"\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CConfigDialog\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+class CConfigDialog : public CDialog\r
+{\r
+public:\r
+\r
+ CConfigDialog();\r
+\r
+protected:\r
+\r
+ //{{AFX_DATA(CConfigDialog)\r
+ enum { IDD = IDR_APPLET };\r
+ //}}AFX_DATA\r
+\r
+ //{{AFX_VIRTUAL(CConfigDialog)\r
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support\r
+ //}}AFX_VIRTUAL\r
+\r
+ //{{AFX_MSG(CConfigDialog)\r
+ //}}AFX_MSG\r
+ DECLARE_MESSAGE_MAP()\r
+\r
+ DECLARE_DYNCREATE(CConfigDialog)\r
+};\r
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: ConfigPropertySheet.cpp,v $
+Revision 1.3 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#include "ConfigPropertySheet.h"
+#include <WinServices.h>
+#include <process.h>
+
+// Custom events
+
+#define WM_DATAREADY ( WM_USER + 0x100 )
+#define WM_REGISTRYCHANGED ( WM_USER + 0x101 )
+
+
+IMPLEMENT_DYNCREATE(CConfigPropertySheet, CPropertySheet)
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::CConfigPropertySheet
+//---------------------------------------------------------------------------------------------------------------------------
+
+CConfigPropertySheet::CConfigPropertySheet()
+:
+ CPropertySheet(),
+ m_browseDomainsRef( NULL ),
+ m_regDomainsRef( NULL ),
+ m_thread( NULL ),
+ m_threadExited( NULL )
+{
+ AddPage(&m_firstPage);
+ AddPage(&m_secondPage);
+ AddPage(&m_thirdPage);
+
+ InitializeCriticalSection( &m_lock );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::~CConfigPropertySheet
+//---------------------------------------------------------------------------------------------------------------------------
+
+CConfigPropertySheet::~CConfigPropertySheet()
+{
+ DeleteCriticalSection( &m_lock );
+}
+
+
+BEGIN_MESSAGE_MAP(CConfigPropertySheet, CPropertySheet)
+ //{{AFX_MSG_MAP(CConfigPropertySheet)
+ //}}AFX_MSG_MAP
+ ON_MESSAGE( WM_DATAREADY, OnDataReady )
+ ON_MESSAGE( WM_REGISTRYCHANGED, OnRegistryChanged )
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::OnInitDialog
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CConfigPropertySheet::OnInitDialog()
+{
+ OSStatus err;
+
+ BOOL b = CPropertySheet::OnInitDialog();
+
+ err = SetupBrowsing();
+ require_noerr( err, exit );
+
+ err = SetupRegistryNotifications();
+ require_noerr( err, exit );
+
+exit:
+
+ return b;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::OnCommand
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CConfigPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+ // Check if OK or Cancel was hit
+
+ if ( ( wParam == ID_WIZFINISH ) || ( wParam == IDOK ) || ( wParam == IDCANCEL ) )
+ {
+ OnEndDialog();
+ }
+
+ return CPropertySheet::OnCommand(wParam, lParam);
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::OnDataReady
+//---------------------------------------------------------------------------------------------------------------------------
+
+LONG
+CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam)
+{
+ if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
+ {
+ dlog( kDebugLevelError, "OnSocket: window error\n" );
+ }
+ else
+ {
+ SOCKET sock = (SOCKET) inWParam;
+
+ if ( m_browseDomainsRef && DNSServiceRefSockFD( m_browseDomainsRef ) == (int) sock )
+ {
+ DNSServiceProcessResult( m_browseDomainsRef );
+ }
+ else if ( m_regDomainsRef && DNSServiceRefSockFD( m_regDomainsRef ) == (int) sock )
+ {
+ DNSServiceProcessResult( m_regDomainsRef );
+ }
+ }
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::OnRegistryChanged
+//---------------------------------------------------------------------------------------------------------------------------
+
+afx_msg LONG
+CConfigPropertySheet::OnRegistryChanged( WPARAM inWParam, LPARAM inLParam )
+{
+ DEBUG_UNUSED( inWParam );
+ DEBUG_UNUSED( inLParam );
+
+ if ( GetActivePage() == &m_firstPage )
+ {
+ m_firstPage.OnRegistryChanged();
+ }
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::OnEndDialog
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CConfigPropertySheet::OnEndDialog()
+{
+ OSStatus err;
+
+ err = TearDownRegistryNotifications();
+ check_noerr( err );
+
+ err = TearDownBrowsing();
+ check_noerr( err );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::SetupBrowsing
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CConfigPropertySheet::SetupBrowsing()
+{
+ OSStatus err;
+
+ // Start browsing for browse domains
+
+ err = DNSServiceEnumerateDomains( &m_browseDomainsRef, kDNSServiceFlagsBrowseDomains, 0, BrowseDomainsReply, this );
+ require_noerr( err, exit );
+
+ err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE );
+ require_noerr( err, exit );
+
+ // Start browsing for registration domains
+
+ err = DNSServiceEnumerateDomains( &m_regDomainsRef, kDNSServiceFlagsRegistrationDomains, 0, RegDomainsReply, this );
+ require_noerr( err, exit );
+
+ err = WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( err )
+ {
+ TearDownBrowsing();
+ }
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::TearDownBrowsing
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CConfigPropertySheet::TearDownBrowsing()
+{
+ OSStatus err = kNoErr;
+
+ if ( m_browseDomainsRef )
+ {
+ err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, 0, 0 );
+ check_noerr( err );
+
+ DNSServiceRefDeallocate( m_browseDomainsRef );
+
+ m_browseDomainsRef = NULL;
+ }
+
+ if ( m_regDomainsRef )
+ {
+ err = WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef ), m_hWnd, 0, 0 );
+ check_noerr( err );
+
+ DNSServiceRefDeallocate( m_regDomainsRef );
+
+ m_regDomainsRef = NULL;
+ }
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::SetupRegistryNotifications
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CConfigPropertySheet::SetupRegistryNotifications()
+{
+ unsigned int threadId;
+ OSStatus err;
+
+ check( m_threadExited == NULL );
+ check( m_thread == NULL );
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\State\\Hostnames", &m_statusKey );
+ require_noerr( err, exit );
+
+ m_threadExited = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( m_threadExited, (OSStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // Create thread with _beginthreadex() instead of CreateThread() to avoid memory leaks when using static run-time
+ // libraries. See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
+
+ m_thread = (HANDLE) _beginthreadex_compat( NULL, 0, WatchRegistry, this, 0, &threadId );
+ err = translate_errno( m_thread, (OSStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( err )
+ {
+ TearDownRegistryNotifications();
+ }
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::TearDownRegistryNotifications
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CConfigPropertySheet::TearDownRegistryNotifications()
+{
+ OSStatus err = kNoErr;
+
+ if ( m_statusKey )
+ {
+ EnterCriticalSection( &m_lock );
+
+ RegCloseKey( m_statusKey );
+ m_statusKey = NULL;
+
+ LeaveCriticalSection( &m_lock );
+ }
+
+ if ( m_threadExited )
+ {
+ err = WaitForSingleObject( m_threadExited, 5 * 1000 );
+ require_noerr( err, exit );
+ }
+
+exit:
+
+ if ( m_threadExited )
+ {
+ CloseHandle( m_threadExited );
+ m_threadExited = NULL;
+ }
+
+ if ( m_thread )
+ {
+ CloseHandle( m_thread );
+ m_thread = NULL;
+ }
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::DecodeDomainName
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CConfigPropertySheet::DecodeDomainName( const char * raw, CString & decoded )
+{
+ char nextLabel[128] = "\0";
+ char decodedDomainString[kDNSServiceMaxDomainName];
+ char * buffer = (char *) raw;
+ int labels = 0, i;
+ char text[64];
+ const char *label[128];
+ OSStatus err;
+
+ // Initialize
+
+ decodedDomainString[0] = '\0';
+
+ // Count the labels
+
+ while ( *buffer )
+ {
+ label[labels++] = buffer;
+ buffer = (char *) GetNextLabel(buffer, text);
+ }
+
+ buffer = (char*) raw;
+
+ for (i = 0; i < labels; i++)
+ {
+ buffer = (char *)GetNextLabel(buffer, nextLabel);
+ strcat(decodedDomainString, nextLabel);
+ strcat(decodedDomainString, ".");
+ }
+
+ // Remove trailing dot from domain name.
+
+ decodedDomainString[ strlen( decodedDomainString ) - 1 ] = '\0';
+
+ // Convert to Unicode
+
+ err = UTF8StringToStringObject( decodedDomainString, decoded );
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::GetNextLabel
+//---------------------------------------------------------------------------------------------------------------------------
+
+const char*
+CConfigPropertySheet::GetNextLabel( const char * cstr, char label[64] )
+{
+ char *ptr = label;
+ while (*cstr && *cstr != '.') // While we have characters in the label...
+ {
+ char c = *cstr++;
+ if (c == '\\')
+ {
+ c = *cstr++;
+ if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
+ {
+ int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal
+ int v1 = cstr[ 0] - '0';
+ int v2 = cstr[ 1] - '0';
+ int val = v0 * 100 + v1 * 10 + v2;
+ if (val <= 255) { c = (char)val; cstr += 2; } // If valid three-digit decimal value, use it
+ }
+ }
+ *ptr++ = c;
+ if (ptr >= label+64) return(NULL);
+ }
+ if (*cstr) cstr++; // Skip over the trailing dot (if present)
+ *ptr++ = 0;
+ return(cstr);
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::BrowseDomainsReply
+//---------------------------------------------------------------------------------------------------------------------------
+
+void DNSSD_API
+CConfigPropertySheet::BrowseDomainsReply
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * replyDomain,
+ void * context
+ )
+{
+ CConfigPropertySheet * self = reinterpret_cast<CConfigPropertySheet*>(context);
+ CString decoded;
+ OSStatus err;
+
+ DEBUG_UNUSED( sdRef );
+ DEBUG_UNUSED( interfaceIndex );
+
+ if ( errorCode )
+ {
+ goto exit;
+ }
+
+ check( replyDomain );
+
+ // Ignore local domains
+
+ if ( strcmp( replyDomain, "local." ) == 0 )
+ {
+ goto exit;
+ }
+
+
+
+ err = self->DecodeDomainName( replyDomain, decoded );
+ require_noerr( err, exit );
+
+ // Remove trailing '.'
+
+ decoded.TrimRight( '.' );
+
+ if ( flags & kDNSServiceFlagsAdd )
+ {
+ self->m_browseDomains.push_back( decoded );
+ }
+ else
+ {
+ self->m_browseDomains.remove( decoded );
+ }
+
+exit:
+
+ return;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::RegDomainsReply
+//---------------------------------------------------------------------------------------------------------------------------
+
+void DNSSD_API
+CConfigPropertySheet::RegDomainsReply
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * replyDomain,
+ void * context
+ )
+{
+ CConfigPropertySheet * self = reinterpret_cast<CConfigPropertySheet*>(context);
+ CString decoded;
+ OSStatus err;
+
+ DEBUG_UNUSED( sdRef );
+ DEBUG_UNUSED( interfaceIndex );
+
+ if ( errorCode )
+ {
+ goto exit;
+ }
+
+ check( replyDomain );
+
+ // Ignore local domains
+
+ if ( strcmp( replyDomain, "local." ) == 0 )
+ {
+ goto exit;
+ }
+
+ err = self->DecodeDomainName( replyDomain, decoded );
+ require_noerr( err, exit );
+
+ // Remove trailing '.'
+
+ decoded.TrimRight( '.' );
+
+ if ( flags & kDNSServiceFlagsAdd )
+ {
+ if ( self->GetActivePage() == &self->m_secondPage )
+ {
+ self->m_secondPage.OnAddRegistrationDomain( decoded );
+ }
+
+ self->m_regDomains.push_back( decoded );
+ }
+ else
+ {
+ if ( self->GetActivePage() == &self->m_secondPage )
+ {
+ self->m_secondPage.OnRemoveRegistrationDomain( decoded );
+ }
+
+ self->m_regDomains.remove( decoded );
+ }
+
+exit:
+
+ return;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet::WatchRegistry
+//---------------------------------------------------------------------------------------------------------------------------
+
+unsigned WINAPI
+CConfigPropertySheet::WatchRegistry ( LPVOID inParam )
+{
+ bool done = false;
+
+ CConfigPropertySheet * self = reinterpret_cast<CConfigPropertySheet*>(inParam);
+ check( self );
+
+ while ( !done )
+ {
+ RegNotifyChangeKeyValue( self->m_statusKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, NULL, FALSE );
+
+ EnterCriticalSection( &self->m_lock );
+
+ done = ( self->m_statusKey == NULL ) ? true : false;
+
+ if ( !done )
+ {
+ self->PostMessage( WM_REGISTRYCHANGED, 0, 0 );
+ }
+
+ LeaveCriticalSection( &self->m_lock );
+ }
+
+ SetEvent( self->m_threadExited );
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: ConfigPropertySheet.h,v $
+Revision 1.4 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#ifndef _ConfigPropertySheet_h
+#define _ConfigPropertySheet_h
+
+#include "stdafx.h"
+#include "FirstPage.h"
+#include "SecondPage.h"
+#include "ThirdPage.h"
+
+#include <RegNames.h>
+#include <dns_sd.h>
+#include <list>
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CConfigPropertySheet
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CConfigPropertySheet : public CPropertySheet
+{
+public:
+
+ CConfigPropertySheet();
+ virtual ~CConfigPropertySheet();
+
+ typedef std::list<CString> StringList;
+
+ StringList m_browseDomains;
+ StringList m_regDomains;
+
+protected:
+
+ CFirstPage m_firstPage;
+ CSecondPage m_secondPage;
+ CThirdPage m_thirdPage;
+
+ //{{AFX_VIRTUAL(CConfigPropertySheet)
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CConfigPropertySheet)
+
+ //{{AFX_MSG(CConfigPropertySheet)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ afx_msg BOOL OnInitDialog();
+ afx_msg BOOL OnCommand( WPARAM wParam, LPARAM lParam );\r
+ afx_msg LONG OnDataReady( WPARAM inWParam, LPARAM inLParam );\r
+ afx_msg LONG OnRegistryChanged( WPARAM inWParam, LPARAM inLParam );\r
+ void OnEndDialog();
+
+private:
+
+ OSStatus
+ SetupBrowsing();
+
+ OSStatus
+ TearDownBrowsing();
+
+ OSStatus
+ SetupRegistryNotifications();
+
+ OSStatus
+ TearDownRegistryNotifications();
+
+ OSStatus
+ DecodeDomainName( const char * raw, CString & decoded );
+
+ const char*
+ GetNextLabel( const char * cstr, char label[64] );
+
+ static void DNSSD_API
+ BrowseDomainsReply
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * replyDomain,
+ void * context
+ );
+
+ static void DNSSD_API
+ RegDomainsReply
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * replyDomain,
+ void * context
+ );
+
+ // This thread will watch for registry changes
+
+ static unsigned WINAPI
+ WatchRegistry
+ (
+ LPVOID inParam
+ );
+
+ HKEY m_statusKey;
+ HANDLE m_thread;
+ HANDLE m_threadExited;
+ DNSServiceRef m_browseDomainsRef;
+ DNSServiceRef m_regDomainsRef;
+ CRITICAL_SECTION m_lock;
+};
+
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: ControlPanel.cpp,v $
+Revision 1.2 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+
+#include "ControlPanel.h"
+#include "ConfigDialog.h"
+#include "ConfigPropertySheet.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+static CCPApp theApp;
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// GetControlPanelApp
+//---------------------------------------------------------------------------------------------------------------------------
+
+CCPApp*
+GetControlPanelApp()
+{
+ CCPApp * pApp = (CCPApp*) AfxGetApp();
+
+ check( pApp );
+ check( pApp->IsKindOf( RUNTIME_CLASS( CCPApp ) ) );
+
+ return pApp;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CPlApplet
+//---------------------------------------------------------------------------------------------------------------------------
+
+LONG APIENTRY
+CPlApplet(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ CCPApp * pApp = GetControlPanelApp();
+
+ return ( LONG ) pApp->OnCplMsg(hWndCPl, uMsg, lParam1, lParam2);
+}
+
+
+IMPLEMENT_DYNAMIC(CCPApplet, CCmdTarget);
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::CCPApplet
+//---------------------------------------------------------------------------------------------------------------------------
+
+CCPApplet::CCPApplet(UINT resourceId, UINT descId, CRuntimeClass * uiClass)
+:
+ m_resourceId(resourceId),
+ m_descId(descId),
+ m_uiClass(uiClass),
+ m_pageNumber(0)
+{
+ check( uiClass );
+ check( uiClass->IsDerivedFrom( RUNTIME_CLASS( CDialog ) ) ||
+ uiClass->IsDerivedFrom( RUNTIME_CLASS( CPropertySheet ) ) );
+
+ m_name.LoadString(resourceId);
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::~CCPApplet
+//---------------------------------------------------------------------------------------------------------------------------
+
+CCPApplet::~CCPApplet()
+{
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::OnStartParms
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApplet::OnStartParms(CWnd * pParentWnd, LPCTSTR extra)
+{
+ DEBUG_UNUSED( pParentWnd );
+
+ if ( extra )
+ {
+ m_pageNumber = ::_ttoi( extra ) - 1;
+ }
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::OnRun
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApplet::OnRun(CWnd* pParentWnd)
+{
+ LRESULT lResult = 1;
+ CWnd * pWnd = (CWnd*) m_uiClass->CreateObject();
+
+ if ( pWnd )
+ {
+ lResult = ERROR_SUCCESS;
+
+ if ( pWnd->IsKindOf( RUNTIME_CLASS( CPropertySheet ) ) )
+ {
+ CPropertySheet * pSheet = (CPropertySheet*) pWnd;
+
+ pSheet->Construct(m_name, pParentWnd, m_pageNumber);
+
+ pSheet->DoModal();
+ }
+ else
+ {
+ check( pWnd->IsKindOf( RUNTIME_CLASS( CDialog ) ) );
+
+ CDialog * pDialog = (CDialog*) pWnd;
+
+ pDialog->DoModal();
+ }
+
+ delete pWnd;
+ }
+
+ return lResult;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::OnInquire
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApplet::OnInquire(CPLINFO* pInfo)
+{
+ pInfo->idIcon = m_resourceId;
+ pInfo->idName = m_resourceId;
+ pInfo->idInfo = m_descId;
+ pInfo->lData = reinterpret_cast<LONG>(this);
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::OnNewInquire
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApplet::OnNewInquire(NEWCPLINFO* pInfo)
+{
+ DEBUG_UNUSED( pInfo );
+
+ return 1;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::OnSelect
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApplet::OnSelect()
+{
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApplet::OnStop
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApplet::OnStop()
+{
+ return 0;
+}
+
+
+IMPLEMENT_DYNAMIC(CCPApp, CWinApp);
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApp::CCPApp
+//---------------------------------------------------------------------------------------------------------------------------
+
+CCPApp::CCPApp()
+{
+ debug_initialize( kDebugOutputTypeWindowsEventLog, "DNS-SD Control Panel", GetModuleHandle( NULL ) );
+ debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApp::~CCPApp
+//---------------------------------------------------------------------------------------------------------------------------
+
+CCPApp::~CCPApp()
+{
+ while ( !m_applets.IsEmpty() )
+ {
+ delete m_applets.RemoveHead();
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApp::AddApplet
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CCPApp::AddApplet( CCPApplet * applet )
+{
+ check( applet );
+
+ m_applets.AddTail( applet );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApp::OnInit
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApp::OnInit()
+{
+ CCPApplet * applet;
+
+ try
+ {
+ applet = new CCPApplet( IDR_APPLET, IDS_APPLET_DESCRIPTION, RUNTIME_CLASS( CConfigPropertySheet ) );
+ }
+ catch (...)
+ {
+ applet = NULL;
+ }
+
+ require_action( applet, exit, kNoMemoryErr );
+
+ AddApplet( applet );
+
+exit:
+
+ return m_applets.GetCount();
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApp::OnExit
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApp::OnExit()
+{
+ return 1;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CCPApp::OnCplMsg
+//---------------------------------------------------------------------------------------------------------------------------
+
+LRESULT
+CCPApp::OnCplMsg(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2)
+{
+ LRESULT lResult = 1;
+
+ switch ( uMsg )
+ {
+ case CPL_INIT:
+ {
+ lResult = OnInit();
+ }
+ break;
+
+ case CPL_EXIT:
+ {
+ lResult = OnExit();
+ }
+ break;
+
+ case CPL_GETCOUNT:
+ {
+ lResult = m_applets.GetCount();
+ }
+ break;
+
+ default:
+ {
+ POSITION pos = m_applets.FindIndex( lParam1 );
+ check( pos );
+
+ CCPApplet * applet = m_applets.GetAt( pos );
+ check( applet );
+
+ switch (uMsg)
+ {
+ case CPL_INQUIRE:
+ {
+ LPCPLINFO pInfo = reinterpret_cast<LPCPLINFO>(lParam2);
+ lResult = applet->OnInquire(pInfo);
+ }
+ break;
+
+ case CPL_NEWINQUIRE:
+ {
+ LPNEWCPLINFO pInfo = reinterpret_cast<LPNEWCPLINFO>(lParam2);
+ lResult = applet->OnNewInquire(pInfo);
+ }
+ break;
+
+ case CPL_STARTWPARMS:
+ {
+ CWnd * pParentWnd = CWnd::FromHandle(hWndCPl);
+ LPCTSTR lpszExtra = reinterpret_cast<LPCTSTR>(lParam2);
+ lResult = applet->OnStartParms(pParentWnd, lpszExtra);
+ }
+ break;
+
+ case CPL_DBLCLK:
+ {
+ CWnd* pParentWnd = CWnd::FromHandle(hWndCPl);
+ lResult = applet->OnRun(pParentWnd);
+ }
+ break;
+
+ case CPL_SELECT:
+ {
+ lResult = applet->OnSelect();
+ }
+ break;
+
+ case CPL_STOP:
+ {
+ lResult = applet->OnStop();
+ }
+ break;
+
+ default:
+ {
+ // TRACE(_T("Warning, Received an unknown control panel message:%d\n"), uMsg);
+ lResult = 1;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return lResult;
+}
--- /dev/null
+;\r
+; Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.\r
+;\r
+; @APPLE_LICENSE_HEADER_START@\r
+; \r
+; This file contains Original Code and/or Modifications of Original Code\r
+; as defined in and that are subject to the Apple Public Source License\r
+; Version 2.0 (the 'License'). You may not use this file except in\r
+; compliance with the License. Please obtain a copy of the License at\r
+; http://www.opensource.apple.com/apsl/ and read it before using this\r
+; file.\r
+; \r
+; The Original Code and all software distributed under the License are\r
+; distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
+; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
+; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
+; FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
+; Please see the License for the specific language governing rights and\r
+; limitations under the License.\r
+; \r
+; @APPLE_LICENSE_HEADER_END@\r
+;\r
+; Change History (most recent first):\r
+;\r
+; $Log: ControlPanel.def,v $
+; Revision 1.3 2005/03/03 19:55:22 shersche
+; <rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+;\r
+;\r
+;\r
+ \r
+LIBRARY "Bonjour"\r
+\r
+EXPORTS\r
+ CPlApplet\r
--- /dev/null
+/*\r
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.\r
+ *\r
+ * @APPLE_LICENSE_HEADER_START@\r
+ * \r
+ * This file contains Original Code and/or Modifications of Original Code\r
+ * as defined in and that are subject to the Apple Public Source License\r
+ * Version 2.0 (the 'License'). You may not use this file except in\r
+ * compliance with the License. Please obtain a copy of the License at\r
+ * http://www.opensource.apple.com/apsl/ and read it before using this\r
+ * file.\r
+ * \r
+ * The Original Code and all software distributed under the License are\r
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
+ * Please see the License for the specific language governing rights and\r
+ * limitations under the License.\r
+ * \r
+ * @APPLE_LICENSE_HEADER_END@\r
+\r
+ Change History (most recent first):\r
+\r
+$Log: ControlPanel.h,v $
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+\r
+\r
+*/\r
+\r
+ \r
+#pragma once\r
+\r
+#include "stdafx.h"\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CCPApplet\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+class CCPApplet : public CCmdTarget\r
+{\r
+public:\r
+\r
+ CCPApplet( UINT nResourceID, UINT nDescriptionID, CRuntimeClass* pUIClass );\r
+\r
+ virtual ~CCPApplet();\r
+\r
+protected:\r
+\r
+ virtual LRESULT OnRun(CWnd* pParentWnd);\r
+ virtual LRESULT OnStartParms(CWnd* pParentWnd, LPCTSTR lpszExtra);\r
+ virtual LRESULT OnInquire(CPLINFO* pInfo);\r
+ virtual LRESULT OnNewInquire(NEWCPLINFO* pInfo);\r
+ virtual LRESULT OnSelect();\r
+ virtual LRESULT OnStop();\r
+\r
+ CRuntimeClass * m_uiClass;\r
+ UINT m_resourceId;\r
+ UINT m_descId;\r
+ CString m_name;\r
+ int m_pageNumber;\r
+ \r
+ friend class CCPApp;\r
+\r
+ DECLARE_DYNAMIC(CCPApplet);\r
+};\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CCPApp\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+class CCPApp : public CWinApp\r
+{\r
+public:\r
+\r
+ CCPApp();\r
+ virtual ~CCPApp();\r
+\r
+ void AddApplet( CCPApplet* pApplet );\r
+\r
+protected:\r
+\r
+ CList<CCPApplet*, CCPApplet*&> m_applets;\r
+\r
+ friend LONG APIENTRY\r
+ CPlApplet(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2);\r
+\r
+ virtual LRESULT OnCplMsg(HWND hWndCPl, UINT msg, LPARAM lp1, LPARAM lp2);\r
+ virtual LRESULT OnInit();\r
+ virtual LRESULT OnExit();\r
+\r
+ DECLARE_DYNAMIC(CCPApp);\r
+};\r
+\r
+\r
+CCPApp * GetControlPanelApp();\r
--- /dev/null
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+#include "WinVersRes.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION MASTER_PROD_VERS\r
+ PRODUCTVERSION MASTER_PROD_VERS\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x2L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "CompanyName", "Apple Computer, Inc."\r
+ VALUE "FileDescription", "Bonjour Configuration Applet"\r
+ VALUE "FileVersion", MASTER_PROD_VERS_STR\r
+ VALUE "InternalName", "Bonjour.cpl"\r
+ VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT\r
+ VALUE "OriginalFilename", "Bonjour.cpl"\r
+ VALUE "ProductName", MASTER_PROD_NAME\r
+ VALUE "ProductVersion", MASTER_PROD_VERS_STR\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\r
+END\r
+\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+ "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+ "#include ""afxres.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"\r
+ "#define _AFX_NO_OLE_RESOURCES\r\n"\r
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"\r
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"\r
+ "\r\n"\r
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"\r
+ "#ifdef _WIN32\r\n"\r
+ "LANGUAGE 9, 1\r\n"\r
+ "#pragma code_page(1252)\r\n"\r
+ "#endif\r\n"\r
+ "#include ""res\\ControlPanel.rc2"" // non-Microsoft Visual C++ edited resources\r\n"\r
+ "#include ""afxres.rc"" // Standard components\r\n"\r
+ "#endif\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDR_APPLET ICON "res\\controlpanel.ico"\r
+IDI_FAILURE ICON "res\\failure.ico"\r
+IDI_SUCCESS ICON "res\\success.ico"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+IDR_APPLET_PAGE1 DIALOGEX 0, 0, 262, 140\r
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION\r
+CAPTION "Hostname"\r
+FONT 8, "MS Sans Serif", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Enter a hostname for this computer. Other computers on the Internet will be able to reach your computer using this hostname.",\r
+ IDC_STATIC,7,19,248,28\r
+ LTEXT "Hostname:",IDC_STATIC,15,55,35,8\r
+ EDITTEXT IDC_EDIT1,52,53,187,14,ES_AUTOHSCROLL\r
+ PUSHBUTTON "Password...",IDC_BUTTON1,52,72,67,14\r
+ ICON IDI_FAILURE,IDC_FAILURE,240,50,21,20,SS_CENTERIMAGE | \r
+ SS_REALSIZEIMAGE\r
+ ICON IDI_SUCCESS,IDC_SUCCESS,240,50,21,20,SS_CENTERIMAGE | \r
+ SS_REALSIZEIMAGE | NOT WS_VISIBLE\r
+END\r
+\r
+IDR_APPLET_PAGE2 DIALOGEX 0, 0, 262, 140\r
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION\r
+CAPTION "Registration"\r
+FONT 8, "MS Sans Serif", 0, 0, 0x0\r
+BEGIN\r
+ CONTROL "Domain:",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | \r
+ WS_TABSTOP,13,54,42,10\r
+ COMBOBOX IDC_COMBO2,59,53,189,46,CBS_DROPDOWN | CBS_SORT | \r
+ WS_DISABLED | WS_VSCROLL | WS_TABSTOP\r
+ PUSHBUTTON "Password...",IDC_BUTTON1,59,72,65,14\r
+ LTEXT "Check the box and enter a registration domain to enable Bonjour advertising beyond the local subnet. ",\r
+ IDC_STATIC,14,20,233,23\r
+END\r
+\r
+IDR_SECRET DIALOGEX 0, 0, 251, 90\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "Password"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ DEFPUSHBUTTON "OK",IDOK,139,69,50,14\r
+ PUSHBUTTON "Cancel",IDCANCEL,194,69,50,14\r
+ LTEXT "Name:",IDC_STATIC,9,28,22,8\r
+ EDITTEXT IDC_SECRET_NAME,36,26,208,14,ES_AUTOHSCROLL\r
+ LTEXT "Secret:",IDC_STATIC,9,44,24,8\r
+ EDITTEXT IDC_SECRET,36,42,208,14,ES_PASSWORD | ES_AUTOHSCROLL\r
+ LTEXT "Enter a Password if your DNS server requires authentication.",\r
+ IDC_STATIC,7,7,237,15\r
+END\r
+\r
+IDR_APPLET_PAGE3 DIALOGEX 0, 0, 262, 140\r
+STYLE DS_SETFONT | WS_CHILD | WS_CAPTION\r
+CAPTION "Browsing"\r
+FONT 8, "MS Sans Serif", 0, 0, 0x0\r
+BEGIN\r
+ LTEXT "Choose which domains to browse using Wide-Area Bonjour",\r
+ -1,7,16,248,12\r
+ CONTROL "",IDC_BROWSE_LIST,"SysListView32",LVS_REPORT | \r
+ LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | \r
+ WS_TABSTOP,7,37,248,57\r
+ PUSHBUTTON "Add",IDC_ADD_BROWSE_DOMAIN,152,100,50,14\r
+ PUSHBUTTON "Remove",IDC_REMOVE_BROWSE_DOMAIN,205,100,50,14\r
+END\r
+\r
+IDR_ADD_BROWSE_DOMAIN DIALOGEX 0, 0, 230, 95\r
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "Add Browse Domain"\r
+FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
+BEGIN\r
+ DEFPUSHBUTTON "OK",IDOK,117,74,50,14\r
+ PUSHBUTTON "Cancel",IDCANCEL,173,74,50,14\r
+ COMBOBOX IDC_COMBO1,35,42,188,30,CBS_DROPDOWN | CBS_SORT | \r
+ WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Domain:",IDC_STATIC,7,43,27,8\r
+ LTEXT "The following domain will be added to your list of Bonjour browse domains.",\r
+ IDC_STATIC,7,15,216,16\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO \r
+BEGIN\r
+ IDR_APPLET_PAGE1, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 255\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 133\r
+ END\r
+\r
+ IDR_APPLET_PAGE2, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 255\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 133\r
+ END\r
+\r
+ IDR_SECRET, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 244\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 83\r
+ END\r
+\r
+ IDR_APPLET_PAGE3, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 255\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 133\r
+ END\r
+\r
+ IDR_ADD_BROWSE_DOMAIN, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 223\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 88\r
+ END\r
+END\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE \r
+BEGIN\r
+ IDR_APPLET "Bonjour"\r
+ IDS_APPLET_DESCRIPTION "Wide-Area Bonjour Control Panel"\r
+END\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+#define _AFX_NO_SPLITTER_RESOURCES\r
+#define _AFX_NO_OLE_RESOURCES\r
+#define _AFX_NO_TRACKER_RESOURCES\r
+#define _AFX_NO_PROPERTY_RESOURCES\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#endif\r
+#include "res\ControlPanel.rc2" // non-Microsoft Visual C++ edited resources\r
+#include "afxres.rc" // Standard components\r
+#endif\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+<?xml version="1.0" encoding = "Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.00"\r
+ Name="ControlPanel"\r
+ SccProjectName=""\r
+ SccLocalPath=""\r
+ Keyword="MFCProj">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory=".\Debug"\r
+ IntermediateDirectory=".\Debug"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;DEBUG=1;UNICODE;_UNICODE;_WINDOWS;_USRDLL"\r
+ RuntimeLibrary="1"\r
+ UsePrecompiledHeader="0"\r
+ PrecompiledHeaderThrough=""\r
+ PrecompiledHeaderFile=""\r
+ AssemblerListingLocation=".\Debug/"\r
+ ObjectFile=".\Debug/"\r
+ ProgramDataBaseFileName=".\Debug/"\r
+ WarningLevel="4"\r
+ SuppressStartupBanner="TRUE"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"\r
+ DisableSpecificWarnings="4311;4312"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../DLL/Debug/dnssd.lib ws2_32.lib"\r
+ OutputFile="Debug/Bonjour.cpl"\r
+ LinkIncremental="2"\r
+ SuppressStartupBanner="TRUE"\r
+ ModuleDefinitionFile=".\ControlPanel.def"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile=".\Debug/ControlPanel.pdb"\r
+ SubSystem="2"\r
+ ImportLibrary=".\Debug/Bonjour.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName=".\Debug/ControlPanel.tlb"\r
+ HeaderFileName=""/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="_DEBUG"\r
+ Culture="6153"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory=".\Release"\r
+ IntermediateDirectory=".\Release"\r
+ ConfigurationType="2"\r
+ UseOfMFC="1"\r
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ InlineFunctionExpansion="1"\r
+ AdditionalIncludeDirectories="..;../../mDNSCore;../../mDNSShared"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICODE;_UNICODE"\r
+ StringPooling="TRUE"\r
+ RuntimeLibrary="0"\r
+ EnableFunctionLevelLinking="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ AssemblerListingLocation=".\Release/"\r
+ ObjectFile=".\Release/"\r
+ ProgramDataBaseFileName=".\Release/"\r
+ WarningLevel="4"\r
+ SuppressStartupBanner="TRUE"\r
+ DisableSpecificWarnings="4702"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="../DLL/Release/dnssd.lib ws2_32.lib"\r
+ OutputFile="Release/Bonjour.cpl"\r
+ LinkIncremental="1"\r
+ SuppressStartupBanner="TRUE"\r
+ ModuleDefinitionFile=".\ControlPanel.def"\r
+ ProgramDatabaseFile=".\Release/ControlPanel.pdb"\r
+ SubSystem="2"\r
+ ImportLibrary=".\Release/Bonjour.lib"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ MkTypLibCompatible="TRUE"\r
+ SuppressStartupBanner="TRUE"\r
+ TargetEnvironment="1"\r
+ TypeLibraryName=".\Release/ControlPanel.tlb"\r
+ HeaderFileName=""/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ PreprocessorDefinitions="NDEBUG"\r
+ Culture="6153"\r
+ AdditionalIncludeDirectories="../"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+ <File\r
+ RelativePath="ConfigDialog.cpp">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="ConfigPropertySheet.cpp">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="ControlPanel.cpp">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="ControlPanel.def">\r
+ </File>\r
+ <File\r
+ RelativePath="FirstPage.cpp">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="SecondPage.cpp">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ PreprocessorDefinitions=""/>\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="SharedSecret.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="ThirdPage.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="stdafx.cpp">\r
+ <FileConfiguration\r
+ Name="Debug|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ PreprocessorDefinitions=""\r
+ UsePrecompiledHeader="0"/>\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="2"\r
+ PreprocessorDefinitions=""\r
+ UsePrecompiledHeader="0"/>\r
+ </FileConfiguration>\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl">\r
+ <File\r
+ RelativePath="..\CommonServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ConfigDialog.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ConfigPropertySheet.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ControlPanel.h">\r
+ </File>\r
+ <File\r
+ RelativePath="FirstPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath="Resource.h">\r
+ </File>\r
+ <File\r
+ RelativePath="SecondPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath="SharedSecret.h">\r
+ </File>\r
+ <File\r
+ RelativePath="ThirdPage.h">\r
+ </File>\r
+ <File\r
+ RelativePath="stdafx.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">\r
+ <File\r
+ RelativePath="ControlPanel.rc">\r
+ </File>\r
+ <File\r
+ RelativePath="res\ControlPanel.rc2">\r
+ </File>\r
+ <File\r
+ RelativePath="res\configurator.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\controlpanel.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\failure.ico">\r
+ </File>\r
+ <File\r
+ RelativePath="res\success.ico">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Support"\r
+ Filter="">\r
+ <File\r
+ RelativePath="..\DebugServices.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\DebugServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\WinServices.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath="..\WinServices.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\mDNSShared\dns_sd.h">\r
+ </File>\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: FirstPage.cpp,v $
+Revision 1.3 2005/03/07 18:27:42 shersche
+<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
+
+Revision 1.2 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#include "FirstPage.h"
+#include "resource.h"
+
+#include "ConfigPropertySheet.h"
+#include "SharedSecret.h"
+
+#define MAX_KEY_LENGTH 255
+
+
+IMPLEMENT_DYNCREATE(CFirstPage, CPropertyPage)
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::CFirstPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CFirstPage::CFirstPage()
+:
+ CPropertyPage(CFirstPage::IDD),
+ m_ignoreHostnameChange( false ),
+ m_statusKey( NULL )
+{
+ //{{AFX_DATA_INIT(CFirstPage)
+ //}}AFX_DATA_INIT
+
+ OSStatus err;
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\State\\Hostnames", &m_statusKey );
+ check_noerr( err );
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\Hostnames", &m_setupKey );
+ check_noerr( err );
+}
+
+CFirstPage::~CFirstPage()
+{
+ if ( m_statusKey )
+ {
+ RegCloseKey( m_statusKey );
+ m_statusKey = NULL;
+ }
+
+ if ( m_setupKey )
+ {
+ RegCloseKey( m_setupKey );
+ m_setupKey = NULL;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CFirstPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CFirstPage)
+ //}}AFX_DATA_MAP
+ DDX_Control(pDX, IDC_EDIT1, m_hostnameControl);
+ DDX_Control(pDX, IDC_FAILURE, m_failureIcon);
+ DDX_Control(pDX, IDC_SUCCESS, m_successIcon);
+}
+
+BEGIN_MESSAGE_MAP(CFirstPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CFirstPage)
+ //}}AFX_MSG_MAP
+ ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret)
+ ON_EN_CHANGE(IDC_EDIT1, OnEnChangeHostname)
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::OnEnChangedHostname
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CFirstPage::OnEnChangeHostname()
+{
+ if ( !m_ignoreHostnameChange )
+ {
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::OnBnClickedSharedSecret
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CFirstPage::OnBnClickedSharedSecret()
+{
+ CString name;
+
+ m_hostnameControl.GetWindowText( name );
+
+ CSharedSecret dlg;
+
+ dlg.m_secretName = name;
+
+ if ( dlg.DoModal() == IDOK )
+ {
+ dlg.Commit();
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CFirstPage::SetModified( BOOL bChanged )
+{
+ m_modified = bChanged ? true : false;
+
+ CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CFirstPage::OnSetActive()
+{
+ TCHAR name[kDNSServiceMaxDomainName + 1];
+ DWORD nameLen = ( kDNSServiceMaxDomainName + 1 ) * sizeof( TCHAR );
+ DWORD err;
+
+ BOOL b = CPropertyPage::OnSetActive();
+
+ m_modified = FALSE;
+
+ if ( m_setupKey )
+ {
+ err = RegQueryValueEx( m_setupKey, L"", NULL, NULL, (LPBYTE) name, &nameLen );
+
+ if ( !err )
+ {
+ m_ignoreHostnameChange = true;
+ m_hostnameControl.SetWindowText( name );
+ m_ignoreHostnameChange = false;
+ }
+ }
+
+ // Check the status of this hostname
+
+ err = CheckStatus();
+ check_noerr( err );
+
+ return b;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CFirstPage::OnOK()
+{
+ if ( m_modified )
+ {
+ Commit();
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CFirstPage::Commit()
+{
+ DWORD enabled = 1;
+ CString name;
+ DWORD err;
+
+ m_hostnameControl.GetWindowText( name );
+
+ // Convert to lower case
+
+ name.MakeLower();
+
+ // Remove trailing dot
+
+ name.TrimRight( '.' );
+
+ err = RegSetValueEx( m_setupKey, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) name, ( name.GetLength() + 1 ) * sizeof( TCHAR ) );
+ require_noerr( err, exit );
+
+ err = RegSetValueEx( m_setupKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
+ require_noerr( err, exit );
+
+exit:
+
+ return;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::CheckStatus
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CFirstPage::CheckStatus()
+{
+ DWORD status = 0;
+ DWORD dwSize = sizeof( DWORD );
+ OSStatus err;
+
+ // Get the status field
+
+ err = RegQueryValueEx( m_statusKey, L"Status", NULL, NULL, (LPBYTE) &status, &dwSize );
+ require_noerr( err, exit );
+
+ ShowStatus( status );
+
+exit:
+
+ return kNoErr;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::ShowStatus
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CFirstPage::ShowStatus( DWORD status )
+{
+ if ( status )
+ {
+ m_failureIcon.ShowWindow( SW_HIDE );
+ m_successIcon.ShowWindow( SW_SHOW );
+ }
+ else
+ {
+ m_failureIcon.ShowWindow( SW_SHOW );
+ m_successIcon.ShowWindow( SW_HIDE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage::OnRegistryChanged
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CFirstPage::OnRegistryChanged()
+{
+ CheckStatus();
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: FirstPage.h,v $
+Revision 1.3 2005/03/07 18:27:42 shersche
+<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
+
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+#include "afxwin.h"
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CFirstPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CFirstPage : public CPropertyPage
+{
+public:
+ CFirstPage();
+ ~CFirstPage();
+
+protected:
+ //{{AFX_DATA(CFirstPage)
+ enum { IDD = IDR_APPLET_PAGE1 };
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CFirstPage)
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CFirstPage)
+
+ //{{AFX_MSG(CFirstPage)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+public:
+ afx_msg void OnBnClickedSharedSecret();
+ void OnRegistryChanged();
+private:
+
+ afx_msg BOOL OnSetActive();
+ afx_msg void OnOK();
+
+ void SetModified( BOOL bChanged = TRUE );
+ void Commit();
+
+ OSStatus CheckStatus();
+ void ShowStatus( DWORD status );
+
+ CEdit m_hostnameControl;
+ bool m_ignoreHostnameChange;
+ bool m_modified;
+ HKEY m_statusKey;
+ HKEY m_setupKey;
+
+public:
+
+ afx_msg void OnEnChangeHostname();
+ CStatic m_failureIcon;
+ CStatic m_successIcon;
+};
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: SecondPage.cpp,v $
+Revision 1.3 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#include "SecondPage.h"
+#include "resource.h"
+
+#include "ConfigPropertySheet.h"
+#include "SharedSecret.h"
+
+#include <WinServices.h>
+
+IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage)
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::CSecondPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CSecondPage::CSecondPage()
+:
+ CPropertyPage(CSecondPage::IDD)
+{
+ //{{AFX_DATA_INIT(CSecondPage)
+ //}}AFX_DATA_INIT
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::~CSecondPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CSecondPage::~CSecondPage()
+{
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CSecondPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSecondPage)
+ //}}AFX_DATA_MAP
+ DDX_Control(pDX, IDC_CHECK1, m_advertiseServicesButton);
+ DDX_Control(pDX, IDC_BUTTON1, m_sharedSecretButton);
+ DDX_Control(pDX, IDC_COMBO2, m_regDomainsBox);
+}
+
+BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CSecondPage)
+ //}}AFX_MSG_MAP
+ ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret)
+ ON_BN_CLICKED(IDC_CHECK1, OnBnClickedAdvertise)
+ ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelChange)
+ ON_CBN_EDITCHANGE(IDC_COMBO1, OnCbnEditChange)
+ ON_CBN_EDITCHANGE(IDC_COMBO2, OnCbnEditChange)
+ ON_CBN_SELCHANGE(IDC_COMBO2, OnCbnSelChange)
+
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CSecondPage::SetModified( BOOL bChanged )
+{
+ m_modified = bChanged;
+
+ CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CSecondPage::OnSetActive()
+{
+ CConfigPropertySheet * psheet;
+ HKEY key = NULL;
+ DWORD dwSize;
+ DWORD enabled;
+ DWORD err;
+ BOOL b = CPropertyPage::OnSetActive();
+
+ psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ m_modified = FALSE;
+
+ // Clear out what's there
+
+ EmptyComboBox( m_regDomainsBox );
+
+ // Now populate the registration domain box
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key );
+ require_noerr( err, exit );
+
+ err = Populate( m_regDomainsBox, key, psheet->m_regDomains );
+ check_noerr( err );
+
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+ m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED );
+ m_regDomainsBox.EnableWindow( ( !err && enabled ) );
+ m_sharedSecretButton.EnableWindow( (!err && enabled ) );
+
+ RegCloseKey( key );
+
+exit:
+
+ return b;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CSecondPage::OnOK()
+{
+ if ( m_modified )
+ {
+ Commit();
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CSecondPage::Commit()
+{
+ HKEY key = NULL;
+ DWORD err;
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key );
+ require_noerr( err, exit );
+
+ err = Commit( m_regDomainsBox, key, m_advertiseServicesButton.GetCheck() == BST_CHECKED );
+ check_noerr( err );
+
+exit:
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled )
+{
+ CString selected;
+ OSStatus err = kNoErr;
+
+ // Get selected text
+
+ box.GetWindowText( selected );
+
+ // If we haven't seen this string before, add the string to the box and
+ // the registry
+
+ if ( ( selected.GetLength() > 0 ) && ( box.FindStringExact( -1, selected ) == CB_ERR ) )
+ {
+ CString string;
+
+ box.AddString( selected );
+
+ err = RegQueryString( key, L"UserDefined", string );
+ check_noerr( err );
+
+ if ( string.GetLength() )
+ {
+ string += L"," + selected;
+ }
+ else
+ {
+ string = selected;
+ }
+
+ err = RegSetValueEx( key, L"UserDefined", 0, REG_SZ, (LPBYTE) (LPCTSTR) string, ( string.GetLength() + 1) * sizeof( TCHAR ) );
+ check_noerr ( err );
+ }
+
+ // Save selected text in registry. This will trigger mDNSResponder to setup
+ // DynDNS config again
+
+ err = RegSetValueEx( key, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) selected, ( selected.GetLength() + 1 ) * sizeof( TCHAR ) );
+ check_noerr( err );
+
+ err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
+ check_noerr( err );
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnBnClickedSharedSecret
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CSecondPage::OnBnClickedSharedSecret()
+{
+ CString string;
+
+ m_regDomainsBox.GetWindowText( string );
+
+ CSharedSecret dlg;
+
+ dlg.m_secretName = string;
+
+ dlg.DoModal();
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnBnClickedAdvertise
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CSecondPage::OnBnClickedAdvertise()
+{
+ int state;
+
+ state = m_advertiseServicesButton.GetCheck();
+
+ m_regDomainsBox.EnableWindow( state );
+ m_sharedSecretButton.EnableWindow( state );
+
+ SetModified( TRUE );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnCbnSelChange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CSecondPage::OnCbnSelChange()
+{
+ SetModified( TRUE );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnCbnEditChange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CSecondPage::OnCbnEditChange()
+{
+ SetModified( TRUE );
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnAddRegistrationDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CSecondPage::OnAddRegistrationDomain( CString & domain )
+{
+ int index = m_regDomainsBox.FindStringExact( -1, domain );
+
+ if ( index == CB_ERR )
+ {
+ m_regDomainsBox.AddString( domain );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::OnRemoveRegistrationDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CSecondPage::OnRemoveRegistrationDomain( CString & domain )
+{
+ int index = m_regDomainsBox.FindStringExact( -1, domain );
+
+ if ( index != CB_ERR )
+ {
+ m_regDomainsBox.DeleteString( index );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::EmptyComboBox
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CSecondPage::EmptyComboBox( CComboBox & box )
+{
+ while ( box.GetCount() > 0 )
+ {
+ box.DeleteString( 0 );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::Populate
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CSecondPage::Populate( CComboBox & box, HKEY key, StringList & l )
+{
+ TCHAR rawString[kDNSServiceMaxDomainName + 1];
+ DWORD rawStringLen;
+ CString string;
+ OSStatus err;
+
+ err = RegQueryString( key, L"UserDefined", string );
+
+ if ( !err && string.GetLength() )
+ {
+ bool done = false;
+
+ while ( !done )
+ {
+ CString tok;
+
+ tok = string.SpanExcluding( L"," );
+
+ box.AddString( tok );
+
+ if ( tok != string )
+ {
+ // Get rid of that string and comma
+
+ string = string.Right( string.GetLength() - tok.GetLength() - 1 );
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ }
+
+ StringList::iterator it;
+
+ for ( it = l.begin(); it != l.end(); it++ )
+ {
+ if ( box.FindStringExact( -1, *it ) == CB_ERR )
+ {
+ box.AddString( *it );
+ }
+ }
+
+ // Now look to see if there is a selected string, and if so,
+ // select it
+
+ rawString[0] = '\0';
+
+ rawStringLen = sizeof( rawString );
+
+ err = RegQueryValueEx( key, L"", 0, NULL, (LPBYTE) rawString, &rawStringLen );
+
+ string = rawString;
+
+ if ( !err && ( string.GetLength() != 0 ) )
+ {
+ // See if it's there
+
+ if ( box.SelectString( -1, string ) == CB_ERR )
+ {
+ // If not, add it
+
+ box.AddString( string );
+ }
+
+ box.SelectString( -1, string );
+ }
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::CreateKey
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CSecondPage::CreateKey( CString & name, DWORD enabled )
+{
+ HKEY key = NULL;
+ OSStatus err;
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, (LPCTSTR) name, &key );
+ require_noerr( err, exit );
+
+ err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
+ check_noerr( err );
+
+exit:
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ return err;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage::RegQueryString
+//---------------------------------------------------------------------------------------------------------------------------
+
+OSStatus
+CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value )
+{
+ TCHAR * string;
+ DWORD stringLen;
+ int i;
+ OSStatus err;
+
+ stringLen = 1024;
+ string = NULL;
+ i = 0;
+
+ do
+ {
+ if ( string )
+ {
+ free( string );
+ }
+
+ string = (TCHAR*) malloc( stringLen );
+ require_action( string, exit, err = kUnknownErr );
+
+ err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen );
+
+ i++;
+ }
+ while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
+
+ value = string;
+
+exit:
+
+ if ( string )
+ {
+ free( string );
+ }
+
+ return err;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: SecondPage.h,v $
+Revision 1.3 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+#include <list>
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CSecondPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CSecondPage : public CPropertyPage
+{
+public:
+ CSecondPage();
+ ~CSecondPage();
+
+protected:
+
+ //{{AFX_DATA(CSecondPage)
+ enum { IDD = IDR_APPLET_PAGE2 };
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CSecondPage)
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CSecondPage)
+
+ //{{AFX_MSG(CSecondPage)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+public:
+
+ afx_msg void OnBnClickedSharedSecret();
+ afx_msg void OnBnClickedAdvertise();
+
+ void OnAddRegistrationDomain( CString & domain );
+ void OnRemoveRegistrationDomain( CString & domain );
+
+private:
+
+ typedef std::list<CString> StringList;
+
+ afx_msg BOOL
+ OnSetActive();
+
+ afx_msg void
+ OnOK();
+
+ void
+ EmptyComboBox
+ (
+ CComboBox & box
+ );
+
+ OSStatus
+ Populate(
+ CComboBox & box,
+ HKEY key,
+ StringList & l
+ );
+
+ void
+ SetModified( BOOL bChanged = TRUE );
+
+ void
+ Commit();
+
+ OSStatus
+ Commit( CComboBox & box, HKEY key, DWORD enabled );
+
+ OSStatus
+ CreateKey( CString & name, DWORD enabled );
+
+ OSStatus
+ RegQueryString( HKEY key, CString valueName, CString & value );
+
+ CComboBox m_regDomainsBox;
+ CButton m_advertiseServicesButton;
+ CButton m_sharedSecretButton;
+ BOOL m_modified;
+
+public:
+ afx_msg void OnCbnSelChange();
+ afx_msg void OnCbnEditChange();
+};
--- /dev/null
+/*\r
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.\r
+ *\r
+ * @APPLE_LICENSE_HEADER_START@\r
+ * \r
+ * This file contains Original Code and/or Modifications of Original Code\r
+ * as defined in and that are subject to the Apple Public Source License\r
+ * Version 2.0 (the 'License'). You may not use this file except in\r
+ * compliance with the License. Please obtain a copy of the License at\r
+ * http://www.opensource.apple.com/apsl/ and read it before using this\r
+ * file.\r
+ * \r
+ * The Original Code and all software distributed under the License are\r
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
+ * Please see the License for the specific language governing rights and\r
+ * limitations under the License.\r
+ * \r
+ * @APPLE_LICENSE_HEADER_END@\r
+\r
+ Change History (most recent first):\r
+\r
+$Log: SharedSecret.cpp,v $
+Revision 1.2 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+\r
+\r
+*/\r
+\r
+ \r
+// SharedSecret.cpp : implementation file\r
+//\r
+\r
+#include "stdafx.h"\r
+#include "SharedSecret.h"\r
+\r
+#include <DebugServices.h>\r
+#include <ntsecapi.h>\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// Private declarations\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+static BOOL\r
+InitLsaString\r
+ (\r
+ PLSA_UNICODE_STRING pLsaString,\r
+ LPCWSTR pwszString\r
+ );\r
+\r
+// SharedSecret dialog\r
+\r
+IMPLEMENT_DYNAMIC(CSharedSecret, CDialog)\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CSharedSecret::CSharedSecret\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+CSharedSecret::CSharedSecret(CWnd* pParent /*=NULL*/)\r
+ : CDialog(CSharedSecret::IDD, pParent)\r
+ , m_secret(_T(""))\r
+ , m_secretName(_T(""))\r
+{\r
+}\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CSharedSecret::~CSharedSecret\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+CSharedSecret::~CSharedSecret()\r
+{\r
+}\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CSharedSecret::DoDataExchange\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+void CSharedSecret::DoDataExchange(CDataExchange* pDX)\r
+{\r
+ CDialog::DoDataExchange(pDX);\r
+ DDX_Text(pDX, IDC_SECRET, m_secret);\r
+ DDX_Text(pDX, IDC_SECRET_NAME, m_secretName);\r
+}\r
+\r
+\r
+BEGIN_MESSAGE_MAP(CSharedSecret, CDialog)\r
+END_MESSAGE_MAP()\r
+\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CSharedSecret::Commit\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+void\r
+CSharedSecret::Commit()\r
+{\r
+ LSA_OBJECT_ATTRIBUTES attrs;\r
+ LSA_HANDLE handle = NULL;\r
+ NTSTATUS res;\r
+ LSA_UNICODE_STRING lucKeyName;\r
+ LSA_UNICODE_STRING lucPrivateData;\r
+ BOOL ok;\r
+ OSStatus err;\r
+\r
+ // If there isn't a trailing dot, add one because the mDNSResponder\r
+ // presents names with the trailing dot.\r
+\r
+ if ( m_secretName.ReverseFind( '.' ) != m_secretName.GetLength() )\r
+ {\r
+ m_secretName += '.';\r
+ }\r
+\r
+ // attrs are reserved, so initialize to zeroes.\r
+\r
+ ZeroMemory(&attrs, sizeof( attrs ) );\r
+\r
+ // Get a handle to the Policy object on the local system\r
+\r
+ res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle );\r
+ err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );\r
+ require_noerr( err, exit );\r
+\r
+ // Intializing PLSA_UNICODE_STRING structures\r
+\r
+ ok = InitLsaString( &lucKeyName, m_secretName );\r
+ err = translate_errno( ok, errno_compat(), kUnknownErr );\r
+ require_noerr( err, exit );\r
+\r
+ ok = InitLsaString( &lucPrivateData, m_secret );\r
+ err = translate_errno( ok, errno_compat(), kUnknownErr );\r
+ require_noerr( err, exit );\r
+\r
+ // Store the private data.\r
+\r
+ res = LsaStorePrivateData( handle, &lucKeyName, &lucPrivateData );\r
+ err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );\r
+ require_noerr( err, exit );\r
+\r
+exit:\r
+\r
+ if ( handle )\r
+ {\r
+ LsaClose( handle );\r
+ handle = NULL;\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// InitLsaString\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+static BOOL\r
+InitLsaString\r
+ (\r
+ PLSA_UNICODE_STRING pLsaString,\r
+ LPCWSTR pwszString\r
+ )\r
+{\r
+ size_t dwLen = 0;\r
+ BOOL ret = FALSE;\r
+ \r
+ if ( pLsaString == NULL )\r
+ {\r
+ goto exit;\r
+ }\r
+\r
+ if ( pwszString != NULL ) \r
+ {\r
+ dwLen = wcslen(pwszString);\r
+\r
+ // String is too large\r
+ if (dwLen > 0x7ffe)\r
+ {\r
+ goto exit;\r
+ }\r
+ }\r
+\r
+ // Store the string.\r
+ \r
+ pLsaString->Buffer = (WCHAR *) pwszString;\r
+ pLsaString->Length = (USHORT) dwLen * sizeof(WCHAR);\r
+ pLsaString->MaximumLength = (USHORT)(dwLen+1) * sizeof(WCHAR);\r
+\r
+ ret = TRUE;\r
+\r
+exit:\r
+\r
+ return ret;\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.\r
+ *\r
+ * @APPLE_LICENSE_HEADER_START@\r
+ * \r
+ * This file contains Original Code and/or Modifications of Original Code\r
+ * as defined in and that are subject to the Apple Public Source License\r
+ * Version 2.0 (the 'License'). You may not use this file except in\r
+ * compliance with the License. Please obtain a copy of the License at\r
+ * http://www.opensource.apple.com/apsl/ and read it before using this\r
+ * file.\r
+ * \r
+ * The Original Code and all software distributed under the License are\r
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
+ * Please see the License for the specific language governing rights and\r
+ * limitations under the License.\r
+ * \r
+ * @APPLE_LICENSE_HEADER_END@\r
+\r
+ Change History (most recent first):\r
+\r
+$Log: SharedSecret.h,v $
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+\r
+\r
+*/\r
+\r
+ \r
+#pragma once\r
+\r
+#include "resource.h"\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+// CSharedSecret\r
+//---------------------------------------------------------------------------------------------------------------------------\r
+\r
+class CSharedSecret : public CDialog\r
+{\r
+ DECLARE_DYNAMIC(CSharedSecret)\r
+\r
+public:\r
+ CSharedSecret(CWnd* pParent = NULL); // standard constructor\r
+ virtual ~CSharedSecret();\r
+\r
+// Dialog Data\r
+ enum { IDD = IDR_SECRET };\r
+\r
+ void\r
+ Commit();\r
+\r
+protected:\r
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support\r
+\r
+ DECLARE_MESSAGE_MAP()\r
+\r
+public:\r
+ CString m_secret;\r
+ CString m_secretName;\r
+};\r
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: ThirdPage.cpp,v $
+Revision 1.3 2005/03/07 18:27:42 shersche
+<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
+
+Revision 1.2 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#include "ThirdPage.h"
+#include "resource.h"
+
+#include "ConfigPropertySheet.h"
+#include "SharedSecret.h"
+
+#include <WinServices.h>
+
+#define MAX_KEY_LENGTH 255\r
+
+
+IMPLEMENT_DYNCREATE(CThirdPage, CPropertyPage)
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::CThirdPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CThirdPage::CThirdPage()
+:
+ CPropertyPage(CThirdPage::IDD)
+{
+ //{{AFX_DATA_INIT(CThirdPage)
+ //}}AFX_DATA_INIT
+
+ m_firstTime = true;
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::~CThirdPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+CThirdPage::~CThirdPage()
+{
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::DoDataExchange
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CThirdPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CThirdPage)
+ //}}AFX_DATA_MAP
+ DDX_Control(pDX, IDC_BROWSE_LIST, m_browseListCtrl);\r
+ DDX_Control(pDX, IDC_REMOVE_BROWSE_DOMAIN, m_removeButton);\r
+}
+
+BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CThirdPage)
+ //}}AFX_MSG_MAP
+ ON_BN_CLICKED(IDC_ADD_BROWSE_DOMAIN, OnBnClickedAddBrowseDomain)\r
+ ON_BN_CLICKED(IDC_REMOVE_BROWSE_DOMAIN, OnBnClickedRemoveBrowseDomain)\r
+ ON_NOTIFY(LVN_ITEMCHANGED, IDC_BROWSE_LIST, OnLvnItemchangedBrowseList)\r
+END_MESSAGE_MAP()
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::SetModified
+//---------------------------------------------------------------------------------------------------------------------------
+
+void CThirdPage::SetModified( BOOL bChanged )
+{
+ m_modified = bChanged;
+
+ CPropertyPage::SetModified( bChanged );
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::OnSetActive
+//---------------------------------------------------------------------------------------------------------------------------
+
+BOOL
+CThirdPage::OnSetActive()
+{
+ CConfigPropertySheet * psheet;
+ HKEY key = NULL;
+ HKEY subKey = NULL;
+ DWORD dwSize;
+ DWORD enabled;
+ DWORD err;
+ TCHAR subKeyName[MAX_KEY_LENGTH];\r
+ DWORD cSubKeys = 0;\r
+ DWORD cbMaxSubKey;\r
+ DWORD cchMaxClass;\r
+ int nIndex;\r
+ DWORD i;
+ BOOL b = CPropertyPage::OnSetActive();
+
+ psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ m_modified = FALSE;
+
+ if ( m_firstTime )
+ {
+ m_browseListCtrl.SetExtendedStyle((m_browseListCtrl.GetStyle() & (~LVS_EX_GRIDLINES))|LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+
+ m_browseListCtrl.InsertColumn(0, L"", LVCFMT_LEFT, 20 );
+ m_browseListCtrl.InsertColumn(1, L"", LVCFMT_LEFT, 345);
+
+ m_firstTime = false;
+ }
+
+ m_initialized = false;
+
+ // Clear out what's there
+
+ m_browseListCtrl.DeleteAllItems();
+
+ // Now populate the browse domain box
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
+ require_noerr( err, exit );
+
+ // Get information about this node\r
+\r
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); \r
+ require_noerr( err, exit );
+\r
+ for ( i = 0; i < cSubKeys; i++)\r
+ { \r
+ dwSize = MAX_KEY_LENGTH;\r
+ \r
+ err = RegEnumKeyEx( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );\r
+ require_noerr( err, exit );\r
+\r
+ err = RegOpenKey( key, subKeyName, &subKey );\r
+ require_noerr( err, exit );\r
+\r
+ dwSize = sizeof( DWORD );\r
+ err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );\r
+ require_noerr( err, exit );\r
+\r
+ nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
+ m_browseListCtrl.SetItemText( nIndex, 1, subKeyName );\r
+ m_browseListCtrl.SetCheck( nIndex, enabled );\r
+\r
+ RegCloseKey( subKey );\r
+ subKey = NULL;\r
+ }\r
+\r
+ m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );\r
+\r
+ m_removeButton.EnableWindow( FALSE );\r
+
+exit:
+
+ if ( subKey )
+ {
+ RegCloseKey( subKey );
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+
+ m_initialized = true;
+
+ return b;
+}
+\r
+ \r
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::OnOK
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CThirdPage::OnOK()
+{
+ if ( m_modified )
+ {
+ Commit();
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::Commit
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CThirdPage::Commit()
+{
+ HKEY key = NULL;
+ HKEY subKey = NULL;
+ TCHAR subKeyName[MAX_KEY_LENGTH];\r
+ DWORD cSubKeys = 0;\r
+ DWORD cbMaxSubKey;\r
+ DWORD cchMaxClass;
+ DWORD dwSize;
+ int i;
+ DWORD err;
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" kServiceName L"\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
+ require_noerr( err, exit );
+
+ // First, remove all the entries that are there\r
+\r
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); \r
+ require_noerr( err, exit );
+\r
+ for ( i = 0; i < (int) cSubKeys; i++ )\r
+ { \r
+ dwSize = MAX_KEY_LENGTH;\r
+ \r
+ err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );\r
+ require_noerr( err, exit );\r
+ \r
+ err = RegDeleteKey( key, subKeyName );\r
+ require_noerr( err, exit );\r
+ }
+
+ // Now re-populate
+
+ for ( i = 0; i < m_browseListCtrl.GetItemCount(); i++ )
+ {
+ DWORD enabled = (DWORD) m_browseListCtrl.GetCheck( i );
+
+ err = RegCreateKey( key, m_browseListCtrl.GetItemText( i, 1 ), &subKey );
+ require_noerr( err, exit );
+
+ err = RegSetValueEx( subKey, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
+ require_noerr( err, exit );
+
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
+
+exit:
+
+ if ( subKey )
+ {
+ RegCloseKey( subKey );
+ }
+
+ if ( key )
+ {
+ RegCloseKey( key );
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::OnBnClickedAddBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CThirdPage::OnBnClickedAddBrowseDomain()
+{
+ CAddBrowseDomain dlg( GetParent() );
+
+ if ( ( dlg.DoModal() == IDOK ) && ( dlg.m_text.GetLength() > 0 ) )
+ {
+ int nIndex;
+
+ nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
+ m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text );\r
+ m_browseListCtrl.SetCheck( nIndex, 1 );\r
+\r
+ m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
+
+ m_browseListCtrl.Invalidate();
+
+ SetModified( TRUE );
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage::OnBnClickedRemoveBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+
+void
+CThirdPage::OnBnClickedRemoveBrowseDomain()
+{
+ UINT selectedCount = m_browseListCtrl.GetSelectedCount();\r
+ int nItem = -1;\r
+ UINT i;\r
+\r
+ // Update all of the selected items.\r
+\r
+ for ( i = 0; i < selectedCount; i++ )\r
+ {\r
+ nItem = m_browseListCtrl.GetNextItem( -1, LVNI_SELECTED );\r
+ check( nItem != -1 );\r
+\r
+ m_browseListCtrl.DeleteItem( nItem );\r
+\r
+ SetModified( TRUE );\r
+ }\r
+\r
+ m_removeButton.EnableWindow( FALSE );\r
+}
+
+
+void\r
+CThirdPage::OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)\r
+{\r
+ if ( m_browseListCtrl.GetSelectedCount() )\r
+ {\r
+ m_removeButton.EnableWindow( TRUE );\r
+ }\r
+\r
+ if ( m_initialized )\r
+ {\r
+ NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR; \r
+ \r
+ BOOL bPrevState = (BOOL) ( ( ( pNMListView->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 ); \r
+ \r
+ if ( bPrevState < 0 )\r
+ {\r
+ bPrevState = 0;\r
+ }\r
+\r
+\r
+ BOOL bChecked = ( BOOL ) ( ( ( pNMListView->uNewState & LVIS_STATEIMAGEMASK ) >> 12) - 1 ); \r
+ \r
+ if ( bChecked < 0 )\r
+ {\r
+ bChecked = 0;\r
+ }\r
+\r
+ if ( bPrevState != bChecked )\r
+ {\r
+ SetModified( TRUE );\r
+ }\r
+ }\r
+\r
+ *pResult = 0;\r
+}
+
+
+
+int CALLBACK \r
+CThirdPage::SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)\r
+{\r
+ CString str1;\r
+ CString str2;\r
+ int ret = 0;\r
+\r
+ CThirdPage * self = reinterpret_cast<CThirdPage*>( lParamSort );
+ require_quiet( self, exit );
+\r
+ str1 = self->m_browseListCtrl.GetItemText( (int) lParam1, 1 );\r
+ str2 = self->m_browseListCtrl.GetItemText( (int) lParam2, 1 );\r
+\r
+ ret = str1.Compare( str2 );\r
+\r
+exit:\r
+\r
+ return ret;\r
+}
+\r
+\r
+// CAddBrowseDomain dialog\r
+\r
+IMPLEMENT_DYNAMIC(CAddBrowseDomain, CDialog)\r
+CAddBrowseDomain::CAddBrowseDomain(CWnd* pParent /*=NULL*/)\r
+ : CDialog(CAddBrowseDomain::IDD, pParent)\r
+{\r
+}\r
+\r
+CAddBrowseDomain::~CAddBrowseDomain()\r
+{\r
+}\r
+\r
+void CAddBrowseDomain::DoDataExchange(CDataExchange* pDX)\r
+{\r
+ CDialog::DoDataExchange(pDX);\r
+ DDX_Control(pDX, IDC_COMBO1, m_comboBox);\r
+}\r
+\r
+\r
+BOOL\r
+CAddBrowseDomain::OnInitDialog()\r
+{\r
+ CConfigPropertySheet * psheet;\r
+ CConfigPropertySheet::StringList::iterator it;\r
+ \r
+ BOOL b = CDialog::OnInitDialog();\r
+\r
+ psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
+ require_quiet( psheet, exit );\r
+\r
+ for ( it = psheet->m_browseDomains.begin(); it != psheet->m_browseDomains.end(); it++ )\r
+ {\r
+ CString text = *it;\r
+\r
+ if ( m_comboBox.FindStringExact( -1, *it ) == CB_ERR )
+ {
+ m_comboBox.AddString( *it );
+ }\r
+ }\r
+\r
+exit:\r
+\r
+ return b;\r
+}\r
+\r
+\r
+void\r
+CAddBrowseDomain::OnOK()\r
+{\r
+ m_comboBox.GetWindowText( m_text );\r
+\r
+ CDialog::OnOK();\r
+}\r
+\r
+\r
+\r
+BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog)\r
+END_MESSAGE_MAP()\r
+\r
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: ThirdPage.h,v $
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#pragma once
+
+#include "stdafx.h"
+#include "resource.h"
+
+#include <DebugServices.h>
+#include <list>
+#include "afxcmn.h"\r
+#include "afxwin.h"\r
+
+\r
+
+//---------------------------------------------------------------------------------------------------------------------------
+// CThirdPage
+//---------------------------------------------------------------------------------------------------------------------------
+
+class CThirdPage : public CPropertyPage
+{
+public:
+ CThirdPage();
+ ~CThirdPage();
+
+protected:
+
+ //{{AFX_DATA(CThirdPage)
+ enum { IDD = IDR_APPLET_PAGE3 };
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CThirdPage)
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ DECLARE_DYNCREATE(CThirdPage)
+
+ //{{AFX_MSG(CThirdPage)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+
+ typedef std::list<CString> StringList;
+
+ afx_msg BOOL
+ OnSetActive();
+
+ afx_msg void
+ OnOK();
+
+ void
+ SetModified( BOOL bChanged = TRUE );
+
+ void
+ Commit();
+
+ BOOL m_modified;
+
+public:
+private:\r
+ static int CALLBACK \r
+ SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);\r
+\r
+ CListCtrl m_browseListCtrl;\r
+ bool m_initialized;\r
+ bool m_firstTime;\r
+\r
+public:\r
+\r
+ afx_msg void OnBnClickedAddBrowseDomain();\r
+ afx_msg void OnBnClickedRemoveBrowseDomain();\r
+ afx_msg void OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);\r
+ CButton m_removeButton;\r
+};\r
+\r
+\r
+//---------------------------------------------------------------------------------------------------------------------------
+// CAddBrowseDomain
+//---------------------------------------------------------------------------------------------------------------------------
+\r
+class CAddBrowseDomain : public CDialog\r
+{\r
+ DECLARE_DYNAMIC(CAddBrowseDomain)\r
+\r
+public:\r
+ CAddBrowseDomain(CWnd* pParent = NULL); // standard constructor\r
+ virtual ~CAddBrowseDomain();\r
+\r
+// Dialog Data\r
+ enum { IDD = IDR_ADD_BROWSE_DOMAIN };\r
+\r
+protected:\r
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support\r
+ virtual BOOL OnInitDialog();\r
+ virtual void OnOK();\r
+ DECLARE_MESSAGE_MAP()\r
+public:\r
+ CComboBox m_comboBox;\r
+ CString m_text;\r
+};\r
--- /dev/null
+//\r
+// CPL_PP.RC2 - resources Microsoft Visual C++ does not edit directly\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+ #error this file is not editable by Microsoft Visual C++\r
+#endif //APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Add manually edited resources here...\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by ControlPanel.rc\r
+//\r
+#define IDR_APPLET 131\r
+#define IDR_APPLET_PAGE1 131\r
+#define IDS_APPLET_DESCRIPTION 132\r
+#define IDR_APPLET_PAGE2 132\r
+#define IDR_SECRET 133\r
+#define IDR_APPLET_PAGE3 134\r
+#define IDI_FAILURE 140\r
+#define IDI_SUCCESS 141\r
+#define IDD_ADD_BROWSE_DOMAIN 142\r
+#define IDR_ADD_BROWSE_DOMAIN 142\r
+#define IDC_EDIT1 1000\r
+#define IDC_BUTTON1 1001\r
+#define IDC_COMBO1 1002\r
+#define IDC_CHECK1 1003\r
+#define IDC_COMBO2 1004\r
+#define IDC_EDIT2 1005\r
+#define IDC_SECRET 1005\r
+#define IDC_COMBO3 1007\r
+#define IDC_FAILURE 1008\r
+#define IDC_SUCCESS 1009\r
+#define IDC_SECRET_NAME 1010\r
+#define IDC_LIST1 1011\r
+#define IDC_BROWSE_LIST 1011\r
+#define IDC_BUTTON2 1012\r
+#define IDC_REMOVE_BROWSE_DOMAIN 1012\r
+#define IDC_ADD_BROWSE_DOMAIN 1013\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE 143\r
+#define _APS_NEXT_COMMAND_VALUE 32771\r
+#define _APS_NEXT_CONTROL_VALUE 1014\r
+#define _APS_NEXT_SYMED_VALUE 101\r
+#endif\r
+#endif\r
--- /dev/null
+/*
+ * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: stdafx.cpp,v $
+Revision 1.2 2005/03/03 19:55:22 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#include "stdafx.h"
+
+
--- /dev/null
+/*
+ * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: stdafx.h,v $
+Revision 1.2 2005/03/03 19:55:21 shersche
+<rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
+
+
+*/
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
+#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
+#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+// Step 3: We want to see one image, but not a tile
+#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
+#define _WIN32_IE 0x0500 // Change this to the appropriate value to target IE 5.0 or later.
+#endif
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+// turns off MFC's hiding of some common and often safely ignored warning messages
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdisp.h> // MFC Automation classes
+
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+#include <afxdlgs.h>\r
+#include <cpl.h> // Control Panel Applet functions and defines\r
+#include <afxtempl.h> // MFC Template support
-/*\r
- * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.\r
- *\r
- * @APPLE_LICENSE_HEADER_START@\r
- * \r
- * This file contains Original Code and/or Modifications of Original Code\r
- * as defined in and that are subject to the Apple Public Source License\r
- * Version 2.0 (the 'License'). You may not use this file except in\r
- * compliance with the License. Please obtain a copy of the License at\r
- * http://www.opensource.apple.com/apsl/ and read it before using this\r
- * file.\r
- * \r
- * The Original Code and all software distributed under the License are\r
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
- * Please see the License for the specific language governing rights and\r
- * limitations under the License.\r
- * \r
- * @APPLE_LICENSE_HEADER_END@\r
-\r
- Change History (most recent first):\r
-\r
+/*
+ * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
$Log: Stdafx.cpp,v $
+Revision 1.2 2005/02/05 02:37:01 cheshire
+Convert newlines to Unix-style (ASCII 10)
+
Revision 1.1 2004/06/26 04:01:22 shersche
Initial revision
-\r
-\r
- */\r
- \r
-// stdafx.cpp : source file that includes just the standard includes\r
-// dotNET.pch will be the pre-compiled header\r
-// stdafx.obj will contain the pre-compiled type information\r
-\r
-#include "stdafx.h"\r
+
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// dotNET.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
-/*\r
- * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.\r
- *\r
- * @APPLE_LICENSE_HEADER_START@\r
- * \r
- * This file contains Original Code and/or Modifications of Original Code\r
- * as defined in and that are subject to the Apple Public Source License\r
- * Version 2.0 (the 'License'). You may not use this file except in\r
- * compliance with the License. Please obtain a copy of the License at\r
- * http://www.opensource.apple.com/apsl/ and read it before using this\r
- * file.\r
- * \r
- * The Original Code and all software distributed under the License are\r
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\r
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\r
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\r
- * Please see the License for the specific language governing rights and\r
- * limitations under the License.\r
- * \r
- * @APPLE_LICENSE_HEADER_END@\r
-\r
- Change History (most recent first):\r
-\r
+/*
+ * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
$Log: Stdafx.h,v $
+Revision 1.3 2005/02/05 02:40:59 cheshire
+Convert newlines to Unix-style (ASCII 10)
+
+Revision 1.2 2005/02/05 02:37:01 cheshire
+Convert newlines to Unix-style (ASCII 10)
+
Revision 1.1 2004/06/26 04:01:22 shersche
Initial revision
-\r
-\r
- */\r
- \r
-// stdafx.h : include file for standard system include files,\r
-// or project specific include files that are used frequently,\r
-// but are changed infrequently\r
-\r
-#pragma once\r
-\r
-#using <mscorlib.dll>\r
-#using <System.dll>\r
-\r
+
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#using <mscorlib.dll>
+#using <System.dll>
+
Bug #: 3786226
Revision 1.6 2004/09/02 21:20:56 cheshire
-<rdar://problem/3774871> Rendezvous DLL.NET crashes on null record
+<rdar://problem/3774871> DLL.NET crashes on null record
Revision 1.5 2004/07/27 07:12:56 shersche
make TextRecord an instantiable class object
* (not into any common system area where it might interfere with other
* applications using a future completed version of these APIs).
* If you plan to do this, please be sure to inform us by sending email
- * to rendezvous@apple.com to let us know.
- * You may want to discuss what you're doing on the Rendezvous mailing
+ * to bonjour@apple.com to let us know.
+ * You may want to discuss what you're doing on the Bonjour mailing
* list to see if others in similar positions have any suggestions for you:
*
- * <http://lists.apple.com/mailman/listinfo/rendezvous-dev/>
+ * <http://lists.apple.com/bonjour-dev/>
*
Change History (most recent first):
$Log: dnssd_NET.h,v $
+Revision 1.8 2005/02/10 22:35:33 cheshire
+<rdar://problem/3727944> Update name
+
Revision 1.7 2004/12/16 19:56:12 cheshire
Update comments
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Apple Computer, Inc."
- VALUE "FileDescription", "dnssd.NET Dynamic Link Library"
+ VALUE "FileDescription", "Bonjour.NET Client Library"
VALUE "FileVersion", MASTER_PROD_VERS_STR
- VALUE "InternalName", "dnssd.NET"
+ VALUE "InternalName", "dnssd.NET.dll"
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "dnssd.NET.dll"
VALUE "ProductName", MASTER_PROD_NAME
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Apple Computer, Inc."
- VALUE "FileDescription", "dnssd Dynamic Link Library"
+ VALUE "FileDescription", "Bonjour Client Library"
VALUE "FileVersion", MASTER_PROD_VERS_STR
- VALUE "InternalName", "dnssd"
+ VALUE "InternalName", "dnssd.dll"
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "dnssd.dll"
VALUE "ProductName", MASTER_PROD_NAME
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\bin"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
CharacterSet="2">\r
Change History (most recent first):
$Log: ChooserDialog.cpp,v $
+Revision 1.3 2005/02/10 22:35:35 cheshire
+<rdar://problem/3727944> Update name
+
Revision 1.2 2004/07/13 21:24:26 rpantos
Fix for <rdar://problem/3701120>.
{ "_printer._tcp.", "Printer (LPR)", "lpr://", false },
{ "_ptp._tcp.", "Picture Transfer (PTP)", "ptp://", false },
{ "_register._tcp", "DNS Service Discovery", "", false },
- { "_rendezvouspong._tcp", "RendezvousPong", "", false },
{ "_rfb._tcp.", "Remote Frame Buffer", "", false },
{ "_riousbprint._tcp.", "Remote I/O USB Printer Protocol", "", false },
{ "_rtsp._tcp.", "Real Time Stream Control Protocol", "", false },
# @APPLE_LICENSE_HEADER_END@
#
# $Log: makefile,v $
+# Revision 1.6 2005/02/10 22:35:36 cheshire
+# <rdar://problem/3727944> Update name
+#
+# Revision 1.5 2005/02/08 23:47:51 shersche
+# Build into proper directories for installer
+#
# Revision 1.4 2004/12/16 22:38:00 shersche
# Compile DNSSDException.java first to avoid build errors, copy output to appropriate "buildroot" folder
#
CFLAGS_DEBUG = -Zi -DMDNS_DEBUGMSGS=2
OBJDIR = objects\debug
BUILDDIR = build\debug
+INSTALLDIR = root\"Program Files"\Bonjour
LIBDIR = ..\DLL\Debug
!else
CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0
OBJDIR = objects\prod
BUILDDIR = build\prod
+INSTALLDIR = root\"Program Files"\Bonjour
LIBDIR = ..\DLL\Release
!endif
@if not exist $(OBJDIR) mkdir $(OBJDIR)
@if not exist $(BUILDDIR) mkdir $(BUILDDIR)
-!if DEFINED(DNSSD_BUILD_ROOT)
-!if $(DEBUG) == 1
-postbuild:
- copy $(BUILDDIR)\dns_sd.jar $(DNSSD_BUILD_ROOT)\Debug\Root\"Program Files"\bin
- copy $(BUILDDIR)\jdns_sd.dll $(DNSSD_BUILD_ROOT)\Debug\Root\"Program Files"\bin
-!else
postbuild:
- copy $(BUILDDIR)\dns_sd.jar $(DNSSD_BUILD_ROOT)\Release\Root\"Program Files"\bin
- copy $(BUILDDIR)\jdns_sd.dll $(DNSSD_BUILD_ROOT)\Release\Root\"Program Files"\bin
-!endif
-!else
-postbuild:
-!endif
+ @if not exist root mkdir root
+ @if not exist root\"Program Files" mkdir root\"Program Files"
+ @if not exist $(INSTALLDIR) mkdir $(INSTALLDIR)
+ copy $(BUILDDIR)\dns_sd.jar $(INSTALLDIR)
+ copy $(BUILDDIR)\jdns_sd.dll $(INSTALLDIR)
# clean removes targets and objects
clean:
--- /dev/null
+/*
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: RegNames.h,v $
+Revision 1.1 2005/03/03 02:31:37 shersche
+Consolidates all registry key names and can safely be included in any component that needs it
+
+
+*/
+
+//----------------------------------------------------------------------------------------
+// Registry Constants
+//----------------------------------------------------------------------------------------
+
+#if defined(UNICODE)
+
+# define kServiceName L"Bonjour Service"
+# define kServiceDynDNSBrowseDomains L"BrowseDomains"
+# define kServiceDynDNSHostNames L"HostNames"
+# define kServiceDynDNSRegistrationDomains L"RegistrationDomains"
+# define kServiceDynDNSDomains L"Domains" // value is comma separated list of domains
+# define kServiceDynDNSEnabled L"Enabled"
+# define kServiceDynDNSStatus L"Status"
+# define kServiceManageLLRouting L"ManageLLRouting"
+# define kServiceCacheEntryCount L"CacheEntryCount"
+# define kServiceManageFirewall L"ManageFirewall"
+
+# else
+
+# define kServiceName "Bonjour Service"
+# define kServiceDynDNSBrowseDomains "BrowseDomains"
+# define kServiceDynDNSHostNames "HostNames"
+# define kServiceDynDNSRegistrationDomains "RegistrationDomains"
+# define kServiceDynDNSDomains "Domains" // value is comma separated list of domains
+# define kServiceDynDNSEnabled "Enabled"
+# define kServiceDynDNSStatus "Status"
+# define kServiceManageLLRouting "ManageLLRouting"
+# define kServiceCacheEntryCount "CacheEntryCount"
+# define kServiceManageFirewall "ManageFirewall"
+
+#endif
Define DNS_SD_CLIENT_ENABLED=0 so DNSSD.c can be included without linking the client IPC code.
Revision 1.1 2004/01/30 02:58:39 bradley
-mDNSResponder Windows Service. Provides global Rendezvous support with an IPC interface.
+mDNSResponder Windows Service. Provides global Bonjour support with an IPC interface.
*/
Change History (most recent first):
$Log: Service.c,v $
+Revision 1.29 2005/03/06 05:21:56 shersche
+<rdar://problem/4037635> Fix corrupt UTF-8 name when non-ASCII system name used, enabled unicode support
+
+Revision 1.28 2005/03/03 02:27:24 shersche
+Include the RegNames.h header file for names of registry keys
+
+Revision 1.27 2005/03/02 20:12:59 shersche
+Update name
+
+Revision 1.26 2005/02/15 08:00:27 shersche
+<rdar://problem/4007151> Update name
+
+Revision 1.25 2005/02/10 22:35:36 cheshire
+<rdar://problem/3727944> Update name
+
Revision 1.24 2005/01/27 20:02:43 cheshire
udsSupportRemoveFDFromEventLoop() needs to close the SocketRef as well
Remove the XP SP2 check before attempting to manage the firewall. There is a race condition in the SP2 updater such that upon first reboot after the upgrade, mDNSResponder might not know that it is running under SP2 yet. This necessitates a second reboot before the firewall is managed. Removing the check will cause mDNSResponder to try and manage the firewall everytime it boots up, if and only if it hasn't managed the firewall a previous time.
Revision 1.15 2004/09/15 17:13:33 shersche
-Change Firewall name from "Apple mDNSResponder" to "Rendezvous"
+Change Firewall name
Revision 1.14 2004/09/15 09:37:25 shersche
Add SharedAccess to dependency list, call CheckFirewall after sending status back to SCM
Move up one level.
Revision 1.1 2004/01/30 02:58:39 bradley
-mDNSResponder Windows Service. Provides global Rendezvous support with an IPC interface.
+mDNSResponder Windows Service. Provides global Bonjour support with an IPC interface.
*/
#include "CommonServices.h"
#include "DebugServices.h"
+#include "RegNames.h"
#include "uds_daemon.h"
#include "GenLinkedList.h"
// Constants
//===========================================================================================================================
-#define DEBUG_NAME "[Server] "
-#define kServiceName "Apple mDNSResponder"
-#define kServiceFirewallName L"Rendezvous"
-#define kServiceDependencies "Tcpip\0winmgmt\0\0"
-#define kServiceManageLLRouting "ManageLLRouting"
-#define kServiceCacheEntryCount "CacheEntryCount"
-#define kServiceManageFirewall "ManageFirewall"
+#define DEBUG_NAME "[Server] "
+#define kServiceFirewallName L"Bonjour"
+#define kServiceDependencies TEXT("Tcpip\0winmgmt\0\0")
#define kDNSServiceCacheEntryCountDefault 512
#define RR_CACHE_SIZE 500
//===========================================================================================================================
// Prototypes
//===========================================================================================================================
-
+#if defined(UNICODE)
+int __cdecl wmain( int argc, LPTSTR argv[] );
+#else
int __cdecl main( int argc, char *argv[] );
+#endif
static void Usage( void );
static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent );
-static OSStatus InstallService( const char *inName, const char *inDisplayName, const char *inDescription, const char *inPath );
-static OSStatus RemoveService( const char *inName );
+static OSStatus InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath );
+static OSStatus RemoveService( LPCTSTR inName );
static OSStatus SetServiceParameters();
static OSStatus GetServiceParameters();
static OSStatus CheckFirewall();
-static OSStatus SetServiceInfo( SC_HANDLE inSCM, const char *inServiceName, const char *inDescription );
+static OSStatus SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription );
static void ReportStatus( int inType, const char *inFormat, ... );
-static OSStatus RunDirect( int argc, char *argv[] );
+static OSStatus RunDirect( int argc, LPTSTR argv[] );
-static void WINAPI ServiceMain( DWORD argc, LPSTR argv[] );
+static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] );
static OSStatus ServiceSetupEventLogging( void );
static DWORD WINAPI ServiceControlHandler( DWORD inControl, DWORD inEventType, LPVOID inEventData, LPVOID inContext );
-static OSStatus ServiceRun( int argc, char *argv[] );
+static OSStatus ServiceRun( int argc, LPTSTR argv[] );
static void ServiceStop( void );
-static OSStatus ServiceSpecificInitialize( int argc, char *argv[] );
-static OSStatus ServiceSpecificRun( int argc, char *argv[] );
+static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] );
+static OSStatus ServiceSpecificRun( int argc, LPTSTR argv[] );
static OSStatus ServiceSpecificStop( void );
-static void ServiceSpecificFinalize( int argc, char *argv[] );
+static void ServiceSpecificFinalize( int argc, LPTSTR argv[] );
static mStatus EventSourceFinalize(Win32EventSource * source);
static void EventSourceLock();
static void EventSourceUnlock();
static bool HaveLLRoute(PMIB_IPFORWARDROW rowExtant);
static OSStatus SetLLRoute();
+#if defined(UNICODE)
+# define StrLen(X) wcslen(X)
+# define StrCmp(X,Y) wcscmp(X,Y)
+#else
+# define StrLen(X) strlen(X)
+# define StrCmp(X,Y) strcmp(X,Y)
+#endif
+
+
#define kLLNetworkAddr "169.254.0.0"
#define kLLNetworkAddrMask "255.255.0.0"
//===========================================================================================================================
// main
//===========================================================================================================================
-
+#if defined(UNICODE)
+int __cdecl wmain( int argc, wchar_t * argv[] )
+#else
int __cdecl main( int argc, char *argv[] )
+#endif
{
OSStatus err;
BOOL ok;
debug_initialize( kDebugOutputTypeMetaConsole );
debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
-
+
// Default to automatically starting the service dispatcher if no extra arguments are specified.
start = ( argc <= 1 );
for( i = 1; i < argc; ++i )
{
- if( strcmp( argv[ i ], "-install" ) == 0 ) // Install
+ if( StrCmp( argv[ i ], TEXT("-install") ) == 0 ) // Install
{
- char desc[ 256 ];
+ TCHAR desc[ 256 ];
desc[ 0 ] = 0;
- LoadStringA( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
- err = InstallService( kServiceName, kServiceName, desc, argv[ 0 ] );
+ LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
+ err = InstallService( kServiceName, kServiceName, desc, argv[0] );
if( err )
{
ReportStatus( EVENTLOG_ERROR_TYPE, "install service failed (%d)\n", err );
goto exit;
}
}
- else if( strcmp( argv[ i ], "-remove" ) == 0 ) // Remove
+ else if( StrCmp( argv[ i ], TEXT("-remove") ) == 0 ) // Remove
{
err = RemoveService( kServiceName );
if( err )
goto exit;
}
}
- else if( strcmp( argv[ i ], "-start" ) == 0 ) // Start
+ else if( StrCmp( argv[ i ], TEXT("-start") ) == 0 ) // Start
{
start = TRUE;
}
- else if( strcmp( argv[ i ], "-server" ) == 0 ) // Server
+ else if( StrCmp( argv[ i ], TEXT("-server") ) == 0 ) // Server
{
err = RunDirect( argc, argv );
if( err )
}
goto exit;
}
- else if( strcmp( argv[ i ], "-q" ) == 0 ) // Quiet Mode (toggle)
+ else if( StrCmp( argv[ i ], TEXT("-q") ) == 0 ) // Quiet Mode (toggle)
{
gServiceQuietMode = !gServiceQuietMode;
}
- else if( strcmp( argv[ i ], "-remote" ) == 0 ) // Allow Remote Connections
- {
- gServiceAllowRemote = true;
- }
- else if( strcmp( argv[ i ], "-cache" ) == 0 ) // Number of mDNS cache entries
- {
- if( i <= argc )
- {
- ReportStatus( EVENTLOG_ERROR_TYPE, "-cache used, but number of cache entries not specified\n" );
- err = kParamErr;
- goto exit;
- }
- gServiceCacheEntryCount = atoi( argv[ ++i ] );
- }
- else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || // Help
- ( strcmp( argv[ i ], "-h" ) == 0 ) )
+ else if( ( StrCmp( argv[ i ], TEXT("-help") ) == 0 ) || // Help
+ ( StrCmp( argv[ i ], TEXT("-h") ) == 0 ) )
{
Usage();
err = 0;
// InstallService
//===========================================================================================================================
-static OSStatus InstallService( const char *inName, const char *inDisplayName, const char *inDescription, const char *inPath )
+static OSStatus InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath )
{
OSStatus err;
SC_HANDLE scm;
// RemoveService
//===========================================================================================================================
-static OSStatus RemoveService( const char *inName )
+static OSStatus RemoveService( LPCTSTR inName )
{
OSStatus err;
SC_HANDLE scm;
DWORD value;
DWORD valueLen = sizeof(DWORD);
DWORD type;
- const char * s;
+ LPCTSTR s;
OSStatus err;
HKEY key;
//
// Add/Open Parameters section under service entry in registry
//
- s = "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters";
+ s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters");
err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
require_noerr( err, exit );
DWORD value;
DWORD valueLen;
DWORD type;
- const char * s;
+ LPCTSTR s;
OSStatus err;
HKEY key;
//
// Add/Open Parameters section under service entry in registry
//
- s = "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters";
+ s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters");
err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
require_noerr( err, exit );
DWORD value;
DWORD valueLen;
DWORD type;
- const char * s;
+ LPCTSTR s;
HKEY key = NULL;
OSStatus err = kUnknownErr;
// the case, then we need to manipulate the firewall
// so networking works correctly.
- s = "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters";
+ s = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters");
err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
require_noerr( err, exit );
// SetServiceInfo
//===========================================================================================================================
-static OSStatus SetServiceInfo( SC_HANDLE inSCM, const char *inServiceName, const char *inDescription )
+static OSStatus SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription )
{
OSStatus err;
SC_LOCK lock;
// Change the description.
- description.lpDescription = (char *) inDescription;
+ description.lpDescription = (LPTSTR) inDescription;
ok = ChangeServiceConfig2( service, SERVICE_CONFIG_DESCRIPTION, &description );
err = translate_errno( ok, (OSStatus) GetLastError(), kParamErr );
require_noerr( err, exit );
vsprintf( s, inFormat, args );
array[ 0 ] = s;
- ok = ReportEvent( gServiceEventSource, (WORD) inType, 0, 0x20000001L, NULL, 1, 0, array, NULL );
+ ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, 0x20000001L, NULL, 1, 0, array, NULL );
check_translated_errno( ok, GetLastError(), kUnknownErr );
}
else
// RunDirect
//===========================================================================================================================
-static OSStatus RunDirect( int argc, char *argv[] )
+static OSStatus RunDirect( int argc, LPTSTR argv[] )
{
OSStatus err;
BOOL initialized;
// ServiceMain
//===========================================================================================================================
-static void WINAPI ServiceMain( DWORD argc, LPSTR argv[] )
+static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] )
{
OSStatus err;
BOOL ok;
- char desc[ 256 ];
+ TCHAR desc[ 256 ];
err = ServiceSetupEventLogging();
check_noerr( err );
// Setup the description. This should be done by the installer, but it doesn't support that yet.
desc[ 0 ] = '\0';
- LoadStringA( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
+ LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
err = SetServiceInfo( NULL, kServiceName, desc );
check_noerr( err );
{
OSStatus err;
HKEY key;
- const char * s;
+ LPCTSTR s;
DWORD typesSupported;
- char path[ MAX_PATH ];
+ TCHAR path[ MAX_PATH ];
DWORD n;
key = NULL;
// Add/Open source name as a sub-key under the Application key in the EventLog registry key.
- s = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" kServiceName;
+ s = TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\") kServiceName;
err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
require_noerr( err, exit );
// Add the name to the EventMessageFile subkey.
-
+
path[ 0 ] = '\0';
GetModuleFileName( NULL, path, MAX_PATH );
- n = (DWORD)( strlen( path ) + 1 );
- err = RegSetValueEx( key, "EventMessageFile", 0, REG_EXPAND_SZ, (const LPBYTE) path, n );
+ n = (DWORD) ( ( StrLen( path ) + 1 ) * sizeof( TCHAR ) );
+ err = RegSetValueEx( key, TEXT("EventMessageFile"), 0, REG_EXPAND_SZ, (const LPBYTE) path, n );
require_noerr( err, exit );
// Set the supported event types in the TypesSupported subkey.
| EVENTLOG_INFORMATION_TYPE
| EVENTLOG_AUDIT_SUCCESS
| EVENTLOG_AUDIT_FAILURE;
- err = RegSetValueEx( key, "TypesSupported", 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) );
+ err = RegSetValueEx( key, TEXT("TypesSupported"), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) );
require_noerr( err, exit );
// Set up the event source.
// ServiceRun
//===========================================================================================================================
-static OSStatus ServiceRun( int argc, char *argv[] )
+static OSStatus ServiceRun( int argc, LPTSTR argv[] )
{
OSStatus err;
BOOL initialized;
// ServiceSpecificInitialize
//===========================================================================================================================
-static OSStatus ServiceSpecificInitialize( int argc, char *argv[] )
+static OSStatus ServiceSpecificInitialize( int argc, LPTSTR argv[] )
{
OSStatus err;
// ServiceSpecificRun
//===========================================================================================================================
-static OSStatus ServiceSpecificRun( int argc, char *argv[] )
+static OSStatus ServiceSpecificRun( int argc, LPTSTR argv[] )
{
DWORD result;
// ServiceSpecificFinalize
//===========================================================================================================================
-static void ServiceSpecificFinalize( int argc, char *argv[] )
+static void ServiceSpecificFinalize( int argc, LPTSTR argv[] )
{
DEBUG_UNUSED( argc );
DEBUG_UNUSED( argv );
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Apple Computer, Inc."
- VALUE "FileDescription", "mDNSResponder"
+ VALUE "FileDescription", "Bonjour Service"
VALUE "FileVersion", MASTER_PROD_VERS_STR
- VALUE "InternalName", "mDNSResponder"
+ VALUE "InternalName", "mDNSResponder.exe"
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "mDNSResponder.exe"
VALUE "ProductName", MASTER_PROD_NAME
Name="VCCLCompilerTool"\r
Optimization="0"\r
AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include""\r
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""""\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DEBUG=1;MDNS_DEBUGMSGS=0;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""";UNICODE;_UNICODE"\r
StringPooling="TRUE"\r
MinimalRebuild="TRUE"\r
ExceptionHandling="FALSE"\r
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\bin"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="1"\r
CharacterSet="2">\r
<Tool\r
Name="VCCLCompilerTool"\r
AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include""\r
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""""\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;TARGET_OS_WIN32;WIN32_LEAN_AND_MEAN;USE_TCP_LOOPBACK;PLATFORM_NO_STRSEP;PLATFORM_NO_EPIPE;PLATFORM_NO_RLIMIT;PID_FILE="""";UNICODE;_UNICODE"\r
RuntimeLibrary="0"\r
UsePrecompiledHeader="0"\r
WarningLevel="4"\r
Change History (most recent first):
$Log: WinVersRes.h,v $
+Revision 1.30 2005/03/07 19:18:18 shersche
+<rdar://problem/4039831> Update Windows build to 1.0.0.58
+
+Revision 1.29 2005/03/02 20:11:45 shersche
+Update name
+
+Revision 1.28 2005/03/02 03:57:51 shersche
+Bump to 1.0.0.57
+
+Revision 1.27 2005/02/23 03:12:27 shersche
+Bump to 1.0.0.56
+
+Revision 1.26 2005/02/15 23:20:18 shersche
+Bump to 1.0.0.55 and update name
+
+Revision 1.25 2005/02/10 22:35:29 cheshire
+<rdar://problem/3727944> Update name
+
+Revision 1.24 2005/02/08 23:32:24 shersche
+Bump to 1.0.0.54
+
+Revision 1.23 2005/02/02 02:08:28 shersche
+Bump to version 1.0.0.53
+
Revision 1.22 2005/01/25 17:15:52 shersche
Bump to 1.0.0.51. Add legal copyright string.
#ifndef WINRESVERS_H
#define WINRESVERS_H
-#define MASTER_PROD_NAME "Rendezvous"
+#define MASTER_PROD_NAME "Bonjour"
// Define the product version for mDNSResponder on Windows
-#define MASTER_PROD_VERS 1,0,0,52
-#define MASTER_PROD_VERS_STR "1,0,0,52"
-#define MASTER_PROD_VERS_STR2 "1.0.0.52"
-#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.52"
+#define MASTER_PROD_VERS 1,0,0,58
+#define MASTER_PROD_VERS_STR "1,0,0,58"
+#define MASTER_PROD_VERS_STR2 "1.0.0.58"
+#define MASTER_PROD_VERS_STR3 "Explorer Plugin 1.0.0.58"
// Define the legal copyright
#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2005 Apple Computer, Inc."
static DNameListElem *DefRegList = mDNSNULL; // manually generated list of domains where we register for empty string registrations
static ARListElem *SCPrefBrowseDomains = mDNSNULL; // manually generated local-only PTR records for browse domains we get from SCPreferences
-static domainname dDNSRegDomain; // Default wide-area zone for service registration
-static domainname dDNSBrowseDomain; // Default wide-area zone for legacy ("empty string") browses
-static domainname dDNSHostname;
+static domainname dDNSRegDomain; // Default wide-area zone for service registration
+static DNameListElem * dDNSBrowseDomains; // Default wide-area zone for legacy ("empty string") browses
+static domainname dDNSHostname;
mStatus dDNS_SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
return mStatus_NoError;
}
+
+mDNSlocal void RegisterBrowseDomainPTR(mDNS *m, const domainname *d, int type)
+ {
+ // allocate/register legacy and non-legacy _browse PTR record
+ mStatus err;
+ ARListElem *browse = mallocL("ARListElem", sizeof(*browse));
+ mDNS_SetupResourceRecord(&browse->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, browse);
+ MakeDomainNameFromDNSNameString(browse->ar.resrec.name, mDNS_DomainTypeNames[type]);
+ AppendDNSNameString (browse->ar.resrec.name, "local");
+ AssignDomainName(&browse->ar.resrec.rdata->u.name, d);
+ err = mDNS_Register(m, &browse->ar);
+ if (err)
+ {
+ LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
+ freeL("ARListElem", browse);
+ }
+ else
+ {
+ browse->next = SCPrefBrowseDomains;
+ SCPrefBrowseDomains = browse;
+ }
+ }
+
+mDNSlocal void DeregisterBrowseDomainPTR(mDNS *m, const domainname *d, int type)
+ {
+ ARListElem *remove, **ptr = &SCPrefBrowseDomains;
+ domainname lhs; // left-hand side of PTR, for comparison
+
+ MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
+ AppendDNSNameString (&lhs, "local");
+
+ while (*ptr)
+ {
+ if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
+ {
+ remove = *ptr;
+ *ptr = (*ptr)->next;
+ mDNS_Deregister(m, &remove->ar);
+ return;
+ }
+ else ptr = &(*ptr)->next;
+ }
+ }
+
// Add or remove a user-specified domain to the list of empty-string browse domains
// Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
mDNSlocal void SetSCPrefsBrowseDomain(mDNS *m, const domainname *d, mDNSBool add)
{
- AuthRecord rec;
-
LogMsg("%s default browse domain %##s", add ? "Adding" : "Removing", d->c);
- // Create dummy record pointing to the domain to be added/removed
- mDNS_SetupResourceRecord(&rec, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
- AssignDomainName(&rec.resrec.rdata->u.name, d);
-
- // add/remove the "_legacy" entry
- MakeDomainNameFromDNSNameString(rec.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeBrowseLegacy]);
- AppendDNSNameString (rec.resrec.name, "local");
- FoundDefBrowseDomain(m, &LegacyBrowseDomainQ, &rec.resrec, add);
-
if (add)
{
- mStatus err;
-
- // allocate/register a non-legacy _browse PTR record
- ARListElem *ptr = mallocL("ARListElem", sizeof(*ptr));
- mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, ptr);
- MakeDomainNameFromDNSNameString(ptr->ar.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeBrowse]);
- AppendDNSNameString (ptr->ar.resrec.name, "local");
- AssignDomainName(&ptr->ar.resrec.rdata->u.name, d);
- err = mDNS_Register(m, &ptr->ar);
- if (err)
- {
- LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
- freeL("ARListElem", ptr);
- }
- else
- {
- ptr->next = SCPrefBrowseDomains;
- SCPrefBrowseDomains = ptr;
- }
+ RegisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowse);
+ RegisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowseLegacy);
}
else
{
- ARListElem **remove = &SCPrefBrowseDomains;
- while (*remove && !SameDomainName(&(*remove)->ar.resrec.rdata->u.name, d)) remove = &(*remove)->next;
- if (!*remove) { LogMsg("SetSCPrefsBrowseDomain (remove) - domain %##s not found!", d->c); return; }
- mDNS_Deregister(m, &(*remove)->ar);
- *remove = (*remove)->next;
+ DeregisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowse);
+ DeregisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowseLegacy);
}
}
+mDNSlocal void SetSCPrefsBrowseDomains(mDNS *m, DNameListElem * browseDomains, mDNSBool add)
+ {
+ DNameListElem * browseDomain;
+
+ for ( browseDomain = browseDomains; browseDomain; browseDomain = browseDomain->next )
+ {
+ if ( !browseDomain->name.c[0] )
+ {
+ LogMsg("SetSCPrefsBrowseDomains bad DDNS browse domain: %s", browseDomain->name.c[0] ? browseDomain->name.c : "(unknown)");
+ }
+ else
+ {
+ SetSCPrefsBrowseDomain(m, &browseDomain->name, add);
+ }
+ }
+ }
mStatus dDNS_Setup( mDNS *const m )
{
static mDNSBool LegacyNATInitialized = mDNSfalse;
mDNSBool dict = mDNStrue;
mDNSAddr ip;
- mDNSAddr r;
- // YO CFDictionaryRef dict;
- // YO CFStringRef key;
- domainname BrowseDomain, RegDomain, fqdn;
+ mDNSAddr r;
+ DNameListElem * BrowseDomains;
+ domainname RegDomain, fqdn;
// get fqdn, zone from SCPrefs
- dDNSPlatformGetConfig(&fqdn, &RegDomain, &BrowseDomain);
+ dDNSPlatformGetConfig(&fqdn, &RegDomain, &BrowseDomains);
// YO if (!fqdn.c[0] && !RegDomain.c[0]) ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &fqdn, &RegDomain);
}
}
- if (!SameDomainName(&BrowseDomain, &dDNSBrowseDomain))
- {
- if (dDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &dDNSBrowseDomain, mDNSfalse);
- AssignDomainName(&dDNSBrowseDomain, &BrowseDomain);
- if (dDNSBrowseDomain.c[0]) SetSCPrefsBrowseDomain(m, &dDNSBrowseDomain, mDNStrue);
- }
+ // Add new browse domains to internal list
+
+ if ( BrowseDomains )
+ {
+ SetSCPrefsBrowseDomains( m, BrowseDomains, mDNStrue );
+ }
+
+ // Remove old browse domains from internal list
+
+ if ( dDNSBrowseDomains )
+ {
+ SetSCPrefsBrowseDomains( m, dDNSBrowseDomains, mDNSfalse );
+ mDNS_FreeDNameList( dDNSBrowseDomains );
+ }
+
+ // Replace the old browse domains array with the new array
+
+ dDNSBrowseDomains = BrowseDomains;
+
if (!SameDomainName(&fqdn, &dDNSHostname))
{
// This section defines the interface to the DynDNS Platform Support layer.
-extern void dDNSPlatformGetConfig(domainname *const fqdn, domainname *const regDomain, domainname *const browseDomain);
+extern void dDNSPlatformGetConfig(domainname *const fqdn, domainname *const regDomain, DNameListElem ** browseDomains);
extern void dDNSPlatformSetNameStatus(domainname *const dname, mStatus status);
extern void dDNSPlatformSetSecretForDomain( mDNS *m, const domainname *domain );
extern DNameListElem * dDNSPlatformGetSearchDomainList( void );
* ----------------------------------------------------------------------
*/
+#include "DebugServices.h"
#include <windows.h>
#include <stdio.h>
#include "isocode.h"
#include <sys/stat.h>
#include <wchar.h>
+
#ifdef __cplusplus
extern "c" {
#endif
static char appPathNameA[MAX_PATH] = "";
-int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen) {
- if (!strcmp(appPathNameA,"")) {
- GetModuleFileNameA(module, appPathNameA, MAX_PATH);
+int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen)
+{
+ int ret = 0;
+
+ if ( !strcmp( appPathNameA, "" ) )
+ {
+ char folder[MAX_PATH];
+ char * app;
+
+ GetModuleFileNameA( module, folder, MAX_PATH );
+
+ // Get folder string
+
+ app = strrchr( folder, '\\' );
+ require_action( app, exit, ret = 0 );
+
+ *app++ = '\0';
+
+ snprintf( appPathNameA, MAX_PATH, "%s\\Resources\\%s", folder, app );
}
- return PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen);
+ ret = PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen);
+
+exit:
+ return ret;
}
static wchar_t appPathNameW[MAX_PATH] = L"";
-int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen) {
- if (!wcscmp(appPathNameW,L"")) {
- GetModuleFileNameW( module, appPathNameW, MAX_PATH);
+int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen)
+{
+ int ret = 0;
+
+ if ( !wcscmp( appPathNameW, L"" ) )
+ {
+ wchar_t folder[MAX_PATH];
+ wchar_t * app;
+
+ GetModuleFileNameW( module, folder, MAX_PATH);
+
+ // Get folder string
+
+ app = wcsrchr( folder, '\\' );
+ require_action( app, exit, ret = 0 );
+
+ *app++ = '\0';
+
+ swprintf( appPathNameW, MAX_PATH, L"%ls\\Resources\\%ls", folder, app );
}
-OutputDebugString( appPathNameW );
+ ret = PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen);
+
+exit:
- return PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen);
+ return ret;
}
}
// fall back on DEFAULT_LANG_CODE if still no good
- swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%s.lproj\\%ls",
+ swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%S.lproj\\%ls",
path, DEFAULT_LANG_CODE, nm);
// we can't find the resource, so return 0
Change History (most recent first):
$Log: mDNSWin32.c,v $
+Revision 1.83 2005/03/07 18:27:42 shersche
+<rdar://problem/4037940> Fix problem when ControlPanel commits changes to the browse domain list
+
+Revision 1.82 2005/03/06 05:20:24 shersche
+<rdar://problem/4037635> Fix corrupt UTF-8 name when non-ASCII system name used, enabled unicode support
+
+Revision 1.81 2005/03/04 22:44:53 shersche
+<rdar://problem/4022802> mDNSResponder did not notice changes to DNS server config
+
+Revision 1.80 2005/03/03 21:07:38 shersche
+<rdar://problem/4034460> mDNSResponder doesn't handle multiple browse domains
+
+Revision 1.79 2005/03/03 02:29:00 shersche
+Use the RegNames.h header file for registry key names
+
+Revision 1.78 2005/03/02 04:04:17 shersche
+Support for multiple browse domains
+
+Revision 1.77 2005/02/25 20:02:18 shersche
+<rdar://problem/4022802> Call ProcessingThreadDynDNSConfigChanged() when interface list changes
+
+Revision 1.76 2005/02/23 02:59:20 shersche
+<rdar://problem/4013482> Check to see if locks have been initialized before using them.
+
+Revision 1.75 2005/02/16 02:36:25 shersche
+<rdar://problem/3830846> Use IPv6 if interface has no routable IPv4 address
+
+Revision 1.74 2005/02/08 06:06:16 shersche
+<rdar://problem/3986597> Implement mDNSPlatformTCPConnect, mDNSPlatformTCPCloseConnection, mDNSPlatformTCPRead, mDNSPlatformTCPWrite
+
+Revision 1.73 2005/02/01 19:35:43 ksekar
+Removed obsolete arguments from mDNS_SetSecretForZone
+
+Revision 1.72 2005/02/01 01:38:53 shersche
+Handle null DynDNS configuration more gracefully
+
Revision 1.71 2005/01/27 22:57:57 cheshire
Fix compile errors on gcc4
#include "CommonServices.h"
#include "DebugServices.h"
+#include "RegNames.h"
#include <dns_sd.h>
#include <Iphlpapi.h>
#define MDNS_WINDOWS_USE_IPV6_IF_ADDRS 1
#define MDNS_WINDOWS_ENABLE_IPV4 1
#define MDNS_WINDOWS_ENABLE_IPV6 1
-#define MDNS_WINDOWS_EXCLUDE_IPV4_ROUTABLE_IPV6 1
-#define MDNS_WINDOWS_AAAA_OVER_IPV4 1
#define MDNS_FIX_IPHLPAPI_PREFIX_BUG 1
#define kMDNSDefaultName "My Computer"
#define kWaitListInterfaceListChangedEvent ( WAIT_OBJECT_0 + 1 )
#define kWaitListWakeupEvent ( WAIT_OBJECT_0 + 2 )
#define kWaitListComputerDescriptionEvent ( WAIT_OBJECT_0 + 3 )
-#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 4 )
-#define kWaitListFixedItemCount 5 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6
+#define kWaitListTCPIPEvent ( WAIT_OBJECT_0 + 4 )
+#define kWaitListDynDNSEvent ( WAIT_OBJECT_0 + 5 )
+#define kWaitListFixedItemCount 6 + MDNS_WINDOWS_ENABLE_IPV4 + MDNS_WINDOWS_ENABLE_IPV6
+#define kRegistryMaxKeyLength 255
#if( !TARGET_OS_WINDOWS_CE )
static GUID kWSARecvMsgGUID = WSAID_WSARECVMSG;
mDNSlocal void ProcessingThreadProcessPacket( mDNS *inMDNS, mDNSInterfaceData *inIFD, SocketRef inSock );
mDNSlocal void ProcessingThreadInterfaceListChanged( mDNS *inMDNS );
mDNSlocal void ProcessingThreadComputerDescriptionChanged( mDNS * inMDNS );
+mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS );
mDNSlocal void ProcessingThreadDynDNSConfigChanged( mDNS * inMDNS );
mDNSAddr ip;
};
+typedef struct mDNSTCPConnectionData mDNSTCPConnectionData;
+struct mDNSTCPConnectionData
+{
+ SocketRef sock;
+ BOOL connected;
+ TCPConnectionCallback callback;
+ void * context;
+ HANDLE pendingEvent;
+ mDNSTCPConnectionData * next;
+};
+
+
mDNSexport mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
mDNSlocal mDNSBool CanReceiveUnicast( void );
-mDNSlocal mStatus StringToAddress( mDNSAddr * ip, const char * string );
-mDNSlocal mStatus RegQueryString( HKEY key, const char * param, char ** string, DWORD * stringLen, DWORD * enabled );
+mDNSlocal mStatus StringToAddress( mDNSAddr * ip, LPSTR string );
+mDNSlocal mStatus RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled );
mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh);
+mDNSlocal OSStatus TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
+mDNSlocal OSStatus WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
mDNSlocal OSStatus ConvertUTF8ToLsaString( const char * input, PLSA_UNICODE_STRING output );
mDNSlocal OSStatus ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char ** output );
+mDNSlocal void FreeTCPConnectionData( mDNSTCPConnectionData * data );
#ifdef __cplusplus
}
mDNSlocal mDNS_PlatformSupport gMDNSPlatformSupport;
mDNSs32 mDNSPlatformOneSecond = 0;
+mDNSlocal mDNSTCPConnectionData * gTCPConnectionList = NULL;
+mDNSlocal int gTCPConnections = 0;
+mDNSlocal BOOL gWaitListChanged = FALSE;
#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
int supported;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
+ int sa4len;
+ int sa6len;
dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
sa4.sin_addr.s_addr = INADDR_ANY;
err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4 );
check_noerr( err );
+ sa4len = sizeof( sa4 );
+ err = getsockname( inMDNS->p->unicastSock4, (struct sockaddr*) &sa4, &sa4len );
+ require_noerr( err, exit );
+ inMDNS->UnicastPort4.NotAnInteger = sa4.sin_port;
inMDNS->p->unicastSock4ReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
err = translate_errno( inMDNS->p->unicastSock4ReadEvent, (mStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
if ( inMDNS->p->unicastSock6 != INVALID_SOCKET )
{
+ sa6len = sizeof( sa6 );
+ err = getsockname( inMDNS->p->unicastSock6, (struct sockaddr*) &sa6, &sa6len );
+ require_noerr( err, exit );
+ inMDNS->UnicastPort6.NotAnInteger = sa6.sin6_port;
+
err = WSAEventSelect( inMDNS->p->unicastSock6, inMDNS->p->unicastSock6ReadEvent, FD_READ );
require_noerr( err, exit );
void mDNSPlatformLock( const mDNS * const inMDNS )
{
check( inMDNS );
- check( inMDNS->p->lockInitialized );
- EnterCriticalSection( &inMDNS->p->lock );
+ if ( inMDNS->p->lockInitialized )
+ {
+ EnterCriticalSection( &inMDNS->p->lock );
+ }
}
//===========================================================================================================================
{
check( inMDNS );
check( inMDNS->p );
- check( inMDNS->p->lockInitialized );
- check( inMDNS->p->threadID );
+
+ if ( inMDNS->p->lockInitialized )
+ {
+ check( inMDNS->p->threadID );
- // Signal a wakeup event if when called from a task other than the mDNS task since if we are called from mDNS task,
- // we'll loop back and call mDNS_Execute anyway. Signaling is needed to re-evaluate the wakeup via mDNS_Execute.
+ // Signal a wakeup event if when called from a task other than the mDNS task since if we are called from mDNS task,
+ // we'll loop back and call mDNS_Execute anyway. Signaling is needed to re-evaluate the wakeup via mDNS_Execute.
- if( GetCurrentThreadId() != inMDNS->p->threadID )
- {
- BOOL wasSet;
+ if( GetCurrentThreadId() != inMDNS->p->threadID )
+ {
+ BOOL wasSet;
- wasSet = SetEvent( inMDNS->p->wakeupEvent );
- check_translated_errno( wasSet, GetLastError(), kUnknownErr );
+ wasSet = SetEvent( inMDNS->p->wakeupEvent );
+ check_translated_errno( wasSet, GetLastError(), kUnknownErr );
+ }
+ LeaveCriticalSection( &inMDNS->p->lock );
}
- LeaveCriticalSection( &inMDNS->p->lock );
}
//===========================================================================================================================
void * inContext,
int * outSock )
{
- DEBUG_UNUSED( inDstIP );
- DEBUG_UNUSED( inDstPort );
+ u_long on = 1; // "on" for setsockopt
+ struct sockaddr_in saddr;
+ mDNSTCPConnectionData * tcd = NULL;
+ mStatus err = mStatus_NoError;
+
DEBUG_UNUSED( inInterfaceID );
- DEBUG_UNUSED( inCallback );
- DEBUG_UNUSED( inContext );
- DEBUG_UNUSED( outSock );
- return( mStatus_UnsupportedErr );
+ *outSock = INVALID_SOCKET;
+
+ if ( inDstIP->type != mDNSAddrType_IPv4 )
+ {
+ LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
+ return mStatus_UnknownErr;
+ }
+
+ // Setup connection data object
+
+ tcd = (mDNSTCPConnectionData*) malloc( sizeof( mDNSTCPConnectionData ) );
+ require_action( tcd, exit, err = mStatus_NoMemoryErr );
+ memset( tcd, 0, sizeof( mDNSTCPConnectionData ) );
+
+ tcd->sock = INVALID_SOCKET;
+ tcd->callback = inCallback;
+ tcd->context = inContext;
+
+ bzero(&saddr, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = inDstPort.NotAnInteger;
+ memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
+
+ // Create the socket
+
+ tcd->sock = socket(AF_INET, SOCK_STREAM, 0);
+ err = translate_errno( tcd->sock != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr );
+ require_noerr( err, exit );
+
+ // Set it to be non-blocking
+
+ err = ioctlsocket( tcd->sock, FIONBIO, &on );
+ err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
+ require_noerr( err, exit );
+
+ // Try and do connect
+
+ err = connect( tcd->sock, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
+ require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
+ tcd->connected = !err ? TRUE : FALSE;
+ tcd->pendingEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ err = translate_errno( tcd->pendingEvent, GetLastError(), mStatus_UnknownErr );
+ require_noerr( err, exit );
+ err = WSAEventSelect( tcd->sock, tcd->pendingEvent, FD_CONNECT|FD_READ|FD_CLOSE );
+ require_noerr( err, exit );
+
+ // Bookkeeping
+
+ tcd->next = gTCPConnectionList;
+ gTCPConnectionList = tcd;
+ gTCPConnections++;
+ gWaitListChanged = TRUE;
+
+ *outSock = (int) tcd->sock;
+
+exit:
+
+ if ( !err )
+ {
+ err = tcd->connected ? mStatus_ConnEstablished : mStatus_ConnPending;
+ }
+ else if ( tcd )
+ {
+ FreeTCPConnectionData( tcd );
+ }
+
+ return err;
}
//===========================================================================================================================
void mDNSPlatformTCPCloseConnection( int inSock )
{
- DEBUG_UNUSED( inSock );
+ mDNSTCPConnectionData * tcd = gTCPConnectionList;
+ mDNSTCPConnectionData * last = NULL;
+
+ while ( tcd )
+ {
+ if ( tcd->sock == ( SOCKET ) inSock )
+ {
+ if ( last == NULL )
+ {
+ gTCPConnectionList = tcd->next;
+ }
+ else
+ {
+ last->next = tcd->next;
+ }
+
+ FreeTCPConnectionData( tcd );
+
+ gTCPConnections--;
+ gWaitListChanged = TRUE;
+
+ break;
+ }
+
+ last = tcd;
+ tcd = tcd->next;
+ }
}
//===========================================================================================================================
int mDNSPlatformReadTCP( int inSock, void *inBuffer, int inBufferSize )
{
- DEBUG_UNUSED( inSock );
- DEBUG_UNUSED( inBuffer );
- DEBUG_UNUSED( inBufferSize );
-
- return( -1 );
+ int nread;
+ OSStatus err;
+
+ nread = recv( inSock, inBuffer, inBufferSize, 0);
+ err = translate_errno( ( nread >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
+ require_noerr( err, exit );
+
+ if ( nread < 0 )
+ {
+ nread = 0;
+ }
+
+exit:
+
+ return nread;
}
//===========================================================================================================================
int mDNSPlatformWriteTCP( int inSock, const char *inMsg, int inMsgSize )
{
- DEBUG_UNUSED( inSock );
- DEBUG_UNUSED( inMsg );
- DEBUG_UNUSED( inMsgSize );
-
- return( -1 );
-}
+ int nsent;
+ OSStatus err;
+ nsent = send( inSock, inMsg, inMsgSize, 0 );
+
+ err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
+ require_noerr( err, exit );
+
+ if ( nsent < 0)
+ {
+ nsent = 0;
+ }
+
+exit:
+
+ return nsent;
+}
//===========================================================================================================================
// dDNSPlatformGetConfig
//===========================================================================================================================
void
-dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, domainname *const browseDomain)
+dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, DNameListElem ** browseDomains)
{
- char * name = NULL;
+ LPSTR name = NULL;
+ char subKeyName[kRegistryMaxKeyLength + 1];
+ DWORD cSubKeys = 0;
+ DWORD cbMaxSubKey;
+ DWORD cchMaxClass;
DWORD dwSize;
DWORD enabled;
HKEY key;
+ HKEY subKey = NULL;
+ domainname dname;
+ DWORD i;
OSStatus err;
// Initialize
- fqdn->c[0] = regDomain->c[0] = browseDomain->c[0] = 0;
+ fqdn->c[0] = regDomain->c[0] = '\0';
+
+ *browseDomains = NULL;
- err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSHostNames, &key );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
require_noerr( err, exit );
err = RegQueryString( key, "", &name, &dwSize, &enabled );
name = NULL;
}
- err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, &key );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains, &key );
require_noerr( err, exit );
- err = RegQueryString( key, "", &name, &dwSize, &enabled );
- if ( !err && ( name[0] != '\0' ) && enabled )
+ // Get information about this node
+
+ err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
+ require_noerr( err, exit );
+
+ for ( i = 0; i < cSubKeys; i++)
{
- if ( !MakeDomainNameFromDNSNameString( browseDomain, name ) || !browseDomain->c[0] )
+ DWORD enabled;
+
+ dwSize = kRegistryMaxKeyLength;
+
+ err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+
+ if ( !err )
{
- dlog( kDebugLevelError, "bad DDNS browse domain in registry: %s", name[0] ? name : "(unknown)");
- }
+ err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
+ require_noerr( err, exit );
+
+ dwSize = sizeof( DWORD );
+ err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+
+ if ( !err && ( subKeyName[0] != '\0' ) && enabled )
+ {
+ if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] )
+ {
+ dlog( kDebugLevelError, "bad DDNS browse domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)");
+ }
+ else
+ {
+ DNameListElem * browseDomain = (DNameListElem*) malloc( sizeof( DNameListElem ) );
+ require_action( browseDomain, exit, err = mStatus_NoMemoryErr );
+
+ AssignDomainName(&browseDomain->name, &dname);
+ browseDomain->next = *browseDomains;
+
+ *browseDomains = browseDomain;
+ }
+ }
+
+ RegCloseKey( subKey );
+ subKey = NULL;
+ }
}
if ( key )
key = NULL;
}
- if ( name )
- {
- free( name );
- name = NULL;
- }
-
- err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, &key );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains, &key );
require_noerr( err, exit );
err = RegQueryString( key, "", &name, &dwSize, &enabled );
exit:
+ if ( subKey )
+ {
+ RegCloseKey( subKey );
+ }
+
if ( key )
{
RegCloseKey( key );
dDNSPlatformSetNameStatus(domainname *const dname, mStatus status)
{
char uname[MAX_ESCAPED_DOMAIN_NAME];
- char name[MAX_ESCAPED_DOMAIN_NAME + 256];
+ LPCTSTR name;
HKEY key = NULL;
mStatus err;
char * p;
}
check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
- sprintf( name, "SYSTEM\\CurrentControlSet\\Services\\%s\\Parameters\\DynDNS\\State\\HostNames", kServiceName );
+ name = TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\State\\HostNames");
err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
require_noerr( err, exit );
+ status = ( status ) ? 0 : 1;
err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &status, sizeof(DWORD) );
require_noerr( err, exit );
err = ConvertLsaStringToUTF8( secret, &converted );
require_noerr( err, exit );
- mDNS_SetSecretForZone( m, d, d, converted, (mDNSu32) strlen( converted ) + 1, mDNStrue );
+ mDNS_SetSecretForZone( m, d, d, converted );
exit:
HKEY key;
mStatus err;
- err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", &key );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key );
require_noerr( err, exit );
err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
{
mStatus err = 0;
char tempString[ 256 ];
+ char utf8[ 256 ];
check( inMDNS );
// Set up the nice name.
tempString[ 0 ] = '\0';
+ utf8[0] = '\0';
// First try and open the registry key that contains the computer description value
if (inMDNS->p->descKey == NULL)
{
- const char * s = "SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters";
+ LPCTSTR s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &inMDNS->p->descKey);
check_translated_errno( err == 0, errno_compat(), kNameErr );
// if we opened it...
if (inMDNS->p->descKey != NULL)
{
- DWORD type;
- DWORD valueLen = sizeof(tempString);
+ TCHAR desc[256];
+ DWORD descSize = sizeof( desc );
// look for the computer description
- err = RegQueryValueEx(inMDNS->p->descKey, "srvcomment", 0, &type, (LPBYTE) &tempString, &valueLen);
- check_translated_errno( err == 0, errno_compat(), kNameErr );
+ err = RegQueryValueEx(inMDNS->p->descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
+
+ if ( !err )
+ {
+ err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) );
+ }
+
+ if ( err )
+ {
+ utf8[ 0 ] = '\0';
+ }
}
// if we can't find it in the registry, then use the hostname of the machine
- if (err || ( tempString[ 0] == '\0' ) )
+ if ( err || ( utf8[ 0 ] == '\0' ) )
{
err = gethostname( tempString, sizeof( tempString ) - 1 );
check_translated_errno( err == 0, errno_compat(), kNameErr );
+
+ if( !err )
+ {
+ err = WindowsLatin1toUTF8( tempString, utf8, sizeof( utf8 ) );
+ }
+
+ if ( err )
+ {
+ utf8[ 0 ] = '\0';
+ }
}
// if we can't get the hostname
- if( err || ( tempString[ 0 ] == '\0' ) )
+ if ( err || ( utf8[ 0 ] == '\0' ) )
{
// Invalidate name so fall back to a default name.
- strcpy( tempString, kMDNSDefaultName );
+ strcpy( utf8, kMDNSDefaultName );
}
- tempString[ sizeof( tempString ) - 1 ] = '\0';
-
- inMDNS->nicelabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL);
- memcpy( &inMDNS->nicelabel.c[ 1 ], tempString, inMDNS->nicelabel.c[ 0 ] );
+ utf8[ sizeof( utf8 ) - 1 ] = '\0';
+ inMDNS->nicelabel.c[ 0 ] = (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL);
+ memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] );
dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD )
{
- mStatus err;
- mDNSInterfaceData * ifd;
+ mDNSInterfaceData * ifd;
+ mDNSInterfaceData * p;
SocketRef sock;
+ mStatus err;
ifd = NULL;
dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" );
// but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only
// devices on a large configured network, so we are willing to make that sacrifice.
- ifd->interfaceInfo.McastTxRx = mDNStrue;
-
-#if( MDNS_WINDOWS_EXCLUDE_IPV4_ROUTABLE_IPV6 )
- if( inIFA->ifa_addr->sa_family != AF_INET )
+ ifd->interfaceInfo.McastTxRx = mDNStrue;
+ ifd->interfaceInfo.InterfaceID = NULL;
+
+ for( p = inMDNS->p->interfaceList; p; p = p->next )
{
- const mDNSInterfaceData * p;
-
- for( p = inMDNS->p->interfaceList; p; p = p->next )
+ if ( strcmp( p->name, ifd->name ) == 0 )
{
- if( ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
- ( ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 ) && ( p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) ) &&
- ( strcmp( p->name, inIFA->ifa_name ) == 0 ) )
+ if (!ifd->interfaceInfo.InterfaceID)
+ {
+ p->scopeID = ifd->scopeID;
+ ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) p;
+ }
+
+ if ( ( inIFA->ifa_addr->sa_family != AF_INET ) &&
+ ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
+ ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) )
{
ifd->interfaceInfo.McastTxRx = mDNSfalse;
- break;
}
+
+ break;
}
}
-#endif
- // If this is an IPv6 interface, search for its IPv4 equivalent and use that InterfaceID. This causes the IPv4
- // interface to send both A and AAAA records so we can publish IPv6 support without doubling the packet rate.
- // Note: this search only works because we register all IPv4 interfaces before IPv6 interfaces.
-
- ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
-
-#if( MDNS_WINDOWS_AAAA_OVER_IPV4 )
- if( inIFA->ifa_addr->sa_family != AF_INET )
+ if ( !ifd->interfaceInfo.InterfaceID )
{
- mDNSInterfaceData * ipv4IFD;
-
- for( ipv4IFD = inMDNS->p->interfaceList; ipv4IFD; ipv4IFD = ipv4IFD->next )
- {
- if( strcmp( ipv4IFD->name, ifd->name ) == 0 )
- {
- ipv4IFD->scopeID = ifd->scopeID;
- ifd->interfaceInfo.McastTxRx = mDNSfalse;
- ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ipv4IFD;
- break;
- }
- }
+ ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
}
-#endif
-
+
// Set up a socket for this interface (if needed).
if( ifd->interfaceInfo.McastTxRx )
require_noerr( err, exit );
}
+ // This will catch all changes to tcp/ip networking, including changes to the domain search list
+
+ inMDNS->p->tcpipChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ err = translate_errno( inMDNS->p->tcpipChangedEvent, (mStatus) GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &inMDNS->p->tcpipKey );
+ require_noerr( err, exit );
+
+ err = RegNotifyChangeKeyValue(inMDNS->p->tcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->tcpipChangedEvent, TRUE);
+ require_noerr( err, exit );
+
+ // This will catch all changes to ddns configuration
+
inMDNS->p->ddnsChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
err = translate_errno( inMDNS->p->ddnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
- err = RegCreateKey( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\" kServiceName "\\Parameters\\DynDNS\\Setup", &inMDNS->p->ddnsKey );
+ err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\") kServiceName TEXT("\\Parameters\\DynDNS\\Setup"), &inMDNS->p->ddnsKey );
require_noerr( err, exit );
err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
inMDNS->p->descKey = NULL;
}
+ if ( inMDNS->p->tcpipChangedEvent != NULL )
+ {
+ CloseHandle( inMDNS->p->tcpipChangedEvent );
+ inMDNS->p->tcpipChangedEvent = NULL;
+ }
+
if ( inMDNS->p->ddnsChangedEvent != NULL )
{
CloseHandle( inMDNS->p->ddnsChangedEvent );
// Main processing loop.
+ gWaitListChanged = FALSE;
+
for( ;; )
{
// Give the mDNS core a chance to do its work and determine next event time.
mDNSs32 interval = mDNS_Execute(m) - mDNS_TimeNow(m);
+
+ if ( gWaitListChanged )
+ {
+ break;
+ }
+
if (m->p->idleThreadCallback)
{
interval = m->p->idleThreadCallback(m, interval);
ProcessingThreadComputerDescriptionChanged( m );
break;
}
+ else if ( result == kWaitListTCPIPEvent )
+ {
+ //
+ // The TCP/IP might have changed
+ //
+ ProcessingThreadTCPIPConfigChanged( m );
+ break;
+ }
else if ( result == kWaitListDynDNSEvent )
{
//
{
HANDLE signaledObject;
int n = 0;
- mDNSInterfaceData * ifd;
+ mDNSInterfaceData * ifd;
+ mDNSTCPConnectionData * tcd;
signaledObject = waitList[ waitItemIndex ];
}
}
+ for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
+ {
+ if ( tcd->pendingEvent == signaledObject )
+ {
+ mDNSBool connect = FALSE;
+
+ if ( !tcd->connected )
+ {
+ tcd->connected = mDNStrue;
+ connect = mDNStrue;
+ }
+
+ tcd->callback( ( int ) tcd->sock, tcd->context, connect );
+
+ ++n;
+
+ break;
+ }
+ }
+
check( n > 0 );
}
else
mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount )
{
- mStatus err;
- int waitListCount;
- HANDLE * waitList;
- HANDLE * waitItemPtr;
- mDNSInterfaceData * ifd;
+ mStatus err;
+ int waitListCount;
+ HANDLE * waitList;
+ HANDLE * waitItemPtr;
+ mDNSInterfaceData * ifd;
+ mDNSTCPConnectionData * tcd;
dlog( kDebugLevelTrace, DEBUG_NAME "thread setting up wait list\n" );
check( inMDNS );
// Allocate an array to hold all the objects to wait on.
- waitListCount = kWaitListFixedItemCount + inMDNS->p->interfaceCount;
+ waitListCount = kWaitListFixedItemCount + inMDNS->p->interfaceCount + gTCPConnections;
waitList = (HANDLE *) malloc( waitListCount * sizeof( *waitList ) );
require_action( waitList, exit, err = mStatus_NoMemoryErr );
waitItemPtr = waitList;
*waitItemPtr++ = inMDNS->p->interfaceListChangedEvent;
*waitItemPtr++ = inMDNS->p->wakeupEvent;
*waitItemPtr++ = inMDNS->p->descChangedEvent;
+ *waitItemPtr++ = inMDNS->p->tcpipChangedEvent;
*waitItemPtr++ = inMDNS->p->ddnsChangedEvent;
// Append all the dynamic wait items to the list.
{
*waitItemPtr++ = ifd->readPendingEvent;
}
+
+ for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
+ {
+ *waitItemPtr++ = tcd->pendingEvent;
+ }
+
check( (int)( waitItemPtr - waitList ) == waitListCount );
*outWaitList = waitList;
}
+//===========================================================================================================================
+// ProcessingThreadTCPIPConfigChanged
+//===========================================================================================================================
+mDNSlocal void ProcessingThreadTCPIPConfigChanged( mDNS * inMDNS )
+{
+ mStatus err;
+
+ dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
+ check( inMDNS );
+
+ mDNSPlatformLock( inMDNS );
+
+ err = dDNS_Setup( inMDNS );
+ check_noerr( err );
+
+ // and reset the event handler
+
+ if ( ( inMDNS->p->tcpipKey != NULL ) && ( inMDNS->p->tcpipChangedEvent ) )
+ {
+ err = RegNotifyChangeKeyValue( inMDNS->p->tcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->tcpipChangedEvent, TRUE );
+ check_noerr( err );
+ }
+
+ mDNSPlatformUnlock( inMDNS );
+}
+
+
//===========================================================================================================================
// ProcessingThreadDynDNSConfigChanged
//===========================================================================================================================
check_noerr( err );
// and reset the event handler
+
if ((inMDNS->p->ddnsKey != NULL) && (inMDNS->p->ddnsChangedEvent))
{
err = RegNotifyChangeKeyValue(inMDNS->p->ddnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, inMDNS->p->ddnsChangedEvent, TRUE);
//===========================================================================================================================
static mStatus
-RegQueryString( HKEY key, const char * valueName, char ** string, DWORD * stringLen, DWORD * enabled )
+RegQueryString( HKEY key, LPCSTR valueName, LPSTR * string, DWORD * stringLen, DWORD * enabled )
{
DWORD type;
int i;
*string = (char*) malloc( *stringLen );
require_action( *string, exit, err = mStatus_NoMemoryErr );
- err = RegQueryValueEx( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
+ err = RegQueryValueExA( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
i++;
}
while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
+ require_noerr_quiet( err, exit );
+
if ( enabled )
{
DWORD dwSize = sizeof( DWORD );
- err = RegQueryValueEx( key, "Enabled", NULL, NULL, (LPBYTE) enabled, &dwSize );
+ err = RegQueryValueEx( key, TEXT("Enabled"), NULL, NULL, (LPBYTE) enabled, &dwSize );
check_noerr( err );
err = kNoErr;
// StringToAddress
//===========================================================================================================================
-static mStatus StringToAddress( mDNSAddr * ip, const char * string )
+static mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
{
struct sockaddr_in6 sa6;
struct sockaddr_in sa4;
sa6.sin6_family = AF_INET6;
dwSize = sizeof( sa6 );
- err = WSAStringToAddress( (LPSTR) string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
+ err = WSAStringToAddressA( string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
if ( err == mStatus_NoError )
{
sa4.sin_family = AF_INET;
dwSize = sizeof( sa4 );
- err = WSAStringToAddress( (LPSTR) string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
+ err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
require_noerr( err, exit );
err = dDNS_SetupAddr( ip, (struct sockaddr*) &sa4 );
}
+//===========================================================================================================================
+// TCHARtoUTF8
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize )
+{
+#if( defined( UNICODE ) || defined( _UNICODE ) )
+ OSStatus err;
+ int len;
+
+ len = WideCharToMultiByte( CP_UTF8, 0, inString, -1, inBuffer, (int) inBufferSize, NULL, NULL );
+ err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+ return( err );
+#else
+ return( WindowsLatin1toUTF8( inString, inBuffer, inBufferSize ) );
+#endif
+}
+
+
+//===========================================================================================================================
+// WindowsLatin1toUTF8
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize )
+{
+ OSStatus err;
+ WCHAR * utf16;
+ int len;
+
+ utf16 = NULL;
+
+ // Windows doesn't support going directly from Latin-1 to UTF-8 so we have to go from Latin-1 to UTF-16 first.
+
+ len = MultiByteToWideChar( CP_ACP, 0, inString, -1, NULL, 0 );
+ err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ utf16 = (WCHAR *) malloc( len * sizeof( *utf16 ) );
+ require_action( utf16, exit, err = kNoMemoryErr );
+
+ len = MultiByteToWideChar( CP_ACP, 0, inString, -1, utf16, len );
+ err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // Now convert the temporary UTF-16 to UTF-8.
+
+ len = WideCharToMultiByte( CP_UTF8, 0, utf16, -1, inBuffer, (int) inBufferSize, NULL, NULL );
+ err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+ if( utf16 ) free( utf16 );
+ return( err );
+}
+
+
//===========================================================================================================================
// ConvertUTF8ToLsaString
//===========================================================================================================================
return err;
}
+
+
+//===========================================================================================================================
+// FreeTCPConnectionData
+//===========================================================================================================================
+
+mDNSlocal void
+FreeTCPConnectionData( mDNSTCPConnectionData * data )
+{
+ check( data );
+
+ if ( data->pendingEvent )
+ {
+ CloseHandle( data->pendingEvent );
+ }
+
+ if ( data->sock != INVALID_SOCKET )
+ {
+ closesocket( data->sock );
+ }
+
+ free( data );
+}
Change History (most recent first):
$Log: mDNSWin32.h,v $
+Revision 1.22 2005/03/04 22:44:53 shersche
+<rdar://problem/4022802> mDNSResponder did not notice changes to DNS server config
+
+Revision 1.21 2005/03/03 02:29:00 shersche
+Use the RegNames.h header file for registry key names
+
Revision 1.20 2005/01/25 08:12:52 shersche
<rdar://problem/3947417> Enable Unicast and add Dynamic DNS support.
Bug #: 3947417
HANDLE quitEvent;
HANDLE interfaceListChangedEvent;
HANDLE descChangedEvent; // Computer description changed event
+ HANDLE tcpipChangedEvent; // TCP/IP config changed
HANDLE ddnsChangedEvent; // DynDNS config changed
HANDLE wakeupEvent;
HANDLE initEvent;
HKEY descKey;
+ HKEY tcpipKey;
HKEY ddnsKey;
mStatus initStatus;
SocketRef interfaceListChangedSocket;
void freeifaddrs( struct ifaddrs *inAddrs );
-//---------------------------------------------------------------------------------------------------------------------------
-// Registry Constants
-//---------------------------------------------------------------------------------------------------------------------------
-
-#define kServiceName "Apple mDNSResponder"
-#define kServiceDynDNSBrowseDomains "BrowseDomains"
-#define kServiceDynDNSHostNames "HostNames"
-#define kServiceDynDNSRegistrationDomains "RegistrationDomains"
-#define kServiceDynDNSDomains "Domains" // value is comma separated list of domains
-#define kServiceDynDNSEnabled "Enabled"
-#define kServiceDynDNSStatus "Status"
-
-
#ifdef __cplusplus
}
#endif
Change History (most recent first):
$Log: mdnsNSP.c,v $
+Revision 1.10 2005/02/23 22:16:07 shersche
+Unregister the NSP before registering to workaround an installer problem during upgrade installs
+
+Revision 1.9 2005/02/01 01:45:55 shersche
+Change mdnsNSP timeout to 2 seconds
+
+Revision 1.8 2005/01/31 23:27:25 shersche
+<rdar://problem/3936771> Don't try and resolve .local hostnames that are referenced in the hosts file
+
+Revision 1.7 2005/01/28 23:50:13 shersche
+<rdar://problem/3942551> Implement DllRegisterServer,DllUnregisterServer so mdnsNSP.dll can self-register
+Bug #: 3942551
+
Revision 1.6 2004/12/06 01:56:53 shersche
<rdar://problem/3789425> Use the DNS types and classes defined in dns_sd.h
Bug #: 3789425
bool addrValid;
};
+#define BUFFER_INITIAL_SIZE 4192
+#define ALIASES_INITIAL_SIZE 5
+
+typedef struct HostsFile
+{
+ int m_bufferSize;
+ char * m_buffer;
+ FILE * m_fp;
+} HostsFile;
+
+
+typedef struct HostsFileInfo
+{
+ struct hostent m_host;
+ struct HostsFileInfo * m_next;
+} HostsFileInfo;
+
+
#if 0
#pragma mark == Prototypes ==
#endif
// DLL Exports
BOOL WINAPI DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved );
+STDAPI DllRegisterServer( void );
+STDAPI DllRegisterServer( void );
+
// NSP SPIs
int WSPAPI NSPCleanup( LPGUID inProviderID );
#define dlog_query_set( LEVEL, SET )
#endif
+DEBUG_LOCAL BOOL InHostsTable( const char * name );
+DEBUG_LOCAL BOOL IsLocalName( HostsFileInfo * node );
+DEBUG_LOCAL BOOL IsSameName( HostsFileInfo * node, const char * name );
+DEBUG_LOCAL OSStatus HostsFileOpen( HostsFile ** self, const char * fname );
+DEBUG_LOCAL OSStatus HostsFileClose( HostsFile * self );
+DEBUG_LOCAL void HostsFileInfoFree( HostsFileInfo * info );
+DEBUG_LOCAL OSStatus HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo );
+
+
#if 0
#pragma mark == Globals ==
#endif
//===========================================================================================================================
// {B600E6E9-553B-4a19-8696-335E5C896153}
-// GUID kmdnsNSPGUID = { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x33, 0x5e, 0x5c, 0x89, 0x61, 0x53 } };
-
+DEBUG_LOCAL HINSTANCE gInstance = NULL;
+DEBUG_LOCAL wchar_t * gNSPName = L"mdnsNSP";
+DEBUG_LOCAL GUID gNSPGUID = { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x33, 0x5e, 0x5c, 0x89, 0x61, 0x53 } };
DEBUG_LOCAL LONG gRefCount = 0;
DEBUG_LOCAL CRITICAL_SECTION gLock;
DEBUG_LOCAL bool gLockInitialized = false;
DEBUG_LOCAL bool gDNSSDInitialized = false;
DEBUG_LOCAL QueryRef gQueryList = NULL;
+DEBUG_LOCAL HostsFileInfo * gHostsFileInfo = NULL;
#if 0
#pragma mark -
switch( inReason )
{
case DLL_PROCESS_ATTACH:
+ gInstance = inInstance;
+ gHostsFileInfo = NULL;
debug_initialize( kDebugOutputTypeWindowsEventLog, "mDNS NSP", inInstance );
debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
dlog( kDebugLevelTrace, "\n" );
break;
case DLL_PROCESS_DETACH:
+ HostsFileInfoFree( gHostsFileInfo );
+ gHostsFileInfo = NULL;
dlog( kDebugLevelVerbose, "%s: process detach\n", __ROUTINE__ );
break;
return( TRUE );
}
+
+//===========================================================================================================================
+// DllRegisterServer
+//===========================================================================================================================
+
+STDAPI DllRegisterServer( void )
+{
+ WSADATA wsd;
+ WCHAR path[ MAX_PATH ];
+ HRESULT err;
+
+ dlog( kDebugLevelTrace, "DllRegisterServer\n" );
+
+ err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
+ err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
+ require_noerr( err, exit );
+
+ // Unregister before registering to workaround an installer
+ // problem during upgrade installs.
+
+ WSCUnInstallNameSpace( &gNSPGUID );
+
+ err = GetModuleFileNameW( gInstance, path, sizeof( path ) );
+ err = translate_errno( err != 0, errno_compat(), kUnknownErr );
+ require_noerr( err, exit );
+
+ err = WSCInstallNameSpace( gNSPName, path, NS_DNS, 1, &gNSPGUID );
+ err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
+ require_noerr( err, exit );
+
+exit:
+
+ WSACleanup();
+ return( err );
+}
+
+//===========================================================================================================================
+// DllUnregisterServer
+//===========================================================================================================================
+
+STDAPI DllUnregisterServer( void )
+{
+ WSADATA wsd;
+ HRESULT err;
+
+ dlog( kDebugLevelTrace, "DllUnregisterServer\n" );
+
+ err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
+ err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
+ require_noerr( err, exit );
+
+ err = WSCUnInstallNameSpace( &gNSPGUID );
+ err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
+ require_noerr( err, exit );
+
+exit:
+
+ WSACleanup();
+ return err;
+}
+
+
//===========================================================================================================================
// NSPStartup
//
exit, err = WSASERVICE_NOT_FOUND );
}
}
+ else
+ {
+ // <rdar://problem/3936771>
+ //
+ // Check to see if the name of this host is in the hosts table. If so,
+ // don't try and resolve it
+
+ char translated[ kDNSServiceMaxDomainName ];
+ int n;
+
+ n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL );
+ require_action( n > 0, exit, err = WSASERVICE_NOT_FOUND );
+ require_action( InHostsTable( translated ) == FALSE, exit, err = WSASERVICE_NOT_FOUND );
+ }
- // The name ends in .local, .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
+ // The name ends in .local ( and isn't in the hosts table ), .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
NSPLock();
if( !gDNSSDInitialized )
// Wait for data or a cancel. Release the lock while waiting. This is safe because we've retained the query.
NSPUnlock();
- waitResult = WaitForMultipleObjects( obj->waitCount, obj->waitHandles, FALSE, 5 * 1000 );
+ waitResult = WaitForMultipleObjects( obj->waitCount, obj->waitHandles, FALSE, 2 * 1000 );
NSPLock();
require_action_quiet( waitResult != ( WAIT_OBJECT_0 + 1 ), exit, err = WSA_E_CANCELLED );
err = translate_errno( waitResult == WAIT_OBJECT_0, (OSStatus) GetLastError(), WSASERVICE_NOT_FOUND );
}
}
#endif
+
+
+//===========================================================================================================================
+// InHostsTable
+//===========================================================================================================================
+
+DEBUG_LOCAL BOOL
+InHostsTable( const char * name )
+{
+ HostsFileInfo * node;
+ BOOL ret = FALSE;
+ OSStatus err;
+
+ check( name );
+
+ if ( gHostsFileInfo == NULL )
+ {
+ TCHAR systemDirectory[MAX_PATH];
+ TCHAR hFileName[MAX_PATH];
+ HostsFile * hFile;
+
+ GetSystemDirectory( systemDirectory, sizeof( systemDirectory ) );
+ sprintf( hFileName, "%s\\drivers\\etc\\hosts", systemDirectory );
+ err = HostsFileOpen( &hFile, hFileName );
+ require_noerr( err, exit );
+
+ while ( HostsFileNext( hFile, &node ) == 0 )
+ {
+ if ( IsLocalName( node ) )
+ {
+ node->m_next = gHostsFileInfo;
+ gHostsFileInfo = node;
+ }
+ else
+ {
+ HostsFileInfoFree( node );
+ }
+ }
+
+ HostsFileClose( hFile );
+ }
+
+ for ( node = gHostsFileInfo; node; node = node->m_next )
+ {
+ if ( IsSameName( node, name ) )
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+exit:
+
+ return ret;
+}
+
+
+//===========================================================================================================================
+// IsLocalName
+//===========================================================================================================================
+
+DEBUG_LOCAL BOOL
+IsLocalName( HostsFileInfo * node )
+{
+ BOOL ret = TRUE;
+
+ check( node );
+
+ if ( strstr( node->m_host.h_name, ".local" ) == NULL )
+ {
+ int i;
+
+ for ( i = 0; node->m_host.h_aliases[i]; i++ )
+ {
+ if ( strstr( node->m_host.h_aliases[i], ".local" ) )
+ {
+ goto exit;
+ }
+ }
+
+ ret = FALSE;
+ }
+
+exit:
+
+ return ret;
+}
+
+
+//===========================================================================================================================
+// IsSameName
+//===========================================================================================================================
+
+DEBUG_LOCAL BOOL
+IsSameName( HostsFileInfo * node, const char * name )
+{
+ BOOL ret = TRUE;
+
+ check( node );
+ check( name );
+
+ if ( strcmp( node->m_host.h_name, name ) != 0 )
+ {
+ int i;
+
+ for ( i = 0; node->m_host.h_aliases[i]; i++ )
+ {
+ if ( strcmp( node->m_host.h_aliases[i], name ) == 0 )
+ {
+ goto exit;
+ }
+ }
+
+ ret = FALSE;
+ }
+
+exit:
+
+ return ret;
+}
+
+
+//===========================================================================================================================
+// HostsFileOpen
+//===========================================================================================================================
+
+DEBUG_LOCAL OSStatus
+HostsFileOpen( HostsFile ** self, const char * fname )
+{
+ OSStatus err = kNoErr;
+
+ *self = (HostsFile*) malloc( sizeof( HostsFile ) );
+ require_action( *self, exit, err = kNoMemoryErr );
+ memset( *self, 0, sizeof( HostsFile ) );
+
+ (*self)->m_bufferSize = BUFFER_INITIAL_SIZE;
+ (*self)->m_buffer = (char*) malloc( (*self)->m_bufferSize );
+ require_action( (*self)->m_buffer, exit, err = kNoMemoryErr );
+
+ // check malloc
+
+ (*self)->m_fp = fopen( fname, "r" );
+ require_action( (*self)->m_fp, exit, err = kUnknownErr );
+
+exit:
+
+ if ( err && *self )
+ {
+ HostsFileClose( *self );
+ *self = NULL;
+ }
+
+ return err;
+}
+
+
+//===========================================================================================================================
+// HostsFileClose
+//===========================================================================================================================
+
+DEBUG_LOCAL OSStatus
+HostsFileClose( HostsFile * self )
+{
+ check( self );
+
+ if ( self->m_buffer )
+ {
+ free( self->m_buffer );
+ self->m_buffer = NULL;
+ }
+
+ if ( self->m_fp )
+ {
+ fclose( self->m_fp );
+ self->m_fp = NULL;
+ }
+
+ free( self );
+
+ return kNoErr;
+}
+
+
+//===========================================================================================================================
+// HostsFileInfoFree
+//===========================================================================================================================
+
+DEBUG_LOCAL void
+HostsFileInfoFree( HostsFileInfo * info )
+{
+ while ( info )
+ {
+ HostsFileInfo * next = info->m_next;
+
+ if ( info->m_host.h_addr_list )
+ {
+ if ( info->m_host.h_addr_list[0] )
+ {
+ free( info->m_host.h_addr_list[0] );
+ info->m_host.h_addr_list[0] = NULL;
+ }
+
+ free( info->m_host.h_addr_list );
+ info->m_host.h_addr_list = NULL;
+ }
+
+ if ( info->m_host.h_aliases )
+ {
+ int i;
+
+ for ( i = 0; info->m_host.h_aliases[i]; i++ )
+ {
+ free( info->m_host.h_aliases[i] );
+ }
+
+ free( info->m_host.h_aliases );
+ }
+
+ if ( info->m_host.h_name )
+ {
+ free( info->m_host.h_name );
+ info->m_host.h_name = NULL;
+ }
+
+ free( info );
+
+ info = next;
+ }
+}
+
+
+//===========================================================================================================================
+// HostsFileNext
+//===========================================================================================================================
+
+DEBUG_LOCAL OSStatus
+HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo )
+{
+ struct sockaddr_in6 addr_6;
+ struct sockaddr_in addr_4;
+ int numAliases = ALIASES_INITIAL_SIZE;
+ char * line;
+ char * tok;
+ int dwSize;
+ int idx;
+ int i;
+ short family;
+ OSStatus err = kNoErr;
+
+ check( self );
+ check( self->m_fp );
+ check( hInfo );
+
+ idx = 0;
+
+ *hInfo = (HostsFileInfo*) malloc( sizeof( HostsFileInfo ) );
+ require_action( *hInfo, exit, err = kNoMemoryErr );
+ memset( *hInfo, 0, sizeof( HostsFileInfo ) );
+
+ for ( ; ; )
+ {
+ line = fgets( self->m_buffer + idx, self->m_bufferSize - idx, self->m_fp );
+
+ if ( line == NULL )
+ {
+ err = 1;
+ goto exit;
+ }
+
+ // If there's no eol and no eof, then we didn't get the whole line
+
+ if ( !strchr( line, '\n' ) && !feof( self->m_fp ) )
+ {
+ int bufferSize;
+ char * buffer;
+
+ /* Try and allocate space for longer line */
+
+ bufferSize = self->m_bufferSize * 2;
+ buffer = (char*) realloc( self->m_buffer, bufferSize );
+ require_action( buffer, exit, err = kNoMemoryErr );
+ self->m_bufferSize = bufferSize;
+ self->m_buffer = buffer;
+ idx = (int) strlen( self->m_buffer );
+
+ continue;
+ }
+
+ line = self->m_buffer;
+ idx = 0;
+
+ if (*line == '#')
+ {
+ continue;
+ }
+
+ // Get rid of either comments or eol characters
+
+ if (( tok = strpbrk(line, "#\n")) != NULL )
+ {
+ *tok = '\0';
+ }
+
+ // Make sure there is some whitespace on this line
+
+ if (( tok = strpbrk(line, " \t")) == NULL )
+ {
+ continue;
+ }
+
+ // Create two strings, where p == the IP Address and tok is the name list
+
+ *tok++ = '\0';
+
+ while ( *tok == ' ' || *tok == '\t')
+ {
+ tok++;
+ }
+
+ // Now we have the name
+
+ (*hInfo)->m_host.h_name = (char*) malloc( strlen( tok ) + 1 );
+ require_action( (*hInfo)->m_host.h_name, exit, err = kNoMemoryErr );
+ strcpy( (*hInfo)->m_host.h_name, tok );
+
+ // Now create the address (IPv6/IPv4)
+
+ addr_6.sin6_family = family = AF_INET6;
+ dwSize = sizeof( addr_6 );
+
+ if ( WSAStringToAddress( line, AF_INET6, NULL, ( struct sockaddr*) &addr_6, &dwSize ) != 0 )
+ {
+ addr_4.sin_family = family = AF_INET;
+ dwSize = sizeof( addr_4 );
+
+ if (WSAStringToAddress( line, AF_INET, NULL, ( struct sockaddr*) &addr_4, &dwSize ) != 0 )
+ {
+ continue;
+ }
+ }
+
+ (*hInfo)->m_host.h_addr_list = (char**) malloc( sizeof( char**) * 2 );
+ require_action( (*hInfo)->m_host.h_addr_list, exit, err = kNoMemoryErr );
+
+ if ( family == AF_INET6 )
+ {
+ (*hInfo)->m_host.h_length = (short) sizeof( addr_6.sin6_addr );
+ (*hInfo)->m_host.h_addr_list[0] = (char*) malloc( (*hInfo)->m_host.h_length );
+ require_action( (*hInfo)->m_host.h_addr_list[0], exit, err = kNoMemoryErr );
+ memmove( (*hInfo)->m_host.h_addr_list[0], &addr_6.sin6_addr, sizeof( addr_6.sin6_addr ) );
+
+ }
+ else
+ {
+ (*hInfo)->m_host.h_length = (short) sizeof( addr_4.sin_addr );
+ (*hInfo)->m_host.h_addr_list[0] = (char*) malloc( (*hInfo)->m_host.h_length );
+ require_action( (*hInfo)->m_host.h_addr_list[0], exit, err = kNoMemoryErr );
+ memmove( (*hInfo)->m_host.h_addr_list[0], &addr_4.sin_addr, sizeof( addr_4.sin_addr ) );
+ }
+
+ (*hInfo)->m_host.h_addr_list[1] = NULL;
+ (*hInfo)->m_host.h_addrtype = family;
+
+ // Now get the aliases
+
+ if ((tok = strpbrk(tok, " \t")) != NULL)
+ {
+ *tok++ = '\0';
+ }
+
+ i = 0;
+
+ (*hInfo)->m_host.h_aliases = (char**) malloc( sizeof(char**) * numAliases );
+ require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr );
+ (*hInfo)->m_host.h_aliases[0] = NULL;
+
+ while ( tok && *tok )
+ {
+ // Skip over the whitespace, waiting for the start of the next alias name
+
+ if (*tok == ' ' || *tok == '\t')
+ {
+ tok++;
+ continue;
+ }
+
+ // Check to make sure we don't exhaust the alias buffer
+
+ if ( i >= ( numAliases - 1 ) )
+ {
+ numAliases = numAliases * 2;
+ (*hInfo)->m_host.h_aliases = (char**) realloc( (*hInfo)->m_host.h_aliases, numAliases * sizeof( char** ) );
+ require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr );
+ }
+
+ (*hInfo)->m_host.h_aliases[i] = (char*) malloc( strlen( tok ) + 1 );
+ require_action( (*hInfo)->m_host.h_aliases[i], exit, err = kNoMemoryErr );
+
+ strcpy( (*hInfo)->m_host.h_aliases[i], tok );
+
+ if (( tok = strpbrk( tok, " \t")) != NULL )
+ {
+ *tok++ = '\0';
+ }
+
+ (*hInfo)->m_host.h_aliases[++i] = NULL;
+ }
+
+ break;
+ }
+
+exit:
+
+ if ( err && ( *hInfo ) )
+ {
+ HostsFileInfoFree( *hInfo );
+ *hInfo = NULL;
+ }
+
+ return err;
+}
; Change History (most recent first):
;
; $Log: mdnsNSP.def,v $
+; Revision 1.3 2005/01/28 23:48:46 shersche
+; <rdar://problem/3942551> Export DllRegisterServer, DllUnregisterServer which can be called from the Installer or regsvr32
+; Bug #: 3942551
+;
; Revision 1.2 2004/07/13 21:24:28 rpantos
; Fix for <rdar://problem/3701120>.
;
EXPORTS
NSPStartup
NSPCleanup
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Apple Computer, Inc."
- VALUE "FileDescription", "mdnsNSP Dynamic Link Library"
+ VALUE "FileDescription", "Bonjour Namespace Provider"
VALUE "FileVersion", MASTER_PROD_VERS_STR
- VALUE "InternalName", "mdnsNSP"
+ VALUE "InternalName", "mdnsNSP.dll"
VALUE "LegalCopyright", MASTER_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "mdnsNSP.dll"
VALUE "ProductName", MASTER_PROD_NAME
</Configuration>\r
<Configuration\r
Name="Release|Win32"\r
- OutputDirectory=".\Release\Root\Program Files\bin"\r
+ OutputDirectory=".\Release\Root\Program Files\Bonjour"\r
IntermediateDirectory=".\Release"\r
ConfigurationType="2"\r
CharacterSet="2">\r