diff --git a/windows/install_giveio.bat b/windows/install_giveio.bat new file mode 100755 index 00000000..4a02b093 --- /dev/null +++ b/windows/install_giveio.bat @@ -0,0 +1,34 @@ +@set DIRVERNAME=giveio +@set DIRVERFILE=%DIRVERNAME%.sys + +@echo Copying the driver to the windows directory +@echo target file: %WINDIR%\%DIRVERFILE% +@copy %DIRVERFILE% %WINDIR%\%DIRVERFILE% + +@echo Remove a running service if needed... +@loaddrv stop %DIRVERNAME% >NUL +@if errorlevel 2 goto install + +@loaddrv remove %DIRVERNAME% >NUL +@if errorlevel 1 goto install + +:install +@echo Installing Windows NT/2k/XP driver: %DIRVERNAME% + +@loaddrv install %DIRVERNAME% %WINDIR%\%DIRVERFILE% +@if errorlevel 3 goto error + +@loaddrv start %DIRVERNAME% +@if errorlevel 1 goto error + +@loaddrv starttype %DIRVERNAME% auto +@if errorlevel 1 goto error + +@echo Success +@goto exit + +:error +@echo ERROR: Installation of %DIRVERNAME% failed + +:exit + diff --git a/windows/loaddrv.c b/windows/loaddrv.c new file mode 100644 index 00000000..ca92a2a1 --- /dev/null +++ b/windows/loaddrv.c @@ -0,0 +1,460 @@ +// loaddrv.c - Dynamic driver install/start/stop/remove +// based on Paula Tomlinson's LOADDRV program. +// She describes it in her May 1995 article in Windows/DOS Developer's +// Journal (now Windows Developer's Journal). +// Modified by Chris Liechti +// I removed the old/ugly dialog, it now accepts command line options and +// prints error messages with textual description from the OS. + +#include +#include +#include +#include +#include +#include "loaddrv.h" + +// globals +SC_HANDLE hSCMan = NULL; + +//get ext messages for windows error codes: +void DisplayErrorText(DWORD dwLastError) { + LPSTR MessageBuffer; + DWORD dwBufferLength; + + DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM; + + dwBufferLength = FormatMessageA( + dwFormatFlags, + NULL, // module to get message from (NULL == system) + dwLastError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language + (LPSTR) &MessageBuffer, + 0, + NULL + ); + if (dwBufferLength) { + // Output message + puts(MessageBuffer); + // Free the buffer allocated by the system. + LocalFree(MessageBuffer); + } +} + +int exists(char *filename) { + FILE * pFile; + pFile = fopen(filename, "r"); + return pFile != NULL; +} + +void usage(void) { + printf("USGAE: loaddrv command drivername [args...]\n\n" + "NT/2k/XP Driver and Service modification tool.\n" + "(C)2002 Chris Liechti \n\n" + "Suported commands:\n\n" + " install [fullpathforinstall]\n" + " Install new service. Loaded from given path. If path is not present,\n" + " the local directory is searched for a .sys file. If the service\n" + " already exists, it must be removed first.\n" + " start\n" + " Start service. It must be installed in advance.\n" + " stop\n" + " Stop service.\n" + " remove\n" + " Remove service. It must be stopped in advance.\n" + " status\n" + " Show status information about service.\n" + " starttype auto|manual|system|disable\n" + " Change startup type to the given type.\n" + ); +} + +int main(int argc, char *argv[]) { + DWORD status = 0; + int level = 0; + if (argc < 3) { + usage(); + exit(1); + } + LoadDriverInit(); + if (strcmp(argv[1], "start") == 0) { + printf("starting %s... ", argv[2]); + status = DriverStart(argv[2]); + if ( status != OKAY) { + printf("start failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "stop") == 0) { + printf("stoping %s... ", argv[2]); + status = DriverStop(argv[2]); + if ( status != OKAY) { + printf("stop failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "install") == 0) { + char path[MAX_PATH*2]; + if (argc<4) { + char cwd[MAX_PATH]; + getcwd(cwd, sizeof cwd); + sprintf(path, "%s\\%s.sys", cwd, argv[2]); + } else { + strncpy(path, argv[3], MAX_PATH); + } + if (exists(path)) { + printf("installing %s from %s... ", argv[2], path); + status = DriverInstall(path, argv[2]); + if ( status != OKAY) { + printf("install failed (status %ld):\n", status); + level = 2; + } else { + printf("ok.\n"); + } + } else { + printf("install failed, file not found: %s\n", path); + level = 1; + } + } else if (strcmp(argv[1], "remove") == 0) { + printf("removing %s... ", argv[2]); + status = DriverRemove(argv[2]); + if ( status != OKAY) { + printf("remove failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "status") == 0) { + printf("status of %s:\n", argv[2]); + status = DriverStatus(argv[2]); + if ( status != OKAY) { + printf("stat failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } else if (strcmp(argv[1], "starttype") == 0) { + if (argc < 4) { + printf("Error: need start type (string) as argument.\n"); + level = 2; + } else { + DWORD type = 0; + printf("set start type of %s to %s... ", argv[2], argv[3]); + if (strcmp(argv[1], "boot") == 0) { + type = SERVICE_BOOT_START; + } else if (strcmp(argv[3], "system") == 0) { + type = SERVICE_SYSTEM_START; + } else if (strcmp(argv[3], "auto") == 0) { + type = SERVICE_AUTO_START; + } else if (strcmp(argv[3], "manual") == 0) { + type = SERVICE_DEMAND_START; + } else if (strcmp(argv[3], "disabled") == 0) { + type = SERVICE_DISABLED; + } else { + printf("unknown type\n"); + level = 1; + } + if (level == 0) { + status = DriverStartType(argv[2], type); + if ( status != OKAY) { + printf("set start type failed (status %ld):\n", status); + level = 1; + } else { + printf("ok.\n"); + } + } + } + } else { + usage(); + level = 1; + } + if (status) DisplayErrorText(status); + LoadDriverCleanup(); + exit(level); + return 0; +} + + +DWORD LoadDriverInit(void) { + // connect to local service control manager + if ((hSCMan = OpenSCManager(NULL, NULL, + SC_MANAGER_ALL_ACCESS)) == NULL) { + return -1; + } + return OKAY; +} + +void LoadDriverCleanup(void) { + if (hSCMan != NULL) CloseServiceHandle(hSCMan); +} + +/**-----------------------------------------------------**/ +DWORD DriverInstall(LPSTR lpPath, LPSTR lpDriver) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + // add to service control manager's database + if ((hService = CreateService(hSCMan, lpDriver, + lpDriver, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, lpPath, + NULL, NULL, NULL, NULL, NULL)) == NULL) + dwStatus = GetLastError(); + else CloseServiceHandle(hService); + + return dwStatus; +} // DriverInstall + +/**-----------------------------------------------------**/ +DWORD DriverStart(LPSTR lpDriver) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { + // start the driver + if (!StartService(hService, 0, NULL)) + dwStatus = GetLastError(); + } else dwStatus = GetLastError(); + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStart + +/**-----------------------------------------------------**/ +DWORD DriverStop(LPSTR lpDriver) +{ + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + SERVICE_STATUS serviceStatus; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { + // stop the driver + if (!ControlService(hService, SERVICE_CONTROL_STOP, + &serviceStatus)) + dwStatus = GetLastError(); + } else dwStatus = GetLastError(); + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStop + +/**-----------------------------------------------------**/ +DWORD DriverRemove(LPSTR lpDriver) +{ + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { // remove the driver + if (!DeleteService(hService)) + dwStatus = GetLastError(); + } else dwStatus = GetLastError(); + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverRemove + +/**-----------------------------------------------------**/ +////extensions by Lch +/**-----------------------------------------------------**/ +DWORD DriverStatus(LPSTR lpDriver) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + DWORD dwBytesNeeded; + + // get a handle to the service + if ((hService = OpenService(hSCMan, lpDriver, + SERVICE_ALL_ACCESS)) != NULL) + { + LPQUERY_SERVICE_CONFIG lpqscBuf; + //~ LPSERVICE_DESCRIPTION lpqscBuf2; + // Allocate a buffer for the configuration information. + if ((lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc( + LPTR, 4096)) != NULL) + { + //~ if ((lpqscBuf2 = (LPSERVICE_DESCRIPTION) LocalAlloc( + //~ LPTR, 4096)) != NULL) + { + // Get the configuration information. + if (QueryServiceConfig( + hService, + lpqscBuf, + 4096, + &dwBytesNeeded) //&& + //~ QueryServiceConfig2( + //~ hService, + //~ SERVICE_CONFIG_DESCRIPTION, + //~ lpqscBuf2, + //~ 4096, + //~ &dwBytesNeeded + ) + { + // Print the configuration information. + printf("Type: [0x%02lx] ", lpqscBuf->dwServiceType); + switch (lpqscBuf->dwServiceType) { + case SERVICE_WIN32_OWN_PROCESS: + printf("The service runs in its own process."); + break; + case SERVICE_WIN32_SHARE_PROCESS: + printf("The service shares a process with other services."); + break; + case SERVICE_KERNEL_DRIVER: + printf("Kernel driver."); + break; + case SERVICE_FILE_SYSTEM_DRIVER: + printf("File system driver."); + break; + case SERVICE_INTERACTIVE_PROCESS: + printf("The service can interact with the desktop."); + break; + default: + printf("Unknown type."); + } + printf("\nStart Type: [0x%02lx] ", lpqscBuf->dwStartType); + switch (lpqscBuf->dwStartType) { + case SERVICE_BOOT_START: + printf("Boot"); + break; + case SERVICE_SYSTEM_START: + printf("System"); + break; + case SERVICE_AUTO_START: + printf("Automatic"); + break; + case SERVICE_DEMAND_START: + printf("Manual"); + break; + case SERVICE_DISABLED: + printf("Disabled"); + break; + default: + printf("Unknown."); + } + printf("\nError Control: [0x%02lx] ", lpqscBuf->dwErrorControl); + switch (lpqscBuf->dwErrorControl) { + case SERVICE_ERROR_IGNORE: + printf("IGNORE: Ignore."); + break; + case SERVICE_ERROR_NORMAL: + printf("NORMAL: Display a message box."); + break; + case SERVICE_ERROR_SEVERE: + printf("SEVERE: Restart with last-known-good config."); + break; + case SERVICE_ERROR_CRITICAL: + printf("CRITICAL: Restart w/ last-known-good config."); + break; + default: + printf("Unknown."); + } + printf("\nBinary path: %s\n", lpqscBuf->lpBinaryPathName); + + if (lpqscBuf->lpLoadOrderGroup != NULL) + printf("Load order grp: %s\n", lpqscBuf->lpLoadOrderGroup); + if (lpqscBuf->dwTagId != 0) + printf("Tag ID: %ld\n", lpqscBuf->dwTagId); + if (lpqscBuf->lpDependencies != NULL) + printf("Dependencies: %s\n", lpqscBuf->lpDependencies); + if (lpqscBuf->lpServiceStartName != NULL) + printf("Start Name: %s\n", lpqscBuf->lpServiceStartName); + //~ if (lpqscBuf2->lpDescription != NULL) + //~ printf("Description: %s\n", lpqscBuf2->lpDescription); + } + //~ LocalFree(lpqscBuf2); + } + LocalFree(lpqscBuf); + } else { + dwStatus = GetLastError(); + } + } else { + dwStatus = GetLastError(); + } + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStatus + +/**-----------------------------------------------------**/ +DWORD DriverStartType(LPSTR lpDriver, DWORD dwStartType) { + BOOL dwStatus = OKAY; + SC_HANDLE hService = NULL; + + SC_LOCK sclLock; + LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf; + DWORD dwBytesNeeded; + + // Need to acquire database lock before reconfiguring. + sclLock = LockServiceDatabase(hSCMan); + + // If the database cannot be locked, report the details. + if (sclLock == NULL) { + // Exit if the database is not locked by another process. + if (GetLastError() == ERROR_SERVICE_DATABASE_LOCKED) { + + // Allocate a buffer to get details about the lock. + lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc( + LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256); + if (lpqslsBuf != NULL) { + // Get and print the lock status information. + if (QueryServiceLockStatus( + hSCMan, + lpqslsBuf, + sizeof(QUERY_SERVICE_LOCK_STATUS)+256, + &dwBytesNeeded) ) + { + if (lpqslsBuf->fIsLocked) { + printf("Locked by: %s, duration: %ld seconds\n", + lpqslsBuf->lpLockOwner, + lpqslsBuf->dwLockDuration + ); + } else { + printf("No longer locked\n"); + } + } + LocalFree(lpqslsBuf); + } + } + dwStatus = GetLastError(); + } else { + // The database is locked, so it is safe to make changes. + // Open a handle to the service. + hService = OpenService( + hSCMan, // SCManager database + lpDriver, // name of service + SERVICE_CHANGE_CONFIG + ); // need CHANGE access + if (hService != NULL) { + // Make the changes. + if (!ChangeServiceConfig( + hService, // handle of service + SERVICE_NO_CHANGE, // service type: no change + dwStartType, // change service start type + SERVICE_NO_CHANGE, // error control: no change + NULL, // binary path: no change + NULL, // load order group: no change + NULL, // tag ID: no change + NULL, // dependencies: no change + NULL, // account name: no change + NULL, // password: no change + NULL) ) // display name: no change + { + dwStatus = GetLastError(); + } + } + // Release the database lock. + UnlockServiceDatabase(sclLock); + } + + if (hService != NULL) CloseServiceHandle(hService); + return dwStatus; +} // DriverStartType diff --git a/windows/loaddrv.h b/windows/loaddrv.h new file mode 100644 index 00000000..d7d102b9 --- /dev/null +++ b/windows/loaddrv.h @@ -0,0 +1,20 @@ +#ifndef LOADDRV_H +#define LOADDRV_H + +#include + +#define OKAY 0 +#define UNEXPECTED_ERROR 9999 + +//prototypes +DWORD LoadDriverInit(void); +void LoadDriverCleanup(void); +DWORD DriverInstall(LPSTR, LPSTR); +DWORD DriverStart(LPSTR); +DWORD DriverStop(LPSTR); +DWORD DriverRemove(LPSTR); +DWORD DriverStatus(LPSTR); +DWORD DriverStartType(LPSTR, DWORD); +#endif //LOADDRV_H + + diff --git a/windows/remove_giveio.bat b/windows/remove_giveio.bat new file mode 100755 index 00000000..024427db --- /dev/null +++ b/windows/remove_giveio.bat @@ -0,0 +1,14 @@ +@set DIRVERNAME=giveio + +@loaddrv stop %DIRVERNAME% +@if errorlevel 2 goto error + +@loaddrv remove %DIRVERNAME% +@if errorlevel 1 goto error + +@goto exit + +:error +@echo ERROR: Deinstallation of %DIRVERNAME% failed + +:exit diff --git a/windows/status_giveio.bat b/windows/status_giveio.bat new file mode 100755 index 00000000..bc821474 --- /dev/null +++ b/windows/status_giveio.bat @@ -0,0 +1,12 @@ +@set DIRVERNAME=giveio + +@loaddrv status %DIRVERNAME% +@if errorlevel 1 goto error + +@goto exit + +:error +@echo ERROR: Status querry for %DIRVERNAME% failed + +:exit +