https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4e4328ac8a6c75461a074bd54aa0595eee65b990

commit 4e4328ac8a6c75461a074bd54aa0595eee65b990
Author:     Max Korostil <mrmk...@yandex.ru>
AuthorDate: Wed Oct 21 23:11:35 2020 +0300
Commit:     Mark Jansen <mark.jan...@reactos.org>
CommitDate: Sat May 8 14:24:20 2021 +0200

    [SDBINST] Add sdbinst uility.
    
    It can install sdb to the system
---
 base/applications/CMakeLists.txt         |   1 +
 base/applications/sdbinst/CMakeLists.txt |   6 +
 base/applications/sdbinst/sdbinst.c      | 482 +++++++++++++++++++++++++++++++
 3 files changed, 489 insertions(+)

diff --git a/base/applications/CMakeLists.txt b/base/applications/CMakeLists.txt
index 082b2121b35..179d548a07b 100644
--- a/base/applications/CMakeLists.txt
+++ b/base/applications/CMakeLists.txt
@@ -46,3 +46,4 @@ add_subdirectory(winver)
 add_subdirectory(wordpad)
 add_subdirectory(write)
 add_subdirectory(wusa)
+add_subdirectory(sdbinst)
diff --git a/base/applications/sdbinst/CMakeLists.txt 
b/base/applications/sdbinst/CMakeLists.txt
new file mode 100644
index 00000000000..682b84117cb
--- /dev/null
+++ b/base/applications/sdbinst/CMakeLists.txt
@@ -0,0 +1,6 @@
+include_directories(${REACTOS_SOURCE_DIR}/dll/appcompat/apphelp)
+add_executable(sdbinst sdbinst.c)
+
+set_module_type(sdbinst win32cui UNICODE)
+add_importlibs(sdbinst msvcrt kernel32 ntdll advapi32 apphelp ole32)
+add_cd_file(TARGET sdbinst DESTINATION reactos/system32 FOR all)
diff --git a/base/applications/sdbinst/sdbinst.c 
b/base/applications/sdbinst/sdbinst.c
new file mode 100644
index 00000000000..530071d1749
--- /dev/null
+++ b/base/applications/sdbinst/sdbinst.c
@@ -0,0 +1,482 @@
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <tchar.h>
+#include <winreg.h>
+#include <strsafe.h>
+#include <objbase.h>
+#include <apphelp.h>
+
+
+
+#define APPCOMPAT_REG_PATH L"Software\\Microsoft\\Windows 
NT\\CurrentVersion\\AppCompatFlags\\Custom\\"
+#define UNINSTALL_REG_PATH 
L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
+
+HRESULT
+RegisterSdbEntry(
+    _In_ PWCHAR sdbEntryName,
+    _In_ LPCWSTR dbGuid,
+    _In_ ULONGLONG time)
+{
+    WCHAR regName[MAX_PATH] = {0};
+    HKEY  hKey;
+
+    HRESULT hres = StringCchPrintf(regName, sizeof(regName) / sizeof(WCHAR), 
L"%ls\\%ls", APPCOMPAT_REG_PATH, sdbEntryName);
+    if (FAILED(hres))
+    {
+        wprintf(L"StringCchPrintfW error: 0x%08X", hres);
+        goto end;
+    }
+
+    LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                                    regName,
+                                    0,
+                                    NULL,
+                                    REG_OPTION_NON_VOLATILE,
+                                    KEY_ALL_ACCESS,
+                                    NULL,
+                                    &hKey,
+                                    NULL);
+
+    if (status != ERROR_SUCCESS)
+    {
+        wprintf(L"RegKeyCreateEx error: 0x%08X", status);
+        hres = HRESULT_FROM_WIN32(status);
+        goto end;
+    }
+
+    status = RegSetValueEx(hKey,
+                           dbGuid,
+                           0,
+                           REG_QWORD,
+                           (PBYTE)&time,
+                           sizeof(time));
+    if (status != ERROR_SUCCESS)
+    {
+        wprintf(L"RegSetValueEx error: 0x%08X", status);
+        hres = HRESULT_FROM_WIN32(status);
+        goto end;
+    }
+
+end:
+    return hres;
+}
+
+HRESULT
+AddUninstallKey(
+    _In_ LPCWSTR dbName,
+    _In_ LPCWSTR sdbInstalledPath,
+    _In_ LPCWSTR guidDbStr)
+{
+    WCHAR sdbinstPath[MAX_PATH] = {0};
+    WCHAR regName[MAX_PATH] = {0};
+    WCHAR uninstString[MAX_PATH * 2] = {0};
+    HKEY hKey;
+    HRESULT hres;
+
+    UINT count = GetSystemWindowsDirectory(sdbinstPath, sizeof(sdbinstPath) / 
sizeof(WCHAR));
+    if (sdbinstPath[count - 1] != L'\\')
+    {
+        sdbinstPath[count] = L'\\';
+    }
+    
+    hres = StringCchCat(sdbinstPath, sizeof(sdbinstPath) / sizeof(WCHAR), 
L"System32\\sdbinst.exe");
+    if (FAILED(hres))
+    {
+        wprintf(L"StringCchCat error: 0x%08X", hres);
+    }
+
+    hres = StringCchPrintf(regName, sizeof(regName) / sizeof(WCHAR), 
L"%ls\\%ls", UNINSTALL_REG_PATH, guidDbStr);
+    if (FAILED(hres))
+    {
+        wprintf(L"StringCchPrintfW error: 0x%08X", hres);
+        goto end;
+    }
+
+    wprintf(L"%ls\n", sdbinstPath);
+    wprintf(L"%ls\n", regName);
+
+    LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                                    regName,
+                                    0,
+                                    NULL,
+                                    REG_OPTION_NON_VOLATILE,
+                                    KEY_ALL_ACCESS,
+                                    NULL,
+                                    &hKey,
+                                    NULL);
+
+    if (status != ERROR_SUCCESS)
+    {
+        wprintf(L"RegKeyCreateEx error: 0x%08X", status);
+        hres = HRESULT_FROM_WIN32(status);
+        goto end;
+    }
+
+    DWORD length = wcslen(dbName) * sizeof(WCHAR);
+    status = RegSetValueEx(hKey,
+                           L"DisplayName",
+                           0,
+                           REG_SZ,
+                           (PBYTE)dbName,
+                           length + sizeof(WCHAR));
+    if (status != ERROR_SUCCESS)
+    {
+        wprintf(L"RegSetValueEx error: 0x%08X", status);
+        hres = HRESULT_FROM_WIN32(status);
+        goto end;
+    }
+
+    // Uninst string 
+    hres = StringCchPrintf(uninstString, sizeof(uninstString) / sizeof(WCHAR), 
L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath);
+    if (FAILED(hres))
+    {
+        wprintf(L"StringCchPrintfW error: 0x%08X", hres);
+        goto end;
+    }
+
+    //wprintf(L"%ls\n", uninstString);
+
+    length = wcslen(uninstString) * sizeof(WCHAR);
+    status = RegSetValueEx(hKey,
+                           L"UninstallString",
+                           0,
+                           REG_SZ,
+                           (PBYTE)uninstString,
+                           length + sizeof(WCHAR));
+    if (status != ERROR_SUCCESS)
+    {
+        wprintf(L"RegSetValueEx error: 0x%08X", status);
+        hres = HRESULT_FROM_WIN32(status);
+        goto end;
+    }
+
+end:
+
+    return hres;
+}
+
+//
+// Get database guid id
+//
+BOOL
+GetSdbGuid(
+    _In_ PDB pdb,
+    _In_ TAGID tagDb,
+    _Out_ GUID* guid)
+{
+    TAGID tagDbId;
+
+    tagDbId = SdbFindFirstTag(pdb, tagDb, TAG_DATABASE_ID);
+    
+    if (!tagDbId)
+    {
+        wprintf(L"Can't find database id tag");
+        return FALSE;
+    }
+
+    if (!SdbReadBinaryTag(pdb, tagDbId, (PBYTE)guid, sizeof(GUID)))
+    {
+        wprintf(L"Can't read database id");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+HRESULT
+ProcessLayers(
+    _In_ PDB pdb,
+    _In_ TAGID tagDb,
+    _In_ LPCWSTR guidDbStr,
+    _In_ ULONGLONG time)
+{
+    HRESULT res = ERROR_SUCCESS;
+    TAGID tagLayerName;
+
+    TAGID tagLayer = SdbFindFirstTag(pdb, tagDb, TAG_LAYER);
+    
+    while (tagLayer)
+    {
+        tagLayerName = SdbFindFirstTag(pdb, tagLayer, TAG_NAME);
+        if (!tagLayerName)
+        {
+            res = ERROR_NOT_FOUND;
+            break;
+        }
+
+        LPWSTR name = SdbGetStringTagPtr(pdb, tagLayerName);
+        wprintf(L"Layer name %ls", name);
+
+        res = RegisterSdbEntry(name, guidDbStr, time);
+        if (FAILED(res))
+        {
+            wprintf(L"Can't register layer\n");
+            break;
+        }
+
+        tagLayer = SdbFindNextTag(pdb, tagDb, TAG_LAYER);
+    }
+
+    return res;
+}
+
+HRESULT
+ProcessExe(
+    _In_ PDB pdb,
+    _In_ TAGID tagDb,
+    _In_ LPCWSTR guidDbStr,
+    _In_ ULONGLONG time
+)
+{
+    HRESULT res = ERROR_SUCCESS;
+    TAGID tagExeName;
+
+    TAGID tagExe = SdbFindFirstTag(pdb, tagDb, TAG_EXE);
+
+    while (tagExe)
+    {
+        tagExeName = SdbFindFirstTag(pdb, tagExe, TAG_NAME);
+        if (!tagExeName)
+        {
+            wprintf(L"Can't find exe tag\n");
+            res = ERROR_NOT_FOUND;
+            break;
+        }
+
+        LPWSTR name = SdbGetStringTagPtr(pdb, tagExeName);
+        wprintf(L"Exe name %ls\n", name);
+
+        res = RegisterSdbEntry(name, guidDbStr, time);
+        if (FAILED(res))
+        {
+            wprintf(L"Can't register exe\n");
+            break;
+        }
+
+        tagExe = SdbFindNextTag(pdb, tagDb, TAG_EXE);
+    }
+
+    return res;
+}
+
+HRESULT
+CopySdbToAppPatch(
+    _In_ LPCWSTR sourceSdbPath,
+    _In_ LPCWSTR destSdbPath)
+{
+    DWORD error = ERROR_SUCCESS;
+    PWCHAR pTmpSysdir = NULL;
+    SIZE_T destLen = wcslen(destSdbPath);
+    PWCHAR sysdirPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, destLen * 
sizeof(WCHAR));
+
+    if (sysdirPath == NULL)
+    {
+        error = ERROR_NOT_ENOUGH_MEMORY;
+        goto end;
+    }
+
+    CopyMemory(sysdirPath, destSdbPath, destLen * sizeof(WCHAR));
+    pTmpSysdir = sysdirPath + destLen;
+
+    while (*pTmpSysdir != L'\\')
+    {
+        *pTmpSysdir = L'\0';
+        --pTmpSysdir;
+    }
+
+    wprintf(L"%ls\n", sysdirPath);
+
+    if (!CreateDirectory(sysdirPath, NULL))
+    {
+        error = GetLastError();
+        if (error != ERROR_ALREADY_EXISTS)
+        {
+            wprintf(L"Can't create folder %ls\n Error: 0x%08\n", sysdirPath, 
error);
+            goto end;
+        }
+        error = ERROR_SUCCESS;
+    }
+
+    if (!CopyFile(sourceSdbPath, destSdbPath, TRUE))
+    {
+        error = GetLastError();
+        wprintf(L"Can't copy sdb file");
+    }
+
+    HeapFree(GetProcessHeap(), 0, sysdirPath);
+
+end:
+    return HRESULT_FROM_WIN32(error);
+}
+
+HRESULT
+BuildPathToSdb(
+    _In_ PWCHAR* buffer,
+    _In_ SIZE_T bufLen,
+    _In_ LPCWSTR guidDbStr)
+{
+    PWCHAR pBuffer = *buffer;
+    ZeroMemory(pBuffer, bufLen * sizeof(WCHAR));
+
+    UINT count = GetSystemWindowsDirectory(pBuffer, bufLen);
+    if (pBuffer[count - 1] != L'\\')
+    {
+        pBuffer[count] = L'\\';
+    }
+
+    HRESULT res = StringCchCatW(pBuffer, bufLen, L"AppPatch\\Custom\\");
+    if (FAILED(res))
+    {
+        goto end;
+    }
+
+    res = StringCchCatW(pBuffer, bufLen, guidDbStr);
+
+end:
+    return res;
+}
+
+BOOL
+SdbInstall(
+    _In_ LPCWSTR sdbPath)
+{
+    BOOL res = FALSE;
+    PDB pdb = NULL;
+    TAGID tagDb;
+    TAGID tagDbName;
+    GUID dbGuid = {0};
+    FILETIME systemTime = {0};
+    ULARGE_INTEGER currentTime = {0};
+    PWCHAR sysdirPatchPath = NULL;
+    WCHAR guidDbStr[MAX_PATH] = {0};
+
+    GetSystemTimeAsFileTime(&systemTime);
+    currentTime.LowPart  = systemTime.dwLowDateTime;
+    currentTime.HighPart = systemTime.dwHighDateTime;
+
+    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;
+    }
+
+    StringFromGUID2(&dbGuid, guidDbStr, MAX_PATH);
+    HRESULT hres = StringCchCatW(guidDbStr, sizeof(guidDbStr) / sizeof(WCHAR), 
L".sdb");
+    if (FAILED(hres))
+    {
+        wprintf(L"StringCchCatW error 0x%08X\n", hres);
+        goto end;
+    }
+
+    wprintf(L"Database guid %wZ\n", &guidDbStr);
+
+    tagDbName = SdbFindFirstTag(pdb, tagDb, TAG_NAME);
+    if (!tagDbName)
+    {
+        wprintf(L"Can't get tag name\n");
+        goto end;
+    }
+    
+    LPWSTR dbName = SdbGetStringTagPtr(pdb, tagDbName);
+    wprintf(L"Database name %ls\n", dbName);
+
+    hres = ProcessExe(pdb, tagDb, guidDbStr, currentTime.QuadPart);
+    if (FAILED(hres))
+    {
+        wprintf(L"Process exe failed. Status: 0x%08X", res);
+        goto end;
+    }
+
+    hres = ProcessLayers(pdb, tagDb, guidDbStr, currentTime.QuadPart);
+    if (FAILED(hres))
+    {
+        wprintf(L"Process layers failed. Status: 0x%08X", res);
+        goto end;
+    }
+
+    SIZE_T bufLen = MAX_PATH * 2;
+    sysdirPatchPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, bufLen * 
sizeof(WCHAR));
+
+    hres = BuildPathToSdb(&sysdirPatchPath, bufLen, guidDbStr);
+    if (FAILED(hres))
+    {
+        wprintf(L"Build path error\n");
+        goto end;
+    }
+
+    wprintf(L"file path %ls\n", sysdirPatchPath);
+
+    res = CopySdbToAppPatch(sdbPath, sysdirPatchPath);
+    if (FAILED(res))
+    {
+        wprintf(L"Copy sdb error. Status: 0x%08X\n", res);
+        goto end;
+    }
+
+    AddUninstallKey(dbName, sysdirPatchPath, guidDbStr);
+
+    if (!SdbRegisterDatabaseEx(sysdirPatchPath, SDB_DATABASE_SHIM, 
&currentTime.QuadPart))
+    {
+        wprintf(L"SdbRegisterDatabaseEx UNSUCCESS");
+        goto end;
+    }
+
+    res = TRUE;
+
+end:
+    if (pdb)
+    {
+        SdbCloseDatabase(pdb);
+    }
+
+    return res;
+}
+
+void
+ShowHelp()
+{
+    wprintf(L"Using: sdbinst [-?][-q][-u][-g][-n] foo.sdb | {guid} | \"name\" 
\n"
+            L"-? - show help\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");
+}
+
+int _tmain(int argc, LPCWSTR argv[])
+{
+    LPCWSTR sdbPath = NULL;
+
+    if (argc < 2)
+    {
+        ShowHelp();
+    }
+
+    if (argv[1][0] == L'-' && argv[1][1] == L'?')
+    {
+        ShowHelp();
+        return ERROR_SUCCESS;
+    }
+
+    sdbPath = argv[1];
+
+    SdbInstall(sdbPath);
+
+    return ERROR_SUCCESS;
+}
\ No newline at end of file

Reply via email to