venus: Remove dedebug
[openafs.git] / src / WINNT / install / loopback / wmi.cpp
index 80cfaa6..79793fe 100644 (file)
@@ -1,6 +1,7 @@
 /*
 
 Copyright 2004 by the Massachusetts Institute of Technology
+Copyright 2006 by Secure Endpoints Inc.
 
 All rights reserved.
 
@@ -32,7 +33,7 @@ SOFTWARE.
 //
 // Note:
 //
-//     The EnableStatic method is notsupported on Win9x platforms.
+//     The EnableStatic method is not supported on Win9x platforms.
 //
 //**************************************************************************
 
@@ -44,6 +45,11 @@ SOFTWARE.
 
 #include <devguid.h>
 
+/* __RPC__out is not defined in the v6.0 Windows SDK */
+#ifndef __RPC__out
+#define __RPC__out
+#endif
+
 /* These two are from the Windows DDK */
 #include <netcfgx.h>
 #include <netcfgn.h>
@@ -142,7 +148,7 @@ FindNetworkAdapterConfigurationInstanceByGUID(
         CLEANUP_ON_FAILURE(hr);
 
         bFound = !wcscmp(adapter_guid, V_BSTR(&Value));
-        
+
         if (bFound)
         {
             ReportMessage(1,"Found adapter", NULL,V_BSTR(&Value),0);
@@ -155,11 +161,11 @@ FindNetworkAdapterConfigurationInstanceByGUID(
             CLEANUP_ON_FAILURE(hr);
 
             *pPath = SysAllocString(V_BSTR(&Value));
-            
+
         }
-        
+
         VariantClear(&Value);
-        
+
         // Release it.
         // ===========
         pObj->Release();    // Release objects not owned.
@@ -214,6 +220,44 @@ SetupStringAsSafeArray(LPCWSTR s, VARIANT* v)
     return hr;
 }
 
+static BOOL
+IsXP(void)
+{
+    OSVERSIONINFOEX osInfoEx;
+    memset(&osInfoEx, 0, sizeof(osInfoEx));
+    osInfoEx.dwOSVersionInfoSize = sizeof(osInfoEx);
+
+    GetVersionEx((POSVERSIONINFO)&osInfoEx);
+
+    return(osInfoEx.dwMajorVersion == 5 && osInfoEx.dwMinorVersion == 1 && osInfoEx.wServicePackMajor < 2);
+}
+
+static VOID
+FixupXPDNSRegistrations(LPCWSTR pCfgGuidString)
+{
+    // As per http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B834440
+    // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<NetworkAdapterGUID>
+    HKEY hkInterfaces=NULL, hkAdapter=NULL;
+    DWORD dw = 0;
+
+    if (!IsXP())
+       return;         // Nothing to do
+
+    RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"),
+                0, KEY_READ, &hkInterfaces);
+
+    RegOpenKeyEx(hkInterfaces, pCfgGuidString, 0, KEY_READ|KEY_WRITE, &hkAdapter);
+
+    RegDeleteValue(hkAdapter, TEXT("DisableDynamicUpdate"));
+    RegDeleteValue(hkAdapter, TEXT("EnableAdapterDomainNameRegistration"));
+    RegSetValueEx(hkAdapter, TEXT("RegistrationEnabled"), 0, REG_DWORD, (BYTE *)&dw, sizeof(DWORD));
+    RegSetValueEx(hkAdapter, TEXT("RegisterAdapterName"), 0, REG_DWORD, (BYTE *)&dw, sizeof(DWORD));
+
+    if (hkInterfaces)
+       RegCloseKey(hkInterfaces);
+    if (hkAdapter)
+       RegCloseKey(hkAdapter);
+}
 
 HRESULT
 WMIEnableStatic(
@@ -223,19 +267,21 @@ WMIEnableStatic(
     LPCWSTR mask
     )
 {
-    HRESULT hr = 0;
+    HRESULT hr = 0, hr2 = 0;
+
+    IWbemLocator* pLocator = NULL;
+    IWbemServices* pNamespace = NULL;
+    IWbemClassObject* pClass = NULL;
+    IWbemClassObject* pOutInst = NULL;
+    IWbemClassObject* pInClass = NULL;
+    IWbemClassObject* pInInst = NULL;
 
-    IWbemLocator* pLocator = 0;
-    IWbemServices* pNamespace = 0;
-    IWbemClassObject* pClass = 0;
-    IWbemClassObject* pOutInst = 0;
-    IWbemClassObject* pInClass = 0;
-    IWbemClassObject* pInInst = 0;
+    BSTR NamespacePath = NULL;
+    BSTR ClassPath = NULL;
+    BSTR InstancePath = NULL;
+    BSTR MethodName = NULL; // needs to be BSTR for ExecMethod()
 
-    BSTR NamespacePath = 0;
-    BSTR ClassPath = 0;
-    BSTR InstancePath = 0;
-    BSTR MethodName = 0; // needs to be BSTR for ExecMethod()
+    BOOL comInitialized = FALSE;
 
     VARIANT v_ip_list;
     VariantInit(&v_ip_list);
@@ -246,6 +292,12 @@ WMIEnableStatic(
     VARIANT v_ret_value;
     VariantInit(&v_ret_value);
 
+    VARIANT v_reg_enabled;
+    VariantInit(&v_reg_enabled);
+
+    VARIANT v_netbios;
+    VariantInit(&v_netbios);
+
     int count;
 
     // end of declarations & NULL initialization
@@ -256,13 +308,15 @@ WMIEnableStatic(
     ClassPath = SysAllocString(L"Win32_NetWorkAdapterConfiguration");
     CLEANUP_ON_AND_SET(!ClassPath, hr, E_OUTOFMEMORY);
 
-    MethodName = SysAllocString(L"EnableStatic");
-    CLEANUP_ON_AND_SET(!MethodName, hr, E_OUTOFMEMORY);
-
     // Initialize COM and connect up to CIMOM
 
+    ReportMessage(0, "Intializing COM", NULL, NULL, 0);
     hr = CoInitializeEx(0, COINIT_MULTITHREADED);
-    CLEANUP_ON_FAILURE(hr);
+    if (hr == S_OK || hr == S_FALSE) {
+        comInitialized = TRUE;
+    } else {
+        goto cleanup;
+    }
 
     /* When called from an MSI this will generally fail.  This should only be called once
           per process and not surprisingly MSI beats us to it.  So ignore return value and
@@ -271,12 +325,15 @@ WMIEnableStatic(
                               RPC_C_AUTHN_LEVEL_CONNECT,
                               RPC_C_IMP_LEVEL_IMPERSONATE,
                               NULL, EOAC_NONE, 0);
+
     /* CLEANUP_ON_FAILURE(hr); */
 
+    ReportMessage(0, "Creating Wbem Locator object", NULL, NULL, 0);
     hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
                           IID_IWbemLocator, (LPVOID *) &pLocator);
     CLEANUP_ON_FAILURE(hr);
 
+    ReportMessage(0, "Connecting to WMI", NULL, NULL, 0);
     hr = pLocator->ConnectServer(NamespacePath, NULL, NULL, NULL, 0,
                                  NULL, NULL, &pNamespace);
     CLEANUP_ON_FAILURE(hr);
@@ -304,19 +361,8 @@ WMIEnableStatic(
 
     ReportMessage(0,"Found Adapter Instance",NULL, InstancePath,0);
 
-#if 0
-    // Use the adapter instance index to set MAXLANA in the registry.
-    {
-        DWORD dwIndex;
-        if (swscanf(InstancePath, L"Win32_NetworkAdapterConfiguration.Index=%u", &dwIndex)==1)
-        {
-            DWORD ret = 0; 
-            ReportMessage(1,"Setting MAXLANA",NULL,NULL,dwIndex+1);
-            ret = AdjustMaxLana(dwIndex+1);
-            if (ret) ReportMessage(0,"AdjustMaxLana returned the error code ",NULL,NULL,ret);
-        }
-    }
-#endif
+    MethodName = SysAllocString(L"EnableStatic");
+    CLEANUP_ON_AND_SET(!MethodName, hr, E_OUTOFMEMORY);
 
     // Get the input argument and set the property
     hr = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
@@ -338,14 +384,6 @@ WMIEnableStatic(
     hr = pInInst->Put(L"SubNetMask", 0, &v_mask_list, 0);
     CLEANUP_ON_FAILURE(hr);
 
-    // Sleep for a twenty seconds
-    ReportMessage(0,"Calling ExecMethod in 20 seconds...",NULL,NULL,0);
-    Sleep(10000);
-    ReportMessage(0,"Calling ExecMethod in 10 seconds...",NULL,NULL,0);
-    Sleep(5000);  
-    ReportMessage(0,"Calling ExecMethod in  5 seconds...",NULL,NULL,0);
-    Sleep(2000);
-
 //    printf("Skipping ExecMethod\n");
 //    hr = 0;
 //    goto cleanup;
@@ -353,53 +391,166 @@ WMIEnableStatic(
     // Try up to five times, sleeping 3 seconds between tries
     for (count=0; count<5; count++)
     {
-        if (count>0) ReportMessage(0,"Trying again in 3 seconds...",NULL,NULL,0);
-
-       Sleep(3000);
-  
-        ReportMessage(0,"Calling ExecMethod NOW...          ",NULL,NULL,0);     
-
-        // Call the method
+       if (count>1) {
+           ReportMessage(0,"Trying again in 3 seconds...",NULL,NULL,0);
+           Sleep(3000);
+       } else if (count>0) {
+           ReportMessage(0,"Trying again in 20 seconds...",NULL,NULL,0);
+           Sleep(10000);
+           ReportMessage(0,"Trying again in 10 seconds...",NULL,NULL,0);
+           Sleep(5000);
+           ReportMessage(0,"Trying again in  5 seconds...",NULL,NULL,0);
+           Sleep(2000);
+       }
 
+        ReportMessage(0,"Calling ExecMethod EnableStatic NOW...          ",NULL,NULL,0);
+       // Call the method
         hr = pNamespace->ExecMethod(InstancePath, MethodName, 0, NULL, pInInst,
-                                  &pOutInst, NULL);   
-
+                                  &pOutInst, NULL);
         if (!SUCCEEDED(hr))
         {
-           ReportMessage(0,"ExecMethod failed",NULL,NULL, hr);
+           ReportMessage(0,"ExecMethod EnableStatic failed",NULL,NULL, hr);
            continue;
         }
 
         // Get the EnableStatic method return value
         hr = pOutInst->Get(L"ReturnValue", 0, &v_ret_value, 0, 0);
-
         if (!SUCCEEDED(hr))
         {
           ReportMessage(0,"WARNING: Could not determine return value for EnableStatic ",NULL,NULL, hr);
           continue;
         }
 
-        hr = V_I4(&v_ret_value);                
-
-
-        if(hr != 0)
+        hr = V_I4(&v_ret_value);
+        if (hr != 0)
             ReportMessage(0,"EnableStatic failed ", NULL,NULL,hr);
         else
         {
             ReportMessage(0,"EnableStatic succeeded",NULL,NULL,0);
             break;
         }
+    }
+
+    /* if failure, skip SetDynamicDNSRegistration */
+    if (hr)
+       goto cleanup;
+
+    /* Cleanup and Prepare for SetDynamicDNSRegistration */
+    if (pInClass) {
+       pInClass->Release();
+       pInClass = NULL;
+    }
+    if (pInInst) {
+       pInInst->Release();
+       pInInst = NULL;
+    }
+    SysFreeString(MethodName);
+    VariantClear(&v_ret_value);
+
+    MethodName = SysAllocString(L"SetDynamicDNSRegistration");
+    CLEANUP_ON_AND_SET(!MethodName, hr2, E_OUTOFMEMORY);
+
+    // Get the input argument and set the property
+    hr2 = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
+    CLEANUP_ON_FAILURE(hr2);
+
+    hr2 = pInClass->SpawnInstance(0, &pInInst);
+    CLEANUP_ON_FAILURE(hr2);
+
+    // Set up parameters
+    V_VT(&v_reg_enabled) = VT_BOOL;
+    V_BOOL(&v_reg_enabled) = VARIANT_FALSE;
+
+    hr2 = pInInst->Put(L"FullDNSRegistrationEnabled", 0, &v_reg_enabled, 0);
+    CLEANUP_ON_FAILURE(hr2);
+
+    hr2 = pInInst->Put(L"DomainDNSRegistrationEnabled", 0, &v_reg_enabled, 0);
+    CLEANUP_ON_FAILURE(hr2);
+
+    // Call the method
+    hr2 = pNamespace->ExecMethod(InstancePath, MethodName, 0, NULL, pInInst,
+                                &pOutInst, NULL);
+    if (!SUCCEEDED(hr2))       {
+       ReportMessage(0,"ExecMethod SetDynamicDNSRegistration failed",NULL,NULL, hr2);
+       goto cleanup;
+    }
+
+    // Get the EnableStatic method return value
+    hr2 = pOutInst->Get(L"ReturnValue", 0, &v_ret_value, 0, 0);
+    if (!SUCCEEDED(hr2)) {
+       ReportMessage(0,"WARNING: Could not determine return value for SetDynamicDNSRegistration ",NULL,NULL, hr2);
+    } else {
+       hr2 = V_I4(&v_ret_value);
+       if (hr2 != 0)
+           ReportMessage(0,"SetDynamicDNSRegistration failed ", NULL,NULL,hr2);
+       else
+           ReportMessage(0,"SetDynamicDNSRegistration succeeded",NULL,NULL,0);
+    }
 
+    /* if failure, skip SetTcpipNetbios */
+    if (hr)
+       goto cleanup;
+
+    /* Cleanup and Prepare for SetTcpipNetbios */
+    if (pInClass) {
+       pInClass->Release();
+       pInClass = NULL;
+    }
+    if (pInInst) {
+       pInInst->Release();
+       pInInst = NULL;
     }
+    SysFreeString(MethodName);
+    VariantClear(&v_ret_value);
+
+    ReportMessage(0,"Preparing for SetTcpipNetbios",NULL,NULL,0);
+
+    MethodName = SysAllocString(L"SetTcpipNetbios");
+    CLEANUP_ON_AND_SET(!MethodName, hr2, E_OUTOFMEMORY);
+
+    // Get the input argument and set the property
+    hr2 = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
+    CLEANUP_ON_FAILURE(hr2);
 
+    hr2 = pInClass->SpawnInstance(0, &pInInst);
+    CLEANUP_ON_FAILURE(hr2);
 
+    // Set up parameters
+    V_VT(&v_netbios) = VT_BSTR;
+    V_BSTR(&v_netbios) = SysAllocString(L"1"); /* Use Netbios */
+
+    hr2 = pInInst->Put(L"TcpipNetbiosOptions", 0, &v_netbios, 0);
+    CLEANUP_ON_FAILURE(hr2);
+
+    // Call the method
+    hr2 = pNamespace->ExecMethod(InstancePath, MethodName, 0, NULL, pInInst,
+                                &pOutInst, NULL);
+    if (!SUCCEEDED(hr2)) {
+       ReportMessage(0,"ExecMethod SetTcpipNetbios failed",NULL,NULL, hr2);
+       goto cleanup;
+    }
+
+    // Get the EnableStatic method return value
+    hr2 = pOutInst->Get(L"ReturnValue", 0, &v_ret_value, 0, 0);
+    if (!SUCCEEDED(hr2)) {
+       ReportMessage(0,"WARNING: Could not determine return value for SetTcpipNetbios ",NULL,NULL, hr2);
+    } else {
+       hr2 = V_I4(&v_ret_value);
+       if (hr2 != 0)
+           ReportMessage(0,"SetTcpipNetbios failed ", NULL,NULL,hr2);
+       else
+           ReportMessage(0,"SetTcpipNetbios succeeded",NULL,NULL,0);
+    }
 
  cleanup:
     // Free up resources
     VariantClear(&v_ret_value);
     VariantClear(&v_ip_list);
     VariantClear(&v_mask_list);
+    VariantClear(&v_reg_enabled);
+    VariantClear(&v_netbios);
 
+    // SysFreeString is NULL safe
     SysFreeString(NamespacePath);
     SysFreeString(ClassPath);
     SysFreeString(InstancePath);
@@ -412,16 +563,19 @@ WMIEnableStatic(
     if (pLocator) pLocator->Release();
     if (pNamespace) pNamespace->Release();
 
-    CoUninitialize();
+    if (comInitialized)
+        CoUninitialize();
+
     return hr;
 }
 
 
 /**********************************************************
-* LoopbackBindings :  unbind all other 
-*       protocols except TCP/IP, netbios, netbt. 
+* LoopbackBindings :  unbind all other
+*       protocols except TCP/IP, netbios, netbt.
 */
-extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
+extern "C" HRESULT
+LoopbackBindings (LPCWSTR loopback_guid)
 {
     HRESULT                    hr = 0;
     INetCfg                    *pCfg = NULL;
@@ -434,63 +588,61 @@ extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
     LPWSTR                     swName = NULL;
     GUID            g;
     wchar_t         device_guid[100];
-    DWORD                      lenDeviceId;    
-    
+
     ReportMessage(0,"Running LoopbackBindings()...",NULL,NULL,0);
-    
-    hr = CoInitializeEx( NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED ); 
+
+    hr = CoInitializeEx( NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED );
     CLEANUP_ON_FAILURE(hr);
-    
+
     hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void**)&pCfg );
     CLEANUP_ON_FAILURE(hr);
-    
+
     hr = pCfg->QueryInterface( IID_INetCfgLock, (void**)&pLock );
     CLEANUP_ON_FAILURE(hr);
-    
+
     hr = pLock->AcquireWriteLock( 1000, L"AFS Configuration", NULL );
     CLEANUP_ON_FAILURE(hr);
     bLockGranted = TRUE;
-    
+
     hr = pCfg->Initialize( NULL );
     CLEANUP_ON_FAILURE(hr);
     bInitialized = TRUE;
-    
+
     hr = pCfg->EnumComponents( &GUID_DEVCLASS_NET, &pEnumComponent );
     CLEANUP_ON_FAILURE(hr);
-    
-    
+
     while( pEnumComponent->Next( 1, &pAdapter, NULL ) == S_OK )
     {
         pAdapter->GetDisplayName( &swName );
         pAdapter->GetInstanceGuid( &g );
         StringFromGUID2(g, device_guid, 99);
-        
-        if(!wcscmp( device_guid, loopback_guid )) // found loopback adapter
+
+        if (!wcscmp( device_guid, loopback_guid )) // found loopback adapter
         {
             INetCfgComponentBindings *pBindings;
             INetCfgBindingPath *pPath;
             IEnumNetCfgBindingPath *pEnumPaths;
             INetCfgComponent *upper;
-            
+
             ReportMessage(0,"LoopbackBindings found", NULL, device_guid,0 );
-            
+
             hr = pAdapter->QueryInterface( IID_INetCfgComponentBindings, (void**) &pBindings);
-            if(hr==S_OK)
+            if (hr==S_OK)
             {
                 hr = pBindings->EnumBindingPaths( EBP_ABOVE, &pEnumPaths );
-                if(hr==S_OK)
+                if (hr==S_OK)
                 {
                     while(pEnumPaths->Next( 1, &pPath, NULL ) == S_OK)
                     {
                         pPath->GetOwner( &upper );
-                        
+
                         LPWSTR swId = NULL, swName = NULL;
-                        
+
                         upper->GetDisplayName( &swName );
                         upper->GetId( &swId );
-                        
+
                         ReportMessage(1,"Looking at ",NULL, swName, 0);
-                                                                        
+
                         {
                             ReportMessage(1,"  Moving to the end of binding order...",NULL,NULL,0);
                             INetCfgComponentBindings *pBindings2;
@@ -498,17 +650,18 @@ extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
                             if (hr==S_OK)
                             {
                                 ReportMessage(1,"...",0,0,0);
-                                hr = pBindings2->MoveAfter(pPath, NULL);                                
-                                pBindings2->Release();                               
+                                hr = pBindings2->MoveAfter(pPath, NULL);
+                                pBindings2->Release();
                                 bConfigChanged=TRUE;
                             }
-                            if (hr==S_OK) ReportMessage(1,"success",0,0,0); else ReportMessage(0,"Binding change failed",0,0,hr);                                                        
-                                                                                                            
-                        }                        
-                        
-                        if ( !_wcsicmp(swId, L"ms_netbios")  || 
-                            !_wcsicmp(swId, L"ms_tcpip")    ||
-                            !_wcsicmp(swId, L"ms_netbt")      )
+                            if (hr==S_OK) ReportMessage(1,"success",0,0,0); else ReportMessage(0,"Binding change failed",0,0,hr);
+
+                        }
+
+                        if ( !_wcsicmp(swId, L"ms_netbios")  ||
+                             !_wcsicmp(swId, L"ms_tcpip")    ||
+                             !_wcsicmp(swId, L"ms_netbt")    ||
+                             !_wcsicmp(swId, L"ms_msclient"))
                         {
                             if (pPath->IsEnabled()!=S_OK)
                             {
@@ -517,10 +670,9 @@ extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
                                 if (hr==S_OK) ReportMessage(1,"success",0,0,0); else ReportMessage(0,"Proto failed",0,0,hr);
                                 bConfigChanged=TRUE;
                             }
-                            
-                            
+
                         }
-                        else //if (!_wcsicmp(swId, L"ms_server") || (!_wcsicmp(swId, L"ms_msclient")) 
+                        else //if (!_wcsicmp(swId, L"ms_server") || (!_wcsicmp(swId, L"ms_msclient"))
                         {
                             if (pPath->IsEnabled()==S_OK)
                             {
@@ -530,10 +682,10 @@ extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
                                 bConfigChanged=TRUE;
                             }
                         }
-                        
+
                         CoTaskMemFree( swName );
                         CoTaskMemFree( swId );
-                        
+
                         pPath->Release();
                     }
                     pEnumPaths->Release();
@@ -541,51 +693,49 @@ extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
                 pBindings->Release();
             } // hr==S_OK for QueryInterface IID_INetCfgComponentBindings
         }
-        
+
         CoTaskMemFree( swName );
-        
+
         pAdapter->Release();
     }
-    
-    pEnumComponent->Release();    
-    
+
+    pEnumComponent->Release();
+
     hr = 0;
-    
+
 cleanup:
-    
-    if(bConfigChanged) pCfg->Apply();
-    
-    if(pAdapter) pAdapter->Release();
-    
-    if(bInitialized) pCfg->Uninitialize();
-    if(bLockGranted) pLock->ReleaseWriteLock();
-    
-    if(pLock) pLock->Release();
-    if(pCfg) pCfg->Release();
-    
+
+    if (bConfigChanged) pCfg->Apply();
+
+    if (pAdapter) pAdapter->Release();
+
+    if (bInitialized) pCfg->Uninitialize();
+    if (bLockGranted) pLock->ReleaseWriteLock();
+
+    if (pLock) pLock->Release();
+    if (pCfg) pCfg->Release();
+
     if (hr) ReportMessage(0,"LoopbackBindings() is returning ",0,0,hr);
     return hr;
 }
 
-        
-        extern "C"
-            DWORD
-SetIpAddress(
-    LPCWSTR guid,
-    LPCWSTR ip,
-    LPCWSTR mask
-    )
+
+extern "C"
+DWORD SetIpAddress(LPCWSTR guid, LPCWSTR ip, LPCWSTR mask)
 {
     ReportMessage(0,"Running SetIpAddress()...",0,0,0);
     HRESULT hr = 0;
 
     hr = WMIEnableStatic(FindNetworkAdapterConfigurationInstanceByGUID,
                         (PVOID)guid, ip, mask);
+    if (hr == 0)
+       FixupXPDNSRegistrations(guid);
     return hr;
 }
 
 /* Set MAXLANA in the registry to the specified value, unless the existing registry value is larger */
-DWORD AdjustMaxLana(DWORD dwMaxLana)
+static DWORD
+AdjustMaxLana(DWORD dwMaxLana)
 {
 
     LONG ret = 0;
@@ -594,15 +744,15 @@ DWORD AdjustMaxLana(DWORD dwMaxLana)
 
     ReportMessage(0,"Making sure MaxLana is large enough",0,0, dwMaxLana);
 
-    ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\NetBIOS\\Parameters"), 
+    ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\NetBIOS\\Parameters"),
         0, KEY_ALL_ACCESS , &hNetBiosParamKey);
     if (ret) return ret;
 
 
-    
+
     dwSize = 4;
     ret = RegQueryValueEx(hNetBiosParamKey, _T("MaxLana"), 0, &dwType, (LPBYTE) &dwExistingMaxLana, &dwSize);
-    if ((ret) && (ret != ERROR_MORE_DATA) && (ret != ERROR_FILE_NOT_FOUND)) 
+    if ((ret) && (ret != ERROR_MORE_DATA) && (ret != ERROR_FILE_NOT_FOUND))
     {
         RegCloseKey(hNetBiosParamKey);
         return ret;
@@ -612,15 +762,15 @@ DWORD AdjustMaxLana(DWORD dwMaxLana)
 
     ReportMessage (1,"MaxLana is currently",0,0, dwExistingMaxLana);
 
-    if (dwExistingMaxLana < dwMaxLana) 
+    if (dwExistingMaxLana < dwMaxLana)
     {
         ReportMessage (1,"Changing MaxLana", 0,0,dwMaxLana);
         ret = RegSetValueEx(hNetBiosParamKey, _T("MaxLana"), 0, REG_DWORD, (const BYTE*)&dwMaxLana, 4);
-        if (ret) 
+        if (ret)
         {
             RegCloseKey(hNetBiosParamKey);
             return ret;
-        }       
+        }
 
     }
 
@@ -630,163 +780,167 @@ DWORD AdjustMaxLana(DWORD dwMaxLana)
 
 }
 
-extern "C" 
+extern "C"
 BOOL UpdateHostsFile( LPCWSTR swName, LPCWSTR swIp, LPCSTR szFilename, BOOL bPre )
 {
     char szIp[2048], szName[2048];
     char etcPath[MAX_PATH];
-       char tempPath[MAX_PATH];
-       char buffer[2048], temp[2048];
-       char *str;
-       HRESULT rv;
-       DWORD fa,len;
-       FILE *hFile, *hTemp;
-       
+    char tempPath[MAX_PATH];
+    char buffer[2048], temp[2048];
+    char *str;
+    HRESULT rv;
+    DWORD fa,len;
+    FILE *hFile, *hTemp;
+    size_t nameLen;
+
     _snprintf(szIp, 2047, "%S", swIp);
     _snprintf(szName, 2047, "%S", swName);
     strupr(szName);
+    nameLen = strlen(szName);
     ReportMessage(0,"Starting UpdateHostsFile() on file",szFilename,0,0);
 
-       rv = SHGetFolderPathA( NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT , etcPath );
-       if(rv != S_OK) return FALSE;
+    rv = SHGetFolderPathA( NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, etcPath );
+    if (rv != S_OK)
+        return FALSE;
 
-       strcat( etcPath, ETCDIR );
+    strcat( etcPath, ETCDIR );
 
-       fa = GetFileAttributesA( etcPath );
+    fa = GetFileAttributesA( etcPath );
 
-       if(fa == INVALID_FILE_ATTRIBUTES)
-       {
-               // the directory doesn't exist
-               // it should be there. non-existence implies more things are wrong
-               ReportMessage(0, "Path does not exist ", etcPath,0,0 );
-               return FALSE;
-       }
+    if (fa == INVALID_FILE_ATTRIBUTES)
+    {
+        // the directory doesn't exist
+        // it should be there. non-existence implies more things are wrong
+        ReportMessage(0, "Path does not exist ", etcPath,0,0 );
+        return FALSE;
+    }
+
+    strcpy( tempPath, etcPath );
+    strcat( etcPath, "\\" );
+    strcat( etcPath, szFilename );
+
+    fa = GetFileAttributesA( etcPath );
+
+    if (fa == INVALID_FILE_ATTRIBUTES)
+    {
+        ReportMessage(0, "File not found. Creating...", szFilename,0,0);
 
-       strcpy( tempPath, etcPath );
-       strcat( etcPath, "\\" );
-       strcat( etcPath, szFilename );
+        hFile = fopen( etcPath, "w" );
+        if (!hFile)
+        {
+            ReportMessage(0,"FAILED : can't create file",etcPath,0,errno);
+            return FALSE;
+        }
 
-       fa = GetFileAttributesA( etcPath );
+        fprintf(hFile, "%s\t%s%s\n", szIp, szName, (bPre)?"\t#PRE":"");
 
-       if(fa == INVALID_FILE_ATTRIBUTES)
-       {
-               ReportMessage(0, "File not found. Creating...", szFilename,0,0);
+        fclose( hFile );
 
-               hFile = fopen( etcPath, "w" );
-               if(!hFile)
-               {
-                       ReportMessage(0,"FAILED : can't create file",etcPath,0,errno);
-                       return FALSE;
-               }
+        ReportMessage(1,"done",0,0,0);
+    }
+    else // the file exists. parse and update
+    {
 
-               fprintf(hFile, "%s\t%s%s\n", szIp, szName, (bPre)?"\t#PRE":"");
+        ReportMessage(1, "Updating file ...",szFilename,0,0 );
 
-               fclose( hFile );
+        hFile = fopen( etcPath, "r");
+        if (!hFile)
+        {
+            ReportMessage(0,"FAILED : can't open file",etcPath,0,errno);
+            return FALSE;
+        }
 
-               ReportMessage(1,"done",0,0,0);
-       }
-       else // the file exists. parse and update
-       {
-
-               ReportMessage(1, "Updating file ...",szFilename,0,0 );
-
-               hFile = fopen( etcPath, "r");
-               if(!hFile)
-               {
-                       ReportMessage(0,"FAILED : can't open file",etcPath,0,errno);
-                       return FALSE;
-               }
-
-               strcat( tempPath, szFilename );
-               strcat( tempPath, ".tmp" );
-               hTemp = fopen( tempPath, "w");
-               if(!hTemp)
-               {
-                       ReportMessage(0,"FAILED : can't create temp file",tempPath,0,errno);
-                       fclose(hFile);
-                       return FALSE;
-               }
-
-               while(fgets( buffer, 2046, hFile))
-               {
-                       strcpy( temp, buffer );
-                       strupr( temp );
-
-            if ((strlen(temp)<1) || (*(temp+strlen(temp)-1)!='\n')) strcat(temp, "\n");
-
-                       if(!(str = strstr(temp, szName)))
-                       {
-                               fputs( buffer, hTemp );
-                       }
-                       else
-                       {
-                               // check for FOOBAFS or AFSY
-                               //if(str <= temp || (*(str-1) != '-' && !isspace(*(str+strlen(szName)))))
-                               if ( (str == temp) || (!*(str+strlen(szName))) || (!isspace(*(str-1))) || (!isspace(*(str+strlen(szName)))) )
-                    fputs( buffer, hTemp );
-                       }
-               }
-
-
-               len = 2048;
-               GetComputerNameA( buffer, &len );
-               buffer[11] = 0;
-               fprintf( hTemp, "%s\t%s%s\n", szIp, szName, (bPre)?"\t#PRE":"");
-
-               fclose( hTemp );
-               fclose( hFile );
-
-               strcpy(buffer, etcPath);
-               strcat(buffer, ".old");
-
-        errno = 0;
-               
-        if ((unlink( buffer ) != 0) && (errno == EACCES))
+        strcat( tempPath, szFilename );
+        strcat( tempPath, ".tmp" );
+        hTemp = fopen( tempPath, "w");
+        if (!hTemp)
         {
-            ReportMessage(0,"FAILED : Can't delete file",buffer,0,errno);            
+            ReportMessage(0,"FAILED : can't create temp file",tempPath,0,errno);
+            fclose(hFile);
             return FALSE;
-            
         }
-        
-        if ((errno) && (errno != ENOENT)) ReportMessage(0,"WEIRD : errno after unlink ",0,0,errno);
 
-               if(rename( etcPath, buffer) != 0)
-               {
-                       ReportMessage(0,"FAILED : Can't rename old file",etcPath,0,errno);
-                       return FALSE;
-               }
+        while(fgets( buffer, 2046, hFile))
+        {
+            size_t len;
 
-               if(rename( tempPath, etcPath ) != 0)
-               {
-                       ReportMessage(0,"FAILED : Can't rename new file",tempPath,0,errno);
-                       return FALSE;
-               }
+            strcpy( temp, buffer );
+            strupr( temp );
+            len = strlen(temp);
 
-       }
+            if ((len < 1) || (temp[len-1] != '\n'))
+                strcat(temp, "\n");
 
-       return TRUE;
-}
+            if (!(str = strstr(temp, szName)))
+            {
+                fputs( temp, hTemp );
+            }
+            else
+            {
+                // check for FOOBAFS or AFSY
+                if ( (str == temp) || (!str[nameLen]) || (!isspace(*(str-1))) || (!isspace(str[nameLen])) )
+                    fputs( temp, hTemp );
+            }
+        }
+
+        len = 2048;
+        GetComputerNameA( buffer, &len );
+        buffer[11] = 0;
+        fprintf( hTemp, "%s\t%s%s\n", szIp, szName, (bPre)?"\t#PRE":"");
+
+        fclose( hTemp );
+        fclose( hFile );
+
+        strcpy(buffer, etcPath);
+        strcat(buffer, ".old");
+
+        if (!DeleteFileA(buffer)) {
+            DWORD status;
+            int i;
+            char * eos;
+
+            status = GetLastError();
+            if (status == ERROR_ACCESS_DENIED) {
+                /* try changing the file attribtues. */
+                if (SetFileAttributesA(buffer, FILE_ATTRIBUTE_NORMAL) &&
+                    DeleteFileA(buffer)) {
+                    status = 0;
+                    ReportMessage(0,"Changed attributes and deleted back host file", buffer, 0, 0);
+                }
+            }
+            if (status && status != ERROR_FILE_NOT_FOUND) {
+                /* we can't delete the file.  Try to come up with
+                   a different name that's not already taken. */
+                srand(GetTickCount());
+                eos = buffer + strlen(buffer);
+                for(i=0; i < 50; i++) {
+                    itoa(rand(), eos, 16);
+                    if (GetFileAttributesA(buffer) == INVALID_FILE_ATTRIBUTES &&
+                        GetLastError() == ERROR_FILE_NOT_FOUND)
+                        break;
+                }
+                /* At this point if we don't have a unique name, we just let the rename
+                   fail.  Too bad. */
+            }
+        }
+
+        if (!MoveFileA( etcPath, buffer )) {
+            ReportMessage(0,"FAILED: Can't rename old file", etcPath, 0, GetLastError());
+            return FALSE;
+        }
+
+        if (!MoveFileA( tempPath, etcPath ) != 0)
+        {
+            ReportMessage(0,"FAILED : Can't rename new file", tempPath, 0, GetLastError());
+            return FALSE;
+        }
 
-#ifdef TEST
-#if 0
-int
-wmain(
-    int argc,
-    wchar_t* argv[]
-    )
-{
-    if (argc < 3)
-    {
-        printf("usage: %S ip mask\n"
-               "  example: %S 10.0.0.1 255.0.0.0", argv[0], argv[0]);
-        return 0;
     }
 
-    return WMIEnableStatic(FindNetworkAdapterConfigurationInstanceByGUID,
-                           L"{B4981E32-551C-4164-96B6-B8874BD2E555}",
-                           argv[1], argv[2]);
+    return TRUE;
 }
-#else
+
+#ifdef TEST
 int
 wmain(
     int argc,
@@ -805,5 +959,4 @@ wmain(
                            argv[1], argv[2], argv[3]);
 }
 #endif
-#endif