From 7fd004e50b2fe8b6529757ecfa595704e2b9fad0 Mon Sep 17 00:00:00 2001 From: Max Korostil Date: Thu, 22 Oct 2020 22:45:20 +0300 Subject: [PATCH] [SDBINST] Add uninstall option --- base/applications/sdbinst/sdbinst.c | 257 +++++++++++++++++++++++----- dll/appcompat/apphelp/apphelp.h | 1 + 2 files changed, 218 insertions(+), 40 deletions(-) diff --git a/base/applications/sdbinst/sdbinst.c b/base/applications/sdbinst/sdbinst.c index 530071d1749..f124c667820 100644 --- a/base/applications/sdbinst/sdbinst.c +++ b/base/applications/sdbinst/sdbinst.c @@ -9,34 +9,47 @@ -#define APPCOMPAT_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom\\" +#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 UNINSTALL_REG_PATH L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" HRESULT RegisterSdbEntry( _In_ PWCHAR sdbEntryName, _In_ LPCWSTR dbGuid, - _In_ ULONGLONG time) + _In_ ULONGLONG time, + _In_ BOOL isInstall, + _In_ BOOL isExe) { WCHAR regName[MAX_PATH] = {0}; HKEY hKey; + LSTATUS status; - HRESULT hres = StringCchPrintf(regName, sizeof(regName) / sizeof(WCHAR), L"%ls\\%ls", APPCOMPAT_REG_PATH, sdbEntryName); + HRESULT hres = StringCchPrintf(regName, sizeof(regName) / sizeof(WCHAR), L"%ls\\%ls", + isExe ? APPCOMPAT_CUSTOM_REG_PATH : APPCOMPAT_LAYERS_REG_PATH, sdbEntryName); if (FAILED(hres)) { - wprintf(L"StringCchPrintfW error: 0x%08X", hres); + wprintf(L"StringCchPrintfW error: 0x%08X\n", hres); goto end; } - LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, - regName, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKey, - NULL); + // Remove key + if (!isInstall) + { + status = RegDeleteKey(HKEY_LOCAL_MACHINE, regName); + return HRESULT_FROM_WIN32(status); + } + + // Create main key + status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, + regName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKey, + NULL); if (status != ERROR_SUCCESS) { @@ -45,6 +58,7 @@ RegisterSdbEntry( goto end; } + // Set instlled time status = RegSetValueEx(hKey, dbGuid, 0, @@ -80,12 +94,14 @@ AddUninstallKey( sdbinstPath[count] = L'\\'; } + // Full path to sdbinst.exe hres = StringCchCat(sdbinstPath, sizeof(sdbinstPath) / sizeof(WCHAR), 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); if (FAILED(hres)) { @@ -96,6 +112,7 @@ AddUninstallKey( wprintf(L"%ls\n", sdbinstPath); wprintf(L"%ls\n", regName); + // Create main key LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, regName, 0, @@ -113,6 +130,7 @@ AddUninstallKey( goto end; } + // Set Display name DWORD length = wcslen(dbName) * sizeof(WCHAR); status = RegSetValueEx(hKey, L"DisplayName", @@ -127,7 +145,7 @@ AddUninstallKey( goto end; } - // Uninst string + // Uninstall full string hres = StringCchPrintf(uninstString, sizeof(uninstString) / sizeof(WCHAR), L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath); if (FAILED(hres)) { @@ -135,8 +153,7 @@ AddUninstallKey( goto end; } - //wprintf(L"%ls\n", uninstString); - + // Set uninstall string length = wcslen(uninstString) * sizeof(WCHAR); status = RegSetValueEx(hKey, L"UninstallString", @@ -188,15 +205,18 @@ HRESULT ProcessLayers( _In_ PDB pdb, _In_ TAGID tagDb, - _In_ LPCWSTR guidDbStr, - _In_ ULONGLONG time) + _In_opt_ LPCWSTR guidDbStr, + _In_opt_ ULONGLONG time, + _In_ BOOL isInstall) { HRESULT res = ERROR_SUCCESS; TAGID tagLayerName; + TAGID prevTagLayer = 0; TAGID tagLayer = SdbFindFirstTag(pdb, tagDb, TAG_LAYER); - while (tagLayer) + // Add all exe to registry (AppCompatFlags) + while (tagLayer && (tagLayer != prevTagLayer)) { tagLayerName = SdbFindFirstTag(pdb, tagLayer, TAG_NAME); if (!tagLayerName) @@ -208,14 +228,15 @@ ProcessLayers( LPWSTR name = SdbGetStringTagPtr(pdb, tagLayerName); wprintf(L"Layer name %ls", name); - res = RegisterSdbEntry(name, guidDbStr, time); + res = RegisterSdbEntry(name, guidDbStr, time, isInstall, FALSE); if (FAILED(res)) { wprintf(L"Can't register layer\n"); break; } - tagLayer = SdbFindNextTag(pdb, tagDb, TAG_LAYER); + prevTagLayer = tagLayer; + tagLayer = SdbFindNextTag(pdb, tagDb, tagLayer); } return res; @@ -225,16 +246,18 @@ HRESULT ProcessExe( _In_ PDB pdb, _In_ TAGID tagDb, - _In_ LPCWSTR guidDbStr, - _In_ ULONGLONG time -) + _In_opt_ LPCWSTR guidDbStr, + _In_opt_ ULONGLONG time, + _In_ BOOL isInstall) { HRESULT res = ERROR_SUCCESS; TAGID tagExeName; + TAGID tagExePrev = 0; TAGID tagExe = SdbFindFirstTag(pdb, tagDb, TAG_EXE); - while (tagExe) + // Add all exe to registry (AppCompatFlags) + while (tagExe != 0 && (tagExe != tagExePrev)) { tagExeName = SdbFindFirstTag(pdb, tagExe, TAG_NAME); if (!tagExeName) @@ -247,14 +270,15 @@ ProcessExe( LPWSTR name = SdbGetStringTagPtr(pdb, tagExeName); wprintf(L"Exe name %ls\n", name); - res = RegisterSdbEntry(name, guidDbStr, time); + res = RegisterSdbEntry(name, guidDbStr, time, isInstall, TRUE); if (FAILED(res)) { - wprintf(L"Can't register exe\n"); + wprintf(L"Can't register exe 0x%08X\n", res); break; } - tagExe = SdbFindNextTag(pdb, tagDb, TAG_EXE); + tagExePrev = tagExe; + tagExe = SdbFindNextTag(pdb, tagDb, tagExe); } return res; @@ -276,6 +300,7 @@ CopySdbToAppPatch( goto end; } + // Get parent folder fo sdb file CopyMemory(sysdirPath, destSdbPath, destLen * sizeof(WCHAR)); pTmpSysdir = sysdirPath + destLen; @@ -287,6 +312,7 @@ CopySdbToAppPatch( wprintf(L"%ls\n", sysdirPath); + // Create directory if need if (!CreateDirectory(sysdirPath, NULL)) { error = GetLastError(); @@ -298,6 +324,7 @@ CopySdbToAppPatch( error = ERROR_SUCCESS; } + // Copy file if (!CopyFile(sourceSdbPath, destSdbPath, TRUE)) { error = GetLastError(); @@ -355,6 +382,7 @@ SdbInstall( currentTime.LowPart = systemTime.dwLowDateTime; currentTime.HighPart = systemTime.dwHighDateTime; + // Open db pdb = SdbOpenDatabase(sdbPath, DOS_PATH); if (pdb == NULL) { @@ -369,7 +397,7 @@ SdbInstall( goto end; } - // + // Get db guid if (!GetSdbGuid(pdb, tagDb, &dbGuid)) { wprintf(L"GetSdbGuid error\n"); @@ -396,14 +424,16 @@ SdbInstall( LPWSTR dbName = SdbGetStringTagPtr(pdb, tagDbName); wprintf(L"Database name %ls\n", dbName); - hres = ProcessExe(pdb, tagDb, guidDbStr, currentTime.QuadPart); + // Process exe tags + hres = ProcessExe(pdb, tagDb, guidDbStr, currentTime.QuadPart, TRUE); if (FAILED(hres)) { wprintf(L"Process exe failed. Status: 0x%08X", res); goto end; } - hres = ProcessLayers(pdb, tagDb, guidDbStr, currentTime.QuadPart); + // Proess layer tags + hres = ProcessLayers(pdb, tagDb, guidDbStr, currentTime.QuadPart, TRUE); if (FAILED(hres)) { wprintf(L"Process layers failed. Status: 0x%08X", res); @@ -413,6 +443,7 @@ SdbInstall( SIZE_T bufLen = MAX_PATH * 2; sysdirPatchPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, bufLen * sizeof(WCHAR)); + // Create full path tos db in system folder hres = BuildPathToSdb(&sysdirPatchPath, bufLen, guidDbStr); if (FAILED(hres)) { @@ -431,6 +462,7 @@ SdbInstall( AddUninstallKey(dbName, sysdirPatchPath, guidDbStr); + // Registration if (!SdbRegisterDatabaseEx(sysdirPatchPath, SDB_DATABASE_SHIM, ¤tTime.QuadPart)) { wprintf(L"SdbRegisterDatabaseEx UNSUCCESS"); @@ -448,6 +480,117 @@ end: return res; } +HRESULT +DeleteUninstallKey( + _In_ LPCWSTR keyName) +{ + HKEY hKey; + HRESULT hres = HRESULT_FROM_WIN32(ERROR_SUCCESS); + + LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, + UNINSTALL_REG_PATH, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKey, + NULL); + + if (status != ERROR_SUCCESS) + { + hres = HRESULT_FROM_WIN32(status); + goto end; + } + + status = RegDeleteKey(hKey, keyName); + if (status != ERROR_SUCCESS) + { + hres = HRESULT_FROM_WIN32(status); + } + +end: + return hres; +} + +BOOL +SdbUninstall( + _In_ LPWSTR sdbPath) +{ + BOOL res = FALSE; + PWCHAR sdbName = NULL; + PDB pdb; + TAGID tagDb; + GUID dbGuid; + + SIZE_T sdbPathLen = wcslen(sdbPath); + sdbName = sdbPath + sdbPathLen; + + while (*sdbName != L'\\') + { + --sdbName; + } + sdbName++; + + wprintf(L"uninstall name %ls\n", sdbName); + + // open sdb + pdb = SdbOpenDatabase(sdbPath, DOS_PATH); + if (pdb == NULL) + { + wprintf(L"Can't open database %ls\n", sdbPath); + goto end; + } + + tagDb = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE); + if (!tagDb) + { + wprintf(L"Can't find database tag\n"); + goto end; + } + + // + if (!GetSdbGuid(pdb, tagDb, &dbGuid)) + { + wprintf(L"GetSdbGuid error\n"); + goto end; + } + + //remove regkey in appatch/custom + HRESULT hres = ProcessExe(pdb, tagDb, NULL, 0, FALSE); + if (FAILED(hres)) + { + wprintf(L"Process exe fail\n"); + goto end; + } + + SdbCloseDatabase(pdb); + + hres = DeleteUninstallKey(sdbName); + if (FAILED(hres)) + { + wprintf(L"Remove key fail\n"); + goto end; + } + + if (!SdbUnregisterDatabase(&dbGuid)) + { + wprintf(L"SdbUnregisterDatabase\n"); + goto end; + } + + if (!DeleteFile(sdbPath)) + { + wprintf(L"Remove file fail 0x%08X\n", GetLastError()); + goto end; + } + +end: + return res; +} + + + void ShowHelp() { @@ -459,24 +602,58 @@ ShowHelp() L"-n - \"name\" - file name (only uninstall)\n"); } -int _tmain(int argc, LPCWSTR argv[]) +int _tmain(int argc, LPWSTR argv[]) { - LPCWSTR sdbPath = NULL; + LPWSTR sdbPath = NULL; + BOOL isInstall = TRUE; + //LPWSTR guidSdbStr = NULL; if (argc < 2) { ShowHelp(); } - if (argv[1][0] == L'-' && argv[1][1] == L'?') + for (int i = 1; i < argc; ++i) { - ShowHelp(); - return ERROR_SUCCESS; + if (argv[i][0] != L'-') + { + sdbPath = argv[i]; + break; + } + + switch (argv[i][1]) + { + case L'?': + ShowHelp(); + return ERROR_SUCCESS; + break; + + case L'u': + isInstall = FALSE; + break; + + case L'g': + ++i; + + if (i < argc) + { + return ERROR_INVALID_PARAMETER; + } + + //guidSdbStr = argv[i]; + break; + } } - sdbPath = argv[1]; - - SdbInstall(sdbPath); + if (isInstall) + { + SdbInstall(sdbPath); + } + else + { + // call uninstall + SdbUninstall(sdbPath); + } return ERROR_SUCCESS; -} \ No newline at end of file +} diff --git a/dll/appcompat/apphelp/apphelp.h b/dll/appcompat/apphelp/apphelp.h index 87ddce5cfbe..8dca5408da3 100644 --- a/dll/appcompat/apphelp/apphelp.h +++ b/dll/appcompat/apphelp/apphelp.h @@ -111,6 +111,7 @@ DWORD WINAPI SdbQueryDataExTagID(PDB pdb, TAGID tiExe, LPCWSTR lpszDataName, LPD BOOL WINAPI SdbGetDatabaseInformation(PDB pdb, PDB_INFORMATION information); VOID WINAPI SdbFreeDatabaseInformation(PDB_INFORMATION information); BOOL WINAPI SdbRegisterDatabaseEx(_In_ LPCWSTR pszDatabasePath, _In_ DWORD dwDatabaseType, _In_opt_ const PULONGLONG pTimeStamp); +BOOL WINAPI SdbUnregisterDatabase(_In_ const GUID *pguidDB); /* sdbread.c */ BOOL WINAPI SdbpReadData(PDB pdb, PVOID dest, DWORD offset, DWORD num);