From: Jeffrey Altman Date: Wed, 23 Jun 2004 08:48:18 +0000 (+0000) Subject: new-loopback-dll-20040622 X-Git-Tag: openafs-devel-1_3_65~21 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=be70343e2a5e4d050363c8cad1a1132e43d24a51 new-loopback-dll-20040622 Construct a new afsloopback.dll which contains the routines for installing, removing, and verifying the existance of a loopback adapter. This dll will be used by both the NSIS and the Wix installers. ==================== This delta was composed from multiple commits as part of the CVS->Git migration. The checkin message with each commit was inconsistent. The following are the additional commit messages. ==================== Update the wix installer to use the new version of instloop.exe which uses the new afsloopback.dll --- diff --git a/src/NTMakefile b/src/NTMakefile index ac03c9c..32101b6 100644 --- a/src/NTMakefile +++ b/src/NTMakefile @@ -601,6 +601,13 @@ mkdir: -mkdir $(DESTDIR)\free\bin -@copy $(SRC)\config\NTLANG.BAT . +loopback: + echo ***** Making Loopback Adapter Utility DLL + $(DOCD) $(SRC)\WINNT\install\$@ + $(CD) $(SRC)\WINNT\install\$@ + $(NTMAKE) + $(CD) ..\..\..\.. + NSIS: echo ***** Making NSIS Installer $(DOCD) $(SRC)\WINNT\install\$@ @@ -627,11 +634,11 @@ InstallShield5: $(NTMAKE) $(CD) ..\..\..\.. -media: install InstallShield5 NSIS +media: install loopback InstallShield5 NSIS wix -install-nsis: install NSIS +install-nsis: install loopback NSIS -install-wix: install wix +install-wix: install loopback wix install-is5: install InstallShield5 diff --git a/src/WINNT/install/NSIS/NTMakefile b/src/WINNT/install/NSIS/NTMakefile index c032d8a..b90525f 100644 --- a/src/WINNT/install/NSIS/NTMakefile +++ b/src/WINNT/install/NSIS/NTMakefile @@ -22,12 +22,6 @@ $(OUT)\Killer.obj: Killer.cpp $(EXEDIR)\Killer.exe: $(OUT)\Killer.obj $(EXECONLINK) $(OUT)\Killer.obj -$(OUT)\loopback_install.obj: loopback_install.cpp - $(C2OBJ) -I$(NTDDKDIR) loopback_install.cpp - -$(EXEDIR)\loopback_install.dll: $(OUT)\loopback_install.obj - $(DLLCONLINK) /DEF:loopback_install.def $(OUT)\loopback_install.obj $(LOOPBACK_LIBS) - prebuild: !IF ("$(AFSDEV_BUILDTYPE)" == "FREE") !IF ("$(AFSVER_CL)"=="1310") @@ -87,7 +81,7 @@ prebuild: build: prebuild "C:\Program Files\NSIS\makensis.exe" /DINCLUDEDIR=$(OUT) OpenAFS.nsi -install: $(OUT)\Service.obj $(EXEDIR)\Service.exe $(OUT)\Killer.obj $(EXEDIR)\Killer.exe $(EXEDIR)\loopback_install.dll build +install: $(OUT)\Service.obj $(EXEDIR)\Service.exe $(OUT)\Killer.obj $(EXEDIR)\Killer.exe build #clean: # $(DEL) $(OUT)\Service.obj diff --git a/src/WINNT/install/NSIS/loopback_install.cpp b/src/WINNT/install/NSIS/loopback_install.cpp deleted file mode 100644 index fcefd20..0000000 --- a/src/WINNT/install/NSIS/loopback_install.cpp +++ /dev/null @@ -1,1266 +0,0 @@ -/** - * Copyright (c) 2003 Lingo Systems Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -// Modified 7/18/03 by Ben Creech for NCSU ITECS -// to add command-line parameters and turn into a non-console app. - -// devcon -r install %SYSTEMROOT%\Inf\Netloop.inf *MSLOOP - - -// Win2k -#define _WIN32_DCOM -#define UNICODE -#define _UNICODE - -#include -#include -#include -#include - -// The following two headers are from the Microsoft DDK -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include // WMI interface declarations - -#include -#include - -#define DEFAULT_IPADDR L"10.99.173.207" -#define DEFAULT_SUBNETMASK L"255.255.255.254" - -bool bQuiet; - -// -// UpdateDriverForPlugAndPlayDevices -// -typedef BOOL (WINAPI *UpdateDriverForPlugAndPlayDevicesProto)(HWND hwndParent, - LPCTSTR hwid, - LPCTSTR FullInfPath, - DWORD InstallFlags, - PBOOL bRebootRequired OPTIONAL - ); - -#define UPDATEDRIVERFORPLUGANDPLAYDEVICES "UpdateDriverForPlugAndPlayDevicesA" - -void display_usage(); - -void EasyErrorBox (int hr, WCHAR *format, ...) -{ - - LPWSTR systemMessage; - WCHAR buf[400]; - ULONG offset; - va_list ap; - - if (bQuiet) return; - - if(hr) - swprintf( buf, L"Error %#lx: ", hr ); - else - buf[0] = 0; - - offset = (ULONG) wcslen( buf ); - va_start( ap, format ); - vswprintf( buf+offset, format,ap ); - va_end( ap ); - if(hr) - { - FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - hr, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR)&systemMessage, - 0, - NULL ); - if(systemMessage) - { - offset = (ULONG) wcslen( buf ); - swprintf( buf+offset, L"\n\nPossible cause:\n\n" ); - offset = (ULONG) wcslen( buf ); - wcscat( buf+offset, systemMessage ); - LocalFree( (HLOCAL)systemMessage ); - } - else - { - switch(hr) - { - case WBEM_E_FAILED: systemMessage = L"WBEM request failed."; break; - case WBEM_E_TYPE_MISMATCH: systemMessage = L"WBEM type mismatch."; break; - } - if(systemMessage) - { - offset = (ULONG) wcslen( buf ); - swprintf( buf+offset, L"\n\nPossible cause:\n\n" ); - offset = (ULONG) wcslen( buf ); - wcscat( buf+offset, systemMessage ); - } - } - - - MessageBoxW( NULL, buf, L"Error", MB_ICONERROR | MB_OK ); - } - else - { - MessageBoxW( NULL, buf, L"loopback_install", MB_ICONINFORMATION | MB_OK ); - } -} - -// RSM4: Converted this to stdcall so NSIS System::Call can call it (It defaults to stdcall) -DWORD _stdcall loopback_isInstalled() -{ - TCHAR * hwid = _T("*MSLOOP"); - HDEVINFO DeviceInfoSet; - SP_DEVINFO_DATA DeviceInfoData; - DWORD i,err; - bool found; - - // - // Create a Device Information Set with all present devices. - // - DeviceInfoSet = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system - if (DeviceInfoSet == INVALID_HANDLE_VALUE) - { - EasyErrorBox(GetLastError(), L"GetClassDevs(All Present Devices) failed\n"); - return false; // nothing installed? - } - - // - // Enumerate through all Devices. - // - found = FALSE; - DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for (i=0; SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData); i++) - { - DWORD DataT; - TCHAR *p, *buffer = NULL; - DWORD buffersize = 0; - - // - // We won't know the size of the HardwareID buffer until we call - // this function. So call it with a null to begin with, and then - // use the required buffer size to Alloc the nessicary space. - // Keep calling we have success or an unknown failure. - // - while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,&DeviceInfoData,SPDRP_HARDWAREID,&DataT,(PBYTE)buffer,buffersize,&buffersize)) - { - if (GetLastError() == ERROR_INVALID_DATA) - { - // May be a Legacy Device with no hwid. Continue. - break; - } - else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - // We need to change the buffer size. - if (buffer) - LocalFree(buffer); - buffer = (TCHAR *)LocalAlloc(LPTR,buffersize); - } - else - { - // What the ... ? - EasyErrorBox(GetLastError(), L"Failed to detect Loopback adapter: GetDeviceRegistryProperty() returned an unknown error."); - goto cleanup_DeviceInfo; - } - } - - if (GetLastError() == ERROR_INVALID_DATA) - continue; - - // Compare each entry in the buffer multi-sz list with our hwid. - for (p=buffer; *p && (p < &buffer[buffersize]); p += _tcslen(p)+1) - { - if (!_tcsicmp(hwid,p)) - { - found = TRUE; - break; - } - } - - if (buffer) LocalFree(buffer); - if (found) break; - } - - // Cleanup. -cleanup_DeviceInfo: - err = GetLastError(); - SetupDiDestroyDeviceInfoList(DeviceInfoSet); - SetLastError(err); - - return found; -} - - -// RSM4: Added -bool disable_loopback() -{ - TCHAR * hwid = _T("*MSLOOP"); - HDEVINFO DeviceInfoSet; - SP_DEVINFO_DATA DeviceInfoData; - SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)}; - DWORD i,err; - bool found,status=FALSE; - - // - // Create a Device Information Set with all present devices. - // - DeviceInfoSet = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system - if (DeviceInfoSet == INVALID_HANDLE_VALUE) - { - EasyErrorBox(GetLastError(), L"GetClassDevs(All Present Devices) failed\n"); - return false; // nothing installed? - } - - // - // Enumerate through all Devices. - // - found = FALSE; - DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for (i=0; SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData); i++) - { - DWORD DataT; - TCHAR * p, *buffer = NULL; - DWORD buffersize = 0; - - // - // We won't know the size of the HardwareID buffer until we call - // this function. So call it with a null to begin with, and then - // use the required buffer size to Alloc the nessicary space. - // Keep calling we have success or an unknown failure. - // - while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,&DeviceInfoData,SPDRP_HARDWAREID,&DataT,(PBYTE)buffer,buffersize,&buffersize)) - { - if (GetLastError() == ERROR_INVALID_DATA) - { - // May be a Legacy Device with no hwid. Continue. - break; - } - else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - // We need to change the buffer size. - if (buffer) - LocalFree(buffer); - buffer = (TCHAR *)LocalAlloc(LPTR,buffersize); - } - else - { - // What the ... ? - EasyErrorBox(GetLastError(), L"Failed to detect Loopback adapter: GetDeviceRegistryProperty() returned an unknown error."); - goto cleanup_DeviceInfo; - } - } - - if (GetLastError() == ERROR_INVALID_DATA) - continue; - - // Compare each entry in the buffer multi-sz list with our hwid. - for (p=buffer; *p && (p < &buffer[buffersize]); p += _tcslen(p)+1) - { - if (!_tcsicmp(hwid,p)) - { - found = TRUE; - break; - } - } - - if (buffer) LocalFree(buffer); - if (found) break; - } - - // If we found the device, disable it... - if (found) - { - // - // Set the PropChangeParams structure. - // - PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; - PropChangeParams.Scope = DICS_FLAG_GLOBAL; - PropChangeParams.StateChange = DICS_DISABLE; - - if (SetupDiSetClassInstallParams(DeviceInfoSet, - &DeviceInfoData, - (SP_CLASSINSTALL_HEADER *)&PropChangeParams, - sizeof(PropChangeParams))) - { - // - // Call the ClassInstaller and perform the change. - // - if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, - DeviceInfoSet, - &DeviceInfoData)) - status=TRUE; - else - EasyErrorBox(GetLastError(), L"Could not disable LoopBack adapter: SetupDiSetClassInstallParams failed"); - } - else - EasyErrorBox(GetLastError(), L"Could not disable LoopBack adapter: SetupDiSetClassInstallParams failed"); - - } - - - // Cleanup. -cleanup_DeviceInfo: - err = GetLastError(); - SetupDiDestroyDeviceInfoList(DeviceInfoSet); - SetLastError(err); - - return status; -} - - -bool loopback_install(int *rebootNeeded) -{ - SP_DEVINFO_DATA DeviceInfoData; - GUID ClassGUID; - HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE; - TCHAR ClassName[MAX_CLASS_NAME_LEN]; - TCHAR hwIdList[LINE_LEN+4]; - TCHAR InfPath[MAX_PATH]; - bool success = false; - TCHAR * hwid = _T("*MSLOOP"); - TCHAR * inf = _T("INF\\NETLOOP.INF"); - DWORD flags = 0; - HMODULE newdevMod = NULL; - UpdateDriverForPlugAndPlayDevicesProto UpdateFn; - - TCHAR *systemRoot = _tgetenv(_T("SYSTEMROOT")); - SetCurrentDirectory(systemRoot); - - // Inf must be a full pathname - if(GetFullPathName(inf,MAX_PATH,InfPath,NULL) >= MAX_PATH) { - puts("Failed to configure Loopback adapter: inf pathname too long"); - return false; - } - - // List of hardware ID's must be double zero-terminated - ZeroMemory(hwIdList,sizeof(hwIdList)); - lstrcpyn(hwIdList,hwid,LINE_LEN); - - // Use the INF File to extract the Class GUID. - if (!SetupDiGetINFClass(InfPath,&ClassGUID,ClassName,sizeof(ClassName),0)) - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Failed to read INF for %s\n", InfPath); - goto final; - } - - // - // Create the container for the to-be-created Device Information Element. - // - DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0); - if(DeviceInfoSet == INVALID_HANDLE_VALUE) - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Failed to create device info list for %s\n", ClassName); - goto final; - } - - // - // Now create the element. - // Use the Class GUID and Name from the INF file. - // - DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - if (!SetupDiCreateDeviceInfo(DeviceInfoSet, ClassName, &ClassGUID, NULL, 0, DICD_GENERATE_ID, &DeviceInfoData)) - goto final; - - // - // Add the hwid to the Device's hwid property. - // - if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)hwIdList, (lstrlen(hwIdList)+1+1)*sizeof(TCHAR))) - goto final; - - // - // Transform the registry element into an actual devnode - // in the PnP HW tree. - // - if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData)) - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Failed to call class installer for %s\n", inf); - goto final; - } - - inf = InfPath; - flags |= INSTALLFLAG_FORCE; - - // make use of UpdateDriverForPlugAndPlayDevices - newdevMod = LoadLibrary(TEXT("newdev.dll")); - if(!newdevMod) - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Failed to load newdev.dll\n", inf); - goto final; - } - - UpdateFn = (UpdateDriverForPlugAndPlayDevicesProto)GetProcAddress(newdevMod,UPDATEDRIVERFORPLUGANDPLAYDEVICES); - if(!UpdateFn) - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Failed to read the driver updating function from newdev.dll\n", inf); - goto final; - } - - if(!UpdateFn(NULL,hwid,inf,flags,rebootNeeded)) - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Failed to update the driver for %s\n", inf); - goto final; - } - - success = true; - -final: - - if(newdevMod) { - FreeLibrary(newdevMod); - } - - if (DeviceInfoSet != INVALID_HANDLE_VALUE) { - SetupDiDestroyDeviceInfoList(DeviceInfoSet); - } - - return success; -} - -//+--------------------------------------------------------------------------- -// getWriteLock [in] whether to get write lock -// ppnc [in] pointer to pointer to INetCfg object -// -// Returns: S_OK on success, otherwise an error code -HRESULT getInetCfg(bool getWriteLock, WCHAR *appName, INetCfg** ppnc, WCHAR **holdingAppName) -{ - HRESULT hr=S_OK; - - // Initialize the output parameters. - *ppnc = NULL; - - // Create the object implementing INetCfg. - // - INetCfg* pnc; - hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, - IID_INetCfg, (void**)&pnc); - if (SUCCEEDED(hr)) - { - INetCfgLock * pncLock = NULL; - if (getWriteLock) - { - // Get the locking interface - hr = pnc->QueryInterface(IID_INetCfgLock, - (LPVOID *)&pncLock); - if (SUCCEEDED(hr)) - { - // Attempt to lock the INetCfg for read/write - static const ULONG c_cmsTimeout = 15000; - - hr = pncLock->AcquireWriteLock(c_cmsTimeout, - appName, - holdingAppName); - if (S_FALSE == hr) - { - hr = NETCFG_E_NO_WRITE_LOCK; - EasyErrorBox(hr, L"Failed to configure Loopback adapter: Could not lock INetcfg, it is already locked by '%s'", *holdingAppName); - } - } - } - - if (SUCCEEDED(hr)) - { - // Initialize the INetCfg object. - // - hr = pnc->Initialize(NULL); - if (SUCCEEDED(hr)) - { - *ppnc = pnc; - pnc->AddRef(); - } - else - { - // initialize failed, if obtained lock, release it - if (pncLock) - { - pncLock->ReleaseWriteLock(); - } - } - } - if(pncLock) pncLock->Release(); - if(pnc) pnc->Release(); - } - - - return hr; -} - -//+--------------------------------------------------------------------------- -// hasWriteLock [in] whether write lock needs to be released. -// pnc [in] pointer to INetCfg object - -HRESULT releaseInetCfg(INetCfg* pnc, bool hasWriteLock) -{ - HRESULT hr = S_OK; - - // uninitialize INetCfg - hr = pnc->Uninitialize(); - - // if write lock is present, unlock it - if (SUCCEEDED(hr) && hasWriteLock) - { - INetCfgLock* pncLock; - - // Get the locking interface - hr = pnc->QueryInterface(IID_INetCfgLock, - (LPVOID *)&pncLock); - if (SUCCEEDED(hr)) - { - hr = pncLock->ReleaseWriteLock(); - if(pncLock) pncLock->Release(); - } - } - - if(pnc) pnc->Release(); - - return hr; -} - -bool ChangeBinding(WCHAR *inf, WCHAR *binding, bool bind) -{ - - INetCfg *pnc; - INetCfgComponent *pncc; - INetCfgComponentBindings *pnccb; - INetCfgComponent *pnccToChange; - WCHAR * lpszApp; - HRESULT hr; - bool fChange=false; - - - hr = getInetCfg(TRUE, L"loopback_install", &pnc, &lpszApp); - if(hr == S_OK) - { - // Get a reference to the network component. - hr = pnc->FindComponent(inf, &pncc); - if(hr == S_OK) - { - // Get a reference to the component's binding. - hr = pncc->QueryInterface(IID_INetCfgComponentBindings, (PVOID *)&pnccb); - if(hr == S_OK) - { - // Get a reference to the selected component. - hr = pnc->FindComponent(binding, &pnccToChange); - if(hr == S_OK) - { - if(bind) - { - // Bind the component to the selected component. - hr = pnccb->BindTo(pnccToChange); - fChange = (fChange || hr == S_OK); - - if(hr != S_OK) EasyErrorBox(hr, L"Failed to configure Loopback adapter: %s couldn't be bound to %s.", inf, binding); - } - else - { - // Unbind the component from the selected component. - hr = pnccb->UnbindFrom(pnccToChange); - fChange = (fChange || hr == S_OK); - - if(hr != S_OK) EasyErrorBox(hr, L"Failed to configure Loopback adapter: %s couldn't be unbound from %s.", inf, binding); - //else EasyErrorBox(hr, L"%s will be unbound from %s.", inf, binding); - } - - pnccToChange->Release(); - } - else - { - if(bind) // Don't have to unbind something thats not installed, so only print an error if we're binding it - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: Couldn't get an interface pointer to %s. %s will not be bound to it. (Maybe this is not installed on your system.)", binding, inf); - } - - pnccb->Release(); - } - else - { - EasyErrorBox(hr, L"Failed to configure Loopback adapter: Couldn't get a binding interface of %s.", inf); - } - - pncc->Release(); - } - else - { - EasyErrorBox(hr, L"Couldn't get an interface pointer to %s.", inf); - } - - // - // If one or more network components have been bound/unbound, - // apply the changes. - // - - if(fChange) - { - hr = pnc->Apply(); - - fChange = hr == S_OK; - } - - releaseInetCfg(pnc, true); - } - else - { - if((hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp) - { - EasyErrorBox(hr, L"%s currently holds the lock, try later.", lpszApp); - CoTaskMemFree(lpszApp); - } - else - { - EasyErrorBox(hr, L"Couldn't get the notify object interface."); - } - } - - return fChange; -} - -// Unbind microsoft services so our NetBIOS will be functional: -// ms_msclient will be unbound from *msloop -// ms_server will be unbound from *MSLOOP -int loopback_unbindmsnet() -{ - // Unbind microsoft's NetBIOS hogs - // Whats interesting is that CIFS shares on that device still work - // even when the client for microsoft networks is not bound to that - // device - ChangeBinding(L"ms_msclient", L"*MSLOOP", false); - ChangeBinding(L"ms_server", L"*MSLOOP", false); - - // Bind TCP/IP - ChangeBinding(L"ms_tcpip", L"*MSLOOP", true); - return 1; -} - -// -// Debugging function to help us print variant records -// This is copied from some microsoft sample -// -#define BLOCKSIZE (32 * sizeof(WCHAR)) -#define CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop (this size stolen from cvt.h in c runtime library) */ -LPWSTR ValueToString(VARIANT *pValue, WCHAR **pbuf) -{ - DWORD iNeed = 0; - DWORD iVSize = 0; - DWORD iCurBufSize = 0; - - WCHAR *vbuf = NULL; - WCHAR *buf = NULL; - - - switch (pValue->vt) - { - - case VT_NULL: - buf = (WCHAR *)malloc(BLOCKSIZE); - wcscpy(buf, L""); - break; - - case VT_BOOL: { - VARIANT_BOOL b = pValue->boolVal; - buf = (WCHAR *)malloc(BLOCKSIZE); - - if (!b) { - wcscpy(buf, L"FALSE"); - } else { - wcscpy(buf, L"TRUE"); - } - break; - } - - case VT_UI1: { - BYTE b = pValue->bVal; - buf = (WCHAR *)malloc(BLOCKSIZE); - if (b >= 32) { - swprintf(buf, L"'%c' (%d, 0x%X)", b, b, b); - } else { - swprintf(buf, L"%d (0x%X)", b, b); - } - break; - } - - case VT_I2: { - SHORT i = pValue->iVal; - buf = (WCHAR *)malloc(BLOCKSIZE); - swprintf(buf, L"%d (0x%X)", i, i); - break; - } - - case VT_I4: { - LONG l = pValue->lVal; - buf = (WCHAR *)malloc(BLOCKSIZE); - swprintf(buf, L"%d (0x%X)", l, l); - break; - } - - case VT_R4: { - float f = pValue->fltVal; - buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR)); - swprintf(buf, L"%10.4f", f); - break; - } - - case VT_R8: { - double d = pValue->dblVal; - buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR)); - swprintf(buf, L"%10.4f", d); - break; - } - - case VT_BSTR: { - LPWSTR pWStr = pValue->bstrVal; - buf = (WCHAR *)malloc((wcslen(pWStr) * sizeof(WCHAR)) + sizeof(WCHAR) + (2 * sizeof(WCHAR))); - swprintf(buf, L"\"%wS\"", pWStr); - break; - } - - // the sample GUI is too simple to make it necessary to display - // these 'complicated' types--so ignore them. - case VT_DISPATCH: // Currently only used for embedded objects - case VT_BOOL|VT_ARRAY: - case VT_UI1|VT_ARRAY: - case VT_I2|VT_ARRAY: - case VT_I4|VT_ARRAY: - case VT_R4|VT_ARRAY: - case VT_R8|VT_ARRAY: - case VT_BSTR|VT_ARRAY: - case VT_DISPATCH | VT_ARRAY: - break; - - default: - buf = (WCHAR *)malloc(BLOCKSIZE); - wcscpy(buf, L""); - - } - - *pbuf = buf; - return buf; -} - -void VariantInitStringArray(VARIANT &var, BSTR str) -{ - DWORD hr; - BSTR *arrayContents; - var.vt = VT_BSTR|VT_ARRAY; - var.parray = SafeArrayCreateVector(VT_BSTR, 0, 1); - if((hr = SafeArrayAccessData(var.parray, (void **)&arrayContents))) { EasyErrorBox (0, L"Failed to access contents"); exit(1); } - arrayContents[0] = str; -} - - -WCHAR *EnableStatic_strerror(int err) -{ - switch(err) - { - case 0: return L"Successful completion, no reboot required."; - case 1: return L"Successful completion, reboot required."; - case 64: return L"Method not supported on this platform."; - case 65: return L"Unknown failure."; - case 66: return L"Invalid subnet mask."; - case 67: return L"An error occurred while processing an instance that was returned."; - case 68: return L"Invalid input parameter."; - case 69: return L"More than five gateways specified."; - case 70: return L"Invalid IP address."; - case 71: return L"Invalid gateway IP address."; - case 72: return L"An error occurred while accessing the registry for the requested information."; - case 73: return L"Invalid domain name."; - case 74: return L"Invalid host name."; - case 75: return L"No primary or secondary WINS server defined."; - case 76: return L"Invalid file."; - case 77: return L"Invalid system path."; - case 78: return L"File copy failed."; - case 79: return L"Invalid security parameter."; - case 80: return L"Unable to configure TCP/IP service."; - case 81: return L"Unable to configure DHCP service."; - case 82: return L"Unable to renew DHCP lease."; - case 83: return L"Unable to release DHCP lease."; - case 84: return L"IP not enabled on adapter."; - case 85: return L"IPX not enabled on adapter."; - case 86: return L"Frame/network number bounds error."; - case 87: return L"Invalid frame type."; - case 88: return L"Invalid network number."; - case 89: return L"Duplicate network number."; - case 90: return L"Parameter out of bounds."; - case 91: return L"Access denied."; - case 92: return L"Out of memory."; - case 93: return L"Already exists."; - case 94: return L"Path, file, or object not found."; - case 95: return L"Unable to notify service."; - case 96: return L"Unable to notify DNS service."; - case 97: return L"Interface not configurable."; - case 98: return L"Not all DHCP leases could be released or renewed."; - case 100: return L"DHCP not enabled on adapter."; - default: return L"See online for the description of this error"; - } -} - -// Change the loopback to use a static IP: 127.0.0.2 -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/retrieving_class_or_instance_data.asp -// GetObject() -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/iwbemservices_getobject.asp -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/win32_networkadapter.asp -// EnableStatic() -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/enablestatic_method_in_class_win32_networkadapterconfiguration.asp -// #define loopback_adapter_path "Win32_NetworkAdapter" -int loopback_configure(int *needReboot, WCHAR *loopbackIP, WCHAR *loopbackNetmask) -{ - HRESULT hRes; - BSTR propName = NULL, val = NULL; - VARIANT pVal; - ULONG uReturned; - int result=1; - - IEnumWbemClassObject *pEnumServices = NULL; - IWbemLocator *pIWbemLocator = NULL; - HRESULT hr = S_OK; - - //------------------------ - // Create an instance of the WbemLocator interface. - if(CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pIWbemLocator) == S_OK) - { - //------------------------ - // Use the pointer returned in step two to connect to - // the server using the passed in namespace. - // It is very important never to pass any string not allocated using SysAllocString to any COM function - BSTR pNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); - IWbemServices *pIWbemServices = NULL; - - if((hr = pIWbemLocator->ConnectServer(pNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices)) == S_OK) - { - CoSetProxyBlanket(pIWbemServices, - RPC_C_AUTHN_WINNT, - RPC_C_AUTHZ_NONE, - NULL, - RPC_C_AUTHN_LEVEL_CALL, - RPC_C_IMP_LEVEL_IMPERSONATE, - NULL, - EOAC_NONE - ); - - BSTR className = SysAllocString(L"Win32_NetworkAdapterConfiguration"); - // Lets lookup the class first - IWbemClassObject *pClass = NULL; - if((hRes = pIWbemServices->GetObject(className, 0, NULL, &pClass, NULL)) == S_OK) - { - BSTR methodName = SysAllocString(L"EnableStatic"); - - - /** // Uncomment this debugging code to check the qualifiers of your EnableStatic method - IWbemQualifierSet *quals=NULL; - hr = pClass->GetMethodQualifierSet(methodName, &quals); - if(hr == WBEM_S_NO_ERROR) - { - BSTR qualName, qualValue; - - quals->BeginEnumeration(0); - while(quals->Next(0, &qualName, &pVal, NULL) == S_OK) - { - printf("qualifier: %ws = %ws\n", qualName, ValueToString(&pVal, &qualValue)); - } - quals->Release(); - } - */ - - IWbemClassObject * pInClass = NULL; - hr = pClass->GetMethod(methodName, 0, &pInClass, NULL); - if(hr == WBEM_S_NO_ERROR) - { - // WBEM_E_ACCESS_DENIED - //---------------------- - // execute the query. - BSTR qLang = SysAllocString(L"WQL"); - BSTR query = SysAllocString(L"select * from Win32_NetworkAdapterConfiguration where ServiceName = \"msloop\""); - if((hRes = pIWbemServices->ExecQuery(qLang, query, 0L, NULL, &pEnumServices)) == S_OK) - { - IWbemClassObject *pInstance = NULL; - - //---------------------- - // Only configure the first one; if there are multiple loopback adapters they are up to something - // and we'd rather not interfere (or this tool mistakenly installed a second one) - if(((hRes = pEnumServices->Next(5000, 1, &pInstance, &uReturned)) == S_OK) && (uReturned == 1)) - { - // Lookup the "index" (the primary key for Win32_NetworkAdapterConfiguration) - BSTR varName = SysAllocString(L"Index"); - if(S_OK == pInstance->Get(varName, 0, &pVal, NULL, NULL)) - { - // Create an instance of the input parameters of this method - IWbemClassObject * pInInst = NULL; - hr = pInClass->SpawnInstance(0, &pInInst); - if(hr == WBEM_S_NO_ERROR) - { - // Now fill that instance in with useful parameters. - BSTR ipAddressStr = SysAllocString(L"IPAddress"); - BSTR subnetMaskStr = SysAllocString(L"SubnetMask"); - BSTR loopbackIPCopy = SysAllocString(loopbackIP); - BSTR loopbackNetMaskCopy = SysAllocString(loopbackNetmask); - - // Two string arrays: one with the ip addresses, the other with subnet masks - VARIANT ipVar, maskVar; - - // Create the IP Address array and put our ip address into it - VariantInitStringArray(ipVar, loopbackIPCopy); - - // Create the subnet mask array and put our subnet mask into it - VariantInitStringArray(maskVar, loopbackNetMaskCopy); - - // Write the parameters into the params object - hr = pInInst->Put(ipAddressStr, 0, &ipVar, 0); if(hr) EasyErrorBox(hr, L"Args->Put(IPAddress) failed\n"); - hr = pInInst->Put(subnetMaskStr, 0, &maskVar, 0); if(hr) EasyErrorBox(hr, L"Args->Put(SubnetMask) failed\n"); - - /** // Uncomment this debugging code to view the parameters before the method is called - BSTR pInText=NULL; - pInInst->GetObjectText(0, &pInText); - printf("Parameters: %ws\n", pInText); - */ - - // Call the method - IWbemClassObject * pOutInst = NULL; - - // Compute the object path and copy it into a COM string - WCHAR objectPathBuf[255]; - wsprintfW(objectPathBuf, L"Win32_NetworkAdapterConfiguration.Index=%d", pVal.intVal); - BSTR objectPath = SysAllocString(objectPathBuf); - - // Go go go! - hr = pIWbemServices->ExecMethod(objectPath, methodName, 0, NULL, pInInst, &pOutInst, NULL); - if(hr == WBEM_S_NO_ERROR) - { - // Extract the return value (from the field called "ReturnValue") - VARIANT retVal; - BSTR retValName = SysAllocString(L"ReturnValue"); - hr = pOutInst->Get(retValName, 0, &retVal, 0, 0); - if(hr == WBEM_S_NO_ERROR) - { - // If it returns 1, we should reboot - if(retVal.intVal == 1) - { - *needReboot = 1; - } - else if(retVal.intVal == 0) - { - // Everything is great - } - else - { - if (retVal.intVal == 81) { // "Unable to configure DHCP"; seems to be returned superfluously sometimes - // Just print it out without bugging the user; that way admins can see it but they can also ignore it - EasyErrorBox (0, L"Failed to configure Loopback adapter: EnableStatic() returns %d: %s\n", retVal.intVal, EnableStatic_strerror(retVal.intVal)); - result = 0; - } else { - // For descriptions of these error codes try: - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/enablestatic_method_in_class_win32_networkadapterconfiguration.asp - EasyErrorBox(hr, L"Failed to configure Loopback adapter: EnableStatic() returns %d (%s)", retVal.intVal, EnableStatic_strerror(retVal.intVal)); - result = 0; - } - } - } - else - { - // This shouldn't happen, methinks - BSTR objText=NULL; - pOutInst->GetObjectText(0, &objText); - EasyErrorBox(hr, L"Successfully called EnableStatic(); result = %ws but unable to get ReturnValue\n", objText); - result = 0; - } - } - else - { - // After all that work, we still couldn't execute the method? Probably a BSTR was allocated using SysAllocString but thats just my prophesy - EasyErrorBox(hr, L"Failed to configure Loopback adapter: ExecMethod() failed\n"); - result = 0; - } - - if(pOutInst) - { - pOutInst->Release(); - pOutInst = NULL; - } - - // Release some resources; this function isn't likely to be part of a long running - // program, but I've seen stranger things. - SafeArrayDestroy(ipVar.parray); - SafeArrayDestroy(maskVar.parray); - SysFreeString(ipAddressStr); - SysFreeString(subnetMaskStr); - SysFreeString(loopbackNetMaskCopy); - SysFreeString(loopbackIPCopy); - } - else - { - EasyErrorBox(hr, L"Failed to configure Loopback adapter: Failed to Spawn an instance of the method's parameters\n"); - result = 0; - } - - if(pInInst) - { - pInInst->Release(); - pInInst = NULL; - } - } - else - { - EasyErrorBox(hr, L"Failed to configure Loopback adapter: Unable to read ServiceName\n"); - result = 0; - } - - // done with the ClassObject - if (pInstance) - { - pInstance->Release(); - pInstance = NULL; - } - - SysFreeString(varName); - - } - - // did the while loop exit due to an error? - if((hRes != S_OK) && - (hRes != 1)) - { - EasyErrorBox(hRes, L"Failed to configure Loopback adapter: pEnumServices->Next() failed %s\n"); - result = 0; - } - - if (pEnumServices) - { - pEnumServices->Release(); - pEnumServices = NULL; - } - } - else - { - EasyErrorBox(hRes, L"Failed to configure Loopback adapter: ExecQuery('%s', '%s') failed\n", qLang, query); - result = 0; - } - - SysFreeString(qLang); - SysFreeString(query); - } - else - { - EasyErrorBox(hRes, L"Failed to configure Loopback adapter: GetMethod(\"EnableStatic\") failed\n"); - result = 0; - } - - SysFreeString(methodName); - } - else - { - EasyErrorBox(hRes, L"Failed to configure Loopback adapter: GetObject(\"Win32_NetworkAdapterConfiguration\") failed\n"); - result = 0; - } - - SysFreeString(className); - } - - SysFreeString(pNamespace); - } - else - { - EasyErrorBox(GetLastError(), L"Failed to configure Loopback adapter: CoCreateInstance(CLSID_WbemLocator) failed.\n"); - result = 0; - } - - return result; -} - -class ARGS { -public: - bool bQuiet; - LPWSTR lpIPAddr; - LPWSTR lpSubnetMask; - ARGS () : bQuiet (0), lpIPAddr (0), lpSubnetMask (0) { } - ~ARGS () { - if (lpIPAddr) free (lpIPAddr); - if (lpSubnetMask) free (lpSubnetMask); - } -}; - -void wcsMallocAndCpy (LPWSTR * dst, const LPWSTR src) { - *dst = (LPWSTR) malloc ((wcslen (src) + 1) * sizeof (WCHAR)); - wcscpy (*dst, src); -} - -int process_args (LPWSTR lpCmdLine, ARGS & args) { - int i, iNumArgs; - LPWSTR * argvW; - - argvW = CommandLineToArgvW (lpCmdLine, &iNumArgs); - for (i = 0; i < iNumArgs; i++) - { - if (wcsstr (argvW[i], L"help") - || !_wcsicmp (argvW[i], L"?") - || (wcslen(argvW[i]) == 2 && argvW[i][1] == L'?')) - { - display_usage(); - GlobalFree (argvW); - return 0; - } - - if (!_wcsicmp (argvW[i], L"q") || !_wcsicmp (argvW[i], L"quiet")) { - args.bQuiet = true; - continue; - } - - if (!args.lpIPAddr) { - wcsMallocAndCpy (&args.lpIPAddr, argvW[i]); - continue; - } - - if (!args.lpSubnetMask) { - wcsMallocAndCpy (&args.lpSubnetMask, argvW[i]); - continue; - } - - display_usage(); - GlobalFree (argvW); - return 0; - } - - if (!args.lpIPAddr) - wcsMallocAndCpy (&args.lpIPAddr, DEFAULT_IPADDR); - if (!args.lpSubnetMask) - wcsMallocAndCpy (&args.lpSubnetMask, DEFAULT_SUBNETMASK); - - GlobalFree (argvW); - return 1; -} - -void display_usage() { - EasyErrorBox (0, - L"Installation utility for the MS Loopback Adapter\r\n\r\n" - L"Usage:\r\n" - L"RunDll32 loopback_install.dll doLoopBackEntry [q|quiet] [IP address] [Subnet Mask]\r\n" - L" \"Quiet\" supresses error messages\r\n" - L" \"IP address\" defaults to %s\r\n" - L" \"Subnet Mask\" defaults to %s\r\n", - DEFAULT_IPADDR, DEFAULT_SUBNETMASK); -} - -int doLoopBack (LPWSTR lpIPAddr, LPWSTR lpSubnetMask) { - int rc; - // initialize COM - // This and CoInitializeSecurity fail when running under the MSI - // engine, but there seems to be no ill effect (the security is now - // set on the specific object via CoSetProxyBlanket in loopback_configure) - if(CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED )) - { - //Don't fail (MSI install will have already initialized COM) - //EasyErrorBox(0, L"Failed to initialize COM."); - //return 1; - } - - // Initialize COM security (otherwise we'll get permission denied when we try to use WMI or NetCfg) - CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); - - int rebootNeeded = 0; - - if(loopback_isInstalled() || loopback_install(&rebootNeeded)) - { - rc = loopback_unbindmsnet(); - if (!rc) return 1; - rc = loopback_configure(&rebootNeeded, lpIPAddr, lpSubnetMask); - if (!rc) return 1; - } - - CoUninitialize(); - - if(rebootNeeded) { - EasyErrorBox(0, L"Please reboot.\n"); - return 2; - } - return 0; -} - -void CALLBACK doLoopBackEntryW (HWND hwnd, HINSTANCE hinst, LPWSTR lpCmdLine, int nCmdShow) -{ - ARGS args; - - if (!process_args(lpCmdLine, args)) return; - bQuiet = args.bQuiet; // laziness - - doLoopBack (args.lpIPAddr, args.lpSubnetMask); -} - -void CALLBACK disableLoopBackEntryW (HWND hwnd, HINSTANCE hinst, LPWSTR lpCmdLine, int nCmdSHow) -{ - ARGS args; - int rc; - - // initialize COM - // This and CoInitializeSecurity fail when running under the MSI - // engine, but there seems to be no ill effect (the security is now - // set on the specific object via CoSetProxyBlanket in loopback_configure) - if(CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED )) - { - //Don't fail (MSI install will have already initialized COM) - //EasyErrorBox(0, L"Failed to initialize COM."); - //return 1; - } - - // Initialize COM security (otherwise we'll get permission denied when we try to use WMI or NetCfg) - CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); - - disable_loopback(); - - CoUninitialize(); - - -} - -UINT __stdcall installLoopbackMSI (MSIHANDLE hInstall) -{ - LPWSTR szValueBuf; - DWORD cbValueBuf = 256; - ARGS args; - UINT rc; - - szValueBuf = (LPWSTR) malloc (cbValueBuf * sizeof (WCHAR)); - while (rc = MsiGetPropertyW(hInstall, L"CustomActionData", szValueBuf, &cbValueBuf)) { - free (szValueBuf); - if (rc == ERROR_MORE_DATA) { - cbValueBuf++; - szValueBuf = (LPWSTR) malloc (cbValueBuf * sizeof (WCHAR)); - } else return ERROR_INSTALL_FAILURE; - } - - if (!process_args(szValueBuf, args)) return ERROR_INSTALL_FAILURE; - - rc = doLoopBack (args.lpIPAddr, args.lpSubnetMask); - - if (rc == 1) return ERROR_INSTALL_FAILURE; - - if (rc == 2) { - MsiDoActionW (hInstall, L"ScheduleReboot"); - } - - return ERROR_SUCCESS; -} diff --git a/src/WINNT/install/NSIS/loopback_install.def b/src/WINNT/install/NSIS/loopback_install.def deleted file mode 100644 index defe319..0000000 --- a/src/WINNT/install/NSIS/loopback_install.def +++ /dev/null @@ -1,10 +0,0 @@ -LIBRARY LOOPBACK_INSTALL - -DESCRIPTION "Microsoft Loopback Adapter Installer for OpenAFS" - -EXPORTS - doLoopBackEntryW - disableLoopBackEntryW - loopback_isInstalled - - diff --git a/src/WINNT/install/loopback/NTMakefile b/src/WINNT/install/loopback/NTMakefile new file mode 100644 index 0000000..5870521 --- /dev/null +++ b/src/WINNT/install/loopback/NTMakefile @@ -0,0 +1,58 @@ +# rcsid : $Id$ + +RELDIR=WINNT\install\loopback +!INCLUDE ..\..\..\config\NTMakefile.$(SYS_NAME) +!INCLUDE ..\..\..\config\NTMakefile.version + +MEDIABINDIR = $(DESTDIR)\WinInstall\Config + +EXEFILE = $(MEDIABINDIR)\instloop.exe + +DLLFILE = $(MEDIABINDIR)\afsloopback.dll + +DLLEXPORTS=\ + -EXPORT:UnInstallLoopBack \ + -EXPORT:IsLoopbackInstalled \ + -EXPORT:InstallLoopBack \ + -EXPORT:doLoopBackEntryW \ + -EXPORT:uninstallLoopBackEntryW \ + -EXPORT:installLoopbackMSI + +DLLLIBFILES=\ + setupapi.lib msi.lib uuid.lib Shell32.lib ole32.lib advapi32.lib wbemuuid.lib + +LINK=link + +# afsloopback.dll + +DLLSOURCEFILES = loopbackutils.cpp renameconnection.cpp wmi.cpp +DLLOBJFILES = $(OUT)\loopbackutils.obj $(OUT)\renameconnection.obj $(OUT)\wmi.obj + +$(OUT)\loopbackutils.obj: loopbackutils.cpp + $(CPP2OBJ) -c -DUNICODE -D_UNICODE /Fo$@ $** + +$(OUT)\renameconnection.obj: renameconnection.cpp + $(CPP2OBJ) -c -DUNICODE -D_UNICODE /Fo$@ $** + +$(OUT)\wmi.obj: wmi.cpp + $(CPP2OBJ) -I$(NTDDKDIR) -c -DUNICODE -D_UNICODE /Fo$@ $** + +$(DLLFILE): $(DLLOBJFILES) + $(LINK) -DLL $(DLLEXPORTS) -OUT:$@ $(DLLOBJFILES) $(DLLLIBFILES) + +# instloop.exe + +EXESOURCEFILES = instloop.c +EXEOBJFILES = $(OUT)\instloop.obj +EXELIBFILES = $(MEDIABINDIR)\afsloopback.lib + +$(OUT)\instloop.obj: instloop.c + $(C2OBJ) -c -DUNICODE -D_UNICODE /Fo$@ $** + +$(EXEFILE): $(EXEOBJFILES) $(EXELIBFILES) + $(LINK) /OUT:$@ $(EXEOBJFILES) $(EXELIBFILES) + + +install: $(DLLFILE) $(EXEFILE) + +clean :: diff --git a/src/WINNT/install/loopback/instloop.c b/src/WINNT/install/loopback/instloop.c new file mode 100644 index 0000000..bb7427a --- /dev/null +++ b/src/WINNT/install/loopback/instloop.c @@ -0,0 +1,146 @@ +/* + +Copyright 2004 by the Massachusetts Institute of Technology + +All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +#include +#include +#define INITGUID +#include +#include +#include +#include +#include "loopbackutils.h" + +#undef REDIRECT_STDOUT + +static void +ShowUsage(void) +{ + printf("instloop [-i [name [ip mask]] | -u]\n\n"); + printf(" -i install the %s\n", DRIVER_DESC); + _tprintf(_T(" (if unspecified, uses name %s,\n"), DEFAULT_NAME); + _tprintf(_T(" ip %s, and mask %s)\n"), DEFAULT_IP, DEFAULT_MASK); + printf(" -u uninstall the %s\n", DRIVER_DESC); +} + +static void +DisplayStartup(BOOL bInstall) +{ + printf("%snstalling the %s\n" + " (Note: This may take up to a minute or two...)\n", + bInstall ? "I" : "Un", + DRIVER_DESC); + +} + +static void +DisplayResult(BOOL bInstall, DWORD rc) +{ + if (rc) + { + printf("Could not %sinstall the %s\n", bInstall ? "" : "un", + DRIVER_DESC); + SLEEP; + PAUSE; + } +} + + +int _tmain(int argc, TCHAR *argv[]) +{ + DWORD rc = 0; +#ifdef REDIRECT_STDOUT + FILE *fh = NULL; +#endif + + PAUSE; + +#ifdef REDIRECT_STDOUT + fh = freopen("instlog.txt","a+", stdout); +#endif + + if (argc > 1) + { + if (_tcsicmp(argv[1], _T("-i")) == 0) + { + TCHAR* name = DEFAULT_NAME; + TCHAR* ip = DEFAULT_IP; + TCHAR* mask = DEFAULT_MASK; + + if (argc > 2) + { + name = argv[2]; + if (argc > 3) + { + if (argc < 5) + { + ShowUsage(); +#ifdef REDIRECT_STDOUT + fflush(fh); fclose(fh); +#endif + return 1; + } + else + { + ip = argv[3]; + mask = argv[4]; + } + } + } + DisplayStartup(TRUE); + if(IsLoopbackInstalled()) { + printf("Loopback already installed\n"); + rc = 0; /* don't signal an error. */ + } else { + rc = InstallLoopBack(name, ip, mask); + } + DisplayResult(TRUE, rc); +#ifdef REDIRECT_STDOUT + fflush(fh); fclose(fh); +#endif + return rc; + } + else if (_tcsicmp(argv[1], _T("-u")) == 0) + { + DisplayStartup(FALSE); + rc = UnInstallLoopBack(); + DisplayResult(FALSE, rc); +#ifdef REDIRECT_STDOUT + fflush(fh); fclose(fh); +#endif + return rc; + } + ShowUsage(); +#ifdef REDIRECT_STDOUT + fflush(fh); fclose(fh); +#endif + return 1; + } + ShowUsage(); +#ifdef REDIRECT_STDOUT + fflush(fh); fclose(fh); +#endif + return 0; +} + diff --git a/src/WINNT/install/wix/custom/instloop.c b/src/WINNT/install/loopback/loopbackutils.cpp similarity index 68% rename from src/WINNT/install/wix/custom/instloop.c rename to src/WINNT/install/loopback/loopbackutils.cpp index 5efc202..e460af3 100644 --- a/src/WINNT/install/wix/custom/instloop.c +++ b/src/WINNT/install/loopback/loopbackutils.cpp @@ -1,185 +1,56 @@ /* - -Copyright 2004 by the Massachusetts Institute of Technology - -All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of the Massachusetts -Institute of Technology (M.I.T.) not be used in advertising or publicity -pertaining to distribution of the software without specific, written -prior permission. - -M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - + Copyright 2004 by the Massachusetts Institute of Technology + + All rights reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation, and that the name of the Massachusetts + Institute of Technology (M.I.T.) not be used in advertising or publicity + pertaining to distribution of the software without specific, written + prior permission. + + M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. */ +#define _WIN32_DCOM #include #include +#include + +struct Args { + bool bQuiet; + LPWSTR lpIPAddr; + LPWSTR lpSubnetMask; + LPWSTR lpConnectionName; + Args () : bQuiet (0), lpIPAddr (0), lpSubnetMask (0), lpConnectionName (0) { } + ~Args () { + if (lpIPAddr) free (lpIPAddr); + if (lpSubnetMask) free (lpSubnetMask); + if (lpConnectionName) free (lpConnectionName); + } +}; + +#include #define INITGUID #include #include +#include #include #include +#include +#include +#include "loopbackutils.h" -#undef REDIRECT_STDOUT - -#ifdef USE_PAUSE -#define PAUSE \ - do { \ - char c; \ - printf("PAUSED - PRESS ENTER TO CONTINUE\n"); \ - scanf("%c", &c); \ - } while(0) -#else -#define PAUSE -#endif - -/*#define USE_SLEEP*/ - -#ifdef USE_SLEEP -#define SLEEP Sleep(10*1000) -#else -#define SLEEP -#endif - - -static void ShowUsage(void); -DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask); -DWORD UnInstallLoopBack(void); -int RenameConnection(PCWSTR GuidString, PCWSTR pszNewName); -DWORD SetIpAddress(LPCWSTR guid, LPCWSTR ip, LPCWSTR mask); -HRESULT LoopbackBindings (LPCWSTR loopback_guid); -BOOL UpdateHostsFile( LPCWSTR swName, LPCWSTR swIp, LPCSTR szFilename, BOOL bPre ); - -#define DRIVER_DESC "Microsoft Loopback Adapter" -#define DRIVER _T("loopback") -#define MANUFACTURE _T("microsoft") -#define DEFAULT_NAME _T("AFS") -#define DEFAULT_IP _T("10.254.254.253") -#define DEFAULT_MASK _T("255.255.255.252") - -static void -ShowUsage(void) -{ - printf("instloop [-i [name [ip mask]] | -u]\n\n"); - printf(" -i install the %s\n", DRIVER_DESC); - _tprintf(_T(" (if unspecified, uses name %s,\n"), DEFAULT_NAME); - _tprintf(_T(" ip %s, and mask %s)\n"), DEFAULT_IP, DEFAULT_MASK); - printf(" -u uninstall the %s\n", DRIVER_DESC); -} - -static void -DisplayStartup(BOOL bInstall) -{ - printf("%snstalling the %s\n" - " (Note: This may take up to a minute or two...)\n", - bInstall ? "I" : "Un", - DRIVER_DESC); - -} - -static void -DisplayResult(BOOL bInstall, DWORD rc) -{ - if (rc) - { - printf("Could not %sinstall the %s\n", bInstall ? "" : "un", - DRIVER_DESC); - SLEEP; - PAUSE; - } -} - - -int _tmain(int argc, TCHAR *argv[]) -{ - DWORD rc = 0; -#ifdef REDIRECT_STDOUT - FILE *fh = NULL; -#endif - - PAUSE; - -#ifdef REDIRECT_STDOUT - fh = freopen("instlog.txt","a+", stdout); -#endif - - if (argc > 1) - { - if (_tcsicmp(argv[1], _T("-i")) == 0) - { - TCHAR* name = DEFAULT_NAME; - TCHAR* ip = DEFAULT_IP; - TCHAR* mask = DEFAULT_MASK; - - if (argc > 2) - { - name = argv[2]; - if (argc > 3) - { - if (argc < 5) - { - ShowUsage(); -#ifdef REDIRECT_STDOUT - fflush(fh); fclose(fh); -#endif - return 1; - } - else - { - ip = argv[3]; - mask = argv[4]; - } - } - } - DisplayStartup(TRUE); - if(IsLoopbackInstalled()) { - printf("Loopback already installed\n"); - rc = 0; /* don't signal an error. */ - } else { - rc = InstallLoopBack(name, ip, mask); - } - DisplayResult(TRUE, rc); -#ifdef REDIRECT_STDOUT - fflush(fh); fclose(fh); -#endif - return rc; - } - else if (_tcsicmp(argv[1], _T("-u")) == 0) - { - DisplayStartup(FALSE); - rc = UnInstallLoopBack(); - DisplayResult(FALSE, rc); -#ifdef REDIRECT_STDOUT - fflush(fh); fclose(fh); -#endif - return rc; - } - ShowUsage(); -#ifdef REDIRECT_STDOUT - fflush(fh); fclose(fh); -#endif - return 1; - } - ShowUsage(); -#ifdef REDIRECT_STDOUT - fflush(fh); fclose(fh); -#endif - return 0; -} - - -DWORD UnInstallLoopBack(void) +extern "C" DWORD UnInstallLoopBack(void) { BOOL ok; DWORD ret = 0; @@ -203,7 +74,7 @@ DWORD UnInstallLoopBack(void) if (hDeviceInfo == INVALID_HANDLE_VALUE) return GetLastError(); - deviceDesc = malloc(MAX_PATH*sizeof(TCHAR)); + deviceDesc = (TCHAR *)malloc(MAX_PATH*sizeof(TCHAR)); // enumerate the driver info list while (SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData)) { @@ -219,7 +90,7 @@ DWORD UnInstallLoopBack(void) break; // if the buffer is too small, reallocate free(deviceDesc); - deviceDesc = malloc(size); + deviceDesc = (TCHAR *)malloc(size); ok = SetupDiGetDeviceRegistryProperty(hDeviceInfo, &DeviceInfoData, SPDRP_DEVICEDESC, @@ -270,7 +141,7 @@ cleanup: return ret; } -BOOL IsLoopbackInstalled() +BOOL IsLoopbackInstalled(void) { TCHAR * hwid = _T("*MSLOOP"); HDEVINFO DeviceInfoSet; @@ -351,7 +222,7 @@ cleanup_DeviceInfo: } -DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask) +extern "C" DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask) { BOOL ok; DWORD ret = 0; @@ -616,4 +487,143 @@ cleanup: SetupDiDestroyDeviceInfoList(hDeviceInfo); return ret; +}; + +/* The following functions provide the RunDll32 interface + * RunDll32 loopback_install.dll doLoopBackEntry [Interface Name] [IP address] [Subnet Mask] + */ + +static void wcsMallocAndCpy (LPWSTR * dst, const LPWSTR src) { + *dst = (LPWSTR) malloc ((wcslen (src) + 1) * sizeof (WCHAR)); + wcscpy (*dst, src); +} + +static void display_usage() +{ + MessageBoxW( NULL, + L"Installation utility for the MS Loopback Adapter\r\n\r\n" + L"Usage:\r\n" + L"RunDll32 loopback_install.dll doLoopBackEntry [q|quiet] [Connection Name] [IP address] [Submask]\r\n", + L"loopback_install", MB_ICONINFORMATION | MB_OK ); +} + +static int process_args (LPWSTR lpCmdLine, Args & args) { + int i, iNumArgs; + LPWSTR * argvW; + + argvW = CommandLineToArgvW (lpCmdLine, &iNumArgs); + for (i = 0; i < iNumArgs; i++) + { + if (wcsstr (argvW[i], L"help") + || !_wcsicmp (argvW[i], L"?") + || (wcslen(argvW[i]) == 2 && argvW[i][1] == L'?')) + { + display_usage(); + GlobalFree (argvW); + return 0; + } + + if (!_wcsicmp (argvW[i], L"q") || !_wcsicmp (argvW[i], L"quiet")) { + args.bQuiet = true; + continue; + } + + if (!args.lpConnectionName) { + wcsMallocAndCpy (&args.lpConnectionName, argvW[i]); + continue; + } + + if (!args.lpIPAddr) { + wcsMallocAndCpy (&args.lpIPAddr, argvW[i]); + continue; + } + + if (!args.lpSubnetMask) { + wcsMallocAndCpy (&args.lpSubnetMask, argvW[i]); + continue; + } + + display_usage(); + GlobalFree (argvW); + return 0; + } + + if (!args.lpConnectionName) + wcsMallocAndCpy (&args.lpConnectionName, DEFAULT_NAME); + if (!args.lpIPAddr) + wcsMallocAndCpy (&args.lpIPAddr, DEFAULT_IP); + if (!args.lpSubnetMask) + wcsMallocAndCpy (&args.lpSubnetMask, DEFAULT_MASK); + + GlobalFree (argvW); + return 1; } + +void CALLBACK doLoopBackEntryW (HWND hwnd, HINSTANCE hinst, LPWSTR lpCmdLine, int nCmdShow) +{ + Args args; + + if (!process_args(lpCmdLine, args)) + return; + + InstallLoopBack(args.lpConnectionName, args.lpIPAddr, args.lpSubnetMask); +} + +void CALLBACK uninstallLoopBackEntryW (HWND hwnd, HINSTANCE hinst, LPWSTR lpCmdLine, int nCmdSHow) +{ + Args args; + + // initialize COM + // This and CoInitializeSecurity fail when running under the MSI + // engine, but there seems to be no ill effect (the security is now + // set on the specific object via CoSetProxyBlanket in loopback_configure) + if(CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED )) + { + //Don't fail (MSI install will have already initialized COM) + //EasyErrorBox(0, L"Failed to initialize COM."); + //return 1; + } + + // Initialize COM security (otherwise we'll get permission denied when we try to use WMI or NetCfg) + CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); + + UnInstallLoopBack(); + + CoUninitialize(); +} + +/* And an MSI installer interface */ + +UINT __stdcall installLoopbackMSI (MSIHANDLE hInstall) +{ + LPWSTR szValueBuf; + DWORD cbValueBuf = 256; + Args args; + UINT rc; + + szValueBuf = (LPWSTR) malloc (cbValueBuf * sizeof (WCHAR)); + while (rc = MsiGetPropertyW(hInstall, L"CustomActionData", szValueBuf, &cbValueBuf)) { + free (szValueBuf); + if (rc == ERROR_MORE_DATA) { + cbValueBuf++; + szValueBuf = (LPWSTR) malloc (cbValueBuf * sizeof (WCHAR)); + } + else + return ERROR_INSTALL_FAILURE; + } + + if (!process_args(szValueBuf, args)) + return ERROR_INSTALL_FAILURE; + + rc = InstallLoopBack (args.lpConnectionName, args.lpIPAddr, args.lpSubnetMask); + + if (rc == 1) + return ERROR_INSTALL_FAILURE; + + if (rc == 2) { + MsiDoActionW (hInstall, L"ScheduleReboot"); + } + + return ERROR_SUCCESS; +} + diff --git a/src/WINNT/install/loopback/loopbackutils.h b/src/WINNT/install/loopback/loopbackutils.h new file mode 100644 index 0000000..1a763d1 --- /dev/null +++ b/src/WINNT/install/loopback/loopbackutils.h @@ -0,0 +1,65 @@ +/* + +Copyright 2004 by the Massachusetts Institute of Technology + +All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +#ifdef __cplusplus +extern "C" { +#endif +DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask); +BOOL IsLoopbackInstalled(void); +DWORD UnInstallLoopBack(void); +int RenameConnection(PCWSTR GuidString, PCWSTR pszNewName); +DWORD SetIpAddress(LPCWSTR guid, LPCWSTR ip, LPCWSTR mask); +HRESULT LoopbackBindings (LPCWSTR loopback_guid); +BOOL UpdateHostsFile( LPCWSTR swName, LPCWSTR swIp, LPCSTR szFilename, BOOL bPre ); +#ifdef __cplusplus +} +#endif + +#define DRIVER_DESC "Microsoft Loopback Adapter" +#define DRIVER _T("loopback") +#define MANUFACTURE _T("microsoft") +#define DEFAULT_NAME _T("AFS") +#define DEFAULT_IP _T("10.254.254.253") +#define DEFAULT_MASK _T("255.255.255.252") + +#ifdef USE_PAUSE +#define PAUSE \ + do { \ + char c; \ + printf("PAUSED - PRESS ENTER TO CONTINUE\n"); \ + scanf("%c", &c); \ + } while(0) +#else +#define PAUSE +#endif + +/*#define USE_SLEEP*/ + +#ifdef USE_SLEEP +#define SLEEP Sleep(10*1000) +#else +#define SLEEP +#endif + diff --git a/src/WINNT/install/wix/custom/renameconnection.cpp b/src/WINNT/install/loopback/renameconnection.cpp similarity index 100% rename from src/WINNT/install/wix/custom/renameconnection.cpp rename to src/WINNT/install/loopback/renameconnection.cpp diff --git a/src/WINNT/install/wix/custom/wmi.cpp b/src/WINNT/install/loopback/wmi.cpp similarity index 100% rename from src/WINNT/install/wix/custom/wmi.cpp rename to src/WINNT/install/loopback/wmi.cpp diff --git a/src/WINNT/install/wix/config.wxi b/src/WINNT/install/wix/config.wxi index 9529478..a01c389 100644 --- a/src/WINNT/install/wix/config.wxi +++ b/src/WINNT/install/wix/config.wxi @@ -20,7 +20,8 @@ Directory specs: (all dir. specs end in a '\') - MediaBinDir : Installer binaries (instloop.exe etc.) + MediaDllDir : Installer Dlls + MediaBinDir : Installer Exes SrcDir : openafs\src\ DestDir : $(DEST)\ BinDir : $(DEST)\bin\ @@ -107,8 +108,11 @@ + + + - + diff --git a/src/WINNT/install/wix/custom/NTMakefile b/src/WINNT/install/wix/custom/NTMakefile index 38b6b86..7c37a0d 100644 --- a/src/WINNT/install/wix/custom/NTMakefile +++ b/src/WINNT/install/wix/custom/NTMakefile @@ -6,8 +6,6 @@ RELDIR=WINNT\install\wix\custom MEDIABINDIR = $(DESTDIR)\WinInstall\Dll -EXEFILE = $(MEDIABINDIR)\instloop.exe - DLLFILE = $(MEDIABINDIR)\afscustom.dll DLLEXPORTS=\ @@ -32,25 +30,6 @@ $(DLLFILE): $(OUT)\afscustom.obj $(LINK) -DLL $(DLLEXPORTS) \ -OUT:$@ $** $(DLLLIBFILES) -# instloop.exe - -SOURCEFILES = instloop.c renameconnection.cpp wmi.cpp -OBJFILES = $(OUT)\instloop.obj $(OUT)\renameconnection.obj $(OUT)\wmi.obj -EXELIBFILES = setupapi.lib msi.lib uuid.lib Shell32.lib ole32.lib advapi32.lib wbemuuid.lib - -$(OUT)\instloop.obj: instloop.c - $(CC) -ML -c -DUNICODE -D_UNICODE /Fo$@ $** - -$(OUT)\renameconnection.obj: renameconnection.cpp - $(CC) -ML -c -DUNICODE -D_UNICODE /Fo$@ $** - -$(OUT)\wmi.obj: wmi.cpp - $(CC) -I$(NTDDKDIR) -ML -c -DUNICODE -D_UNICODE /Fo$@ $** - -$(EXEFILE): $(OBJFILES) - $(LINK) /OUT:$@ $(OBJFILES) $(EXELIBFILES) - - -install: $(EXEFILE) $(DLLFILE) +install: $(DLLFILE) clean :: diff --git a/src/WINNT/install/wix/openafs.wxs b/src/WINNT/install/wix/openafs.wxs index 871ba41..03560a7 100644 --- a/src/WINNT/install/wix/openafs.wxs +++ b/src/WINNT/install/wix/openafs.wxs @@ -63,7 +63,7 @@ src="$(var.MediaBinDir)instloop.exe"/> + src="$(var.MediaDllDir)afscustom.dll"/>