15 printf("PAUSED - PRESS ENTER TO CONTINUE\n"); \
25 #define SLEEP Sleep(10*1000)
31 static void ShowUsage(void);
32 DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask);
33 DWORD UnInstallLoopBack(void);
34 int RenameConnection(PCWSTR GuidString, PCWSTR pszNewName);
35 DWORD SetIpAddress(LPCWSTR guid, LPCWSTR ip, LPCWSTR mask);
36 HRESULT LoopbackBindings (LPCWSTR loopback_guid);
37 BOOL UpdateHostsFile( LPCWSTR swName, LPCWSTR swIp, LPCSTR szFilename, BOOL bPre );
39 #define DRIVER_DESC "Microsoft Loopback Adapter"
40 #define DRIVER _T("loopback")
41 #define MANUFACTURE _T("microsoft")
42 #define DEFAULT_NAME _T("AFS")
43 #define DEFAULT_IP _T("10.254.254.253")
44 #define DEFAULT_MASK _T("255.255.255.252")
49 printf("instloop [-i [name [ip mask]] | -u]\n\n");
50 printf(" -i install the %s\n", DRIVER_DESC);
51 _tprintf(_T(" (if unspecified, uses name %s,\n"), DEFAULT_NAME);
52 _tprintf(_T(" ip %s, and mask %s)\n"), DEFAULT_IP, DEFAULT_MASK);
53 printf(" -u uninstall the %s\n", DRIVER_DESC);
57 DisplayStartup(BOOL bInstall)
59 printf("%snstalling the %s\n"
60 " (Note: This may take up to a minute or two...)\n",
61 bInstall ? "I" : "Un",
67 DisplayResult(BOOL bInstall, DWORD rc)
71 printf("Could not %sinstall the %s\n", bInstall ? "" : "un",
79 int _tmain(int argc, TCHAR *argv[])
82 #ifdef REDIRECT_STDOUT
88 #ifdef REDIRECT_STDOUT
89 fh = freopen("instlog.txt","a+", stdout);
94 if (_tcsicmp(argv[1], _T("-i")) == 0)
96 TCHAR* name = DEFAULT_NAME;
97 TCHAR* ip = DEFAULT_IP;
98 TCHAR* mask = DEFAULT_MASK;
108 #ifdef REDIRECT_STDOUT
109 fflush(fh); fclose(fh);
120 DisplayStartup(TRUE);
121 if(IsLoopbackInstalled()) {
122 printf("Loopback already installed\n");
123 rc = 0; /* don't signal an error. */
125 rc = InstallLoopBack(name, ip, mask);
127 DisplayResult(TRUE, rc);
128 #ifdef REDIRECT_STDOUT
129 fflush(fh); fclose(fh);
133 else if (_tcsicmp(argv[1], _T("-u")) == 0)
135 DisplayStartup(FALSE);
136 rc = UnInstallLoopBack();
137 DisplayResult(FALSE, rc);
138 #ifdef REDIRECT_STDOUT
139 fflush(fh); fclose(fh);
144 #ifdef REDIRECT_STDOUT
145 fflush(fh); fclose(fh);
150 #ifdef REDIRECT_STDOUT
151 fflush(fh); fclose(fh);
157 DWORD UnInstallLoopBack(void)
162 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
163 SP_DEVINFO_DATA DeviceInfoData;
169 // initialize the structure size
170 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
172 // copy the net class GUID
173 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
175 // return a device info set contains all installed devices of the Net class
176 hDeviceInfo = SetupDiGetClassDevs(&netGuid, NULL, NULL, DIGCF_PRESENT);
178 if (hDeviceInfo == INVALID_HANDLE_VALUE)
179 return GetLastError();
181 deviceDesc = malloc(MAX_PATH*sizeof(TCHAR));
182 // enumerate the driver info list
183 while (SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData))
185 // try to get the DeviceDesc registry property
186 ok = SetupDiGetDeviceRegistryProperty(hDeviceInfo, &DeviceInfoData,
188 NULL, (PBYTE)deviceDesc,
189 MAX_PATH * sizeof(TCHAR), &size);
192 ret = GetLastError();
193 if (ret != ERROR_INSUFFICIENT_BUFFER)
195 // if the buffer is too small, reallocate
197 deviceDesc = malloc(size);
198 ok = SetupDiGetDeviceRegistryProperty(hDeviceInfo,
201 NULL, (PBYTE)deviceDesc,
207 // case insensitive comparison
209 if( _tcsstr(deviceDesc, DRIVER))
222 ret = GetLastError();
223 printf("The %s does not seem to be installed\n", DRIVER_DESC);
227 ok = SetupDiSetSelectedDevice(hDeviceInfo, &DeviceInfoData);
230 ret = GetLastError();
233 ok = SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
236 ret = GetLastError();
241 // clean up the device info set
242 if (hDeviceInfo != INVALID_HANDLE_VALUE)
243 SetupDiDestroyDeviceInfoList(hDeviceInfo);
248 BOOL IsLoopbackInstalled()
250 TCHAR * hwid = _T("*MSLOOP");
251 HDEVINFO DeviceInfoSet;
252 SP_DEVINFO_DATA DeviceInfoData;
257 // Create a Device Information Set with all present devices.
259 DeviceInfoSet = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system
260 if (DeviceInfoSet == INVALID_HANDLE_VALUE)
262 return FALSE; // nothing installed?
266 // Enumerate through all Devices.
269 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
270 for (i=0; SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData); i++)
273 TCHAR *p, *buffer = NULL;
274 DWORD buffersize = 0;
277 // We won't know the size of the HardwareID buffer until we call
278 // this function. So call it with a null to begin with, and then
279 // use the required buffer size to Alloc the nessicary space.
280 // Keep calling we have success or an unknown failure.
282 while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,&DeviceInfoData,SPDRP_HARDWAREID,&DataT,(PBYTE)buffer,buffersize,&buffersize))
284 if (GetLastError() == ERROR_INVALID_DATA)
286 // May be a Legacy Device with no hwid. Continue.
289 else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
291 // We need to change the buffer size.
294 buffer = (TCHAR *)LocalAlloc(LPTR,buffersize);
298 goto cleanup_DeviceInfo;
302 if (GetLastError() == ERROR_INVALID_DATA)
305 // Compare each entry in the buffer multi-sz list with our hwid.
306 for (p=buffer; *p && (p < &buffer[buffersize]); p += _tcslen(p)+1)
308 if (!_tcsicmp(hwid,p))
315 if (buffer) LocalFree(buffer);
321 err = GetLastError();
322 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
329 DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask)
334 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
335 SP_DEVINFO_DATA DeviceInfoData;
336 SP_DRVINFO_DATA DriverInfoData;
337 SP_DEVINSTALL_PARAMS DeviceInstallParams;
338 TCHAR className[MAX_PATH];
339 TCHAR temp[MAX_PATH];
342 BOOL registered = FALSE;
343 BOOL destroyList = FALSE;
348 TCHAR pCfgGuidString[40];
350 // initialize the structure size
351 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
352 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
354 // copy the net class GUID
355 memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
357 // create an empty device info set associated with the net class GUID
358 hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL);
359 if (hDeviceInfo == INVALID_HANDLE_VALUE)
360 return GetLastError();
362 // get the class name from GUID
363 ok = SetupDiClassNameFromGuid(&netGuid, className, MAX_PATH, NULL);
366 ret = GetLastError();
370 // create a device info element and add the new device instance
372 ok = SetupDiCreateDeviceInfo(hDeviceInfo, className, &netGuid, NULL, NULL,
373 DICD_GENERATE_ID, &DeviceInfoData);
376 ret = GetLastError();
380 // select the newly created device info to be the currently
382 ok = SetupDiSetSelectedDevice(hDeviceInfo, &DeviceInfoData);
385 ret = GetLastError();
389 // build a list of class drivers
390 ok = SetupDiBuildDriverInfoList(hDeviceInfo, &DeviceInfoData,
394 ret = GetLastError();
400 // enumerate the driver info list
401 while (SetupDiEnumDriverInfo(hDeviceInfo, &DeviceInfoData,
402 SPDIT_CLASSDRIVER, index, &DriverInfoData))
404 // if the manufacture is microsoft
405 if (_tcsicmp(DriverInfoData.MfgName, MANUFACTURE) == 0)
407 // case insensitive search for loopback
408 _tcscpy(temp, DriverInfoData.Description);
410 if( _tcsstr(temp, DRIVER))
421 ret = GetLastError();
422 printf("Could not find the %s driver to install\n", DRIVER_DESC);
426 // set the loopback driver to be the currently selected
427 ok = SetupDiSetSelectedDriver(hDeviceInfo, &DeviceInfoData,
431 ret = GetLastError();
435 // register the phantom device to repare for install
436 ok = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDeviceInfo,
440 ret = GetLastError();
444 // registered, but remove if errors occur in the following code
447 // ask the installer if we can install the device
448 ok = SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, hDeviceInfo,
452 ret = GetLastError();
453 if (ret != ERROR_DI_DO_DEFAULT)
461 // install the files first
462 ok = SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, hDeviceInfo,
466 ret = GetLastError();
470 // get the device install parameters and disable filecopy
471 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
472 ok = SetupDiGetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
473 &DeviceInstallParams);
476 DeviceInstallParams.Flags |= DI_NOFILECOPY;
477 ok = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData,
478 &DeviceInstallParams);
481 ret = GetLastError();
487 // Register any device-specific co-installers for this device,
490 ok = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
495 ret = GetLastError();
500 // install any installer-specified interfaces.
501 // and then do the real install
503 ok = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
508 ret = GetLastError();
512 ok = SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
517 ret = GetLastError();
522 /* Skip to the end if we aren't setting the name */
523 if (!pConnectionName) goto cleanup;
525 // Figure out NetCfgInstanceId
526 hkey = SetupDiOpenDevRegKey(hDeviceInfo,
532 if (hkey == INVALID_HANDLE_VALUE)
534 ret = GetLastError();
538 cbSize = sizeof(pCfgGuidString);
539 ret = RegQueryValueEx(hkey, _T("NetCfgInstanceId"), NULL,
540 &dwValueType, (LPBYTE)pCfgGuidString, &cbSize);
543 ret = RenameConnection(pCfgGuidString, pConnectionName);
546 printf("Could not set the connection name to \"%S\"\n",
551 if (!ip) goto cleanup;
552 ret = SetIpAddress(pCfgGuidString, ip, mask);
555 printf("Could not set the ip address and network mask\n");
558 ret = LoopbackBindings(pCfgGuidString);
561 printf("Could not properly set the bindings\n");
564 ret = !UpdateHostsFile( pConnectionName, ip, "hosts", FALSE );
567 printf("Could not update hosts file\n");
570 ret = !UpdateHostsFile( pConnectionName, ip, "lmhosts", TRUE );
573 printf("Could not update lmhosts file\n");
579 // an error has occured, but the device is registered, we must remove it
580 if (ret != 0 && registered)
581 SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
583 found = SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData);
585 // destroy the driver info list
587 SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData,
589 // clean up the device info set
590 if (hDeviceInfo != INVALID_HANDLE_VALUE)
591 SetupDiDestroyDeviceInfoList(hDeviceInfo);