https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7fd004e50b2fe8b6529757ecfa595704e2b9fad0

commit 7fd004e50b2fe8b6529757ecfa595704e2b9fad0
Author:     Max Korostil <[email protected]>
AuthorDate: Thu Oct 22 22:45:20 2020 +0300
Commit:     Mark Jansen <[email protected]>
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, 
&currentTime.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);

Reply via email to