[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" #define UNINSTALL_REG_PATH L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
HRESULT HRESULT
RegisterSdbEntry( RegisterSdbEntry(
_In_ PWCHAR sdbEntryName, _In_ PWCHAR sdbEntryName,
_In_ LPCWSTR dbGuid, _In_ LPCWSTR dbGuid,
_In_ ULONGLONG time) _In_ ULONGLONG time,
_In_ BOOL isInstall,
_In_ BOOL isExe)
{ {
WCHAR regName[MAX_PATH] = {0}; WCHAR regName[MAX_PATH] = {0};
HKEY hKey; 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)) if (FAILED(hres))
{ {
wprintf(L"StringCchPrintfW error: 0x%08X", hres); wprintf(L"StringCchPrintfW error: 0x%08X\n", hres);
goto end; goto end;
} }
LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Remove key
regName, if (!isInstall)
0, {
NULL, status = RegDeleteKey(HKEY_LOCAL_MACHINE, regName);
REG_OPTION_NON_VOLATILE, return HRESULT_FROM_WIN32(status);
KEY_ALL_ACCESS, }
NULL,
&hKey, // Create main key
NULL); status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
regName,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
{ {
@ -45,6 +58,7 @@ RegisterSdbEntry(
goto end; goto end;
} }
// Set instlled time
status = RegSetValueEx(hKey, status = RegSetValueEx(hKey,
dbGuid, dbGuid,
0, 0,
@ -80,12 +94,14 @@ AddUninstallKey(
sdbinstPath[count] = L'\\'; sdbinstPath[count] = L'\\';
} }
// Full path to sdbinst.exe
hres = StringCchCat(sdbinstPath, sizeof(sdbinstPath) / sizeof(WCHAR), L"System32\\sdbinst.exe"); hres = StringCchCat(sdbinstPath, sizeof(sdbinstPath) / sizeof(WCHAR), L"System32\\sdbinst.exe");
if (FAILED(hres)) if (FAILED(hres))
{ {
wprintf(L"StringCchCat error: 0x%08X", 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, sizeof(regName) / sizeof(WCHAR), L"%ls\\%ls", UNINSTALL_REG_PATH, guidDbStr);
if (FAILED(hres)) if (FAILED(hres))
{ {
@ -96,6 +112,7 @@ AddUninstallKey(
wprintf(L"%ls\n", sdbinstPath); wprintf(L"%ls\n", sdbinstPath);
wprintf(L"%ls\n", regName); wprintf(L"%ls\n", regName);
// Create main key
LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LSTATUS status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
regName, regName,
0, 0,
@ -113,6 +130,7 @@ AddUninstallKey(
goto end; goto end;
} }
// Set Display name
DWORD length = wcslen(dbName) * sizeof(WCHAR); DWORD length = wcslen(dbName) * sizeof(WCHAR);
status = RegSetValueEx(hKey, status = RegSetValueEx(hKey,
L"DisplayName", L"DisplayName",
@ -127,7 +145,7 @@ AddUninstallKey(
goto end; goto end;
} }
// Uninst string // Uninstall full string
hres = StringCchPrintf(uninstString, sizeof(uninstString) / sizeof(WCHAR), L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath); hres = StringCchPrintf(uninstString, sizeof(uninstString) / sizeof(WCHAR), L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath);
if (FAILED(hres)) if (FAILED(hres))
{ {
@ -135,8 +153,7 @@ AddUninstallKey(
goto end; goto end;
} }
//wprintf(L"%ls\n", uninstString); // Set uninstall string
length = wcslen(uninstString) * sizeof(WCHAR); length = wcslen(uninstString) * sizeof(WCHAR);
status = RegSetValueEx(hKey, status = RegSetValueEx(hKey,
L"UninstallString", L"UninstallString",
@ -188,15 +205,18 @@ HRESULT
ProcessLayers( ProcessLayers(
_In_ PDB pdb, _In_ PDB pdb,
_In_ TAGID tagDb, _In_ TAGID tagDb,
_In_ LPCWSTR guidDbStr, _In_opt_ LPCWSTR guidDbStr,
_In_ ULONGLONG time) _In_opt_ ULONGLONG time,
_In_ BOOL isInstall)
{ {
HRESULT res = ERROR_SUCCESS; HRESULT res = ERROR_SUCCESS;
TAGID tagLayerName; TAGID tagLayerName;
TAGID prevTagLayer = 0;
TAGID tagLayer = SdbFindFirstTag(pdb, tagDb, TAG_LAYER); 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); tagLayerName = SdbFindFirstTag(pdb, tagLayer, TAG_NAME);
if (!tagLayerName) if (!tagLayerName)
@ -208,14 +228,15 @@ ProcessLayers(
LPWSTR name = SdbGetStringTagPtr(pdb, tagLayerName); LPWSTR name = SdbGetStringTagPtr(pdb, tagLayerName);
wprintf(L"Layer name %ls", name); wprintf(L"Layer name %ls", name);
res = RegisterSdbEntry(name, guidDbStr, time); res = RegisterSdbEntry(name, guidDbStr, time, isInstall, FALSE);
if (FAILED(res)) if (FAILED(res))
{ {
wprintf(L"Can't register layer\n"); wprintf(L"Can't register layer\n");
break; break;
} }
tagLayer = SdbFindNextTag(pdb, tagDb, TAG_LAYER); prevTagLayer = tagLayer;
tagLayer = SdbFindNextTag(pdb, tagDb, tagLayer);
} }
return res; return res;
@ -225,16 +246,18 @@ HRESULT
ProcessExe( ProcessExe(
_In_ PDB pdb, _In_ PDB pdb,
_In_ TAGID tagDb, _In_ TAGID tagDb,
_In_ LPCWSTR guidDbStr, _In_opt_ LPCWSTR guidDbStr,
_In_ ULONGLONG time _In_opt_ ULONGLONG time,
) _In_ BOOL isInstall)
{ {
HRESULT res = ERROR_SUCCESS; HRESULT res = ERROR_SUCCESS;
TAGID tagExeName; TAGID tagExeName;
TAGID tagExePrev = 0;
TAGID tagExe = SdbFindFirstTag(pdb, tagDb, TAG_EXE); 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); tagExeName = SdbFindFirstTag(pdb, tagExe, TAG_NAME);
if (!tagExeName) if (!tagExeName)
@ -247,14 +270,15 @@ ProcessExe(
LPWSTR name = SdbGetStringTagPtr(pdb, tagExeName); LPWSTR name = SdbGetStringTagPtr(pdb, tagExeName);
wprintf(L"Exe name %ls\n", name); wprintf(L"Exe name %ls\n", name);
res = RegisterSdbEntry(name, guidDbStr, time); res = RegisterSdbEntry(name, guidDbStr, time, isInstall, TRUE);
if (FAILED(res)) if (FAILED(res))
{ {
wprintf(L"Can't register exe\n"); wprintf(L"Can't register exe 0x%08X\n", res);
break; break;
} }
tagExe = SdbFindNextTag(pdb, tagDb, TAG_EXE); tagExePrev = tagExe;
tagExe = SdbFindNextTag(pdb, tagDb, tagExe);
} }
return res; return res;
@ -276,6 +300,7 @@ CopySdbToAppPatch(
goto end; goto end;
} }
// Get parent folder fo sdb file
CopyMemory(sysdirPath, destSdbPath, destLen * sizeof(WCHAR)); CopyMemory(sysdirPath, destSdbPath, destLen * sizeof(WCHAR));
pTmpSysdir = sysdirPath + destLen; pTmpSysdir = sysdirPath + destLen;
@ -287,6 +312,7 @@ CopySdbToAppPatch(
wprintf(L"%ls\n", sysdirPath); wprintf(L"%ls\n", sysdirPath);
// Create directory if need
if (!CreateDirectory(sysdirPath, NULL)) if (!CreateDirectory(sysdirPath, NULL))
{ {
error = GetLastError(); error = GetLastError();
@ -298,6 +324,7 @@ CopySdbToAppPatch(
error = ERROR_SUCCESS; error = ERROR_SUCCESS;
} }
// Copy file
if (!CopyFile(sourceSdbPath, destSdbPath, TRUE)) if (!CopyFile(sourceSdbPath, destSdbPath, TRUE))
{ {
error = GetLastError(); error = GetLastError();
@ -355,6 +382,7 @@ SdbInstall(
currentTime.LowPart = systemTime.dwLowDateTime; currentTime.LowPart = systemTime.dwLowDateTime;
currentTime.HighPart = systemTime.dwHighDateTime; currentTime.HighPart = systemTime.dwHighDateTime;
// Open db
pdb = SdbOpenDatabase(sdbPath, DOS_PATH); pdb = SdbOpenDatabase(sdbPath, DOS_PATH);
if (pdb == NULL) if (pdb == NULL)
{ {
@ -369,7 +397,7 @@ SdbInstall(
goto end; goto end;
} }
// // Get db guid
if (!GetSdbGuid(pdb, tagDb, &dbGuid)) if (!GetSdbGuid(pdb, tagDb, &dbGuid))
{ {
wprintf(L"GetSdbGuid error\n"); wprintf(L"GetSdbGuid error\n");
@ -396,14 +424,16 @@ SdbInstall(
LPWSTR dbName = SdbGetStringTagPtr(pdb, tagDbName); LPWSTR dbName = SdbGetStringTagPtr(pdb, tagDbName);
wprintf(L"Database name %ls\n", dbName); 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)) if (FAILED(hres))
{ {
wprintf(L"Process exe failed. Status: 0x%08X", res); wprintf(L"Process exe failed. Status: 0x%08X", res);
goto end; goto end;
} }
hres = ProcessLayers(pdb, tagDb, guidDbStr, currentTime.QuadPart); // Proess layer tags
hres = ProcessLayers(pdb, tagDb, guidDbStr, currentTime.QuadPart, TRUE);
if (FAILED(hres)) if (FAILED(hres))
{ {
wprintf(L"Process layers failed. Status: 0x%08X", res); wprintf(L"Process layers failed. Status: 0x%08X", res);
@ -413,6 +443,7 @@ SdbInstall(
SIZE_T bufLen = MAX_PATH * 2; SIZE_T bufLen = MAX_PATH * 2;
sysdirPatchPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, bufLen * sizeof(WCHAR)); sysdirPatchPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, bufLen * sizeof(WCHAR));
// Create full path tos db in system folder
hres = BuildPathToSdb(&sysdirPatchPath, bufLen, guidDbStr); hres = BuildPathToSdb(&sysdirPatchPath, bufLen, guidDbStr);
if (FAILED(hres)) if (FAILED(hres))
{ {
@ -431,6 +462,7 @@ SdbInstall(
AddUninstallKey(dbName, sysdirPatchPath, guidDbStr); AddUninstallKey(dbName, sysdirPatchPath, guidDbStr);
// Registration
if (!SdbRegisterDatabaseEx(sysdirPatchPath, SDB_DATABASE_SHIM, &currentTime.QuadPart)) if (!SdbRegisterDatabaseEx(sysdirPatchPath, SDB_DATABASE_SHIM, &currentTime.QuadPart))
{ {
wprintf(L"SdbRegisterDatabaseEx UNSUCCESS"); wprintf(L"SdbRegisterDatabaseEx UNSUCCESS");
@ -448,6 +480,117 @@ end:
return res; 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 void
ShowHelp() ShowHelp()
{ {
@ -459,24 +602,58 @@ ShowHelp()
L"-n - \"name\" - file name (only uninstall)\n"); 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) if (argc < 2)
{ {
ShowHelp(); ShowHelp();
} }
if (argv[1][0] == L'-' && argv[1][1] == L'?') for (int i = 1; i < argc; ++i)
{ {
ShowHelp(); if (argv[i][0] != L'-')
return ERROR_SUCCESS; {
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]; if (isInstall)
{
SdbInstall(sdbPath); SdbInstall(sdbPath);
}
else
{
// call uninstall
SdbUninstall(sdbPath);
}
return ERROR_SUCCESS; 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); BOOL WINAPI SdbGetDatabaseInformation(PDB pdb, PDB_INFORMATION information);
VOID WINAPI SdbFreeDatabaseInformation(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 SdbRegisterDatabaseEx(_In_ LPCWSTR pszDatabasePath, _In_ DWORD dwDatabaseType, _In_opt_ const PULONGLONG pTimeStamp);
BOOL WINAPI SdbUnregisterDatabase(_In_ const GUID *pguidDB);
/* sdbread.c */ /* sdbread.c */
BOOL WINAPI SdbpReadData(PDB pdb, PVOID dest, DWORD offset, DWORD num); BOOL WINAPI SdbpReadData(PDB pdb, PVOID dest, DWORD offset, DWORD num);