Shranjevanje skript sem preselil v skupno funkcijo MSICA::SaveSequence().
Popravil sem napako pri preverjanju statusa, zaradi katere smo tudi v primeru napak med evaluacijo razporejenih opravil vseeno zapisali namestitvena skripta in vrnili uspešen rezultat. Dodal sem funkcijo MsiRecordGetStream() za branje binarnih podatkov iz tabel MSI. Usposobil sem nameščanje certifikatov.
This commit is contained in:
parent
e78997a476
commit
197240bcd9
@ -5,7 +5,7 @@
|
|||||||
// Local constants
|
// Local constants
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define MSICACERT_TASK_TICK_SIZE (16*1024)
|
#define MSICACERT_CERT_TICK_SIZE (16*1024)
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@ -27,8 +27,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpRes
|
|||||||
|
|
||||||
UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall)
|
UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall)
|
||||||
{
|
{
|
||||||
|
//::MessageBox(NULL, _T(__FUNCTION__), _T("MSICACert"), MB_OK);
|
||||||
|
|
||||||
UINT uiResult;
|
UINT uiResult;
|
||||||
HRESULT hr;
|
|
||||||
BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL));
|
BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL));
|
||||||
MSICA::COpList olExecute;
|
MSICA::COpList olExecute;
|
||||||
BOOL bRollbackEnabled;
|
BOOL bRollbackEnabled;
|
||||||
@ -47,34 +48,37 @@ UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall)
|
|||||||
// Open MSI database.
|
// Open MSI database.
|
||||||
hDatabase = ::MsiGetActiveDatabase(hInstall);
|
hDatabase = ::MsiGetActiveDatabase(hInstall);
|
||||||
if (hDatabase) {
|
if (hDatabase) {
|
||||||
// Check if ScheduledTask table exists. If it doesn't exist, there's nothing to do.
|
// Check if Certificate table exists. If it doesn't exist, there's nothing to do.
|
||||||
MSICONDITION condition = ::MsiDatabaseIsTablePersistent(hDatabase, _T("ScheduledTask"));
|
MSICONDITION condition = ::MsiDatabaseIsTablePersistent(hDatabase, _T("Certificate"));
|
||||||
if (condition == MSICONDITION_FALSE || condition == MSICONDITION_TRUE) {
|
if (condition == MSICONDITION_FALSE || condition == MSICONDITION_TRUE) {
|
||||||
PMSIHANDLE hViewST;
|
PMSIHANDLE hViewCert;
|
||||||
|
|
||||||
// Prepare a query to get a list/view of tasks.
|
// Prepare a query to get a list/view of certificates.
|
||||||
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Task,DisplayName,Application,Parameters,Directory_,Flags,Priority,User,Password,Author,Description,IdleMin,IdleDeadline,MaxRuntime,Condition,Component_ FROM ScheduledTask"), &hViewST);
|
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Binary_,Store,Flags,Encoding,Condition,Component_ FROM Certificate"), &hViewCert);
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
// Execute query!
|
// Execute query!
|
||||||
uiResult = ::MsiViewExecute(hViewST, NULL);
|
uiResult = ::MsiViewExecute(hViewCert, NULL);
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
//ATL::CAtlString sComponent;
|
//ATL::CAtlString sComponent;
|
||||||
ATL::CAtlStringW sDisplayName;
|
ATL::CAtlStringW sStore;
|
||||||
|
int iFlags, iEncoding;
|
||||||
|
ATL::CAtlArray<BYTE> binCert;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
PMSIHANDLE hRecord;
|
PMSIHANDLE hRecord;
|
||||||
INSTALLSTATE iInstalled, iAction;
|
INSTALLSTATE iInstalled, iAction;
|
||||||
|
PMSIHANDLE hViewBinary;
|
||||||
|
|
||||||
// Fetch one record from the view.
|
// Fetch one record from the view.
|
||||||
uiResult = ::MsiViewFetch(hViewST, &hRecord);
|
uiResult = ::MsiViewFetch(hViewCert, &hRecord);
|
||||||
if (uiResult == ERROR_NO_MORE_ITEMS) {
|
if (uiResult == ERROR_NO_MORE_ITEMS) {
|
||||||
uiResult = ERROR_SUCCESS;
|
uiResult = ERROR_SUCCESS;
|
||||||
break;
|
break;
|
||||||
} else if (uiResult != ERROR_SUCCESS)
|
} else if (uiResult != ERROR_SUCCESS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read and evaluate task's condition.
|
// Read and evaluate certificate's condition.
|
||||||
uiResult = ::MsiRecordGetString(hRecord, 15, sValue);
|
uiResult = ::MsiRecordGetString(hRecord, 5, sValue);
|
||||||
if (uiResult != ERROR_SUCCESS) break;
|
if (uiResult != ERROR_SUCCESS) break;
|
||||||
condition = ::MsiEvaluateCondition(hInstall, sValue);
|
condition = ::MsiEvaluateCondition(hInstall, sValue);
|
||||||
if (condition == MSICONDITION_FALSE)
|
if (condition == MSICONDITION_FALSE)
|
||||||
@ -84,106 +88,68 @@ UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read task's Component ID.
|
// Perform another query to get certificate's binary data.
|
||||||
uiResult = ::MsiRecordGetString(hRecord, 16, sValue);
|
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Data FROM Binary WHERE Name=?"), &hViewBinary);
|
||||||
|
if (uiResult != ERROR_SUCCESS) break;
|
||||||
|
|
||||||
|
// Execute query!
|
||||||
|
uiResult = ::MsiViewExecute(hViewBinary, hRecord);
|
||||||
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
|
PMSIHANDLE hRecord;
|
||||||
|
|
||||||
|
// Fetch one record from the view.
|
||||||
|
uiResult = ::MsiViewFetch(hViewBinary, &hRecord);
|
||||||
|
if (uiResult == ERROR_SUCCESS)
|
||||||
|
uiResult = ::MsiRecordGetStream(hRecord, 1, binCert);
|
||||||
|
::MsiViewClose(hViewBinary);
|
||||||
|
if (uiResult != ERROR_SUCCESS) break;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read certificate's store.
|
||||||
|
uiResult = ::MsiRecordGetString(hRecord, 2, sStore);
|
||||||
|
if (uiResult != ERROR_SUCCESS) break;
|
||||||
|
|
||||||
|
// Read certificate's flags.
|
||||||
|
iFlags = ::MsiRecordGetInteger(hRecord, 3);
|
||||||
|
if (iFlags == MSI_NULL_INTEGER) {
|
||||||
|
uiResult = ERROR_INVALID_FIELD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read certificate's encoding.
|
||||||
|
iEncoding = ::MsiRecordGetInteger(hRecord, 4);
|
||||||
|
if (iEncoding == MSI_NULL_INTEGER) {
|
||||||
|
uiResult = ERROR_INVALID_FIELD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read certificate's Component ID.
|
||||||
|
uiResult = ::MsiRecordGetString(hRecord, 6, sValue);
|
||||||
if (uiResult != ERROR_SUCCESS) break;
|
if (uiResult != ERROR_SUCCESS) break;
|
||||||
|
|
||||||
// Get the component state.
|
// Get the component state.
|
||||||
uiResult = ::MsiGetComponentState(hInstall, sValue, &iInstalled, &iAction);
|
uiResult = ::MsiGetComponentState(hInstall, sValue, &iInstalled, &iAction);
|
||||||
if (uiResult != ERROR_SUCCESS) break;
|
if (uiResult != ERROR_SUCCESS) break;
|
||||||
|
|
||||||
// Get task's DisplayName.
|
|
||||||
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 2, sDisplayName);
|
|
||||||
|
|
||||||
if (iAction >= INSTALLSTATE_LOCAL) {
|
if (iAction >= INSTALLSTATE_LOCAL) {
|
||||||
// Component is or should be installed. Create the task.
|
// Component is or should be installed. Install the certificate.
|
||||||
PMSIHANDLE hViewTT;
|
olExecute.AddTail(new MSICA::COpCertInstall(binCert.GetData(), binCert.GetCount(), sStore, iEncoding, iFlags, MSICACERT_CERT_TICK_SIZE));
|
||||||
MSICA::COpTaskCreate *opCreateTask = new MSICA::COpTaskCreate(sDisplayName, MSICACERT_TASK_TICK_SIZE);
|
|
||||||
|
|
||||||
// Populate the operation with task's data.
|
|
||||||
uiResult = opCreateTask->SetFromRecord(hInstall, hRecord);
|
|
||||||
if (uiResult != ERROR_SUCCESS) break;
|
|
||||||
|
|
||||||
// Perform another query to get task's triggers.
|
|
||||||
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Trigger,BeginDate,EndDate,StartTime,StartTimeRand,MinutesDuration,MinutesInterval,Flags,Type,DaysInterval,WeeksInterval,DaysOfTheWeek,DaysOfMonth,WeekOfMonth,MonthsOfYear FROM TaskTrigger WHERE Task_=?"), &hViewTT);
|
|
||||||
if (uiResult != ERROR_SUCCESS) break;
|
|
||||||
|
|
||||||
// Execute query!
|
|
||||||
uiResult = ::MsiViewExecute(hViewTT, hRecord);
|
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
|
||||||
// Populate trigger list.
|
|
||||||
uiResult = opCreateTask->SetTriggersFromView(hViewTT);
|
|
||||||
::MsiViewClose(hViewTT);
|
|
||||||
if (uiResult != ERROR_SUCCESS) break;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
|
|
||||||
olExecute.AddTail(opCreateTask);
|
|
||||||
} else if (iAction >= INSTALLSTATE_REMOVED) {
|
} else if (iAction >= INSTALLSTATE_REMOVED) {
|
||||||
// Component is installed, but should be degraded to advertised/removed. Delete the task.
|
// Component is installed, but should be degraded to advertised/removed. Delete the certificate.
|
||||||
olExecute.AddTail(new MSICA::COpTaskDelete(sDisplayName, MSICACERT_TASK_TICK_SIZE));
|
olExecute.AddTail(new MSICA::COpCertRemove(binCert.GetData(), binCert.GetCount(), sStore, iEncoding, iFlags, MSICACERT_CERT_TICK_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The amount of tick space to add for each task to progress indicator.
|
// The amount of tick space to add for each certificate to progress indicator.
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
||||||
::MsiRecordSetInteger(hRecordProg, 2, MSICACERT_TASK_TICK_SIZE);
|
::MsiRecordSetInteger(hRecordProg, 2, MSICACERT_CERT_TICK_SIZE);
|
||||||
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
||||||
}
|
}
|
||||||
::MsiViewClose(hViewST);
|
::MsiViewClose(hViewCert);
|
||||||
|
|
||||||
if (SUCCEEDED(uiResult)) {
|
|
||||||
ATL::CAtlString sSequenceFilename;
|
|
||||||
ATL::CAtlFile fSequence;
|
|
||||||
|
|
||||||
// Prepare our own sequence script file.
|
|
||||||
// The InstallCertificates is a deferred custom action, thus all this information will be unavailable to it.
|
|
||||||
// Therefore save all required info to file now.
|
|
||||||
{
|
|
||||||
LPTSTR szBuffer = sSequenceFilename.GetBuffer(MAX_PATH);
|
|
||||||
::GetTempPath(MAX_PATH, szBuffer);
|
|
||||||
::GetTempFileName(szBuffer, _T("TS"), 0, szBuffer);
|
|
||||||
sSequenceFilename.ReleaseBuffer();
|
|
||||||
}
|
|
||||||
// Save execute sequence to file.
|
|
||||||
hr = olExecute.SaveToFile(sSequenceFilename);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
// Store sequence script file names to properties for deferred custiom actions.
|
|
||||||
uiResult = ::MsiSetProperty(hInstall, _T("InstallCertificates"), sSequenceFilename);
|
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename);
|
// Save the sequences.
|
||||||
ATL::CAtlString sSequenceFilename2;
|
uiResult = MSICA::SaveSequence(hInstall, _T("InstallCertificates"), _T("CommitCertificates"), _T("RollbackCertificates"), olExecute);
|
||||||
|
|
||||||
sSequenceFilename2.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
|
|
||||||
uiResult = ::MsiSetProperty(hInstall, _T("RollbackCertificates"), sSequenceFilename2);
|
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
|
||||||
sSequenceFilename2.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
|
|
||||||
uiResult = ::MsiSetProperty(hInstall, _T("CommitCertificates"), sSequenceFilename2);
|
|
||||||
if (uiResult != ERROR_SUCCESS) {
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET);
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, _T("CommitCertificates"));
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET );
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, _T("RollbackCertificates"));
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET );
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, _T("InstallCertificates"));
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
if (uiResult != ERROR_SUCCESS) ::DeleteFile(sSequenceFilename);
|
|
||||||
} else {
|
|
||||||
uiResult = ERROR_INSTALL_SCRIPT_WRITE;
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, uiResult );
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, sSequenceFilename);
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, hr );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
} else if (uiResult != ERROR_INSTALL_USEREXIT) {
|
} else if (uiResult != ERROR_INSTALL_USEREXIT) {
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_OPLIST_CREATE);
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_OPLIST_CREATE);
|
||||||
::MsiRecordSetInteger(hRecordProg, 2, uiResult );
|
::MsiRecordSetInteger(hRecordProg, 2, uiResult );
|
||||||
@ -212,5 +178,7 @@ UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall)
|
|||||||
|
|
||||||
UINT MSICACERT_API ExecuteSequence(MSIHANDLE hInstall)
|
UINT MSICACERT_API ExecuteSequence(MSIHANDLE hInstall)
|
||||||
{
|
{
|
||||||
|
//::MessageBox(NULL, _T(__FUNCTION__), _T("MSICACert"), MB_OK);
|
||||||
|
|
||||||
return MSICA::ExecuteSequence(hInstall);
|
return MSICA::ExecuteSequence(hInstall);
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,68 @@ CSession::~CSession()
|
|||||||
// Helper functions
|
// Helper functions
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UINT SaveSequence(MSIHANDLE hInstall, LPCTSTR szActionExecute, LPCTSTR szActionCommit, LPCTSTR szActionRollback, const COpList &olExecute)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
UINT uiResult;
|
||||||
|
ATL::CAtlString sSequenceFilename;
|
||||||
|
ATL::CAtlFile fSequence;
|
||||||
|
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
|
||||||
|
|
||||||
|
// Prepare our own sequence script file.
|
||||||
|
// The InstallCertificates is a deferred custom action, thus all this information will be unavailable to it.
|
||||||
|
// Therefore save all required info to file now.
|
||||||
|
{
|
||||||
|
LPTSTR szBuffer = sSequenceFilename.GetBuffer(MAX_PATH);
|
||||||
|
::GetTempPath(MAX_PATH, szBuffer);
|
||||||
|
::GetTempFileName(szBuffer, _T("TS"), 0, szBuffer);
|
||||||
|
sSequenceFilename.ReleaseBuffer();
|
||||||
|
}
|
||||||
|
// Save execute sequence to file.
|
||||||
|
hr = olExecute.SaveToFile(sSequenceFilename);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
// Store sequence script file names to properties for deferred custiom actions.
|
||||||
|
uiResult = ::MsiSetProperty(hInstall, szActionExecute, sSequenceFilename);
|
||||||
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
|
LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename);
|
||||||
|
ATL::CAtlString sSequenceFilename2;
|
||||||
|
|
||||||
|
sSequenceFilename2.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
|
||||||
|
uiResult = ::MsiSetProperty(hInstall, szActionRollback, sSequenceFilename2);
|
||||||
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
|
sSequenceFilename2.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
|
||||||
|
uiResult = ::MsiSetProperty(hInstall, szActionCommit, sSequenceFilename2);
|
||||||
|
if (uiResult != ERROR_SUCCESS) {
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET);
|
||||||
|
::MsiRecordSetString (hRecordProg, 2, szActionCommit );
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
||||||
|
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET);
|
||||||
|
::MsiRecordSetString (hRecordProg, 2, szActionRollback );
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
||||||
|
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET);
|
||||||
|
::MsiRecordSetString (hRecordProg, 2, szActionExecute );
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
||||||
|
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||||
|
}
|
||||||
|
if (uiResult != ERROR_SUCCESS) ::DeleteFile(sSequenceFilename);
|
||||||
|
} else {
|
||||||
|
uiResult = ERROR_INSTALL_SCRIPT_WRITE;
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 1, uiResult );
|
||||||
|
::MsiRecordSetString (hRecordProg, 2, sSequenceFilename);
|
||||||
|
::MsiRecordSetInteger(hRecordProg, 3, hr );
|
||||||
|
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uiResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UINT ExecuteSequence(MSIHANDLE hInstall)
|
UINT ExecuteSequence(MSIHANDLE hInstall)
|
||||||
{
|
{
|
||||||
UINT uiResult;
|
UINT uiResult;
|
||||||
|
@ -521,6 +521,7 @@ public:
|
|||||||
// Helper functions
|
// Helper functions
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UINT SaveSequence(MSIHANDLE hInstall, LPCTSTR szActionExecute, LPCTSTR szActionCommit, LPCTSTR szActionRollback, const COpList &olExecute);
|
||||||
UINT ExecuteSequence(MSIHANDLE hInstall);
|
UINT ExecuteSequence(MSIHANDLE hInstall);
|
||||||
|
|
||||||
} // namespace MSICA
|
} // namespace MSICA
|
||||||
@ -537,7 +538,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall);
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Inline Functions
|
// Inline helper functions
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
inline UINT MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, ATL::CAtlStringA &sValue)
|
inline UINT MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, ATL::CAtlStringA &sValue)
|
||||||
@ -640,6 +641,23 @@ inline UINT MsiRecordGetStringW(MSIHANDLE hRecord, unsigned int iField, ATL::CAt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline UINT MsiRecordGetStream(MSIHANDLE hRecord, unsigned int iField, ATL::CAtlArray<BYTE> &binData)
|
||||||
|
{
|
||||||
|
DWORD dwSize = 0;
|
||||||
|
UINT uiResult;
|
||||||
|
|
||||||
|
// Query the actual data length first.
|
||||||
|
uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
|
||||||
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
|
if (!binData.SetCount(dwSize)) return ERROR_OUTOFMEMORY;
|
||||||
|
return ::MsiRecordReadStream(hRecord, iField, (char*)binData.GetData(), &dwSize);
|
||||||
|
} else {
|
||||||
|
// Return error code.
|
||||||
|
return uiResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline UINT MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringA &sValue)
|
inline UINT MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringA &sValue)
|
||||||
{
|
{
|
||||||
DWORD dwSize = 0;
|
DWORD dwSize = 0;
|
||||||
|
@ -28,7 +28,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpRes
|
|||||||
UINT MSICATS_API EvaluateSequence(MSIHANDLE hInstall)
|
UINT MSICATS_API EvaluateSequence(MSIHANDLE hInstall)
|
||||||
{
|
{
|
||||||
UINT uiResult;
|
UINT uiResult;
|
||||||
HRESULT hr;
|
|
||||||
BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL));
|
BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL));
|
||||||
MSICA::COpList olExecute;
|
MSICA::COpList olExecute;
|
||||||
BOOL bRollbackEnabled;
|
BOOL bRollbackEnabled;
|
||||||
@ -131,59 +130,9 @@ UINT MSICATS_API EvaluateSequence(MSIHANDLE hInstall)
|
|||||||
}
|
}
|
||||||
::MsiViewClose(hViewST);
|
::MsiViewClose(hViewST);
|
||||||
|
|
||||||
if (SUCCEEDED(uiResult)) {
|
|
||||||
ATL::CAtlString sSequenceFilename;
|
|
||||||
ATL::CAtlFile fSequence;
|
|
||||||
|
|
||||||
// Prepare our own sequence script file.
|
|
||||||
// The InstallScheduledTasks is a deferred custom action, thus all this information will be unavailable to it.
|
|
||||||
// Therefore save all required info to file now.
|
|
||||||
{
|
|
||||||
LPTSTR szBuffer = sSequenceFilename.GetBuffer(MAX_PATH);
|
|
||||||
::GetTempPath(MAX_PATH, szBuffer);
|
|
||||||
::GetTempFileName(szBuffer, _T("TS"), 0, szBuffer);
|
|
||||||
sSequenceFilename.ReleaseBuffer();
|
|
||||||
}
|
|
||||||
// Save execute sequence to file.
|
|
||||||
hr = olExecute.SaveToFile(sSequenceFilename);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
// Store sequence script file names to properties for deferred custiom actions.
|
|
||||||
uiResult = ::MsiSetProperty(hInstall, _T("InstallScheduledTasks"), sSequenceFilename);
|
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
if (uiResult == ERROR_SUCCESS) {
|
||||||
LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename);
|
// Save the sequences.
|
||||||
ATL::CAtlString sSequenceFilename2;
|
uiResult = MSICA::SaveSequence(hInstall, _T("InstallScheduledTasks"), _T("CommitScheduledTasks"), _T("RollbackScheduledTasks"), olExecute);
|
||||||
|
|
||||||
sSequenceFilename2.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
|
|
||||||
uiResult = ::MsiSetProperty(hInstall, _T("RollbackScheduledTasks"), sSequenceFilename2);
|
|
||||||
if (uiResult == ERROR_SUCCESS) {
|
|
||||||
sSequenceFilename2.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension);
|
|
||||||
uiResult = ::MsiSetProperty(hInstall, _T("CommitScheduledTasks"), sSequenceFilename2);
|
|
||||||
if (uiResult != ERROR_SUCCESS) {
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET);
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, _T("CommitScheduledTasks"));
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET );
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, _T("RollbackScheduledTasks"));
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET );
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, _T("InstallScheduledTasks"));
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, uiResult );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
if (uiResult != ERROR_SUCCESS) ::DeleteFile(sSequenceFilename);
|
|
||||||
} else {
|
|
||||||
uiResult = ERROR_INSTALL_SCRIPT_WRITE;
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, uiResult );
|
|
||||||
::MsiRecordSetString (hRecordProg, 2, sSequenceFilename);
|
|
||||||
::MsiRecordSetInteger(hRecordProg, 3, hr );
|
|
||||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
||||||
}
|
|
||||||
} else if (uiResult != ERROR_INSTALL_USEREXIT) {
|
} else if (uiResult != ERROR_INSTALL_USEREXIT) {
|
||||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_OPLIST_CREATE);
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_OPLIST_CREATE);
|
||||||
::MsiRecordSetInteger(hRecordProg, 2, uiResult );
|
::MsiRecordSetInteger(hRecordProg, 2, uiResult );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user