https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7fd004e50b2fe8b652975…
commit 7fd004e50b2fe8b6529757ecfa595704e2b9fad0
Author: Max Korostil <mrmks04(a)yandex.ru>
AuthorDate: Thu Oct 22 22:45:20 2020 +0300
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sat May 8 14:24:20 2021 +0200
[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;
+ }
- sdbPath = argv[1];
+ 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;
+ }
+ }
- 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);