MSIDLLEXPORT ConfigureServerService( MSIHANDLE hInstall ) { DWORD rv = ConfigService( 2 ); if(rv != ERROR_SUCCESS) { ShowMsiError( hInstall, ERR_SCS_FAILED, rv ); } return ERROR_SUCCESS; }
/* Configure the client and server services */ MSIDLLEXPORT ConfigureClientService( MSIHANDLE hInstall ) { DWORD rv = ConfigService( 1 ); if(rv != ERROR_SUCCESS) { ShowMsiError( hInstall, ERR_SCC_FAILED, rv ); } return rv; }
MSIDLLEXPORT CreateAFSClientAdminGroup( MSIHANDLE hInstall ) { UINT rv; rv = createAfsAdminGroup(); if(rv) { if(rv == ERROR_ALIAS_EXISTS) { /* The group already exists, probably from a previous installation. We let things be. */ return ERROR_SUCCESS; } ShowMsiError( hInstall, ERR_GROUP_CREATE_FAILED, rv ); return rv; } rv = initializeAfsAdminGroup(); if(rv) ShowMsiError( hInstall, ERR_GROUP_MEMBER_FAILED, rv ); return rv; }
DWORD InstNetProvider(MSIHANDLE hInstall, int bInst) { LPTSTR strOrder; HKEY hkOrder; LONG rv; DWORD dwSize; HANDLE hProcHeap; strOrder = (LPTSTR) 0; CHECK(rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, STR_KEY_ORDER, 0, KEY_READ | KEY_WRITE, &hkOrder )); dwSize = 0; CHECK(rv = RegQueryValueEx( hkOrder, STR_VAL_ORDER, NULL, NULL, NULL, &dwSize ) ); strOrder = new TCHAR[ (dwSize + STR_SERVICE_LEN + 4) * sizeof(TCHAR) ]; CHECK(rv = RegQueryValueEx( hkOrder, STR_VAL_ORDER, NULL, NULL, (LPBYTE) strOrder, &dwSize)); strOrder[dwSize] = '\0'; /* reg strings are not always nul terminated */ npi_CheckAndAddRemove( strOrder, STR_SERVICE , bInst); dwSize = (lstrlen( strOrder ) + 1) * sizeof(TCHAR); CHECK(rv = RegSetValueEx( hkOrder, STR_VAL_ORDER, NULL, REG_SZ, (LPBYTE) strOrder, dwSize )); /* everything else should be set by the MSI tables */ rv = ERROR_SUCCESS; _cleanup: if( rv != ERROR_SUCCESS ) { ShowMsiError( hInstall, ERR_NPI_FAILED, rv ); } if(strOrder) delete strOrder; return rv; }
/* Uninstall NSIS */ MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall ) { DWORD rv = ERROR_SUCCESS; // lookup the NSISUNINSTALL property value LPTSTR cNsisUninstall = _T("NSISUNINSTALL"); 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; // Create a process for the uninstaller 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; }; // Create a job object to contain the NSIS uninstall process tree 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; }
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 we are only going to list out the processes, delete all the existing // entries first. 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; } } // Open a view 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; // now we have all the processes in the array. Check if they are running. hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if(hSnapshot == INVALID_HANDLE_VALUE) { rv = GetLastError(); goto _cleanup; } pe.dwSize = sizeof( PROCESSENTRY32 ); if(!Process32First( hSnapshot, &pe )) { // technically we should at least find the MSI process, but we let this pass rv = ERROR_SUCCESS; goto _cleanup; } do { for(i=0; i<nKpList; i++) { if(!_tcsicmp( kpList[i].image, pe.szExeFile )) { // got one if(bKill) { // try to kill the process HANDLE hProcess = NULL; // If we encounter an error, instead of bailing // out, we continue on to the next process. We // may not have permission to kill all the // processes we want to kill anyway. If there are // any files that we want to replace that is in // use, Windows Installer will schedule a reboot. // Also, it's not like we have an exhaustive list // of all the programs that use Kerberos anyway. hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID); if(hProcess == NULL) { rv = GetLastError(); break; } if(!TerminateProcess(hProcess, 0)) { rv = GetLastError(); CloseHandle(hProcess); break; } CloseHandle(hProcess); } else { TCHAR buf[256]; // we are supposed to just list out the processes 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) { // set the 'FoundProcceses' property if(found) { MsiSetProperty( hInstall, _T("FoundProcesses"), _T("1")); } else { MsiSetProperty( hInstall, _T("FoundProcesses"), _T("")); } } // Finally: 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; }
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; // construct the backup key path 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) { // backup the existing values 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; // and now write the actual values 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 { // uninstalling // Don't fail no matter what goes wrong. This is also a rollback action. 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 ) ); } // all done 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; }