https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d4a9879583a0e126fda04679d0ac620b03f770b6
commit d4a9879583a0e126fda04679d0ac620b03f770b6 Author: Max Korostil <mrmk...@yandex.ru> AuthorDate: Sun Oct 25 04:03:34 2020 +0300 Commit: Mark Jansen <mark.jan...@reactos.org> CommitDate: Sat May 8 14:24:20 2021 +0200 [SDBINST] Add uninstall by guid and name --- base/applications/sdbinst/sdbinst.c | 350 +++++++++++++++++++++++++++++++++--- 1 file changed, 324 insertions(+), 26 deletions(-) diff --git a/base/applications/sdbinst/sdbinst.c b/base/applications/sdbinst/sdbinst.c index f124c667820..c4783ae68f7 100644 --- a/base/applications/sdbinst/sdbinst.c +++ b/base/applications/sdbinst/sdbinst.c @@ -1,4 +1,11 @@ -#define WIN32_NO_STATUS +/* + * PROJECT: ReactOS sdbinst + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Application compatibility database installer + * COPYRIGHT: Copyright 2020 Max Korostil (mrmk...@yandex.ru) + */ + + #include <windef.h> #include <winbase.h> #include <tchar.h> @@ -11,7 +18,9 @@ #define APPCOMPAT_CUSTOM_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom" #define APPCOMPAT_LAYERS_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers" +#define APPCOMPAT_INSTALLEDSDB_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB" #define UNINSTALL_REG_PATH L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" +#define DBPATH_KEY_NAME L"DatabasePath" HRESULT RegisterSdbEntry( @@ -21,11 +30,20 @@ RegisterSdbEntry( _In_ BOOL isInstall, _In_ BOOL isExe) { - WCHAR regName[MAX_PATH] = {0}; - HKEY hKey; + PWCHAR regName; + HKEY hKey = NULL; LSTATUS status; + HRESULT hres; + + regName = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + if (!regName) + { + hres = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + goto end; + } + ZeroMemory(regName, MAX_PATH * sizeof(WCHAR)); - HRESULT hres = StringCchPrintf(regName, sizeof(regName) / sizeof(WCHAR), L"%ls\\%ls", + hres = StringCchPrintf(regName, MAX_PATH, L"%ls\\%ls", isExe ? APPCOMPAT_CUSTOM_REG_PATH : APPCOMPAT_LAYERS_REG_PATH, sdbEntryName); if (FAILED(hres)) { @@ -73,6 +91,16 @@ RegisterSdbEntry( } end: + if (hKey) + { + RegCloseKey(hKey); + } + + if (regName) + { + HeapFree(GetProcessHeap(), 0, regName); + } + return hres; } @@ -82,27 +110,41 @@ AddUninstallKey( _In_ LPCWSTR sdbInstalledPath, _In_ LPCWSTR guidDbStr) { - WCHAR sdbinstPath[MAX_PATH] = {0}; - WCHAR regName[MAX_PATH] = {0}; - WCHAR uninstString[MAX_PATH * 2] = {0}; - HKEY hKey; + PWCHAR sdbinstPath; + PWCHAR regName; + PWCHAR uninstString; + HKEY hKey = NULL; HRESULT hres; - UINT count = GetSystemWindowsDirectory(sdbinstPath, sizeof(sdbinstPath) / sizeof(WCHAR)); + sdbinstPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + regName = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + uninstString = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + + if (!sdbinstPath || !regName || !uninstString) + { + hres = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + goto end; + } + + ZeroMemory(sdbinstPath, MAX_PATH * sizeof(WCHAR)); + ZeroMemory(regName, MAX_PATH * sizeof(WCHAR)); + ZeroMemory(uninstString, MAX_PATH * sizeof(WCHAR)); + + UINT count = GetSystemWindowsDirectory(sdbinstPath, MAX_PATH); if (sdbinstPath[count - 1] != L'\\') { sdbinstPath[count] = L'\\'; } // Full path to sdbinst.exe - hres = StringCchCat(sdbinstPath, sizeof(sdbinstPath) / sizeof(WCHAR), L"System32\\sdbinst.exe"); + hres = StringCchCat(sdbinstPath, MAX_PATH, L"System32\\sdbinst.exe"); if (FAILED(hres)) { wprintf(L"StringCchCat error: 0x%08X", hres); } // Sdb guid reg key - hres = StringCchPrintf(regName, sizeof(regName) / sizeof(WCHAR), L"%ls\\%ls", UNINSTALL_REG_PATH, guidDbStr); + hres = StringCchPrintf(regName, MAX_PATH, L"%ls\\%ls", UNINSTALL_REG_PATH, guidDbStr); if (FAILED(hres)) { wprintf(L"StringCchPrintfW error: 0x%08X", hres); @@ -146,7 +188,7 @@ AddUninstallKey( } // Uninstall full string - hres = StringCchPrintf(uninstString, sizeof(uninstString) / sizeof(WCHAR), L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath); + hres = StringCchPrintf(uninstString, MAX_PATH, L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath); if (FAILED(hres)) { wprintf(L"StringCchPrintfW error: 0x%08X", hres); @@ -169,6 +211,25 @@ AddUninstallKey( } end: + if (hKey) + { + RegCloseKey(hKey); + } + + if (sdbinstPath) + { + HeapFree(GetProcessHeap(), 0, sdbinstPath); + } + + if (regName) + { + HeapFree(GetProcessHeap(), 0, regName); + } + + if (uninstString) + { + HeapFree(GetProcessHeap(), 0, uninstString); + } return hres; } @@ -376,7 +437,14 @@ SdbInstall( FILETIME systemTime = {0}; ULARGE_INTEGER currentTime = {0}; PWCHAR sysdirPatchPath = NULL; - WCHAR guidDbStr[MAX_PATH] = {0}; + PWCHAR guidDbStr; + + guidDbStr = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + if (!guidDbStr) + { + goto end; + } + ZeroMemory(guidDbStr, MAX_PATH * sizeof(WCHAR)); GetSystemTimeAsFileTime(&systemTime); currentTime.LowPart = systemTime.dwLowDateTime; @@ -405,14 +473,14 @@ SdbInstall( } StringFromGUID2(&dbGuid, guidDbStr, MAX_PATH); - HRESULT hres = StringCchCatW(guidDbStr, sizeof(guidDbStr) / sizeof(WCHAR), L".sdb"); + HRESULT hres = StringCchCatW(guidDbStr, MAX_PATH, L".sdb"); if (FAILED(hres)) { wprintf(L"StringCchCatW error 0x%08X\n", hres); goto end; } - wprintf(L"Database guid %wZ\n", &guidDbStr); + wprintf(L"Database guid %ls\n", guidDbStr); tagDbName = SdbFindFirstTag(pdb, tagDb, TAG_NAME); if (!tagDbName) @@ -477,6 +545,16 @@ end: SdbCloseDatabase(pdb); } + if (sysdirPatchPath) + { + HeapFree(GetProcessHeap(), 0, sysdirPatchPath); + } + + if (guidDbStr) + { + HeapFree(GetProcessHeap(), 0, guidDbStr); + } + return res; } @@ -484,7 +562,7 @@ HRESULT DeleteUninstallKey( _In_ LPCWSTR keyName) { - HKEY hKey; + HKEY hKey = NULL; HRESULT hres = HRESULT_FROM_WIN32(ERROR_SUCCESS); LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, @@ -510,6 +588,11 @@ DeleteUninstallKey( } end: + if (hKey) + { + RegCloseKey(hKey); + } + return hres; } @@ -521,14 +604,16 @@ SdbUninstall( PWCHAR sdbName = NULL; PDB pdb; TAGID tagDb; - GUID dbGuid; + GUID dbGuid = {0}; SIZE_T sdbPathLen = wcslen(sdbPath); sdbName = sdbPath + sdbPathLen; - while (*sdbName != L'\\') + wprintf(L"uninstall name %ls\n", sdbPath); + while (*sdbName != L'\\' && sdbPathLen > 0) { --sdbName; + --sdbPathLen; } sdbName++; @@ -570,7 +655,7 @@ SdbUninstall( if (FAILED(hres)) { wprintf(L"Remove key fail\n"); - goto end; + //goto end; } if (!SdbUnregisterDatabase(&dbGuid)) @@ -585,10 +670,183 @@ SdbUninstall( goto end; } + res = TRUE; + end: return res; } +#define BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(WCHAR)) +#define STRING_LEN (MAX_PATH + 1) + +BOOL +SdbUninstallByGuid( + _In_ LPWSTR guidSdbStr) +{ + BOOL res = FALSE; + HKEY hKey = NULL; + HKEY guidKey = NULL; + LSTATUS status; + DWORD keyValSize = BUFFER_SIZE; + PWCHAR dbPath = NULL; + + dbPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE); + if (!dbPath) + { + goto end; + } + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, APPCOMPAT_INSTALLEDSDB_REG_PATH, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); + + if (status != ERROR_SUCCESS) + { + wprintf(L"RegOpenKey error: 0x%08X", status); + goto end; + } + + status = RegOpenKeyEx(hKey, guidSdbStr, 0, KEY_READ | KEY_QUERY_VALUE, &guidKey); + + if (status != ERROR_SUCCESS) + { + wprintf(L"Cant open key: 0x%08X %ls\n", status, guidSdbStr); + goto end; + } + + status = RegQueryValueEx(guidKey, DBPATH_KEY_NAME, NULL, NULL, (LPBYTE)dbPath, &keyValSize); + if (status != ERROR_SUCCESS) + { + wprintf(L"RegQueryValueEx: 0x%08X\n", status); + goto end; + } + + res = SdbUninstall(dbPath); + +end: + if (dbPath) + { + HeapFree(GetProcessHeap(), 0, dbPath); + } + + if (hKey) + { + RegCloseKey(hKey); + } + + if (guidKey) + { + RegCloseKey(guidKey); + } + + return res; +} + +BOOL +SdbUninstallByName( + _In_ LPWSTR nameSdbStr) +{ + BOOL res = FALSE; + LSTATUS status; + HKEY hKey = NULL; + HKEY subKey = NULL; + DWORD index = 0; + DWORD keyNameLen = STRING_LEN; + PWCHAR keyName = NULL; + DWORD keyValSize; + PWCHAR dbDescript = NULL; + PWCHAR dbPath = NULL; + + keyName = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE); + dbDescript = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE); + dbPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE); + + if (!keyName || !dbDescript || !dbPath) + { + goto end; + } + + ZeroMemory(keyName, BUFFER_SIZE); + ZeroMemory(dbDescript, BUFFER_SIZE); + ZeroMemory(dbPath, BUFFER_SIZE); + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, APPCOMPAT_INSTALLEDSDB_REG_PATH, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); + + if (status != ERROR_SUCCESS) + { + wprintf(L"RegOpenKey error: 0x%08X", status); + goto end; + } + + status = RegEnumKeyEx(hKey, index, keyName, &keyNameLen, NULL, NULL, NULL, NULL); + wprintf(L"0x%08X %d %ls \n", status, keyNameLen, keyName); + + // Search db guid by name + while (status == ERROR_SUCCESS) + { + status = RegOpenKeyEx(hKey, keyName, 0, KEY_READ | KEY_QUERY_VALUE, &subKey); + if (status != ERROR_SUCCESS) + { + break; + } + + keyValSize = BUFFER_SIZE; + status = RegQueryValueEx(subKey, L"DatabaseDescription", NULL, NULL, (LPBYTE)dbDescript, &keyValSize); + if (status != ERROR_SUCCESS) + { + break; + } + + wprintf(L"dbdescript: %ls \n", dbDescript); + + if (_wcsnicmp(dbDescript, nameSdbStr, keyNameLen) == 0) + { + // Take db full path + keyValSize = BUFFER_SIZE; + status = RegQueryValueEx(subKey, DBPATH_KEY_NAME, NULL, NULL, (LPBYTE)dbPath, &keyValSize); + if (status != ERROR_SUCCESS) + { + dbPath[0] = UNICODE_NULL; + break; + } + + wprintf(L"dbpath: 0x%08X %ls \n", status, dbPath); + RegCloseKey(subKey); + break; + } + + RegCloseKey(subKey); + + keyName[0] = UNICODE_NULL; + + ++index; + keyNameLen = STRING_LEN; + status = RegEnumKeyEx(hKey, index, keyName, &keyNameLen, NULL, NULL, NULL, NULL); + } + + RegCloseKey(hKey); + + if (dbPath[0] != UNICODE_NULL) + { + res = SdbUninstall(dbPath); + } + +end: + if (dbPath) + { + HeapFree(GetProcessHeap(), 0, dbPath); + } + + if (dbDescript) + { + HeapFree(GetProcessHeap(), 0, dbDescript); + } + + if (keyName) + { + HeapFree(GetProcessHeap(), 0, keyName); + } + + return res; +} void @@ -596,7 +854,7 @@ ShowHelp() { wprintf(L"Using: sdbinst [-?][-q][-u][-g][-n] foo.sdb | {guid} | \"name\" \n" L"-? - show help\n" - L"-q - silence mode\n" + //L"-q - silence mode\n" L"-u - uninstall\n" L"-g - {guid} file guid (only uninstall)\n" L"-n - \"name\" - file name (only uninstall)\n"); @@ -606,7 +864,11 @@ int _tmain(int argc, LPWSTR argv[]) { LPWSTR sdbPath = NULL; BOOL isInstall = TRUE; - //LPWSTR guidSdbStr = NULL; + BOOL isUninstByGuid = FALSE; + BOOL isUninstByName = FALSE; + BOOL success = FALSE; + LPWSTR guidSdbStr = NULL; + LPWSTR nameSdbStr = NULL; if (argc < 2) { @@ -635,24 +897,60 @@ int _tmain(int argc, LPWSTR argv[]) case L'g': ++i; - if (i < argc) + if (i >= argc) { return ERROR_INVALID_PARAMETER; } - //guidSdbStr = argv[i]; + guidSdbStr = argv[i]; + wprintf(L"guidSdbStr %ls\n", guidSdbStr); + + isUninstByGuid = TRUE; + isInstall = FALSE; + break; + + case L'n': + ++i; + + if (i >= argc) + { + return ERROR_INVALID_PARAMETER; + } + + nameSdbStr = argv[i]; + wprintf(L"guidSdbStr %ls\n", nameSdbStr); + + isUninstByName = TRUE; + isInstall = FALSE; break; } } if (isInstall) { - SdbInstall(sdbPath); + wprintf(L"install\n"); + success = SdbInstall(sdbPath); + } + else if (isUninstByGuid) + { + wprintf(L"uninstall by guid\n"); + success = SdbUninstallByGuid(guidSdbStr); + } + else if (isUninstByName) + { + wprintf(L"uninstall by name\n"); + success = SdbUninstallByName(nameSdbStr); } else { - // call uninstall - SdbUninstall(sdbPath); + wprintf(L"uninstall\n"); + success = SdbUninstall(sdbPath); + } + + if (!success) + { + wprintf(L"Sdb install failed\n"); + return -1; } return ERROR_SUCCESS;