3 Copyright 2004 by the Massachusetts Institute of Technology
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of the Massachusetts
12 Institute of Technology (M.I.T.) not be used in advertising or publicity
13 pertaining to distribution of the software without specific, written
16 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 //**************************************************************************
30 // Call EnableStatic method of Win32_NetworkAdapterConfiguration
31 // for some network adapter GUID.
35 // The EnableStatic method is notsupported on Win9x platforms.
37 //**************************************************************************
47 /* These two are from the Windows DDK */
52 //#include <objbase.h>
55 //inline void printf(char*, ...) {}
60 #include "loopbackutils.h"
62 #define CLEANUP_ON_FAILURE(hr) \
63 do { if (!SUCCEEDED(hr)) {goto cleanup;} } while (0)
65 #define CLEANUP_ON_AND_SET(check, var, value) \
66 do { if (check) { (var) = (value); goto cleanup; } } while (0)
68 #define ETCDIR "\\drivers\\etc"
73 DWORD AdjustMaxLana(DWORD dwMaxLana);
77 (*FindNetworkAdapterConfigurationInstance_t)(
79 IN IWbemServices *pSvc,
84 FindNetworkAdapterConfigurationInstanceByGUID(
86 IN IWbemServices *pSvc,
94 IEnumWbemClassObject* pEnum = 0;
95 IWbemClassObject* pObj = 0;
98 LPCWSTR adapter_guid = (LPCWSTR)pContext;
101 if (!pPath || !adapter_guid || *pPath)
106 // Query for all network adapters
107 Language = SysAllocString(L"WQL");
108 Query = SysAllocString(L"select * from Win32_NetworkAdapterConfiguration");
111 hr = pSvc->ExecQuery(Language,
113 WBEM_FLAG_FORWARD_ONLY, // Flags
118 ReportMessage(0,"ExecQuery() error",NULL,NULL, hr);
122 // Retrieve the objects in the result set.
127 hr = pEnum->Next(0, // Time out
131 CLEANUP_ON_FAILURE(hr);
137 hr = pObj->Get(L"SettingID", // property name
139 &Value, // output to this variant
142 CLEANUP_ON_FAILURE(hr);
144 bFound = !wcscmp(adapter_guid, V_BSTR(&Value));
148 ReportMessage(1,"Found adapter", NULL,V_BSTR(&Value),0);
149 VariantClear(&Value);
150 hr = pObj->Get(L"__RELPATH", // property name
152 &Value, // output to this variant
155 CLEANUP_ON_FAILURE(hr);
157 *pPath = SysAllocString(V_BSTR(&Value));
161 VariantClear(&Value);
165 pObj->Release(); // Release objects not owned.
172 SysFreeString(Query);
173 SysFreeString(Language);
174 VariantClear(&Value);
180 return *pPath ? 0 : ( SUCCEEDED(hr) ? WBEM_E_NOT_FOUND : hr );
184 SetupStringAsSafeArray(LPCWSTR s, VARIANT* v)
188 SAFEARRAY* array = 0;
191 if (V_VT(v) != VT_EMPTY)
194 b = SysAllocString(s);
195 CLEANUP_ON_AND_SET(!b, hr, E_OUTOFMEMORY);
197 array = SafeArrayCreateVector(VT_BSTR, 0, 1);
198 CLEANUP_ON_AND_SET(!array, hr, E_OUTOFMEMORY);
200 hr = SafeArrayPutElement(array, index, b);
201 CLEANUP_ON_FAILURE(hr);
203 V_VT(v) = VT_ARRAY|VT_BSTR;
212 SafeArrayDestroy(array);
220 FindNetworkAdapterConfigurationInstance_t pFindInstance,
228 IWbemLocator* pLocator = 0;
229 IWbemServices* pNamespace = 0;
230 IWbemClassObject* pClass = 0;
231 IWbemClassObject* pOutInst = 0;
232 IWbemClassObject* pInClass = 0;
233 IWbemClassObject* pInInst = 0;
235 BSTR NamespacePath = 0;
237 BSTR InstancePath = 0;
238 BSTR MethodName = 0; // needs to be BSTR for ExecMethod()
241 VariantInit(&v_ip_list);
244 VariantInit(&v_mask_list);
247 VariantInit(&v_ret_value);
251 // end of declarations & NULL initialization
253 NamespacePath = SysAllocString(L"root\\cimv2");
254 CLEANUP_ON_AND_SET(!NamespacePath, hr, E_OUTOFMEMORY);
256 ClassPath = SysAllocString(L"Win32_NetWorkAdapterConfiguration");
257 CLEANUP_ON_AND_SET(!ClassPath, hr, E_OUTOFMEMORY);
259 MethodName = SysAllocString(L"EnableStatic");
260 CLEANUP_ON_AND_SET(!MethodName, hr, E_OUTOFMEMORY);
262 // Initialize COM and connect up to CIMOM
264 hr = CoInitializeEx(0, COINIT_MULTITHREADED);
265 CLEANUP_ON_FAILURE(hr);
267 /* When called from an MSI this will generally fail. This should only be called once
268 per process and not surprisingly MSI beats us to it. So ignore return value and
269 hope for the best. */
270 hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
271 RPC_C_AUTHN_LEVEL_CONNECT,
272 RPC_C_IMP_LEVEL_IMPERSONATE,
274 /* CLEANUP_ON_FAILURE(hr); */
276 hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
277 IID_IWbemLocator, (LPVOID *) &pLocator);
278 CLEANUP_ON_FAILURE(hr);
280 hr = pLocator->ConnectServer(NamespacePath, NULL, NULL, NULL, 0,
281 NULL, NULL, &pNamespace);
282 CLEANUP_ON_FAILURE(hr);
284 ReportMessage(0,"Connected to WMI",NULL,NULL,0);
286 // Set the proxy so that impersonation of the client occurs.
287 hr = CoSetProxyBlanket(pNamespace,
291 RPC_C_AUTHN_LEVEL_CALL,
292 RPC_C_IMP_LEVEL_IMPERSONATE,
295 CLEANUP_ON_FAILURE(hr);
297 // Get the class object
298 hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);
299 CLEANUP_ON_FAILURE(hr);
302 hr = pFindInstance(pContext, pNamespace, &InstancePath);
303 CLEANUP_ON_FAILURE(hr);
305 ReportMessage(0,"Found Adapter Instance",NULL, InstancePath,0);
308 // Use the adapter instance index to set MAXLANA in the registry.
311 if (swscanf(InstancePath, L"Win32_NetworkAdapterConfiguration.Index=%u", &dwIndex)==1)
314 ReportMessage(1,"Setting MAXLANA",NULL,NULL,dwIndex+1);
315 ret = AdjustMaxLana(dwIndex+1);
316 if (ret) ReportMessage(0,"AdjustMaxLana returned the error code ",NULL,NULL,ret);
321 // Get the input argument and set the property
322 hr = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
323 CLEANUP_ON_FAILURE(hr);
325 hr = pInClass->SpawnInstance(0, &pInInst);
326 CLEANUP_ON_FAILURE(hr);
329 hr = SetupStringAsSafeArray(ip, &v_ip_list);
330 CLEANUP_ON_FAILURE(hr);
332 hr = pInInst->Put(L"IPAddress", 0, &v_ip_list, 0);
333 CLEANUP_ON_FAILURE(hr);
335 hr = SetupStringAsSafeArray(mask, &v_mask_list);
336 CLEANUP_ON_FAILURE(hr);
338 hr = pInInst->Put(L"SubNetMask", 0, &v_mask_list, 0);
339 CLEANUP_ON_FAILURE(hr);
341 // Sleep for a twenty seconds
342 ReportMessage(0,"Calling ExecMethod in 20 seconds...",NULL,NULL,0);
344 ReportMessage(0,"Calling ExecMethod in 10 seconds...",NULL,NULL,0);
346 ReportMessage(0,"Calling ExecMethod in 5 seconds...",NULL,NULL,0);
349 // printf("Skipping ExecMethod\n");
353 // Try up to five times, sleeping 3 seconds between tries
354 for (count=0; count<5; count++)
356 if (count>0) ReportMessage(0,"Trying again in 3 seconds...",NULL,NULL,0);
360 ReportMessage(0,"Calling ExecMethod NOW... ",NULL,NULL,0);
364 hr = pNamespace->ExecMethod(InstancePath, MethodName, 0, NULL, pInInst,
369 ReportMessage(0,"ExecMethod failed",NULL,NULL, hr);
373 // Get the EnableStatic method return value
374 hr = pOutInst->Get(L"ReturnValue", 0, &v_ret_value, 0, 0);
378 ReportMessage(0,"WARNING: Could not determine return value for EnableStatic ",NULL,NULL, hr);
382 hr = V_I4(&v_ret_value);
386 ReportMessage(0,"EnableStatic failed ", NULL,NULL,hr);
389 ReportMessage(0,"EnableStatic succeeded",NULL,NULL,0);
399 VariantClear(&v_ret_value);
400 VariantClear(&v_ip_list);
401 VariantClear(&v_mask_list);
403 SysFreeString(NamespacePath);
404 SysFreeString(ClassPath);
405 SysFreeString(InstancePath);
406 SysFreeString(MethodName);
408 if (pClass) pClass->Release();
409 if (pInInst) pInInst->Release();
410 if (pInClass) pInClass->Release();
411 if (pOutInst) pOutInst->Release();
412 if (pLocator) pLocator->Release();
413 if (pNamespace) pNamespace->Release();
420 /**********************************************************
421 * LoopbackBindings : unbind all other
422 * protocols except TCP/IP, netbios, netbt.
424 extern "C" HRESULT LoopbackBindings (LPCWSTR loopback_guid)
427 INetCfg *pCfg = NULL;
428 INetCfgLock *pLock = NULL;
429 INetCfgComponent *pAdapter = NULL;
430 IEnumNetCfgComponent *pEnumComponent = NULL;
431 BOOL bLockGranted = FALSE;
432 BOOL bInitialized = FALSE;
433 BOOL bConfigChanged = FALSE;
434 LPWSTR swName = NULL;
436 wchar_t device_guid[100];
439 ReportMessage(0,"Running LoopbackBindings()...",NULL,NULL,0);
441 hr = CoInitializeEx( NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED );
442 CLEANUP_ON_FAILURE(hr);
444 hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void**)&pCfg );
445 CLEANUP_ON_FAILURE(hr);
447 hr = pCfg->QueryInterface( IID_INetCfgLock, (void**)&pLock );
448 CLEANUP_ON_FAILURE(hr);
450 hr = pLock->AcquireWriteLock( 1000, L"AFS Configuration", NULL );
451 CLEANUP_ON_FAILURE(hr);
454 hr = pCfg->Initialize( NULL );
455 CLEANUP_ON_FAILURE(hr);
458 hr = pCfg->EnumComponents( &GUID_DEVCLASS_NET, &pEnumComponent );
459 CLEANUP_ON_FAILURE(hr);
462 while( pEnumComponent->Next( 1, &pAdapter, NULL ) == S_OK )
464 pAdapter->GetDisplayName( &swName );
465 pAdapter->GetInstanceGuid( &g );
466 StringFromGUID2(g, device_guid, 99);
468 if(!wcscmp( device_guid, loopback_guid )) // found loopback adapter
470 INetCfgComponentBindings *pBindings;
471 INetCfgBindingPath *pPath;
472 IEnumNetCfgBindingPath *pEnumPaths;
473 INetCfgComponent *upper;
475 ReportMessage(0,"LoopbackBindings found", NULL, device_guid,0 );
477 hr = pAdapter->QueryInterface( IID_INetCfgComponentBindings, (void**) &pBindings);
480 hr = pBindings->EnumBindingPaths( EBP_ABOVE, &pEnumPaths );
483 while(pEnumPaths->Next( 1, &pPath, NULL ) == S_OK)
485 pPath->GetOwner( &upper );
487 LPWSTR swId = NULL, swName = NULL;
489 upper->GetDisplayName( &swName );
490 upper->GetId( &swId );
492 ReportMessage(1,"Looking at ",NULL, swName, 0);
495 ReportMessage(1," Moving to the end of binding order...",NULL,NULL,0);
496 INetCfgComponentBindings *pBindings2;
497 hr = upper->QueryInterface( IID_INetCfgComponentBindings, (void**) &pBindings2);
500 ReportMessage(1,"...",0,0,0);
501 hr = pBindings2->MoveAfter(pPath, NULL);
502 pBindings2->Release();
505 if (hr==S_OK) ReportMessage(1,"success",0,0,0); else ReportMessage(0,"Binding change failed",0,0,hr);
509 if ( !_wcsicmp(swId, L"ms_netbios") ||
510 !_wcsicmp(swId, L"ms_tcpip") ||
511 !_wcsicmp(swId, L"ms_netbt") )
513 if (pPath->IsEnabled()!=S_OK)
515 ReportMessage(1," Enabling ",0,swName,0);
516 hr = pPath->Enable(TRUE);
517 if (hr==S_OK) ReportMessage(1,"success",0,0,0); else ReportMessage(0,"Proto failed",0,0,hr);
523 else //if (!_wcsicmp(swId, L"ms_server") || (!_wcsicmp(swId, L"ms_msclient"))
525 if (pPath->IsEnabled()==S_OK)
527 ReportMessage(1," Disabling ",0,swName,0);
528 hr = pPath->Enable(FALSE);
529 if (hr==S_OK) ReportMessage(1,"success",0,0,0); else ReportMessage(0,"Proto failed",0,0,hr);
534 CoTaskMemFree( swName );
535 CoTaskMemFree( swId );
539 pEnumPaths->Release();
541 pBindings->Release();
542 } // hr==S_OK for QueryInterface IID_INetCfgComponentBindings
545 CoTaskMemFree( swName );
550 pEnumComponent->Release();
556 if(bConfigChanged) pCfg->Apply();
558 if(pAdapter) pAdapter->Release();
560 if(bInitialized) pCfg->Uninitialize();
561 if(bLockGranted) pLock->ReleaseWriteLock();
563 if(pLock) pLock->Release();
564 if(pCfg) pCfg->Release();
566 if (hr) ReportMessage(0,"LoopbackBindings() is returning ",0,0,hr);
579 ReportMessage(0,"Running SetIpAddress()...",0,0,0);
582 hr = WMIEnableStatic(FindNetworkAdapterConfigurationInstanceByGUID,
583 (PVOID)guid, ip, mask);
587 /* Set MAXLANA in the registry to the specified value, unless the existing registry value is larger */
588 DWORD AdjustMaxLana(DWORD dwMaxLana)
592 HKEY hNetBiosParamKey = NULL;
593 DWORD dwType, dwExistingMaxLana, dwSize;
595 ReportMessage(0,"Making sure MaxLana is large enough",0,0, dwMaxLana);
597 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\NetBIOS\\Parameters"),
598 0, KEY_ALL_ACCESS , &hNetBiosParamKey);
604 ret = RegQueryValueEx(hNetBiosParamKey, _T("MaxLana"), 0, &dwType, (LPBYTE) &dwExistingMaxLana, &dwSize);
605 if ((ret) && (ret != ERROR_MORE_DATA) && (ret != ERROR_FILE_NOT_FOUND))
607 RegCloseKey(hNetBiosParamKey);
611 if ((dwType != REG_DWORD) || (ret)) dwExistingMaxLana = 0;
613 ReportMessage (1,"MaxLana is currently",0,0, dwExistingMaxLana);
615 if (dwExistingMaxLana < dwMaxLana)
617 ReportMessage (1,"Changing MaxLana", 0,0,dwMaxLana);
618 ret = RegSetValueEx(hNetBiosParamKey, _T("MaxLana"), 0, REG_DWORD, (const BYTE*)&dwMaxLana, 4);
621 RegCloseKey(hNetBiosParamKey);
627 RegCloseKey(hNetBiosParamKey);
634 BOOL UpdateHostsFile( LPCWSTR swName, LPCWSTR swIp, LPCSTR szFilename, BOOL bPre )
636 char szIp[2048], szName[2048];
637 char etcPath[MAX_PATH];
638 char tempPath[MAX_PATH];
639 char buffer[2048], temp[2048];
645 _snprintf(szIp, 2047, "%S", swIp);
646 _snprintf(szName, 2047, "%S", swName);
648 ReportMessage(0,"Starting UpdateHostsFile() on file",szFilename,0,0);
650 rv = SHGetFolderPathA( NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT , etcPath );
651 if(rv != S_OK) return FALSE;
653 strcat( etcPath, ETCDIR );
655 fa = GetFileAttributesA( etcPath );
657 if(fa == INVALID_FILE_ATTRIBUTES)
659 // the directory doesn't exist
660 // it should be there. non-existence implies more things are wrong
661 ReportMessage(0, "Path does not exist ", etcPath,0,0 );
665 strcpy( tempPath, etcPath );
666 strcat( etcPath, "\\" );
667 strcat( etcPath, szFilename );
669 fa = GetFileAttributesA( etcPath );
671 if(fa == INVALID_FILE_ATTRIBUTES)
673 ReportMessage(0, "File not found. Creating...", szFilename,0,0);
675 hFile = fopen( etcPath, "w" );
678 ReportMessage(0,"FAILED : can't create file",etcPath,0,errno);
682 fprintf(hFile, "%s\t%s%s\n", szIp, szName, (bPre)?"\t#PRE":"");
686 ReportMessage(1,"done",0,0,0);
688 else // the file exists. parse and update
691 ReportMessage(1, "Updating file ...",szFilename,0,0 );
693 hFile = fopen( etcPath, "r");
696 ReportMessage(0,"FAILED : can't open file",etcPath,0,errno);
700 strcat( tempPath, szFilename );
701 strcat( tempPath, ".tmp" );
702 hTemp = fopen( tempPath, "w");
705 ReportMessage(0,"FAILED : can't create temp file",tempPath,0,errno);
710 while(fgets( buffer, 2046, hFile))
712 strcpy( temp, buffer );
715 if ((strlen(temp)<1) || (*(temp+strlen(temp)-1)!='\n')) strcat(temp, "\n");
717 if(!(str = strstr(temp, szName)))
719 fputs( buffer, hTemp );
723 // check for FOOBAFS or AFSY
724 //if(str <= temp || (*(str-1) != '-' && !isspace(*(str+strlen(szName)))))
725 if ( (str == temp) || (!*(str+strlen(szName))) || (!isspace(*(str-1))) || (!isspace(*(str+strlen(szName)))) )
726 fputs( buffer, hTemp );
732 GetComputerNameA( buffer, &len );
734 fprintf( hTemp, "%s\t%s%s\n", szIp, szName, (bPre)?"\t#PRE":"");
739 strcpy(buffer, etcPath);
740 strcat(buffer, ".old");
742 if(!DeleteFileA(buffer)) {
747 status = GetLastError();
748 if(status == ERROR_ACCESS_DENIED) {
749 /* try changing the file attribtues. */
750 if(SetFileAttributesA(buffer, FILE_ATTRIBUTE_NORMAL) &&
751 DeleteFileA(buffer)) {
753 ReportMessage(0,"Changed attributes and deleted back host file", buffer, 0, 0);
756 if(status && status != ERROR_FILE_NOT_FOUND) {
757 /* we can't delete the file. Try to come up with
758 a different name that's not already taken. */
759 srand(GetTickCount());
760 eos = buffer + strlen(buffer);
761 for(i=0; i < 50; i++) {
762 itoa(rand(), eos, 16);
763 if(GetFileAttributesA(buffer) == INVALID_FILE_ATTRIBUTES &&
764 GetLastError() == ERROR_FILE_NOT_FOUND)
767 /* At this point if we don't have a unique name, we just let the rename
772 if(!MoveFileA( etcPath, buffer )) {
773 ReportMessage(0,"FAILED: Can't rename old file", etcPath, 0, GetLastError());
777 if(!MoveFileA( tempPath, etcPath ) != 0)
779 ReportMessage(0,"FAILED : Can't rename new file", tempPath, 0, GetLastError());
798 printf("usage: %S ip mask\n"
799 " example: %S 10.0.0.1 255.0.0.0", argv[0], argv[0]);
803 return WMIEnableStatic(FindNetworkAdapterConfigurationInstanceByGUID,
804 L"{B4981E32-551C-4164-96B6-B8874BD2E555}",
816 printf("usage: %S adapter_guid ip mask\n"
817 " example: %S {B4981E32-551C-4164-96B6-B8874BD2E555} "
818 "10.0.0.1 255.0.0.0", argv[0], argv[0]);
822 return WMIEnableStatic(FindNetworkAdapterConfigurationInstanceByGUID,
823 argv[1], argv[2], argv[3]);