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;

Reply via email to