[SDBINST] Add uninstall option

This commit is contained in:
Max Korostil 2020-10-22 22:45:20 +03:00 committed by Mark Jansen
parent 4e4328ac8a
commit 7fd004e50b
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
2 changed files with 218 additions and 40 deletions

View file

@ -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;
}
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;
}
}

View file

@ -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);