]> git.saurik.com Git - apple/mdnsresponder.git/commitdiff
mDNSResponder-107.tar.gz mac-os-x-104 mac-os-x-1041 mac-os-x-1042 v107
authorApple <opensource@apple.com>
Wed, 20 Apr 2005 20:12:20 +0000 (20:12 +0000)
committerApple <opensource@apple.com>
Wed, 20 Apr 2005 20:12:20 +0000 (20:12 +0000)
140 files changed:
Clients/DNS-SD.VisualStudio/dns-sd.rc [new file with mode: 0755]
Clients/DNS-SD.VisualStudio/dns-sd.vcproj [new file with mode: 0755]
Clients/DNS-SD.VisualStudio/resource.h [new file with mode: 0755]
Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs
Clients/ExplorerPlugin/ExplorerBarWindow.cpp
Clients/ExplorerPlugin/ExplorerBarWindow.h
Clients/ExplorerPlugin/ExplorerPlugin.cpp
Clients/ExplorerPlugin/ExplorerPlugin.rc
Clients/ExplorerPlugin/ExplorerPlugin.vcproj
Clients/ExplorerPlugin/ExplorerPluginLocRes.rc
Clients/ExplorerPlugin/ExplorerPluginLocRes.vcproj
Clients/ExplorerPlugin/ExplorerPluginRes.rc
Clients/ExplorerPlugin/ExplorerPluginRes.vcproj
Clients/ExplorerPlugin/res/button-xp.ico
Clients/ExplorerPlugin/res/globe.bmp
Clients/ExplorerPlugin/resource_dll.h
Clients/ExplorerPlugin/resource_loc_res.h
Clients/ExplorerPlugin/resource_res.h
Clients/Java/nmakefile
Clients/PrinterSetupWizard/FourthPage.cpp
Clients/PrinterSetupWizard/PrinterSetupWizard.rc
Clients/PrinterSetupWizard/PrinterSetupWizard.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp
Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.rc
Clients/PrinterSetupWizard/PrinterSetupWizardLocRes.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardRes.rc
Clients/PrinterSetupWizard/PrinterSetupWizardRes.vcproj
Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp
Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h
Clients/PrinterSetupWizard/SecondPage.cpp
Clients/PrinterSetupWizard/SecondPage.h
Clients/PrinterSetupWizard/ThirdPage.cpp
Clients/PrinterSetupWizard/ThirdPage.h
Clients/PrinterSetupWizard/UtilTypes.h
Clients/PrinterSetupWizard/resource_exe.h
Clients/PrinterSetupWizard/resource_loc_res.h
Clients/PrinterSetupWizard/resource_res.h
Clients/dns-sd.c
Makefile
README.txt
mDNSCore/DNSCommon.c
mDNSCore/DNSCommon.h
mDNSCore/mDNS.c
mDNSCore/mDNSEmbeddedAPI.h
mDNSCore/uDNS.c
mDNSCore/uDNS.h
mDNSMacOS9/mDNSLibraryResources.r
mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/failure.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/Artwork/success.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/ConfigurationAuthority.c [new file with mode: 0644]
mDNSMacOSX/PreferencePane/ConfigurationAuthority.h [new file with mode: 0644]
mDNSMacOSX/PreferencePane/ConfigurationRights.h [new file with mode: 0644]
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h [new file with mode: 0644]
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns [new file with mode: 0644]
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m [new file with mode: 0644]
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff [new file with mode: 0644]
mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib [new file with mode: 0644]
mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib [new file with mode: 0644]
mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib [new file with mode: 0644]
mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings [new file with mode: 0644]
mDNSMacOSX/PreferencePane/PrivilegedOperations.c [new file with mode: 0644]
mDNSMacOSX/PreferencePane/PrivilegedOperations.h [new file with mode: 0644]
mDNSMacOSX/PreferencePane/ddnswriteconfig.m [new file with mode: 0644]
mDNSMacOSX/daemon.c
mDNSMacOSX/mDNSMacOSX.c
mDNSMacOSX/mDNSMacOSX.h
mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings [new file with mode: 0644]
mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings [new file with mode: 0644]
mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj
mDNSPosix/Client.c
mDNSPosix/Makefile
mDNSPosix/PosixDaemon.c
mDNSPosix/ReadMe.txt
mDNSPosix/Responder.c
mDNSPosix/dnsextd.c
mDNSPosix/mDNSPosix.c
mDNSPosix/mDNSPosix.h
mDNSResponder.sln [new file with mode: 0755]
mDNSShared/PlatformCommon.c
mDNSShared/dns-sd.1
mDNSShared/dns_sd.h
mDNSShared/dnssd_clientstub.c
mDNSShared/dnssd_ipc.h
mDNSShared/mDNS.1
mDNSShared/mDNSResponder.8
mDNSShared/uds_daemon.c
mDNSWindows/ControlPanel/ConfigDialog.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/ConfigDialog.h [new file with mode: 0755]
mDNSWindows/ControlPanel/ConfigPropertySheet.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/ConfigPropertySheet.h [new file with mode: 0755]
mDNSWindows/ControlPanel/ControlPanel.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/ControlPanel.def [new file with mode: 0755]
mDNSWindows/ControlPanel/ControlPanel.h [new file with mode: 0755]
mDNSWindows/ControlPanel/ControlPanel.rc [new file with mode: 0755]
mDNSWindows/ControlPanel/ControlPanel.vcproj [new file with mode: 0755]
mDNSWindows/ControlPanel/FirstPage.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/FirstPage.h [new file with mode: 0755]
mDNSWindows/ControlPanel/SecondPage.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/SecondPage.h [new file with mode: 0755]
mDNSWindows/ControlPanel/SharedSecret.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/SharedSecret.h [new file with mode: 0755]
mDNSWindows/ControlPanel/ThirdPage.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/ThirdPage.h [new file with mode: 0755]
mDNSWindows/ControlPanel/res/ControlPanel.rc2 [new file with mode: 0755]
mDNSWindows/ControlPanel/res/controlpanel.ico [new file with mode: 0755]
mDNSWindows/ControlPanel/res/failure.ico [new file with mode: 0755]
mDNSWindows/ControlPanel/res/success.ico [new file with mode: 0755]
mDNSWindows/ControlPanel/resource.h [new file with mode: 0755]
mDNSWindows/ControlPanel/stdafx.cpp [new file with mode: 0755]
mDNSWindows/ControlPanel/stdafx.h [new file with mode: 0755]
mDNSWindows/DLL.NET/Stdafx.cpp
mDNSWindows/DLL.NET/Stdafx.h
mDNSWindows/DLL.NET/dnssd_NET.cpp
mDNSWindows/DLL.NET/dnssd_NET.h
mDNSWindows/DLL.NET/dnssd_NET.rc
mDNSWindows/DLL/dll.rc
mDNSWindows/DLL/dnssd.vcproj
mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
mDNSWindows/Java/makefile
mDNSWindows/RegNames.h [new file with mode: 0644]
mDNSWindows/SystemService/Prefix.h
mDNSWindows/SystemService/Service.c
mDNSWindows/SystemService/Service.rc
mDNSWindows/SystemService/Service.vcproj
mDNSWindows/WinVersRes.h
mDNSWindows/dDNS.c
mDNSWindows/dDNS.h
mDNSWindows/loclibrary.c
mDNSWindows/mDNSWin32.c
mDNSWindows/mDNSWin32.h
mDNSWindows/mdnsNSP/mdnsNSP.c
mDNSWindows/mdnsNSP/mdnsNSP.def
mDNSWindows/mdnsNSP/mdnsNSP.rc
mDNSWindows/mdnsNSP/mdnsNSP.vcproj

diff --git a/Clients/DNS-SD.VisualStudio/dns-sd.rc b/Clients/DNS-SD.VisualStudio/dns-sd.rc
new file mode 100755 (executable)
index 0000000..a57a430
--- /dev/null
@@ -0,0 +1,103 @@
+// 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
diff --git a/Clients/DNS-SD.VisualStudio/dns-sd.vcproj b/Clients/DNS-SD.VisualStudio/dns-sd.vcproj
new file mode 100755 (executable)
index 0000000..dda633b
--- /dev/null
@@ -0,0 +1,132 @@
+<?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
diff --git a/Clients/DNS-SD.VisualStudio/resource.h b/Clients/DNS-SD.VisualStudio/resource.h
new file mode 100755 (executable)
index 0000000..7a92526
--- /dev/null
@@ -0,0 +1,14 @@
+//{{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
index 75bbc93005319f05057b6e20c7d6d591b1607a70..f2cf813fb5fd91b9b4f19b0900eb5b64ac3e4490 100755 (executable)
@@ -23,6 +23,9 @@
     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
@@ -106,10 +109,14 @@ namespace DNSServiceBrowser_NET
                        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.
@@ -267,7 +274,6 @@ namespace DNSServiceBrowser_NET
                                "_raop._tcp",
                                "_rce._tcp",
                                "_realplayfavs._tcp",
-                               "_rendezvouspong._tcp",
                                "_riousbprint._tcp",
                                "_rfb._tcp",
                                "_rtsp._tcp",
index ea9cdc34c4ec76323f9803a231ec98597364e51d..a68880b2a643aae03584be98f22dd215f1973832 100644 (file)
     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
 
@@ -205,12 +214,9 @@ int        ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
        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
@@ -220,48 +226,20 @@ int       ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
        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 ) ) );
@@ -551,18 +529,10 @@ LONG      ExplorerBarWindow::OnServiceAdd( ServiceInfo * service )
                
                // 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 );
 }
index 34a33453d5f2e061738493477e9dd34daeb9f886..deade955257ee9b59c47938ee6faba7aeff62bef 100644 (file)
     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
@@ -186,8 +189,6 @@ struct      ServiceHandlerEntry
        const char *                    urlScheme;
        DNSServiceRef                   ref;
        ServiceInfoArray                array;
-       HTREEITEM                               treeItem;
-       bool                                    treeFirst;
        ExplorerBarWindow *             obj;
        bool                                    needsLogin;
        
@@ -196,8 +197,6 @@ struct      ServiceHandlerEntry
                type            = NULL;
                urlScheme       = NULL;
                ref             = NULL;
-               treeItem        = NULL;
-               treeFirst       = true;
                obj                     = NULL;
                needsLogin      = false;
        }
index 464051abba8c31fc53b5f0c9123297b9aaee3921..766c1737c0bd7a55793614b7bc5f8459e49134e5 100644 (file)
@@ -23,6 +23,9 @@
     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
@@ -101,6 +104,8 @@ DEBUG_LOCAL void            MFCDLLThreadDetach( HINSTANCE inInstance );
 
 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
 
@@ -274,6 +279,9 @@ STDAPI      DllUnregisterServer( void )
        
        err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE );
        require_noerr( err, exit );
+
+       err = UnregisterServer( CLSID_ExplorerBar );
+       require_noerr( err, exit );
        
 exit:
        return( err );
@@ -590,3 +598,138 @@ DEBUG_LOCAL OSStatus      RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOO
 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;
+}
index 88dfeaf07faf7474739d474d47be151c562d21e9..1b97397e5f12a13aa83849aedd3d3465fa5bc4f7 100644 (file)
@@ -81,7 +81,7 @@ BEGIN
         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
index 87f3f8eab0ec8ed018dcc842b838eff4ea644ec4..c0f9af34ae589d969f2612305841c8d379a2743b 100644 (file)
@@ -85,7 +85,7 @@
                </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
index 731a01a81ee2631482356d037080e6ef45a8e98a..7e025f271d645f34e9eb079174bfdb696d7fd697 100755 (executable)
@@ -81,7 +81,7 @@ BEGIN
         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
@@ -121,7 +121,7 @@ END
 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
@@ -163,7 +163,7 @@ IDR_CONTEXT_MENU MENU
 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
@@ -176,13 +176,12 @@ END
 \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
index 5aa578d31d5260b825c985c8a42c2e8f4e657ecf..bcb02693eae341813f5c3694b103db93aaed4517 100755 (executable)
@@ -13,7 +13,7 @@
        <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
@@ -82,7 +86,7 @@
                </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 &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources\en.lproj&quot;"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
index fb9199dbaedc66ef56323afd864dc165b6ae8cbd..d97ab2039ff502ffe359068f2609a788a9b85dae 100755 (executable)
@@ -81,7 +81,7 @@ BEGIN
         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
index 31627b15fb10c326d4a178eb3db231d5389bb7b4..0949120516428fcb676bdf3cb5a8b23635dd8f28 100755 (executable)
@@ -13,7 +13,7 @@
        <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
@@ -81,7 +84,7 @@
                </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 &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\ExplorerPlugin.dll.Resources&quot;"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
index 69d41dd943641702dc5e1659212d4e8d78b0db70..5b22ef70bd95eb6fcd4c5e4cc3f71ad52a044ec6 100755 (executable)
Binary files a/Clients/ExplorerPlugin/res/button-xp.ico and b/Clients/ExplorerPlugin/res/button-xp.ico differ
index 7e4949d1564e45706b661c0accf81b51c01c0e33..af43b4e5ecf8e2efa6501ad1c15551553243d8f3 100755 (executable)
Binary files a/Clients/ExplorerPlugin/res/globe.bmp and b/Clients/ExplorerPlugin/res/globe.bmp differ
index 628228d4f3b082de77917bc8b3d1785327f19ea3..6374ce24c59f4c191f217aa77bb192e44b620901 100755 (executable)
@@ -4,7 +4,6 @@
 //\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
index baf221356e1441f3490d784772adba17ec37e5de..ea18e83437ef233db18485a36b272402781e8cb6 100755 (executable)
@@ -4,7 +4,6 @@
 //\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
index b0217b38e84ff79175dd8e8d3ec138f6ce17c1c6..4f66a0cc966d16f34ef7f3bcbb18a6ed4743e831 100755 (executable)
@@ -4,7 +4,6 @@
 //\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
index 4c655d806db0c4fc42b086e3a193408a9aedbd4a..6fa95cbff246f3f8fb2ce9c88befdd4c9e26e370 100644 (file)
@@ -100,7 +100,7 @@ $(BUILDDIR)\BrowserApp.jar: $(BROWSERAPPOBJ) $(BROWSERAPPMAN)
 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) $<
 
index 8c330df1ae3beb39f04d2800dc442e2f87be2d30..a2a7a502893236ce9cb23c11adc313fe8603b243 100644 (file)
@@ -23,6 +23,9 @@
     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
 
@@ -126,7 +129,7 @@ CFourthPage::OnSetActive()
 
        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 );
index 4899ef780749ad280065b87ca7750e8bad254a3c..71c00d05d0f43cfac27735d7bd9052207a56169f 100644 (file)
@@ -103,11 +103,11 @@ BEGIN
         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
@@ -133,8 +133,8 @@ IDR_MANIFEST            RT_MANIFEST             "res\\PrinterSetupWizard.manifes
 \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
index c26dc3e937ed827f876d16155ba060ca8e2d7a65..4bff36a4540c5e3e8dadd3f17f7ffb97f9fb94a0 100644 (file)
@@ -39,7 +39,7 @@
                        <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
@@ -68,7 +68,7 @@
                </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
@@ -95,7 +95,7 @@
                        <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
index 37b62289a04a0b988822cbc082b6b151a0e6b64a..08a0505ae4e6a05bf549a2c4af044bd975ff36fb 100644 (file)
     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.
 
@@ -117,7 +123,7 @@ BOOL CPrinterSetupWizardApp::InitInstance()
 
        // 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 );
 
@@ -125,15 +131,15 @@ BOOL CPrinterSetupWizardApp::InitInstance()
        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
index 521b2eface201ad7102904c32fe20ec3ab128bec..7a2842fc498dd6c7626756245c29afb2fdc9e36b 100755 (executable)
@@ -103,7 +103,7 @@ END
 \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
@@ -120,13 +120,13 @@ END
 \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
@@ -134,7 +134,7 @@ END
 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
@@ -145,22 +145,22 @@ BEGIN
                     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
@@ -213,11 +213,11 @@ BEGIN
         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
@@ -237,15 +237,15 @@ END
 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
@@ -259,16 +259,18 @@ BEGIN
                             "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
index e7d0271efe4bfedc6d01075f2700f2c79f5c0c6c..c97e842287839ddad98870a7c1a412a758168118 100755 (executable)
@@ -12,7 +12,7 @@
        <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
@@ -38,7 +38,7 @@
                                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
@@ -68,7 +73,7 @@
                </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
@@ -94,7 +99,7 @@
                                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 &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources\en.lproj&quot;"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
index 9a38621b96bc1af5c118e063a70906c09b4461ef..a75e40f1270d058622ddb1546bfaf49c78803788 100755 (executable)
@@ -121,11 +121,11 @@ BEGIN
         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
index f3591f0714c4f057bfe3e6fd899a3c6a6ec96452..79424ffad9c085e18a4775c576f1e4f615209d28 100755 (executable)
@@ -12,7 +12,7 @@
        <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
@@ -38,7 +38,7 @@
                                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
@@ -68,7 +71,7 @@
                </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
@@ -94,7 +97,7 @@
                                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 &quot;Release\Root\Program Files&quot; mkdir &quot;Release\Root\Program Files&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour&quot; mkdir &quot;Release\Root\Program Files\Bonjour&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources&quot;\r
+if not exist &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot; mkdir &quot;Release\Root\Program Files\Bonjour\Resources\PrinterWizard.exe.Resources&quot;"/>\r
                        <Tool\r
                                Name="VCResourceCompilerTool"\r
                                PreprocessorDefinitions="NDEBUG"\r
index 6b026e1fad0e695d788184f255693bbe5136c943..75cda89d51ec2a8a856a6023b0fbcb7aece14b1b 100644 (file)
     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
 
@@ -127,7 +148,8 @@ First checked in
 
 // Private Messages
 
-#define WM_PROCESS_EVENT       ( WM_USER + 0x100 )
+#define WM_SOCKET_EVENT                ( WM_USER + 0x100 )
+#define WM_PROCESS_EVENT       ( WM_USER + 0x101 )
 
 
 // CPrinterSetupWizardSheet
@@ -138,7 +160,10 @@ CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParen
        :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);
@@ -146,15 +171,21 @@ CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParen
        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;
@@ -176,6 +207,60 @@ CPrinterSetupWizardSheet::SetSelectedPrinter(Printer * printer)
 }
 
 
+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
 //
@@ -358,8 +443,8 @@ CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * s
        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;
@@ -415,9 +500,10 @@ CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service
        
        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);
@@ -436,6 +522,7 @@ exit:
 
 
 BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet)
+ON_MESSAGE( WM_SOCKET_EVENT, OnSocketEvent )
 ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent )
 ON_WM_SETCURSOR()
 ON_WM_TIMER()
@@ -468,8 +555,39 @@ BOOL CPrinterSetupWizardSheet::OnCommand(WPARAM wParam, LPARAM lParam)
 //     
 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;
 }
 
@@ -532,6 +650,8 @@ CPrinterSetupWizardSheet::OnOK()
 
                MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION);
        }
+
+       StopBrowse();
 }
 
 
@@ -556,6 +676,39 @@ void CPrinterSetupWizardSheet::Init(void)
 }
 
 
+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)
 {
@@ -594,7 +747,7 @@ CPrinterSetupWizardSheet::InstallDriverThread( LPVOID inParam )
                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 );
@@ -633,3 +786,933 @@ exit:
 
        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;
+}
+
+
+
index be4bd6ae5a89eb8e20bd4e3dc54fe5e3b6343889..cf7f096f76b84b8b628efdcb3ddddc34d67d3746 100644 (file)
     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
 
@@ -97,6 +103,9 @@ public:
        //
        virtual LONG
        OnProcessEvent(WPARAM inWParam, LPARAM inLParam);
+       
+       virtual LONG
+       OnSocketEvent(WPARAM inWParam, LPARAM inLParam);
 
        virtual BOOL
        OnCommand(WPARAM wParam, LPARAM lParam);
@@ -113,6 +122,14 @@ public:
        afx_msg void
        OnOK();
 
+       OSStatus
+       StartResolve( Printer * printer );
+
+       OSStatus
+       StopResolve( Printer * printer );
+
+       Printers                                m_printers;
+
        HCURSOR                                 m_active;
        HCURSOR                                 m_arrow;
        HCURSOR                                 m_wait;
@@ -132,6 +149,106 @@ protected:
 
 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);
 
@@ -144,10 +261,18 @@ private:
        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;
 };
 
 
index 9e3720a6777c62577a024b5e740652171d2152c0..63665ee8f1f9e6bf05b10d4127b5711b32b18cc9 100644 (file)
     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
 
@@ -74,17 +83,11 @@ First checked in
 // 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;
@@ -92,71 +95,14 @@ CSecondPage::CSecondPage()
        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;
 }
 
 
@@ -170,9 +116,9 @@ CSecondPage::InitBrowseList()
        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 );
 
@@ -192,267 +138,20 @@ exit:
 }
 
 
-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
 }
 
 
@@ -481,343 +180,45 @@ CSecondPage::OnSetActive()
 {
        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()
@@ -826,17 +227,10 @@ 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 ) );
@@ -846,131 +240,31 @@ CSecondPage::OnAddPrinter(
        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:
@@ -987,80 +281,44 @@ 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();
@@ -1078,40 +336,25 @@ CSecondPage::OnResolveService( Service * service )
        
        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:
 
@@ -1119,39 +362,6 @@ 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);
@@ -1173,7 +383,7 @@ void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
        // 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 );
 
        //
@@ -1200,53 +410,6 @@ 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 )
 {
@@ -1276,96 +439,17 @@ 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;
 }
 
 
+
index 9d9c4fb77ca165543eff25ea39d62a747bad82a9..aa0826083f910da34319936e6f2bf1ca53639569 100644 (file)
@@ -23,6 +23,9 @@
     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.
 
@@ -73,44 +76,6 @@ public:
 // 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();
@@ -126,68 +91,25 @@ public:
        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 );
@@ -195,22 +117,6 @@ private:
        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
index 76978cdd4bf3ebbe8364c986f5049f87e1f9a17b..acd8d3c5374d4ece89560516cf26577f7ac8b033 100644 (file)
     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
@@ -102,8 +120,17 @@ First checked in
 //
 // 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
@@ -125,11 +152,45 @@ CThirdPage::CThirdPage()
                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;
 }
 
 
@@ -170,7 +231,7 @@ CThirdPage::~CThirdPage()
 //
 // ----------------------------------------------------
 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;
@@ -179,9 +240,6 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man
        check( manufacturer != NULL );
        check( model != NULL );
 
-       Manufacturers manufacturers;
-       manufacturers[manufacturer->name] = manufacturer;
-
        PopulateUI( manufacturers );
 
        //
@@ -202,7 +260,7 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man
        // select the model
        //
        info.flags      = LVFI_STRING;
-       info.psz        = model->name;
+       info.psz        = model->displayName;
 
        nIndex = m_modelListCtrl.FindItem(&info);
 
@@ -229,7 +287,8 @@ void
 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;
 
@@ -261,7 +320,7 @@ CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufactu
 
                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
                {
@@ -583,6 +642,7 @@ CThirdPage::LoadPrintDriverDefsFromFile(Manufacturers & manufacturers, const CSt
                                        require_action( model, exit, err = kNoMemoryErr );
 
                                        model->infFileName              =       filename;
+                                       model->displayName              =       name;
                                        model->name                             =       name;
                                        model->driverInstalled  =       false;
 
@@ -722,6 +782,7 @@ CThirdPage::LoadPrintDriverDefs( Manufacturers & manufacturers )
        
                                require_action( model, exit, err = kNoMemoryErr );
        
+                               model->displayName              =       info[i].pName;
                                model->name                             =       info[i].pName;
                                model->driverInstalled  =       true;
        
@@ -741,6 +802,137 @@ exit:
 }
 
 
+// -------------------------------------------------------
+// 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
 //
@@ -839,11 +1031,13 @@ CThirdPage::NormalizeManufacturerName( const CString & name )
 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
@@ -871,7 +1065,7 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
                        model = MatchModel ( manufacturer, ConvertToModelName ( service->usb_MDL ) );
                }
 
-               if ( model == NULL )
+               if ( ( model == NULL ) && ( service->product.GetLength() > 0 ) )
                {
                        service->product.Remove('(');
                        service->product.Remove(')');
@@ -881,7 +1075,10 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
 
                if ( model != NULL )
                {
-                       SelectMatch(printer, service, manufacturer, model);
+                       Manufacturers manufacturers;
+                       
+                       manufacturers[manufacturer->name] = manufacturer;
+                       SelectMatch(printer, service, manufacturers, manufacturer, model);
                        found = true;
                }
        }
@@ -894,6 +1091,27 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
        {
                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);
@@ -1021,6 +1239,45 @@ CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name)
 }
 
 
+// -------------------------------------------------------
+// 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
@@ -1031,15 +1288,14 @@ CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name)
 
 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 );
@@ -1074,25 +1330,6 @@ OSStatus CThirdPage::OnInitPage()
        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);
 }
 
@@ -1104,7 +1341,8 @@ void CThirdPage::DoDataExchange(CDataExchange* pDX)
        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);
+
 }
 
 
@@ -1230,7 +1468,7 @@ void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult)
                {
                        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);
                }
index b775fb8efe61efe9a205b4c972cc59b43a671e37..a5a9bb6c46bdb1db61111d5c888e1288800f0862 100644 (file)
@@ -23,6 +23,9 @@
     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
@@ -85,6 +88,13 @@ private:
        //
        OSStatus LoadPrintDriverDefs(Manufacturers & manufacturers);
 
+       //
+       // LoadGenericPrintDriversDefs
+       //
+       // Loads generic postscript and pcl print driver defs
+       //
+       OSStatus LoadGenericPrintDriverDefs( Manufacturers & manufacturers );
+
        //
        // PopulateUI
        //
@@ -115,7 +125,8 @@ private:
 
        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;
@@ -126,6 +137,9 @@ private:
        CListCtrl                       m_modelListCtrl;
        Model                   *       m_modelSelected;
 
+       Model                   *       m_genericPostscript;
+       Model                   *       m_genericPCL;
+
        bool                            m_initialized;
 
 public:
index 11042ddf136151afa9ea855832e9d890bc164655..5e2fe196ef91357c12bc4e211281a1b83ce7ac21 100644 (file)
     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
 
@@ -62,7 +71,7 @@ First checked in
 #include <list>
 #include <DebugServices.h>
 
-class CSecondPage;
+class CPrinterSetupWizardSheet;
 
 #define        kDefaultPriority        50
 #define kDefaultQTotal         1
@@ -76,6 +85,7 @@ namespace PrinterSetupWizard
        struct Model;
 
        typedef std::list<Queue*>       Queues;
+       typedef std::list<Printer*>     Printers;
        typedef std::list<Service*>     Services;
        typedef std::list<Model*>       Models;
 
@@ -91,7 +101,7 @@ namespace PrinterSetupWizard
                        const std::string       &       type
                        );
 
-               CSecondPage     *       window;
+               CPrinterSetupWizardSheet        *       window;
                HTREEITEM               item;
 
                //
@@ -120,7 +130,8 @@ namespace PrinterSetupWizard
                bool                    driverInstalled;
                CString                 infFileName;
                CString                 manufacturer;
-               CString                 model;
+               CString                 displayModelName;
+               CString                 modelName;
                CString                 portName;
                bool                    deflt;
 
@@ -152,6 +163,7 @@ namespace PrinterSetupWizard
                DNSServiceRef   serviceRef;
                CString                 hostname;
                unsigned short  portNumber;
+               CString                 pdl;
                CString                 usb_MFG;
                CString                 usb_MDL;
                CString                 description;
@@ -190,6 +202,9 @@ namespace PrinterSetupWizard
                CString         name;
                CString         tag;
                Models          models;
+
+               Model*
+               find( const CString & name );
        };
 
 
@@ -197,6 +212,7 @@ namespace PrinterSetupWizard
        {
                bool            driverInstalled;
                CString         infFileName;
+               CString         displayName;
                CString         name;
        };
 
@@ -275,6 +291,24 @@ namespace PrinterSetupWizard
        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;
+       }
 }
 
 
index c0f542920bd0359a3d728bba426d6e2fa2e00609..46cd451d94ed0af43bfc84cc05cf12d8e10d1cd7 100755 (executable)
@@ -25,7 +25,7 @@
 #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
index 7f77da3341f3850854a3be81e80ab5c32052c0f7..b5a3bf99b7571290513da9d31290df57110cf32b 100755 (executable)
 #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
@@ -49,6 +50,7 @@
 #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
index c0f542920bd0359a3d728bba426d6e2fa2e00609..46cd451d94ed0af43bfc84cc05cf12d8e10d1cd7 100755 (executable)
@@ -25,7 +25,7 @@
 #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
index 5c6adac45689e0b02f2d35bede2d672a8c8ad657..699a93286da4ad51aa85c27cf8f944ddc1a808cc 100644 (file)
@@ -90,7 +90,7 @@ typedef       int     pid_t;
 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;
@@ -269,6 +269,8 @@ static void DNSSD_API enum_reply(DNSServiceRef client, DNSServiceFlags flags, ui
                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,
@@ -281,6 +283,7 @@ static void DNSSD_API browse_reply(DNSServiceRef client, DNSServiceFlags flags,
        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,
@@ -328,6 +331,7 @@ static void DNSSD_API resolve_reply(DNSServiceRef client, DNSServiceFlags flags,
                printf(" TXT %s", txtInfo);
                }
        printf("\n");
+       fflush( stdout );
        }
 
 static void myTimerCallBack(void)
@@ -399,6 +403,7 @@ static void DNSSD_API reg_reply(DNSServiceRef client, DNSServiceFlags flags, DNS
                }
 
        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,
@@ -428,6 +433,7 @@ static void DNSSD_API qr_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint3
        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 );
        }
 
 //*************************************************************************************************************
@@ -517,6 +523,7 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR
                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)
@@ -533,8 +540,8 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef,
        {
        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
@@ -542,16 +549,16 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef,
        
        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)
@@ -573,7 +580,7 @@ int main(int argc, char **argv)
                {
                argc--;
                argv++;
-               interface = kDNSServiceInterfaceIndexLocalOnly;
+               opinterface = kDNSServiceInterfaceIndexLocalOnly;
                printf("Using LocalOnly\n");
                }
 
@@ -584,13 +591,13 @@ int main(int argc, char **argv)
        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;
@@ -599,14 +606,14 @@ int main(int argc, char **argv)
                                        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;
@@ -626,7 +633,7 @@ int main(int argc, char **argv)
                                        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;
                                        }
 
@@ -636,7 +643,7 @@ int main(int argc, char **argv)
                                        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;
                                        }
 
@@ -647,7 +654,7 @@ int main(int argc, char **argv)
                                        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;
                                        }
 
@@ -657,7 +664,7 @@ int main(int argc, char **argv)
                                        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;
                                        }
@@ -667,7 +674,7 @@ int main(int argc, char **argv)
                                        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;
                                        }
index 436297d6217a3ee11001ff5bab5dabba68248071..049754259ed09395919aa4c917fdaad9005cff12 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 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)
index 5f17866c1de4803d7de7e68db63fb40fbab4fb36..86b041ee821288eea2e9e231fc5bbc81e9d20330 100644 (file)
@@ -1,11 +1,11 @@
 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/>
 
@@ -57,8 +57,8 @@ local significance (e.g. "yourcomputer.local.").
 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
index 4116c1cdb1339ffcbe4418964a274b6779ee18d9..a2039b91936b2ba81dc3cec181ae6ef93fd2f338 100644 (file)
     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
 
@@ -55,7 +67,7 @@ Revision 1.74  2004/12/09 22:49:15  ksekar
 <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
@@ -156,7 +168,7 @@ Fix param order error moving putPrereqNameNotInUse from uDNS.c using
 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
@@ -410,6 +422,9 @@ mDNSexport char *DNSTypeName(mDNSu16 rrtype)
                }
        }
 
+// 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;
@@ -817,7 +832,7 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
                                        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"))
@@ -910,6 +925,45 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn,
        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)
@@ -974,13 +1028,7 @@ mDNSexport void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichT
 
        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]] = '-'; }
@@ -1037,10 +1085,9 @@ mDNSexport mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const
 
 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
@@ -1102,10 +1149,6 @@ mDNSexport mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate
 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)
                {
@@ -1121,12 +1164,14 @@ mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength,
                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];
@@ -1135,10 +1180,12 @@ mDNSexport mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength,
 
                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
@@ -1628,8 +1675,7 @@ mDNSexport void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 r
        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)
index 6a6ae706b0df81b439b0a52fb40fcc76dfc80c5d..1b11e11993444bcfeccb2208b293aa526224c227 100644 (file)
@@ -23,6 +23,9 @@
     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
 
@@ -74,7 +77,7 @@ Revision 1.16  2004/08/13 23:46:58  cheshire
 "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
@@ -213,6 +216,7 @@ extern mDNSu32 mDNSRandom(mDNSu32 max);
 
 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);
index f517066a256c5a5d20eede35431f84fd6908de08..d89a42bce2ab23fb9f50f5dc44f45aec1b2a9aa8 100755 (executable)
     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
 
@@ -159,7 +177,7 @@ Revision 1.483  2004/12/07 23:00:14  ksekar
 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
@@ -168,7 +186,7 @@ Revision 1.480  2004/12/07 20:42:33  cheshire
 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
@@ -466,7 +484,7 @@ Revision 1.390  2004/08/11 02:17:01  cheshire
 <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
@@ -2531,8 +2549,9 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        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
@@ -2540,8 +2559,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
                { 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)
                {
@@ -2571,7 +2589,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        
        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.
@@ -2582,7 +2600,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
                }
        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;
                }
@@ -2808,7 +2826,7 @@ mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseR
                        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);
                }
@@ -2999,7 +3017,7 @@ mDNSlocal void SendResponses(mDNS *const m)
                                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
@@ -3401,7 +3419,7 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, DNSQuestion *q)
        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);
        }
 
@@ -3750,7 +3768,7 @@ mDNSlocal void SendQueries(mDNS *const m)
                                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
@@ -3816,6 +3834,7 @@ mDNSlocal void AnswerQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, C
                        {
                        q->LastQTime      = m->timenow;
                        q->LastQTxTime    = m->timenow;
+                       q->RecentAnswerPkts = 0;
                        q->ThisQInterval  = MaxQuestionInterval;
                        q->RequestUnicast = mDNSfalse;
                        }
@@ -4252,7 +4271,7 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre
                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;
                        }
@@ -5063,7 +5082,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                // 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;
@@ -5283,8 +5302,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                // 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
@@ -5366,13 +5385,25 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                                        }
                                                }
 
-                                       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
                                                {
@@ -5383,9 +5414,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                                // 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;
                                        }
                                }
 
@@ -6717,7 +6748,9 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
                {
                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);
@@ -6757,7 +6790,9 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *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; }
@@ -6958,7 +6993,7 @@ mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheEntity *storage, mDNS
        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;
index 6397c1fa6b42f75d6f7ce89051dfe5ec54fddd41..852322fc5e0b1531b7618739e3d908977db6ee97 100755 (executable)
     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
 
@@ -144,10 +162,10 @@ Revision 1.249  2004/12/03 05:18:33  ksekar
 <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
@@ -172,7 +190,7 @@ Revision 1.241  2004/11/22 17:16:19  ksekar
 <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
@@ -360,7 +378,7 @@ Revision 1.184  2004/08/11 17:09:31  cheshire
 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
@@ -1155,8 +1173,8 @@ enum
        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,
@@ -1362,7 +1380,7 @@ typedef packedstruct
 #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:
@@ -1374,7 +1392,7 @@ typedef packedstruct
 // 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
 
@@ -1428,9 +1446,13 @@ typedef struct
        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;
 
@@ -1610,6 +1632,7 @@ typedef struct DNSServer
     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;
@@ -1641,7 +1664,7 @@ struct NetworkInterfaceInfo_struct
        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 } ?
        };
@@ -1938,7 +1961,7 @@ typedef packedstruct
        } 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
        {
@@ -2474,13 +2497,12 @@ typedef struct uDNS_AuthInfo
 //
 // 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
 
index c4eda13b168bb6eeddbd544336dbc72d9fcf567a..e9d0991119e79ebdefed692e2b50098b9f96e36d 100755 (executable)
     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
 
@@ -175,13 +241,13 @@ Revision 1.135  2004/12/03 05:18:33  ksekar
 <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
@@ -220,7 +286,7 @@ Revision 1.121  2004/11/19 04:24:08  ksekar
 <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
@@ -413,7 +479,7 @@ Revision 1.63  2004/08/12 00:32:36  ksekar
 <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
@@ -808,12 +874,12 @@ mDNSlocal void SwapRData(mDNS *m, AuthRecord *rr, mDNSBool DeallocOld)
 
 // 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;
        }
        
 
@@ -871,14 +937,14 @@ mDNSexport void mDNS_DeleteDNSServers(mDNS *const m)
 #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;
        }
@@ -900,7 +966,7 @@ mDNSlocal void DeleteAuthInfoForZone(uDNS_GlobalInfo *u, const domainname *zone)
                }
        }
 
-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];
@@ -910,28 +976,24 @@ mDNSexport mStatus mDNS_SetSecretForZone(mDNS *m, const domainname *zone, const
 
        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;
@@ -1027,7 +1089,7 @@ mDNSlocal void SendNATMsg(NATTraversalInfo *info, mDNS *m)
                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);
@@ -1042,7 +1104,7 @@ mDNSlocal void SendNATMsg(NATTraversalInfo *info, mDNS *m)
        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;
@@ -1052,16 +1114,14 @@ mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt,
        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;
@@ -1084,20 +1144,17 @@ mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt,
                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; }
@@ -1124,11 +1181,12 @@ mDNSlocal void ReceiveNATAddrResponse(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt,
                        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;
        }
 
 
@@ -1197,34 +1255,19 @@ mDNSlocal void LLQNatMapComplete(mDNS *m)
                }
        }
 
-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;
@@ -1259,38 +1302,47 @@ mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mD
 #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
@@ -1298,6 +1350,7 @@ mDNSlocal void ReceivePortMapReply(NATTraversalInfo *n, mDNS *m, mDNSu8 *pkt, mD
                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)
@@ -1645,34 +1698,17 @@ mDNSlocal void GetStaticHostname(mDNS *m)
 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);                
                }
        }
 
@@ -2062,7 +2098,7 @@ mDNSlocal mStatus checkUpdateResult(domainname *displayname, mDNSu8 rcode, mDNS
        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)
@@ -2411,7 +2447,7 @@ mDNSlocal void SetUpdateExpiration(mDNS *m, DNSMessage *msg, const mDNSu8 *end,
 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
@@ -2420,16 +2456,12 @@ mDNSexport void uDNS_ReceiveNATMap(mDNS *m, mDNSu8 *pkt, mDNSu16 len)
        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,
@@ -2466,7 +2498,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
                        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
@@ -2668,7 +2700,7 @@ mDNSlocal void sendLLQRefresh(mDNS *m, DNSQuestion *q, mDNSu32 lease)
        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++;
@@ -2687,10 +2719,10 @@ mDNSlocal mDNSBool recvLLQEvent(mDNS *m, DNSQuestion *q, DNSMessage *msg, const
        (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;
@@ -2702,7 +2734,7 @@ mDNSlocal mDNSBool recvLLQEvent(mDNS *m, DNSQuestion *q, DNSMessage *msg, const
        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;
        }
 
@@ -2747,7 +2779,6 @@ mDNSlocal void sendChallengeResponse(mDNS *m, DNSQuestion *q, LLQOptData *llq)
                return;
                }
                
-
        if (!llq)
                {
                llq = &llqBuf;
@@ -2766,7 +2797,7 @@ mDNSlocal void sendChallengeResponse(mDNS *m, DNSQuestion *q, LLQOptData *llq)
        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;
@@ -2810,7 +2841,7 @@ mDNSlocal void hndlRequestChallenge(mDNS *m, DNSMessage *pktMsg, const mDNSu8 *e
                }
 
        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;
@@ -2912,7 +2943,7 @@ mDNSlocal void startLLQHandshake(mDNS *m, LLQ_Info *info, mDNSBool defer)
        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
                }
        
@@ -3184,9 +3215,9 @@ mDNSlocal mStatus startQuery(mDNS *const m, DNSQuestion *const question, mDNSBoo
                {
                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)
@@ -3513,7 +3544,7 @@ mDNSlocal smAction confirmNS(DNSMessage *msg, const mDNSu8 *end, ntaContext *con
                                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; }
@@ -3687,7 +3718,7 @@ mDNSlocal void conQueryCallback(int sd, void *context, mDNSBool ConnectionEstabl
                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
                {
@@ -3801,11 +3832,11 @@ mDNSlocal void sendRecordRegistration(mDNS *const m, AuthRecord *rr)
 
        if (rr->uDNS_info.lease)
                { ptr = putUpdateLease(&msg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) goto error; }
-               
-       err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &regInfo->ns, regInfo->port, -1, GetAuthInfoForZone(u, &regInfo->zone));
-       if (err) LogMsg("ERROR: sendRecordRegistration - mDNSSendDNSMessage - %ld", err);
 
-       SetRecordRetry(m, rr);
+       err = mDNSSendDNSMessage(m, &msg, ptr, mDNSInterface_Any, &regInfo->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;
@@ -3863,6 +3894,17 @@ mDNSlocal void RecordRegistrationCallback(mStatus err, mDNS *const m, void *auth
                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;
@@ -3980,13 +4022,13 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs)
        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;
@@ -4095,8 +4137,7 @@ mDNSlocal mStatus SetupRecordRegistration(mDNS *m, AuthRecord *rr)
                }
 
        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;
@@ -4127,10 +4168,10 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
        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;
 
@@ -4230,7 +4271,7 @@ mDNSexport mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
        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;
                }  
@@ -4263,10 +4304,10 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
                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;
  
@@ -4380,11 +4421,10 @@ mDNSlocal void SendRecordUpdate(mDNS *m, AuthRecord *rr, uDNS_RegInfo *info)
                { 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
@@ -4591,9 +4631,9 @@ mDNSlocal mDNSs32 CheckQueries(mDNS *m, mDNSs32 timenow)
                                        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
                                                }
                                        }
                                }
@@ -4806,9 +4846,8 @@ mDNSexport void mDNS_UpdateLLQs(mDNS *m)
        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);
@@ -4842,7 +4881,7 @@ mDNSlocal void SleepRecordRegistrations(mDNS *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;
index 7ae7f3cc9c9285e8d79e783c30d0e425e6811573..85b68d577cce8955cd63c250a87c5579f22bc152 100755 (executable)
@@ -23,6 +23,9 @@
     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)
 
@@ -128,12 +131,12 @@ Revision 1.1  2003/12/13 03:05:27  ksekar
        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
index d69b739f78a54a3905a83944558023e1ecc96530..a518d9de105ba1b477be90789e04664bf81410ac 100644 (file)
     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
 
@@ -116,16 +134,16 @@ like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code
 
 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 */
diff --git a/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff b/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff
new file mode 100644 (file)
index 0000000..b78b0c2
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff b/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff
new file mode 100644 (file)
index 0000000..b842e20
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/failure.tiff b/mDNSMacOSX/PreferencePane/Artwork/failure.tiff
new file mode 100644 (file)
index 0000000..89a10df
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/failure.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff b/mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff
new file mode 100644 (file)
index 0000000..340bb33
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/inprogress.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff b/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff
new file mode 100644 (file)
index 0000000..70d3dd9
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff b/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff
new file mode 100644 (file)
index 0000000..dacc97c
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff b/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff
new file mode 100644 (file)
index 0000000..de3f877
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/Artwork/success.tiff b/mDNSMacOSX/PreferencePane/Artwork/success.tiff
new file mode 100644 (file)
index 0000000..21702a9
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/Artwork/success.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c b/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
new file mode 100644 (file)
index 0000000..b0464a8
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+    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);
+}
diff --git a/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h b/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h
new file mode 100644 (file)
index 0000000..5a1a720
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+    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);
diff --git a/mDNSMacOSX/PreferencePane/ConfigurationRights.h b/mDNSMacOSX/PreferencePane/ConfigurationRights.h
new file mode 100644 (file)
index 0000000..85f441e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+    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"
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h
new file mode 100644 (file)
index 0000000..21f98f5
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+    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
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns
new file mode 100644 (file)
index 0000000..028a3a2
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.icns differ
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
new file mode 100644 (file)
index 0000000..e774498
--- /dev/null
@@ -0,0 +1,1204 @@
+/*
+    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(&regQuery.service, flags, 0, registrationDomainReply, (void *)self);
+    if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(&regQuery);
+
+    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
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff
new file mode 100644 (file)
index 0000000..985ae19
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.tiff differ
diff --git a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib
new file mode 100644 (file)
index 0000000..58c1f3e
--- /dev/null
@@ -0,0 +1,59 @@
+{
+    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
diff --git a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib
new file mode 100644 (file)
index 0000000..3759d87
--- /dev/null
@@ -0,0 +1,18 @@
+<?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>
diff --git a/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib
new file mode 100644 (file)
index 0000000..d024da1
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib differ
diff --git a/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings b/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings
new file mode 100644 (file)
index 0000000..e76e125
Binary files /dev/null and b/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings differ
diff --git a/mDNSMacOSX/PreferencePane/PrivilegedOperations.c b/mDNSMacOSX/PreferencePane/PrivilegedOperations.c
new file mode 100644 (file)
index 0000000..242d426
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+    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);
+}
diff --git a/mDNSMacOSX/PreferencePane/PrivilegedOperations.h b/mDNSMacOSX/PreferencePane/PrivilegedOperations.h
new file mode 100644 (file)
index 0000000..706be05
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+    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);
diff --git a/mDNSMacOSX/PreferencePane/ddnswriteconfig.m b/mDNSMacOSX/PreferencePane/ddnswriteconfig.m
new file mode 100644 (file)
index 0000000..f9383c6
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+    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;
+}
index d977a4adedd3fa2306403d8ba4ffbbbc78a6af06..97ef5604d04c373de864085d3708404596892984 100644 (file)
     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
 
@@ -609,6 +646,8 @@ static mach_port_t server_priv_port  = MACH_PORT_NULL;
 static int restarting_via_mach_init = 0;
 static int started_via_launchdaemon = 0;
 
+static int OSXVers;
+
 //*************************************************************************************************************
 // Active client list structures
 
@@ -707,7 +746,7 @@ static DNSServiceRegistration      *DNSServiceRegistrationList      = NULL;
 
 char _malloc_options[] = "AXZ";
 
-static void validatelists(mDNS *const m)
+mDNSlocal void validatelists(mDNS *const m)
        {
        DNSServiceDomainEnumeration *e;
        DNSServiceBrowser           *b;
@@ -1513,7 +1552,6 @@ mDNSexport void DefaultRegDomainChanged(const domainname *d, mDNSBool add)
        {
        DNSServiceRegistration *reg;
 
-       LogMsg("%s default registration domain %##s", add ? "Adding" : "Removing", d->c);
        for (reg = DNSServiceRegistrationList; reg; reg = reg->next)
                {
                if (reg->DefaultDomain)
@@ -1538,7 +1576,7 @@ mDNSexport void DefaultRegDomainChanged(const domainname *d, mDNSBool add)
                                        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
                                }                                       
                        }
                }
@@ -1670,21 +1708,73 @@ fail:
        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
@@ -1692,30 +1782,41 @@ mDNSlocal void RecordUpdatedName(const mDNS *const m, domainlabel *n1, domainlab
                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);
@@ -1730,11 +1831,24 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
        (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)
@@ -1847,6 +1961,11 @@ mDNSlocal mStatus UpdateRecord(ServiceRecordSet *srs, mach_port_t client, AuthRe
        // 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)",
@@ -2223,6 +2342,9 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
                }
        }
 
+// 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;
@@ -2230,7 +2352,7 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void)
        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);
@@ -2252,6 +2374,9 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void)
 
        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);
 
@@ -2275,7 +2400,7 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
        // 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);
@@ -2346,15 +2471,20 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const 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;
                        }
@@ -2436,10 +2566,11 @@ mDNSexport int main(int argc, char **argv)
        // 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
@@ -2502,9 +2633,10 @@ mDNSexport int main(int argc, char **argv)
                mDNS_Close(&mDNSStorage);
                }
 
-       if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService();
-
        LogMsgIdent(mDNSResponderVersionString, "exiting");
+
+exit:
+       if (!mDNS_DebugMode && !started_via_launchdaemon) destroyBootstrapService();
        return(status);
        }
 
@@ -2524,7 +2656,7 @@ typedef struct CFSocketEventSource        CFSocketEventSource;
 
 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
index 8a74c6f74a1a77f291743432d5293b5b9738db8c..8d553caf09daa9187db031bcf060f5294da97470 100644 (file)
     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
@@ -173,7 +219,7 @@ Add "#ifdef MAC_OS_X_VERSION_10_4" around split-DNS code that can't be compiled
 (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
@@ -213,7 +259,7 @@ Let interface name/index mapping capability live directly in JNISupport.c,
 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.
 
@@ -925,10 +971,7 @@ Minor code tidying
 
 #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
@@ -1217,16 +1260,17 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
        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);
@@ -1663,7 +1707,7 @@ mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *co
                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))
@@ -1680,7 +1724,7 @@ mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *co
                                }
 
                        CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("RegistrationDomains"));
-                       if (regArray)
+                       if (regArray && CFArrayGetCount(regArray) > 0)
                                {
                                CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
                                if (regDict && DDNSSettingEnabled(regDict))
@@ -1696,7 +1740,7 @@ mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *co
                                        }
                                }
                        CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("BrowseDomains"));
-                       if (browseArray)
+                       if (browseArray && CFArrayGetCount(browseArray) > 0)
                                {
                                CFRetain(browseArray);
                                *browseDomains = browseArray;
@@ -2342,9 +2386,9 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
 
 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
@@ -2366,20 +2410,25 @@ mDNSlocal mStatus GetDNSConfig(void **result)
                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++)                
@@ -2415,15 +2464,47 @@ mDNSlocal mStatus RegisterSplitDNS(mDNS *m)
                                        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)
@@ -2561,9 +2642,10 @@ mDNSlocal mStatus GetSearchDomains(void)
        {
        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;
@@ -2572,8 +2654,9 @@ mDNSlocal mStatus GetSearchDomains(void)
                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;
        }
 
@@ -2725,14 +2808,20 @@ mDNSlocal void SCPrefsDynDNSCallback(mDNS *const m, AuthRecord *const rr, mStatu
 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);
@@ -2740,30 +2829,63 @@ mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain)
        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)
@@ -2802,6 +2924,7 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m)
        CFStringRef     key;
        domainname RegDomain, fqdn;
        CFArrayRef NewBrowseDomains = NULL;
+       int nAdditions = 0, nDeletions = 0;
        
        // get fqdn, zone from SCPrefs
        GetUserSpecifiedDDNSConfig(&fqdn, &RegDomain, &NewBrowseDomains);
@@ -2843,8 +2966,8 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m)
                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);
                        }
                }
 
@@ -2858,7 +2981,7 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m)
        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);
@@ -2869,8 +2992,12 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m)
        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;
@@ -2896,6 +3023,8 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m)
                }
 
        // 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)
                {
@@ -2938,6 +3067,7 @@ mDNSlocal void DynDNSConfigChanged(mDNS *const m)
 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);
@@ -3047,26 +3177,26 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
        (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);
        }
@@ -3089,6 +3219,9 @@ CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
 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;
@@ -3429,7 +3562,7 @@ mDNSexport mDNSs32 mDNSPlatformRawTime(void)
                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, "");
                }
index 0222d04fe427853750a1ada24f9d6d4fd62163b3..645e8ee57d6d40eb1850d82b03c84dbb31939f40 100644 (file)
@@ -23,6 +23,9 @@
     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)
@@ -241,8 +244,8 @@ struct mDNS_PlatformSupport_struct
     {
     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;
diff --git a/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings b/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings
new file mode 100644 (file)
index 0000000..bba4c2c
--- /dev/null
@@ -0,0 +1,10 @@
+"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.";
diff --git a/mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings b/mDNSMacOSX/mDNSResponder-bundle/Resources/French.lproj/Localizable.strings
new file mode 100644 (file)
index 0000000..be7a444
--- /dev/null
@@ -0,0 +1,10 @@
+"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.";
index 41f07c3ee8ce821b3b95962eb593f0163a339b9f..3fe2b31063f896c1baedc39b4174c215c67bfe7f 100644 (file)
@@ -23,7 +23,7 @@
                                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;
index 7b0d48e8ead8caf65d0aefa37b0e7f7fc8810df8..6aafe37e7d3a6c3ebb93528959bc568bf0660c23 100755 (executable)
@@ -24,6 +24,9 @@
     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
 
@@ -158,21 +161,24 @@ static mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool p
     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 
@@ -192,7 +198,7 @@ static void ParseArguments(int argc, char **argv)
     // 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':
@@ -210,6 +216,9 @@ static void ParseArguments(int argc, char **argv)
                         exit(1);
                     }
                     break;
+                case 'd':
+                    gServiceDomain = optarg;
+                    break;
                 case '?':
                 default:
                     PrintUsage();
@@ -250,7 +259,7 @@ int main(int argc, char **argv)
         // 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);
     
index b9ed8ecf5ee58771fccbeee91a3e28237d88d934..638b56d36ad4e7194113d793512b351b22c0768b 100755 (executable)
@@ -24,6 +24,9 @@
 # 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"
 #
@@ -216,7 +219,7 @@ LD = ld -shared
 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
index 3ebc3044d1b7a00b242e278900290d0a0dbbf28c..6b991ecd149cec30ce57e9264a9b6ff1e3447df9 100644 (file)
        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
 
@@ -41,7 +47,7 @@ Revision 1.22  2004/12/10 13:12:08  cheshire
 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
@@ -118,8 +124,6 @@ Add support for mDNSResponder on Linux.
 #include <fcntl.h>
 #include <pwd.h>
 #include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
 #include "mDNSEmbeddedAPI.h"
 #include "mDNSDebug.h"
@@ -127,8 +131,6 @@ Add support for mDNSResponder on Linux.
 #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;
@@ -138,32 +140,6 @@ static CacheEntity gRRCache[RR_CACHE_SIZE];
 
 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;
@@ -183,7 +159,7 @@ static void ParseCmdLinArgs(int argc, char **argv)
        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)
@@ -191,7 +167,7 @@ static void ParseCmdLinArgs(int argc, char **argv)
                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
                }
@@ -258,6 +234,8 @@ int         main(int argc, char **argv)
 
        ParseCmdLinArgs(argc, argv);
 
+       LogMsgIdent(mDNSResponderVersionString, "starting");
+
        err = mDNS_Init(&mDNSRecord, &platformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, 
                                        mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); 
 
@@ -279,6 +257,8 @@ int         main(int argc, char **argv)
        if (mStatus_NoError == err)
                err = MainLoop(&mDNSRecord);
  
+       LogMsgIdent(mDNSResponderVersionString, "stopping");
+
        mDNS_Close(&mDNSRecord);
 
        if (udsserver_exit() < 0)
index d128c8de2e122441696c384a0f69e5bfdcef379e..80f8fa3db9ed9f34688a7cdde2fbaf02015133b7 100755 (executable)
@@ -15,9 +15,9 @@ technologies, see the zeroconf web site.
 
   <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), 
index b54d3a8edb7f844373a1abec9941d3c35bacd125..7765669be537b1600cbb12eeda6f75511ce259b8 100755 (executable)
@@ -24,6 +24,9 @@
     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
 
@@ -211,42 +214,26 @@ static void HandleSigQuit(int sigraised)
 #pragma mark ***** Parameter Checking
 #endif
 
-static mDNSBool CheckThatRichTextHostNameIsUsable(const char *richTextHostName, mDNSBool printExplanation)
-    // Checks that richTextHostName is a reasonable host nam
+static mDNSBool CheckThatRichTextNameIsUsable(const char *richTextName, mDNSBool printExplanation)
+    // Checks that richTextName is reasonabl
     // 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;
 }
 
@@ -318,7 +305,7 @@ static void PrintUsage()
     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);
@@ -333,7 +320,7 @@ static void PrintUsage()
 }
 
 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)];
@@ -377,8 +364,8 @@ static void ParseArguments(int argc, char **argv)
                     gAvoidPort53 = mDNSfalse;
                     break;
                 case 'n':
-                    gRichTextHostName = optarg;
-                    if ( ! CheckThatRichTextHostNameIsUsable(gRichTextHostName, mDNStrue) ) {
+                    gServiceName = optarg;
+                    if ( ! CheckThatRichTextNameIsUsable(gServiceName, mDNStrue) ) {
                         exit(1);
                     }
                     break;
@@ -435,9 +422,9 @@ static void ParseArguments(int argc, char **argv)
     
     // 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);
     }
 }
@@ -515,7 +502,7 @@ static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegi
 
 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[],
@@ -534,7 +521,7 @@ static mStatus RegisterOneService(const char *  richTextHostName,
         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,
@@ -557,7 +544,7 @@ static mStatus RegisterOneService(const char *  richTextHostName,
                     "%s: Registered service %d, name '%s', type '%s', port %ld\n", 
                     gProgramName, 
                     thisServ->serviceID, 
-                    richTextHostName,
+                    richTextName,
                     serviceType,
                     portNumber);
         }
@@ -575,7 +562,7 @@ static mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp)
        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)
        {
@@ -598,6 +585,7 @@ static mStatus RegisterServicesInFile(const char *filePath)
     if (status == mStatus_NoError) {
         mDNSBool good = mDNStrue;
         do {
+                       int         ch;
                        char name[256];
                        char type[256];
                        const char *dom = kDefaultServiceDomain;
@@ -605,6 +593,10 @@ static mStatus RegisterServicesInFile(const char *filePath)
                        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);               
@@ -623,28 +615,32 @@ static mStatus RegisterServicesInFile(const char *filePath)
                                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
                                }
                        }
@@ -668,8 +664,8 @@ static mStatus RegisterOurServices(void)
     mStatus status;
     
     status = mStatus_NoError;
-    if (gRichTextHostName[0] != 0) {
-        status = RegisterOneService(gRichTextHostName, 
+    if (gServiceName[0] != 0) {
+        status = RegisterOneService(gServiceName, 
                                     gServiceType, 
                                     gServiceDomain, 
                                     gServiceText, gServiceTextLen, 
index c9d0c73ea709abe9de0c241ccdd1391c32907d2f..687507ebda1af75f4313d9587b6a784d40d21394 100644 (file)
     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
 
@@ -71,7 +80,7 @@ Revision 1.16  2004/11/25 02:02:28  ksekar
 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>.
@@ -180,7 +189,7 @@ Revision 1.1  2004/08/11 00:43:26  ksekar
 #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
@@ -213,6 +222,16 @@ typedef enum
        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
        {
@@ -224,7 +243,7 @@ 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
@@ -248,6 +267,7 @@ typedef struct
 
     // 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;
@@ -576,6 +596,7 @@ mDNSlocal void RehashTable(DaemonInfo *d)
        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 *));
@@ -593,6 +614,8 @@ mDNSlocal void RehashTable(DaemonInfo *d)
                        }
                }
        d->nbuckets = newnbuckets;
+       free(d->table);
+       d->table = new;
        }
 
 // print entire contents of hashtable, invoked via SIGINFO
@@ -995,9 +1018,10 @@ mDNSlocal void DeleteExpiredRecords(DaemonInfo *d)
 // 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;
@@ -1014,68 +1038,77 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
        
        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:
@@ -1172,41 +1205,39 @@ mDNSlocal mDNSu32 LLQLease(LLQEntry *e)
        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)
@@ -1227,7 +1258,7 @@ 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;
@@ -1240,13 +1271,13 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd)
        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);
        
@@ -1258,7 +1289,7 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd)
        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);
@@ -1266,18 +1297,16 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd)
 
        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;
@@ -1287,94 +1316,102 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, LLQEntry *e, int sd)
        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)
@@ -1401,38 +1438,69 @@ 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);
        }
 
@@ -1506,14 +1574,43 @@ mDNSlocal void *LLQEventMonitor(void *DInfoPtr)
                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);
@@ -1525,7 +1622,7 @@ mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qn
        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;
@@ -1534,7 +1631,6 @@ mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qn
        e->lease = lease;
        
        // add to table
-       bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
        e->next = d->LLQTable[bucket];
        d->LLQTable[bucket] = e;
        
@@ -1603,9 +1699,10 @@ mDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq,
        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);
@@ -1820,7 +1917,7 @@ mDNSlocal void *UDPUpdateRequestForkFn(void *vptr)
 
        if (reply) free(reply);         
        free(req);
-       return NULL;
+       pthread_exit(NULL);
        }
 
 //!!!KRS this needs to be changed to use non-blocking sockets
@@ -1847,9 +1944,10 @@ mDNSlocal int RecvUDPRequest(int sd, DaemonInfo *d)
                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;
        }
 
@@ -1888,7 +1986,7 @@ mDNSlocal void *TCPRequestForkFn(void *vptr)
        free(req);
        if (in) free(in);
        if (out) free(out);
-       return NULL;    
+       pthread_exit(NULL);
        }
 
 mDNSlocal int RecvTCPRequest(int sd, DaemonInfo *d)
@@ -1905,6 +2003,7 @@ 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;
        }
 
@@ -1978,15 +2077,18 @@ mDNSlocal void HndlSignal(int sig)
 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)
                {
@@ -1998,14 +2100,19 @@ int main(int argc, char *argv[])
                        }       
                }
 
-       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);
        }
-
index f15a88ac9a0d161b9fef123f83a4d49e3bee30d5..3970b4b87bc9e0b32790b977a777105a3b2a00e2 100755 (executable)
        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"
 
@@ -284,6 +290,7 @@ First checkin
 #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
@@ -497,16 +504,21 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s
                // 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)
@@ -520,8 +532,8 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s
                                }
                        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++;
                                }
                        }
@@ -610,6 +622,32 @@ mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel
        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)
@@ -626,7 +664,7 @@ mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const c
        return intf;
        }
 
-extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
+mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
        {
        PosixNetworkInterface *intf;
 
@@ -702,7 +740,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
        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
@@ -1328,6 +1366,9 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
        // 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);
@@ -1360,7 +1401,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
 #endif
        }
 
-extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
+mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
        {
        int err;
        ClearInterfaceList(m);
index 0ee54dd148c761054e9a7fce2d8afaf1538a7e8f..a5af557e543b7ad34e8cdb4ca0f4ada621545424 100755 (executable)
@@ -24,6 +24,9 @@
     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
 
@@ -117,6 +120,8 @@ struct mDNS_PlatformSupport_struct
 #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.
 
diff --git a/mDNSResponder.sln b/mDNSResponder.sln
new file mode 100755 (executable)
index 0000000..423805f
--- /dev/null
@@ -0,0 +1,100 @@
+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
index 9bee556382e8d529f3ab89fa9c879e058e0b580e..3baee26c699bb4c746625fd3f1c303c5b2bc9240 100644 (file)
@@ -24,6 +24,9 @@
     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
 
@@ -96,7 +99,6 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi
        {
        char buf   [MAX_ESCAPED_DOMAIN_NAME];
        char secret[MAX_ESCAPED_DOMAIN_NAME] = "";
-       int slen;
        mStatus err;
        FILE *f = fopen(filename, "r");
 
@@ -122,8 +124,7 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi
        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);
                }
 
index a8a602b3e29f891c6a8fdb7c64e1c53f38a6579f..3611200db597036fc98a6f8bfb66e019fc779bab 100644 (file)
 .\" @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
 .\"
@@ -34,7 +40,7 @@
 .\"
 .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 ...
@@ -160,7 +166,7 @@ print.
 .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
@@ -171,7 +177,7 @@ network.
 .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
index 4f22f679ce135034b386040780c8da21be7f42e1..81e0856d9a42f76856ec5e51563804b1a440ea33 100755 (executable)
@@ -165,7 +165,7 @@ enum
     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. */
@@ -232,8 +232,13 @@ enum
     };
 
 
-/* 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
 
@@ -257,11 +262,18 @@ enum
  * 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
@@ -510,9 +522,9 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
  * 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).
@@ -555,13 +567,18 @@ typedef void (DNSSD_API *DNSServiceRegisterReply)
  *                  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
@@ -581,9 +598,12 @@ typedef void (DNSSD_API *DNSServiceRegisterReply)
  *
  * 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
@@ -844,9 +864,9 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse
  * 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:
  *
@@ -1317,7 +1337,7 @@ typedef struct _TXTRecordRef_t { char privatedata[16]; } TXTRecordRef;
  *
  * 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.
  */
index d06b5d2edad514ef5fab60630d74c8f982d425d4..8cf98d32bae83e344404bf7c1ad0715f625f45fc 100755 (executable)
@@ -28,6 +28,9 @@
     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
 
@@ -38,7 +41,7 @@ Revision 1.42  2005/01/11 02:01:02  shersche
 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,
@@ -78,7 +81,7 @@ Revision 1.30  2004/09/16 23:14:24  cheshire
 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
@@ -186,6 +189,8 @@ Update to APSL 2.0
 // conversion in expression"
 #pragma warning(disable:4152)
 
+#define sleep(X) Sleep((X) * 1000)
+
 static int g_initWinsock = 0;
 #endif
 
index ca0014b4622b21a2865945f0f0ac4567da2949f1..58c0ec391e50cdfbc67fc556c76a3e143a46a5d0 100644 (file)
@@ -27,6 +27,9 @@
     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
 
@@ -47,7 +50,7 @@ Revision 1.13  2004/09/16 23:14:25  cheshire
 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
@@ -118,7 +121,9 @@ Update to APSL 2.0
 #      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     
index 71c3daf3dc95a8543fc484797c6e2f960a65471c..b02dd17c0ba28b771d64f2076d89a071f1c2f3ab 100644 (file)
 .\" @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
 .\"
@@ -43,7 +49,7 @@
 .\"
 .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 ...
@@ -173,7 +179,7 @@ print.
 .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
@@ -184,7 +190,7 @@ network.
 .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
index 8e7a23faa1769593925e31e119c452d736de2ec5..352ad6de970edcdc30cf652ad434969322f92d36 100644 (file)
@@ -20,6 +20,9 @@
 .\" @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
 .\"
@@ -92,11 +95,11 @@ For information on DNS Service Discovery, see
 .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
index e14db7aeecb801c6c81787d5864a7349b68af223..964d2fc1c2cbc9b162875fdb2f73129f00b4175f 100644 (file)
     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()
 
@@ -288,7 +339,7 @@ Revision 1.82  2004/09/16 23:14:25  cheshire
 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
@@ -770,7 +821,7 @@ static void browse_termination_callback(void *context);
 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);
@@ -812,6 +863,32 @@ static void handle_setdomain_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()));
@@ -839,7 +916,10 @@ int udsserver_init(void)
                }
 
        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));
 
@@ -850,7 +930,10 @@ int udsserver_init(void)
                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
                {
@@ -866,7 +949,10 @@ int udsserver_init(void)
                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
 
@@ -880,10 +966,10 @@ int udsserver_init(void)
        #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)
                {
@@ -933,7 +1019,11 @@ int udsserver_exit(void)
        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;
@@ -974,17 +1064,18 @@ mDNSs32 udsserver_idle(mDNSs32 nextevent)
                 }
             }
         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()
             {
@@ -1038,28 +1129,7 @@ void udsserver_info(mDNS *const m)
        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);
@@ -1822,7 +1892,7 @@ static void handle_browse_request(request_state *request)
     domainname typedn, d, temp;
     mDNSs32 NumSubTypes;
     char *ptr;
-    mStatus err;
+    mStatus err = mStatus_NoError;
        DNameListElem *search_domain_list, *sdom;
        browser_info_t *info = NULL;
        
@@ -1874,7 +1944,7 @@ static void handle_browse_request(request_state *request)
        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; }
@@ -1897,7 +1967,7 @@ static void handle_browse_request(request_state *request)
                mDNS_FreeDNameList(search_domain_list);
                }
                
-       deliver_error(request, mStatus_NoError);
+       deliver_error(request, err);
        return;
     
 error:
@@ -2073,7 +2143,8 @@ mDNSexport void udsserver_default_reg_domain_changed(const domainname *d, mDNSBo
        {
        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;
@@ -2105,7 +2176,7 @@ mDNSexport void udsserver_default_reg_domain_changed(const domainname *d, mDNSBo
                                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
                        }
                }
        }
@@ -2115,7 +2186,8 @@ static void handle_regservice_request(request_state *request)
     {
     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;
@@ -2145,7 +2217,7 @@ static void handle_regservice_request(request_state *request)
     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)
@@ -2155,7 +2227,13 @@ static void handle_regservice_request(request_state *request)
        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
@@ -2173,6 +2251,12 @@ static void handle_regservice_request(request_state *request)
                }
     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;
@@ -2209,7 +2293,8 @@ static void handle_regservice_request(request_state *request)
                                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)
@@ -2247,11 +2332,19 @@ bad_param:
 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)
@@ -2272,7 +2365,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta
                        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;
@@ -2311,7 +2404,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta
                    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);
@@ -2325,7 +2418,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta
                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);
@@ -2423,6 +2516,12 @@ static mStatus update_record(AuthRecord *rr, uint16_t rdlen, char *rdata, uint32
     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;
@@ -2493,7 +2592,7 @@ static void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd)
     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;
@@ -2505,7 +2604,7 @@ static void process_service_registration(ServiceRecordSet *const srs)
     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);
@@ -2574,6 +2673,7 @@ static void regservice_termination_callback(void *context)
                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);
        }
 
@@ -2833,12 +2933,14 @@ static void enum_result_callback(mDNS *const m, DNSQuestion *question, const Res
     (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
@@ -3178,7 +3280,7 @@ static int send_msg(reply_state *rs)
 #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;
diff --git a/mDNSWindows/ControlPanel/ConfigDialog.cpp b/mDNSWindows/ControlPanel/ConfigDialog.cpp
new file mode 100755 (executable)
index 0000000..092331a
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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()
diff --git a/mDNSWindows/ControlPanel/ConfigDialog.h b/mDNSWindows/ControlPanel/ConfigDialog.h
new file mode 100755 (executable)
index 0000000..868746b
--- /dev/null
@@ -0,0 +1,62 @@
+/*\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
diff --git a/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp b/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
new file mode 100755 (executable)
index 0000000..07160cf
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * 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;
+}
diff --git a/mDNSWindows/ControlPanel/ConfigPropertySheet.h b/mDNSWindows/ControlPanel/ConfigPropertySheet.h
new file mode 100755 (executable)
index 0000000..a954f18
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * 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
diff --git a/mDNSWindows/ControlPanel/ControlPanel.cpp b/mDNSWindows/ControlPanel/ControlPanel.cpp
new file mode 100755 (executable)
index 0000000..03db2cb
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * 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;
+}
diff --git a/mDNSWindows/ControlPanel/ControlPanel.def b/mDNSWindows/ControlPanel/ControlPanel.def
new file mode 100755 (executable)
index 0000000..ddae9e7
--- /dev/null
@@ -0,0 +1,35 @@
+;\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
diff --git a/mDNSWindows/ControlPanel/ControlPanel.h b/mDNSWindows/ControlPanel/ControlPanel.h
new file mode 100755 (executable)
index 0000000..538fbf0
--- /dev/null
@@ -0,0 +1,98 @@
+/*\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
diff --git a/mDNSWindows/ControlPanel/ControlPanel.rc b/mDNSWindows/ControlPanel/ControlPanel.rc
new file mode 100755 (executable)
index 0000000..db16d91
--- /dev/null
@@ -0,0 +1,280 @@
+// 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
diff --git a/mDNSWindows/ControlPanel/ControlPanel.vcproj b/mDNSWindows/ControlPanel/ControlPanel.vcproj
new file mode 100755 (executable)
index 0000000..e322593
--- /dev/null
@@ -0,0 +1,333 @@
+<?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
diff --git a/mDNSWindows/ControlPanel/FirstPage.cpp b/mDNSWindows/ControlPanel/FirstPage.cpp
new file mode 100755 (executable)
index 0000000..9dfe401
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * 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();
+}
diff --git a/mDNSWindows/ControlPanel/FirstPage.h b/mDNSWindows/ControlPanel/FirstPage.h
new file mode 100755 (executable)
index 0000000..6d875e1
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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;
+};
diff --git a/mDNSWindows/ControlPanel/SecondPage.cpp b/mDNSWindows/ControlPanel/SecondPage.cpp
new file mode 100755 (executable)
index 0000000..a330e84
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * 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;
+}
diff --git a/mDNSWindows/ControlPanel/SecondPage.h b/mDNSWindows/ControlPanel/SecondPage.h
new file mode 100755 (executable)
index 0000000..a8d1f09
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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();
+}; 
diff --git a/mDNSWindows/ControlPanel/SharedSecret.cpp b/mDNSWindows/ControlPanel/SharedSecret.cpp
new file mode 100755 (executable)
index 0000000..6c42aca
--- /dev/null
@@ -0,0 +1,198 @@
+/*\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
diff --git a/mDNSWindows/ControlPanel/SharedSecret.h b/mDNSWindows/ControlPanel/SharedSecret.h
new file mode 100755 (executable)
index 0000000..07e79e1
--- /dev/null
@@ -0,0 +1,64 @@
+/*\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
diff --git a/mDNSWindows/ControlPanel/ThirdPage.cpp b/mDNSWindows/ControlPanel/ThirdPage.cpp
new file mode 100755 (executable)
index 0000000..bfb56bd
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * 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
diff --git a/mDNSWindows/ControlPanel/ThirdPage.h b/mDNSWindows/ControlPanel/ThirdPage.h
new file mode 100755 (executable)
index 0000000..9fe7420
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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
diff --git a/mDNSWindows/ControlPanel/res/ControlPanel.rc2 b/mDNSWindows/ControlPanel/res/ControlPanel.rc2
new file mode 100755 (executable)
index 0000000..e3f7422
--- /dev/null
@@ -0,0 +1,13 @@
+//\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
diff --git a/mDNSWindows/ControlPanel/res/controlpanel.ico b/mDNSWindows/ControlPanel/res/controlpanel.ico
new file mode 100755 (executable)
index 0000000..e5150f5
Binary files /dev/null and b/mDNSWindows/ControlPanel/res/controlpanel.ico differ
diff --git a/mDNSWindows/ControlPanel/res/failure.ico b/mDNSWindows/ControlPanel/res/failure.ico
new file mode 100755 (executable)
index 0000000..f0b8f2b
Binary files /dev/null and b/mDNSWindows/ControlPanel/res/failure.ico differ
diff --git a/mDNSWindows/ControlPanel/res/success.ico b/mDNSWindows/ControlPanel/res/success.ico
new file mode 100755 (executable)
index 0000000..9b97584
Binary files /dev/null and b/mDNSWindows/ControlPanel/res/success.ico differ
diff --git a/mDNSWindows/ControlPanel/resource.h b/mDNSWindows/ControlPanel/resource.h
new file mode 100755 (executable)
index 0000000..1fbf6a5
--- /dev/null
@@ -0,0 +1,41 @@
+//{{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
diff --git a/mDNSWindows/ControlPanel/stdafx.cpp b/mDNSWindows/ControlPanel/stdafx.cpp
new file mode 100755 (executable)
index 0000000..ad80318
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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"
+
+
diff --git a/mDNSWindows/ControlPanel/stdafx.h b/mDNSWindows/ControlPanel/stdafx.h
new file mode 100755 (executable)
index 0000000..6bdeb92
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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
index 7014ab0642a533fd98ce2fcf044ef4204cbad31f..b09cb841fa43e912d2e7f4e575e3728f8bed4762 100755 (executable)
@@ -1,36 +1,38 @@
-/*\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"
index 397a0d1e149bc36d74d6c37f01ddb34cf03a4450..7eeb488cd454bb41ebe87f61fbaca556aa8ab718 100755 (executable)
@@ -1,40 +1,45 @@
-/*\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>
+
index 3aee79c49fa2cbdbe52abd951bf08f484fb66b79..36a5452fd820c84c17468ddbff975a2780ed64d1 100755 (executable)
@@ -37,7 +37,7 @@ Revision 1.7  2004/09/11 00:36:40  shersche
 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
index 312d7b6e58c17cd592987eb2c23726a8eaf74812..6faeb3dcdfdc4fd6563dece9cdb2716712935250 100755 (executable)
  * (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
 
index c6340ee300ff14f3ddd1d92a9edec2e061cb316e..3e783c36915f5383556429abb14815b51a5e10fd 100755 (executable)
@@ -81,9 +81,9 @@ BEGIN
         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
index 7f8506363da97f88c1fc1c3af99199e937f928ff..7e714b7174a0f8196896437a390dc528358e92d0 100644 (file)
@@ -70,9 +70,9 @@ BEGIN
         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
index c8aac787b38901be8c643a04b91c0a45e9f878d5..39750483b70ec739f0b909c6de49b10890c6e080 100644 (file)
@@ -65,7 +65,7 @@
                </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
index 0435f6103668e2c1e980e316717747b61753fa76..ab5f1002e571c171fc5e0985f2a6fa63f5206f1a 100644 (file)
@@ -23,6 +23,9 @@
     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>.
 
@@ -244,7 +247,6 @@ static const KnownServiceEntry              kKnownServiceTable[] =
        { "_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 },
index 1b57da4e7b2662569f457599ac9598b6fc2285bc..b590e307f49897ba5b8de91fbade93a02a2126c3 100644 (file)
 # @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
 #
@@ -78,11 +84,13 @@ DEBUG=0
 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
 
@@ -100,19 +108,12 @@ setup:
        @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:
diff --git a/mDNSWindows/RegNames.h b/mDNSWindows/RegNames.h
new file mode 100644 (file)
index 0000000..5a02c2f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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
index 59d18e8783fb03c20db55a41ce41035feb00e46d..150aa3bb73506001da002c3ae039bf28b934539f 100644 (file)
@@ -30,7 +30,7 @@ Revision 1.2  2004/04/30 02:40:23  bradley
 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.
 
 */
 
index bfbf6a4a628b271e64ca16fac9be09de9aaa1e2e..451c239ce0b7b8b2eb348eeef9445d348d9b7727 100644 (file)
     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
 
@@ -57,7 +72,7 @@ Revision 1.16  2004/09/16 18:49:34  shersche
 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
@@ -114,7 +129,7 @@ Revision 1.1  2004/06/18 04:16:41  rpantos
 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.
 
 */
 
@@ -124,6 +139,7 @@ mDNSResponder Windows Service. Provides global Rendezvous support with an IPC in
 
 #include       "CommonServices.h"
 #include       "DebugServices.h"
+#include       "RegNames.h"
 
 #include       "uds_daemon.h"
 #include       "GenLinkedList.h"
@@ -151,13 +167,9 @@ mDNSResponder Windows Service. Provides global Rendezvous support with an IPC in
 //     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
@@ -211,30 +223,33 @@ typedef struct Win32EventSource
 //===========================================================================================================================
 //     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();
@@ -245,6 +260,15 @@ static OSStatus            GetRouteDestination(DWORD * ifIndex, DWORD * address);
 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"
 
@@ -286,8 +310,11 @@ DEBUG_LOCAL GenLinkedList                          gEventSources;
 //===========================================================================================================================
 //     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;
@@ -296,7 +323,7 @@ int __cdecl main( int argc, char *argv[] )
        
        debug_initialize( kDebugOutputTypeMetaConsole );
        debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
-       
+
        // Default to automatically starting the service dispatcher if no extra arguments are specified.
        
        start = ( argc <= 1 );
@@ -305,20 +332,20 @@ int       __cdecl main( int argc, char *argv[] )
        
        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 )
@@ -327,11 +354,11 @@ int       __cdecl main( int argc, char *argv[] )
                                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 )
@@ -340,26 +367,12 @@ int       __cdecl main( int argc, char *argv[] )
                        }
                        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;
@@ -450,7 +463,7 @@ exit:
 //     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;
@@ -513,7 +526,7 @@ exit:
 //     RemoveService
 //===========================================================================================================================
 
-static OSStatus        RemoveService( const char *inName )
+static OSStatus        RemoveService( LPCTSTR inName )
 {
        OSStatus                        err;
        SC_HANDLE                       scm;
@@ -576,7 +589,7 @@ static OSStatus SetServiceParameters()
        DWORD                   value;
        DWORD                   valueLen = sizeof(DWORD);
        DWORD                   type;
-       const char      *       s;
+       LPCTSTR                 s;
        OSStatus                err;
        HKEY                    key;
 
@@ -585,7 +598,7 @@ static OSStatus SetServiceParameters()
        //
        // 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 );
        
@@ -623,7 +636,7 @@ static OSStatus GetServiceParameters()
        DWORD                   value;
        DWORD                   valueLen;
        DWORD                   type;
-       const char      *       s;
+       LPCTSTR                 s;
        OSStatus                err;
        HKEY                    key;
 
@@ -632,7 +645,7 @@ static OSStatus GetServiceParameters()
        //
        // 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 );
        
@@ -670,7 +683,7 @@ static OSStatus CheckFirewall()
        DWORD                   value;
        DWORD                   valueLen;
        DWORD                   type;
-       const char      *       s;
+       LPCTSTR                 s;
        HKEY                    key = NULL;
        OSStatus                err = kUnknownErr;
        
@@ -680,7 +693,7 @@ static OSStatus CheckFirewall()
        // 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 );
 
@@ -722,7 +735,7 @@ 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;
@@ -759,7 +772,7 @@ static OSStatus     SetServiceInfo( SC_HANDLE inSCM, const char *inServiceName, cons
        
        // 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 );
@@ -811,7 +824,7 @@ static void ReportStatus( int inType, const char *inFormat, ... )
                        
                        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
@@ -829,7 +842,7 @@ static void ReportStatus( int inType, const char *inFormat, ... )
 //     RunDirect
 //===========================================================================================================================
 
-static OSStatus        RunDirect( int argc, char *argv[] )
+static OSStatus        RunDirect( int argc, LPTSTR argv[] )
 {
        OSStatus                err;
        BOOL                    initialized;
@@ -872,11 +885,11 @@ exit:
 //     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 );
@@ -901,7 +914,7 @@ static void WINAPI ServiceMain( DWORD argc, LPSTR argv[] )
        // 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 );
        
@@ -947,25 +960,25 @@ static OSStatus   ServiceSetupEventLogging( void )
 {
        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.
@@ -977,7 +990,7 @@ static OSStatus     ServiceSetupEventLogging( void )
                                         | 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.
@@ -1047,7 +1060,7 @@ static DWORD WINAPI       ServiceControlHandler( DWORD inControl, DWORD inEventType, L
 //     ServiceRun
 //===========================================================================================================================
 
-static OSStatus        ServiceRun( int argc, char *argv[] )
+static OSStatus        ServiceRun( int argc, LPTSTR argv[] )
 {
        OSStatus                err;
        BOOL                    initialized;
@@ -1119,7 +1132,7 @@ static void       ServiceStop( void )
 //     ServiceSpecificInitialize
 //===========================================================================================================================
 
-static OSStatus        ServiceSpecificInitialize( int argc, char *argv[] )
+static OSStatus        ServiceSpecificInitialize( int argc, LPTSTR argv[] )
 {
        OSStatus                                                err;
        
@@ -1164,7 +1177,7 @@ exit:
 //     ServiceSpecificRun
 //===========================================================================================================================
 
-static OSStatus        ServiceSpecificRun( int argc, char *argv[] )
+static OSStatus        ServiceSpecificRun( int argc, LPTSTR argv[] )
 {
        DWORD result;
        
@@ -1201,7 +1214,7 @@ exit:
 //     ServiceSpecificFinalize
 //===========================================================================================================================
 
-static void    ServiceSpecificFinalize( int argc, char *argv[] )
+static void    ServiceSpecificFinalize( int argc, LPTSTR argv[] )
 {
        DEBUG_UNUSED( argc );
        DEBUG_UNUSED( argv );
index 8300753241f15be423e9fcd59b670d124668e598..5c0103acab0c1afa815bfac9466537f274316157 100644 (file)
@@ -44,9 +44,9 @@ BEGIN
         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
index dc458fd4e013c15a6c1c16ba5a907bb07d09cb5f..cbc4e1441cf35b62a91ee941cced97165c6e908d 100644 (file)
@@ -20,7 +20,7 @@
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
                                AdditionalIncludeDirectories=".;../;../../mDNSCore;../../mDNSShared;&quot;C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include&quot;"\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=&quot;&quot;&quot;&quot;"\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=&quot;&quot;&quot;&quot;;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;&quot;C:\Program Files\Microsoft Platform SDK for Windows XP SP2\Include&quot;"\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=&quot;&quot;&quot;&quot;"\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=&quot;&quot;&quot;&quot;;UNICODE;_UNICODE"\r
                                RuntimeLibrary="0"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
index 30d4984b009780d20a97981d50a84bb037a23244..884d661f10b7956767aa35e4367e4be7ef466cbe 100644 (file)
     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.
 
@@ -94,13 +118,13 @@ First checked in.
 #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."
index e2e2d5868fbd352f43a7c06429fa8755f4dd95a5..08cbc886949ddb99b82645964fa04d83c8ca413a 100755 (executable)
@@ -49,9 +49,9 @@ static DNameListElem *DefBrowseList = mDNSNULL;    // cache of answers to above
 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)
@@ -401,68 +401,96 @@ mDNSlocal mStatus RegisterSearchDomains( mDNS *const m )
        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);
 
@@ -484,12 +512,25 @@ mStatus dDNS_Setup( mDNS *const m )
                }
        }
        
-       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))
                {
index e9d7a362ecdea6ee041fba86765f73e17f40163d..e1b148e5d8569ce916c27a060c2bcf4702f20807 100755 (executable)
@@ -61,7 +61,7 @@ extern mStatus dDNS_SetupAddr( mDNSAddr *ip, const struct sockaddr * const sa );
 
 // 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 );
index 78f16a48eb7a568f8f91e03993f063974e08cf71..7a90e66bca5cc4fac1b12cbe2da4efa632d938f2 100755 (executable)
@@ -31,6 +31,7 @@
  * ----------------------------------------------------------------------
  */
  
+#include "DebugServices.h"
 #include <windows.h>
 #include <stdio.h>
 #include "isocode.h"
@@ -40,6 +41,7 @@
 #include <sys/stat.h>
 #include <wchar.h>
 
+
 #ifdef __cplusplus
 extern "c" {
 #endif
@@ -109,25 +111,62 @@ static void _setLanguageIfNeeded(void) {
 
 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;
 }
 
 
@@ -204,7 +243,7 @@ int PathForResourceWithPathW (const wchar_t *path, const wchar_t *nm,
                }
 
                // 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
index 7d4ea02a4e59fa280b5aa157c96c7f89bb289a34..6e7bb361389c072d68ab8155142b0994c62bd8d5 100755 (executable)
     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
 
@@ -297,6 +333,7 @@ Multicast DNS platform plugin for Win32
 
 #include       "CommonServices.h"
 #include       "DebugServices.h"
+#include       "RegNames.h"
 #include       <dns_sd.h>
 
 #include       <Iphlpapi.h>
@@ -323,8 +360,6 @@ Multicast DNS platform plugin for Win32
 #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"
@@ -336,9 +371,11 @@ Multicast DNS platform plugin for Win32
 #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;
@@ -375,6 +412,7 @@ mDNSlocal mStatus                   ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE *
 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 );
 
 
@@ -391,6 +429,18 @@ struct     mDNSPlatformInterfaceInfo
        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 );
 
@@ -410,11 +460,14 @@ mDNSexport mStatus        mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter
 
 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
        }
@@ -430,6 +483,9 @@ mDNSlocal OSStatus                  ConvertLsaStringToUTF8( PLSA_UNICODE_STRING input, char **
 
 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 )
 
@@ -462,6 +518,8 @@ mStatus     mDNSPlatformInit( mDNS * const inMDNS )
        int                     supported;
        struct sockaddr_in      sa4;
        struct sockaddr_in6 sa6;
+       int                                     sa4len;
+       int                                     sa6len;
        
        dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
        
@@ -507,6 +565,10 @@ mStatus    mDNSPlatformInit( mDNS * const inMDNS )
        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 );
@@ -553,6 +615,11 @@ mStatus    mDNSPlatformInit( mDNS * const inMDNS )
 
        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 );
 
@@ -740,9 +807,11 @@ 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 );
+       }
 }
 
 //===========================================================================================================================
@@ -753,20 +822,23 @@ void      mDNSPlatformUnlock( const mDNS * const inMDNS )
 {
        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 );
 }
 
 //===========================================================================================================================
@@ -1049,14 +1121,80 @@ mStatus
                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;
 }
 
 //===========================================================================================================================
@@ -1065,7 +1203,33 @@ mStatus
 
 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;
+       }
 }
 
 //===========================================================================================================================
@@ -1074,11 +1238,21 @@ void    mDNSPlatformTCPCloseConnection( int inSock )
 
 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;
 }
 
 //===========================================================================================================================
@@ -1087,32 +1261,51 @@ int     mDNSPlatformReadTCP( int inSock, void *inBuffer, int inBufferSize )
 
 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 );
@@ -1136,16 +1329,51 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, doma
                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 )
@@ -1154,13 +1382,7 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, doma
                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 );
@@ -1174,6 +1396,11 @@ dDNSPlatformGetConfig(domainname * const fqdn, domainname *const regDomain, doma
 
 exit:
 
+       if ( subKey )
+       {
+               RegCloseKey( subKey );
+       }
+
        if ( key )
        {
                RegCloseKey( key );
@@ -1194,7 +1421,7 @@ void
 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;
@@ -1211,10 +1438,11 @@ dDNSPlatformSetNameStatus(domainname *const dname, mStatus status)
        }
 
        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 );
 
@@ -1285,7 +1513,7 @@ dDNSPlatformSetSecretForDomain( mDNS *m, const domainname * domain )
        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:
 
@@ -1330,7 +1558,7 @@ dDNSPlatformGetSearchDomainList( void )
        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 );
@@ -1847,16 +2075,18 @@ mDNSlocal mStatus       SetupNiceName( mDNS * const inMDNS )
 {
        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 );
 
@@ -1869,33 +2099,51 @@ mDNSlocal mStatus       SetupNiceName( mDNS * const inMDNS )
        // 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 ] );
        
@@ -2229,9 +2477,10 @@ mDNSlocal mStatus        TearDownInterfaceList( mDNS * const inMDNS )
 
 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" );
@@ -2263,50 +2512,35 @@ mDNSlocal mStatus       SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inI
        // 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 )
@@ -2712,11 +2946,25 @@ mDNSlocal mStatus       SetupNotifications( mDNS * const inMDNS )
                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);
@@ -2754,6 +3002,12 @@ mDNSlocal mStatus        TearDownNotifications( mDNS * const inMDNS )
                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 );
@@ -2876,11 +3130,19 @@ mDNSlocal unsigned WINAPI       ProcessingThread( LPVOID inParam )
                
                // 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);
@@ -2929,6 +3191,14 @@ mDNSlocal unsigned WINAPI        ProcessingThread( LPVOID inParam )
                                ProcessingThreadComputerDescriptionChanged( m );
                                break;
                        }
+                       else if ( result == kWaitListTCPIPEvent )
+                       {       
+                               //
+                               // The TCP/IP might have changed
+                               //
+                               ProcessingThreadTCPIPConfigChanged( m );
+                               break;
+                       }
                        else if ( result == kWaitListDynDNSEvent )
                        {
                                //
@@ -2950,7 +3220,8 @@ mDNSlocal unsigned WINAPI ProcessingThread( LPVOID inParam )
                                {
                                        HANDLE                                  signaledObject;
                                        int                                             n = 0;
-                                       mDNSInterfaceData *             ifd;
+                                       mDNSInterfaceData               *       ifd;
+                                       mDNSTCPConnectionData   *       tcd;
                                        
                                        signaledObject = waitList[ waitItemIndex ];
 
@@ -2979,6 +3250,26 @@ mDNSlocal unsigned WINAPI        ProcessingThread( LPVOID inParam )
                                                }
                                        }
 
+                                       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
@@ -3052,11 +3343,12 @@ exit:
 
 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 );
@@ -3066,7 +3358,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
        
        // 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;
@@ -3077,6 +3369,7 @@ mDNSlocal mStatus ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
        *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.
@@ -3092,6 +3385,12 @@ mDNSlocal mStatus        ProcessingThreadSetupWaitList( mDNS * const inMDNS, HANDLE **o
        {
                *waitItemPtr++ = ifd->readPendingEvent;
        }
+
+       for ( tcd = gTCPConnectionList; tcd; tcd = tcd->next )
+       {
+               *waitItemPtr++ = tcd->pendingEvent;
+       }
+
        check( (int)( waitItemPtr - waitList ) == waitListCount );
        
        *outWaitList            = waitList;
@@ -3324,6 +3623,33 @@ mDNSlocal void   ProcessingThreadComputerDescriptionChanged( mDNS *inMDNS )
 }
 
 
+//===========================================================================================================================
+//     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
 //===========================================================================================================================
@@ -3340,6 +3666,7 @@ mDNSlocal void    ProcessingThreadDynDNSConfigChanged( mDNS *inMDNS )
        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);
@@ -4106,7 +4433,7 @@ exit:
 //===========================================================================================================================
 
 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;
@@ -4126,17 +4453,19 @@ RegQueryString( HKEY key, const char * valueName, char ** string, DWORD * string
                *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;
@@ -4152,7 +4481,7 @@ exit:
 //     StringToAddress
 //===========================================================================================================================
 
-static mStatus StringToAddress( mDNSAddr * ip, const char * string )
+static mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
 {
        struct sockaddr_in6 sa6;
        struct sockaddr_in      sa4;
@@ -4162,7 +4491,7 @@ static mStatus StringToAddress( mDNSAddr * ip, const char * string )
        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 )
        {
@@ -4174,7 +4503,7 @@ static mStatus StringToAddress( mDNSAddr * ip, const char * string )
                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 );
@@ -4211,6 +4540,67 @@ myGetIfAddrs(int refresh)
 }
 
 
+//===========================================================================================================================
+//     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
 //===========================================================================================================================
@@ -4297,3 +4687,26 @@ exit:
 
        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 );
+}
index e94150e04cd079edca76f6e030d464333f48b1d8..f5c9c26e1d02304870529e252538c55bb687bcc3 100755 (executable)
     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
@@ -185,10 +191,12 @@ struct    mDNS_PlatformSupport_struct
        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;
@@ -264,19 +272,6 @@ int        getifaddrs( struct ifaddrs **outAddrs );
 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
index 34311f119f4e9d271e0375c78c9396162071fbf5..c690459adcf8b1f708ae50ae0230e0c97849471f 100644 (file)
     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
@@ -93,6 +106,24 @@ struct      Query
        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
@@ -104,7 +135,10 @@ struct     Query
 // DLL Exports
 
 BOOL WINAPI            DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved );
+STDAPI                 DllRegisterServer( void );
+STDAPI                 DllRegisterServer( void );
 
+       
 // NSP SPIs
 
 int    WSPAPI  NSPCleanup( LPGUID inProviderID );
@@ -186,6 +220,15 @@ DEBUG_LOCAL size_t QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *in
        #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
@@ -195,13 +238,15 @@ DEBUG_LOCAL size_t        QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *in
 //===========================================================================================================================
 
 // {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 -
@@ -219,6 +264,8 @@ BOOL APIENTRY       DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
        switch( inReason )
        {
                case DLL_PROCESS_ATTACH:                        
+                       gInstance = inInstance;         
+                       gHostsFileInfo  = NULL;
                        debug_initialize( kDebugOutputTypeWindowsEventLog, "mDNS NSP", inInstance );
                        debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
                        dlog( kDebugLevelTrace, "\n" );
@@ -226,6 +273,8 @@ BOOL APIENTRY       DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
                        break;
                
                case DLL_PROCESS_DETACH:
+                       HostsFileInfoFree( gHostsFileInfo );
+                       gHostsFileInfo = NULL;
                        dlog( kDebugLevelVerbose, "%s: process detach\n", __ROUTINE__ );
                        break;
                
@@ -244,6 +293,68 @@ BOOL APIENTRY      DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
        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
 //
@@ -486,8 +597,22 @@ DEBUG_LOCAL int WSPAPI
                                                                        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 )
@@ -548,7 +673,7 @@ DEBUG_LOCAL int WSPAPI
        // 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 );
@@ -1438,3 +1563,424 @@ void    DebugDumpQuerySet( DebugLevel inLevel, const WSAQUERYSETW *inQuerySet )
        }
 }
 #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;
+}
index 16f4f181da1edca4f9318ce6bf2488ef59acdbe6..338e5a5428fe727b484ae83e7416f61788562e77 100644 (file)
 ;      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>.
 ;
@@ -40,3 +44,5 @@ LIBRARY               mdnsNSP
 EXPORTS
        NSPStartup
        NSPCleanup
+       DllRegisterServer       PRIVATE
+       DllUnregisterServer     PRIVATE
index 4fae1d81c165443cb71f0874a64b4c424948be11..847c02aec303061a03499d54ffdecd738bae31ea 100644 (file)
@@ -72,9 +72,9 @@ BEGIN
         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
index f8aac541c72ed1be864b35dc2bbb1e7b2765f29d..4648cffd03492415a05e93eebf50e2873c42e38c 100644 (file)
@@ -64,7 +64,7 @@
                </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