#ifdef __NMAKE__
# NMAKE portion.
# Build with : nmake /f custom.cpp
# Clean with : nmake /f custom.cpp clean
# Builds custom.dll
OUTPATH = .
# program name macros
CC = cl /nologo
LINK = link /nologo
RM = del
DLLFILE = $(OUTPATH)\custom.dll
DLLEXPORTS =\
-EXPORT:EnableAllowTgtSessionKey \
-EXPORT:RevertAllowTgtSessionKey \
-EXPORT:AbortMsiImmediate \
-EXPORT:UninstallNsisInstallation \
-EXPORT:KillRunningProcesses \
-EXPORT:ListRunningProcesses
$(DLLFILE): $(OUTPATH)\custom.obj
$(LINK) /OUT:$@ /DLL $** $(DLLEXPORTS)
$(OUTPATH)\custom.obj: custom.cpp custom.h
$(CC) /c /Fo$@ custom.cpp
all: $(DLLFILE)
clean:
$(RM) $(DLLFILE)
$(RM) $(OUTPATH)\custom.obj
$(RM) $(OUTPATH)\custom.exp
!IFDEF __C_TEXT__
#else
#pragma unmanaged
#define _WIN32_WINNT 0x500
#include "custom.h"
#pragma comment(lib, "msi")
#pragma comment(lib, "advapi32")
void ShowMsiError( MSIHANDLE hInstall, DWORD errcode, DWORD param ){
MSIHANDLE hRecord;
hRecord = MsiCreateRecord(3);
MsiRecordClearData(hRecord);
MsiRecordSetInteger(hRecord, 1, errcode);
MsiRecordSetInteger(hRecord, 2, param);
MsiProcessMessage( hInstall, INSTALLMESSAGE_ERROR, hRecord );
MsiCloseHandle( hRecord );
}
#define LSA_KERBEROS_KEY "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos"
#define LSA_KERBEROS_PARM_KEY "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Parameters"
#define KFW_CLIENT_KEY "SOFTWARE\\MIT\\Kerberos\\Client\\"
#define SESSKEY_VALUE_NAME "AllowTGTSessionKey"
#define SESSBACKUP_VALUE_NAME "AllowTGTSessionKeyBackup"
#define SESSXPBACKUP_VALUE_NAME "AllowTGTSessionKeyBackupXP"
MSIDLLEXPORT EnableAllowTgtSessionKey( MSIHANDLE hInstall ) {
return SetAllowTgtSessionKey( hInstall, TRUE );
}
MSIDLLEXPORT RevertAllowTgtSessionKey( MSIHANDLE hInstall ) {
return SetAllowTgtSessionKey( hInstall, FALSE );
}
UINT SetAllowTgtSessionKey( MSIHANDLE hInstall, BOOL pInstall ) {
TCHAR tchVersionString[1024];
TCHAR tchVersionKey[2048];
DWORD size;
DWORD type;
DWORD value;
HKEY hkKfwClient = NULL;
HKEY hkLsaKerberos = NULL;
HKEY hkLsaKerberosParm = NULL;
UINT rv;
DWORD phase = 0;
size = sizeof(tchVersionString) / sizeof(TCHAR);
rv = MsiGetProperty( hInstall, _T("CustomActionData"), tchVersionString, &size );
if(rv != ERROR_SUCCESS) {
if(pInstall) {
ShowMsiError( hInstall, ERR_CUSTACTDATA, rv );
return rv;
} else {
return ERROR_SUCCESS;
}
}
_tcscpy( tchVersionKey, _T( KFW_CLIENT_KEY ) );
_tcscat( tchVersionKey, tchVersionString );
phase = 1;
rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, tchVersionKey, 0, ((pInstall)?KEY_WRITE:KEY_READ), &hkKfwClient );
if(rv != ERROR_SUCCESS)
goto cleanup;
phase = 2;
rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( LSA_KERBEROS_KEY ), 0, KEY_READ | KEY_WRITE, &hkLsaKerberos );
if(rv != ERROR_SUCCESS)
goto cleanup;
phase = 3;
rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( LSA_KERBEROS_PARM_KEY ), 0, KEY_READ | KEY_WRITE, &hkLsaKerberosParm );
if(rv != ERROR_SUCCESS) {
hkLsaKerberosParm = NULL;
}
if(pInstall) {
if(hkLsaKerberosParm) {
phase = 4;
size = sizeof(value);
rv = RegQueryValueEx( hkLsaKerberosParm, _T( SESSKEY_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size );
if(rv != ERROR_SUCCESS)
value = 0;
phase = 5;
rv = RegSetValueEx( hkKfwClient, _T( SESSBACKUP_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value));
if(rv != ERROR_SUCCESS)
goto cleanup;
}
phase = 6;
size = sizeof(value);
rv = RegQueryValueEx( hkLsaKerberos, _T( SESSKEY_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size );
if(rv != ERROR_SUCCESS)
value = 0;
phase = 7;
rv = RegSetValueEx( hkKfwClient, _T( SESSXPBACKUP_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value));
if(rv != ERROR_SUCCESS)
goto cleanup;
phase = 8;
value = 1;
rv = RegSetValueEx( hkLsaKerberos, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value));
if(rv != ERROR_SUCCESS)
goto cleanup;
if(hkLsaKerberosParm) {
phase = 9;
value = 1;
rv = RegSetValueEx( hkLsaKerberosParm, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value));
if(rv != ERROR_SUCCESS)
goto cleanup;
}
} else { if(hkLsaKerberosParm) {
size = sizeof(value);
rv = RegQueryValueEx( hkKfwClient, _T( SESSBACKUP_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size );
if(rv != ERROR_SUCCESS)
value = 0;
RegSetValueEx( hkLsaKerberosParm, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value));
}
size = sizeof(value);
rv = RegQueryValueEx( hkKfwClient, _T( SESSXPBACKUP_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size );
if(rv != ERROR_SUCCESS)
value = 0;
RegSetValueEx( hkLsaKerberos, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value));
RegDeleteValue( hkKfwClient, _T( SESSXPBACKUP_VALUE_NAME ) );
RegDeleteValue( hkKfwClient, _T( SESSBACKUP_VALUE_NAME ) );
}
rv = ERROR_SUCCESS;
cleanup:
if(rv != ERROR_SUCCESS && pInstall) {
ShowMsiError(hInstall, 4005, phase);
}
if(hkKfwClient) RegCloseKey( hkKfwClient );
if(hkLsaKerberos) RegCloseKey( hkLsaKerberos );
if(hkLsaKerberosParm) RegCloseKey( hkLsaKerberosParm );
return rv;
}
MSIDLLEXPORT AbortMsiImmediate( MSIHANDLE hInstall ) {
DWORD rv;
DWORD dwSize = 0;
LPTSTR sReason = NULL;
LPTSTR sFormatted = NULL;
MSIHANDLE hRecord = NULL;
LPTSTR cAbortReason = _T("ABORTREASON");
rv = MsiGetProperty( hInstall, cAbortReason, _T(""), &dwSize );
if(rv != ERROR_MORE_DATA) goto _cleanup;
sReason = new TCHAR[ ++dwSize ];
rv = MsiGetProperty( hInstall, cAbortReason, sReason, &dwSize );
if(rv != ERROR_SUCCESS) goto _cleanup;
hRecord = MsiCreateRecord(3);
MsiRecordClearData(hRecord);
MsiRecordSetString(hRecord, 0, sReason);
dwSize = 0;
rv = MsiFormatRecord(hInstall, hRecord, "", &dwSize);
if(rv != ERROR_MORE_DATA) goto _cleanup;
sFormatted = new TCHAR[ ++dwSize ];
rv = MsiFormatRecord(hInstall, hRecord, sFormatted, &dwSize);
if(rv != ERROR_SUCCESS) goto _cleanup;
MsiCloseHandle(hRecord);
hRecord = MsiCreateRecord(3);
MsiRecordClearData(hRecord);
MsiRecordSetInteger(hRecord, 1, ERR_ABORT);
MsiRecordSetString(hRecord,2, sFormatted);
MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecord);
_cleanup:
if(sFormatted) delete sFormatted;
if(hRecord) MsiCloseHandle( hRecord );
if(sReason) delete sReason;
return ~ERROR_SUCCESS;
}
#define MAX_KILL_PROCESSES 255
#define FIELD_SIZE 256
struct _KillProc {
TCHAR * image;
TCHAR * desc;
BOOL found;
DWORD pid;
};
#define RV_BAIL if(rv != ERROR_SUCCESS) goto _cleanup
MSIDLLEXPORT KillRunningProcesses( MSIHANDLE hInstall ) {
return KillRunningProcessesSlave( hInstall, TRUE );
}
MSIDLLEXPORT ListRunningProcesses( MSIHANDLE hInstall ) {
return KillRunningProcessesSlave( hInstall, FALSE );
}
UINT KillRunningProcessesSlave( MSIHANDLE hInstall, BOOL bKill )
{
UINT rv = ERROR_SUCCESS;
_KillProc * kpList;
int nKpList = 0;
int i;
int rowNum = 1;
DWORD size;
BOOL found = FALSE;
MSIHANDLE hDatabase = NULL;
MSIHANDLE hView = NULL;
MSIHANDLE hViewInsert = NULL;
MSIHANDLE hRecord = NULL;
MSIHANDLE hRecordInsert = NULL;
HANDLE hSnapshot = NULL;
PROCESSENTRY32 pe;
kpList = new _KillProc[MAX_KILL_PROCESSES];
memset(kpList, 0, sizeof(*kpList) * MAX_KILL_PROCESSES);
hDatabase = MsiGetActiveDatabase( hInstall );
if( hDatabase == NULL ) {
rv = GetLastError();
goto _cleanup;
}
if(!bKill) {
rv = MsiDatabaseOpenView( hDatabase,
_T( "DELETE FROM `ListBox` WHERE `ListBox`.`Property` = 'KillableProcesses'" ),
&hView); RV_BAIL;
rv = MsiViewExecute( hView, NULL ); RV_BAIL;
MsiCloseHandle( hView );
hView = NULL;
rv = MsiDatabaseOpenView( hDatabase,
_T( "SELECT * FROM `ListBox` WHERE `Property` = 'KillableProcesses'" ),
&hViewInsert); RV_BAIL;
MsiViewExecute(hViewInsert, NULL);
hRecordInsert = MsiCreateRecord(4);
if(hRecordInsert == NULL) {
rv = GetLastError();
goto _cleanup;
}
}
rv = MsiDatabaseOpenView( hDatabase,
_T( "SELECT `Image`,`Desc` FROM `KillProcess`" ),
&hView); RV_BAIL;
rv = MsiViewExecute( hView, NULL ); RV_BAIL;
do {
rv = MsiViewFetch( hView, &hRecord );
if(rv != ERROR_SUCCESS) {
if(hRecord)
MsiCloseHandle(hRecord);
hRecord = NULL;
break;
}
kpList[nKpList].image = new TCHAR[ FIELD_SIZE ]; kpList[nKpList].image[0] = _T('\0');
kpList[nKpList].desc = new TCHAR[ FIELD_SIZE ]; kpList[nKpList].desc[0] = _T('\0');
nKpList++;
size = FIELD_SIZE;
rv = MsiRecordGetString(hRecord, 1, kpList[nKpList-1].image, &size); RV_BAIL;
size = FIELD_SIZE;
rv = MsiRecordGetString(hRecord, 2, kpList[nKpList-1].desc, &size); RV_BAIL;
MsiCloseHandle(hRecord);
} while(nKpList < MAX_KILL_PROCESSES);
hRecord = NULL;
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if(hSnapshot == INVALID_HANDLE_VALUE) {
rv = GetLastError();
goto _cleanup;
}
pe.dwSize = sizeof( PROCESSENTRY32 );
if(!Process32First( hSnapshot, &pe )) {
rv = ERROR_SUCCESS;
goto _cleanup;
}
do {
for(i=0; i<nKpList; i++) {
if(!_tcsicmp( kpList[i].image, pe.szExeFile )) {
if(bKill) {
HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
if(hProcess == NULL) {
rv = GetLastError();
goto _cleanup;
}
if(!TerminateProcess(hProcess, 0)) {
rv = GetLastError();
CloseHandle(hProcess);
goto _cleanup;
}
CloseHandle(hProcess);
} else {
TCHAR buf[256];
rv = MsiRecordClearData( hRecordInsert ); RV_BAIL;
rv = MsiRecordSetString( hRecordInsert, 1, _T("KillableProcesses"));
rv = MsiRecordSetInteger( hRecordInsert, 2, rowNum++ ); RV_BAIL;
_itot( rowNum, buf, 10 );
rv = MsiRecordSetString( hRecordInsert, 3, buf ); RV_BAIL;
if(_tcslen(kpList[i].desc)) {
rv = MsiRecordSetString( hRecordInsert, 4, kpList[i].desc ); RV_BAIL;
} else {
rv = MsiRecordSetString( hRecordInsert, 4, kpList[i].image ); RV_BAIL;
}
MsiViewModify(hViewInsert, MSIMODIFY_INSERT_TEMPORARY, hRecordInsert); RV_BAIL;
found = TRUE;
}
break;
}
}
} while( Process32Next( hSnapshot, &pe ) );
if(!bKill) {
if(found) {
MsiSetProperty( hInstall, _T("FoundProcesses"), _T("1"));
} else {
MsiSetProperty( hInstall, _T("FoundProcesses"), _T(""));
}
}
rv = ERROR_SUCCESS;
_cleanup:
if(hRecordInsert) MsiCloseHandle(hRecordInsert);
if(hViewInsert) MsiCloseHandle(hView);
if(hSnapshot && hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hSnapshot);
while(nKpList) {
nKpList--;
delete kpList[nKpList].image;
delete kpList[nKpList].desc;
}
delete kpList;
if(hRecord) MsiCloseHandle(hRecord);
if(hView) MsiCloseHandle(hView);
if(hDatabase) MsiCloseHandle(hDatabase);
if(rv != ERROR_SUCCESS) {
ShowMsiError(hInstall, ERR_PROC_LIST, rv);
}
return rv;
}
MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall )
{
DWORD rv = ERROR_SUCCESS;
LPTSTR cNsisUninstall = _T("UPGRADENSIS");
HANDLE hIo = NULL;
DWORD dwSize = 0;
LPTSTR strPathUninst = NULL;
HANDLE hJob = NULL;
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
pInfo.hProcess = NULL;
pInfo.hThread = NULL;
rv = MsiGetProperty( hInstall, cNsisUninstall, _T(""), &dwSize );
if(rv != ERROR_MORE_DATA) goto _cleanup;
strPathUninst = new TCHAR[ ++dwSize ];
rv = MsiGetProperty( hInstall, cNsisUninstall, strPathUninst, &dwSize );
if(rv != ERROR_SUCCESS) goto _cleanup;
sInfo.cb = sizeof(sInfo);
sInfo.lpReserved = NULL;
sInfo.lpDesktop = _T("");
sInfo.lpTitle = _T("Foo");
sInfo.dwX = 0;
sInfo.dwY = 0;
sInfo.dwXSize = 0;
sInfo.dwYSize = 0;
sInfo.dwXCountChars = 0;
sInfo.dwYCountChars = 0;
sInfo.dwFillAttribute = 0;
sInfo.dwFlags = 0;
sInfo.wShowWindow = 0;
sInfo.cbReserved2 = 0;
sInfo.lpReserved2 = 0;
sInfo.hStdInput = 0;
sInfo.hStdOutput = 0;
sInfo.hStdError = 0;
if(!CreateProcess(
strPathUninst,
_T("Uninstall /S"),
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
NULL,
&sInfo,
&pInfo)) {
pInfo.hProcess = NULL;
pInfo.hThread = NULL;
rv = 40;
goto _cleanup;
};
JOBOBJECT_ASSOCIATE_COMPLETION_PORT acp;
acp.CompletionKey = 0;
hJob = CreateJobObject(NULL, _T("NSISUninstallObject"));
if(!hJob) {
rv = 41;
goto _cleanup;
}
hIo = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
if(!hIo) {
rv = 42;
goto _cleanup;
}
acp.CompletionPort = hIo;
SetInformationJobObject( hJob, JobObjectAssociateCompletionPortInformation, &acp, sizeof(acp));
AssignProcessToJobObject( hJob, pInfo.hProcess );
ResumeThread( pInfo.hThread );
DWORD a,b,c;
for(;;) {
if(!GetQueuedCompletionStatus(hIo, &a, (PULONG_PTR) &b, (LPOVERLAPPED *) &c, INFINITE)) {
Sleep(1000);
continue;
}
if(a == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
break;
}
}
rv = ERROR_SUCCESS;
_cleanup:
if(hIo) CloseHandle(hIo);
if(pInfo.hProcess) CloseHandle( pInfo.hProcess );
if(pInfo.hThread) CloseHandle( pInfo.hThread );
if(hJob) CloseHandle(hJob);
if(strPathUninst) delete strPathUninst;
if(rv != ERROR_SUCCESS) {
ShowMsiError( hInstall, ERR_NSS_FAILED, rv );
}
return rv;
}
#endif
#ifdef __NMAKE__
!ENDIF
#endif