diff options
author | Wohlstand <admin@wohlnet.ru> | 2020-09-21 00:45:06 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2020-09-21 00:45:06 +0300 |
commit | f95e5ff580b68b13ba308fd54e1c95d4197ad863 (patch) | |
tree | 63539cbf427912686565dab81b3aa820346967b5 /utils/winmm_drv/installer/drvinst.c | |
parent | 193ac787fed2beb43c89312e5f45e231d50c544d (diff) | |
parent | 9b51dd7d667e97338a92711543fc3e942faae52f (diff) | |
download | libADLMIDI-f95e5ff580b68b13ba308fd54e1c95d4197ad863.tar.gz libADLMIDI-f95e5ff580b68b13ba308fd54e1c95d4197ad863.tar.bz2 libADLMIDI-f95e5ff580b68b13ba308fd54e1c95d4197ad863.zip |
Merge branch 'master' of github.com:Wohlstand/libADLMIDI
Diffstat (limited to 'utils/winmm_drv/installer/drvinst.c')
-rw-r--r-- | utils/winmm_drv/installer/drvinst.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/utils/winmm_drv/installer/drvinst.c b/utils/winmm_drv/installer/drvinst.c new file mode 100644 index 0000000..e354691 --- /dev/null +++ b/utils/winmm_drv/installer/drvinst.c @@ -0,0 +1,276 @@ +/* Copyright (C) 2011, 2012 Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define WIN32_LEAN_AND_MEAN +#include <windef.h> +#include <winbase.h> +#include <winuser.h> +#include <winreg.h> +#include <winerror.h> + +const char OPL3EMU_DRIVER_NAME[] = "adlmididrv.dll"; +const char OPL3EMU_CPLAPPLET_NAME[] = "libadlconfig.cpl"; +const char OPL3EMU_SETUPTOOL_NAME[] = "adlmidiconfigtool.exe"; + +const char WDM_DRIVER_NAME[] = "wdmaud.drv"; +const char SYSTEM_DIR_NAME[] = "SYSTEM32"; +const char SYSTEM_ROOT_ENV_NAME[] = "SYSTEMROOT"; +const char INSTALL_COMMAND[] = "install"; +const char UNINSTALL_COMMAND[] = "uninstall"; +const char DRIVERS_REGISTRY_KEY[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"; +const char PATH_SEPARATOR[] = "\\"; + +const char SUCCESSFULLY_INSTALLED_MSG[] = "libADLMIDI synth MIDI Driver successfully installed"; +const char SUCCESSFULLY_UPDATED_MSG[] = "libADLMIDI synth MIDI Driver successfully updated"; +const char SUCCESSFULLY_UNINSTALLED_MSG[] = "libADLMIDI synth MIDI Driver successfully uninstalled"; +const char USAGE_MSG[] = "Usage:\n drvsetup install - install driver\n drvsetup uninstall - uninstall driver"; + +const char CANNOT_OPEN_REGISTRY_ERR[] = "Cannot open registry key"; +const char CANNOT_INSTALL_NO_PORTS_ERR[] = "Cannot install libADLMIDI synth MIDI driver:\n There is no MIDI ports available"; +const char CANNOT_REGISTER_ERR[] = "Cannot register driver"; +const char CANNOT_UNINSTALL_ERR[] = "Cannot uninstall libADLMIDI synth MIDI driver"; +const char CANNOT_UNINSTALL_NOT_FOUND_ERR[] = "Cannot uninstall libADLMIDI synth MIDI driver:\n There is no driver registry entry found"; +const char CANNOT_INSTALL_PATH_TOO_LONG_ERR[] = "libADLMIDI synth MIDI Driver cannot be installed:\n Installation path is too long"; +const char CANNOT_INSTALL_FILE_COPY_ERR[] = "libADLMIDI synth MIDI Driver failed to install:\n File copying error"; + +const char INFORMATION_TITLE[] = "Information"; +const char ERROR_TITLE[] = "Error"; +const char REGISTRY_ERROR_TITLE[] = "Registry error"; +const char FILE_ERROR_TITLE[] = "File error"; + +BOOL registerDriver(BOOL *installMode) +{ + char str[255]; + char drvName[] = "midi0"; + DWORD len, res; + BOOL wdmEntryFound = FALSE; + int freeEntry = -1; + HKEY hReg; + int i; + + if(RegOpenKeyA(HKEY_LOCAL_MACHINE, DRIVERS_REGISTRY_KEY, &hReg)) + { + MessageBoxA(NULL, CANNOT_OPEN_REGISTRY_ERR, REGISTRY_ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + return FALSE; + } + + for(i = 0; i < 10; i++) + { + len = 255; + if(i) + drvName[4] = '0' + i; + else + drvName[4] = 0; + res = RegQueryValueExA(hReg, drvName, NULL, NULL, (LPBYTE)str, &len); + if(res != ERROR_SUCCESS) + { + if((freeEntry == -1) && (res == ERROR_FILE_NOT_FOUND)) + freeEntry = i; + continue; + } + if(!_stricmp(str, OPL3EMU_DRIVER_NAME)) + { + RegCloseKey(hReg); + *installMode = FALSE; + return TRUE; + } + if(freeEntry != -1) continue; + if(strlen(str) == 0) + freeEntry = i; + else if(!_stricmp(str, WDM_DRIVER_NAME)) + { + // Considering multiple WDM entries are just garbage, though one entry shouldn't be modified + if(wdmEntryFound) + freeEntry = i; + else + wdmEntryFound = TRUE; + } + } + + if(freeEntry == -1) + { + MessageBoxA(NULL, CANNOT_INSTALL_NO_PORTS_ERR, ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + RegCloseKey(hReg); + return FALSE; + } + + if(freeEntry) + drvName[4] = '0' + freeEntry; + else + drvName[4] = 0; + + res = RegSetValueExA(hReg, drvName, 0, REG_SZ, (LPBYTE)OPL3EMU_DRIVER_NAME, sizeof(OPL3EMU_DRIVER_NAME)); + if(res != ERROR_SUCCESS) + { + MessageBoxA(NULL, CANNOT_REGISTER_ERR, REGISTRY_ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + RegCloseKey(hReg); + return FALSE; + } + + RegCloseKey(hReg); + + return TRUE; +} + +void unregisterDriver() +{ + char str[255]; + char drvName[] = "midi0"; + DWORD len, res; + HKEY hReg; + int i; + + if(RegOpenKeyA(HKEY_LOCAL_MACHINE, DRIVERS_REGISTRY_KEY, &hReg)) + { + MessageBoxA(NULL, CANNOT_OPEN_REGISTRY_ERR, REGISTRY_ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + return; + } + + for(i = 0; i < 10; i++) + { + len = 255; + if(i) + drvName[4] = '0' + i; + else + drvName[4] = 0; + res = RegQueryValueExA(hReg, drvName, NULL, NULL, (LPBYTE)str, &len); + if(res != ERROR_SUCCESS) + continue; + if(!_stricmp(str, OPL3EMU_DRIVER_NAME)) + { + res = RegDeleteValueA(hReg, drvName); + if(res != ERROR_SUCCESS) + { + MessageBoxA(NULL, CANNOT_UNINSTALL_ERR, REGISTRY_ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + RegCloseKey(hReg); + return; + } + MessageBoxA(NULL, SUCCESSFULLY_UNINSTALLED_MSG, INFORMATION_TITLE, MB_OK | MB_ICONINFORMATION); + RegCloseKey(hReg); + return; + } + } + + MessageBoxA(NULL, CANNOT_UNINSTALL_NOT_FOUND_ERR, ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + RegCloseKey(hReg); +} + +void constructSystemDirName(char *pathName) +{ + char sysRoot[MAX_PATH + 1]; + GetEnvironmentVariableA(SYSTEM_ROOT_ENV_NAME, sysRoot, MAX_PATH); + strncpy(pathName, sysRoot, MAX_PATH + 1); + strncat(pathName, PATH_SEPARATOR, MAX_PATH - strlen(pathName)); + strncat(pathName, SYSTEM_DIR_NAME, MAX_PATH - strlen(pathName)); + strncat(pathName, PATH_SEPARATOR, MAX_PATH - strlen(pathName)); +} + +void constructDriverPathName(char *pathName, const char*fileName) +{ + constructSystemDirName(pathName); + strncat(pathName, fileName, MAX_PATH - strlen(pathName)); +} + +void deleteFileReliably(char *pathName, const char *fileName) +{ + const size_t nameSize = strlen(fileName) + 1; + char tmpFilePrefix[nameSize + 1]; + char tmpDirName[MAX_PATH + 1]; + char tmpPathName[MAX_PATH + 1]; + + if(DeleteFileA(pathName)) + return; + // File doesn't exist, nothing to do + if(ERROR_FILE_NOT_FOUND == GetLastError()) + return; + + // File can't be deleted, rename it and register pending deletion + strncpy(tmpFilePrefix, fileName, nameSize); + strncat(tmpFilePrefix, ".", nameSize); + constructSystemDirName(tmpDirName); + GetTempFileNameA(tmpDirName, tmpFilePrefix, 0, tmpPathName); + DeleteFileA(tmpPathName); + MoveFileA(pathName, tmpPathName); + MoveFileExA(tmpPathName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); +} + +BOOL copyFileIntoSystem(const char *fileName, char **argv) +{ + char driverPathName[MAX_PATH + 1]; + char setupPathName[MAX_PATH + 1]; + int setupPathLen; + + setupPathLen = strrchr(argv[0], '\\') - argv[0]; + if(setupPathLen > (int)(MAX_PATH - strlen(fileName) + 1 - 2)) + { + MessageBoxA(NULL, CANNOT_INSTALL_PATH_TOO_LONG_ERR, ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + return 2; + } + + constructDriverPathName(driverPathName, fileName); + deleteFileReliably(driverPathName, fileName); + + strncpy(setupPathName, argv[0], setupPathLen); + setupPathName[setupPathLen] = 0; + strncat(setupPathName, PATH_SEPARATOR, MAX_PATH - strlen(setupPathName)); + strncat(setupPathName, fileName, MAX_PATH - strlen(setupPathName)); + + if(!CopyFileA(setupPathName, driverPathName, FALSE)) + { + MessageBoxA(NULL, CANNOT_INSTALL_FILE_COPY_ERR, FILE_ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION); + return FALSE; + } + return TRUE; +} + +int main(int argc, char *argv[]) +{ + char pathName[MAX_PATH + 1]; + BOOL installMode; + + if(argc != 2 || (_stricmp(INSTALL_COMMAND, argv[1]) != 0 && _stricmp(UNINSTALL_COMMAND, argv[1]) != 0)) + { + MessageBoxA(NULL, USAGE_MSG, INFORMATION_TITLE, MB_OK | MB_ICONINFORMATION); + return 1; + } + + if(_stricmp(UNINSTALL_COMMAND, argv[1]) == 0) + { + constructDriverPathName(pathName, OPL3EMU_DRIVER_NAME); + deleteFileReliably(pathName, OPL3EMU_DRIVER_NAME); + constructDriverPathName(pathName, OPL3EMU_CPLAPPLET_NAME); + deleteFileReliably(pathName, OPL3EMU_CPLAPPLET_NAME); + constructDriverPathName(pathName, OPL3EMU_SETUPTOOL_NAME); + deleteFileReliably(pathName, OPL3EMU_SETUPTOOL_NAME); + + unregisterDriver(); + return 0; + } + + installMode = TRUE; + if(!registerDriver(&installMode)) + return 3; + + if(!copyFileIntoSystem(OPL3EMU_DRIVER_NAME, argv)) + return 4; + if(!copyFileIntoSystem(OPL3EMU_CPLAPPLET_NAME, argv)) + return 4; + if(!copyFileIntoSystem(OPL3EMU_SETUPTOOL_NAME, argv)) + return 4; + + MessageBoxA(NULL, installMode ? SUCCESSFULLY_INSTALLED_MSG : SUCCESSFULLY_UPDATED_MSG, INFORMATION_TITLE, MB_OK | MB_ICONINFORMATION); + return 0; +} |