ATL::CAtlString, ATL::CAtlArray and ATL::CAtlList replaced with std c++ equivalents

This commit is contained in:
Simon Rozman 2017-04-24 14:30:23 +02:00
parent 365d82a3ee
commit a8b69efe02
11 changed files with 569 additions and 643 deletions

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MSICALib", "build\MSICALib.vcxproj", "{8552EE55-177E-4F51-B51B-BAF7D6462CDE}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MSICALib", "build\MSICALib.vcxproj", "{8552EE55-177E-4F51-B51B-BAF7D6462CDE}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "atlex", "..\atlex\build\atlex.vcxproj", "{5A4EADF2-3237-457A-9DA8-BB9942A91019}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinStd", "..\WinStd\build\WinStd.vcxproj", "{47399D91-7EB9-41DE-B521-514BA5DB0C43}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -21,14 +21,14 @@ Global
{8552EE55-177E-4F51-B51B-BAF7D6462CDE}.Release|Win32.Build.0 = Release|Win32 {8552EE55-177E-4F51-B51B-BAF7D6462CDE}.Release|Win32.Build.0 = Release|Win32
{8552EE55-177E-4F51-B51B-BAF7D6462CDE}.Release|x64.ActiveCfg = Release|x64 {8552EE55-177E-4F51-B51B-BAF7D6462CDE}.Release|x64.ActiveCfg = Release|x64
{8552EE55-177E-4F51-B51B-BAF7D6462CDE}.Release|x64.Build.0 = Release|x64 {8552EE55-177E-4F51-B51B-BAF7D6462CDE}.Release|x64.Build.0 = Release|x64
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Debug|Win32.ActiveCfg = Debug|Win32 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Debug|Win32.ActiveCfg = Debug|Win32
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Debug|Win32.Build.0 = Debug|Win32 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Debug|Win32.Build.0 = Debug|Win32
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Debug|x64.ActiveCfg = Debug|x64 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Debug|x64.ActiveCfg = Debug|x64
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Debug|x64.Build.0 = Debug|x64 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Debug|x64.Build.0 = Debug|x64
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Release|Win32.ActiveCfg = Release|Win32 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Release|Win32.ActiveCfg = Release|Win32
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Release|Win32.Build.0 = Release|Win32 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Release|Win32.Build.0 = Release|Win32
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Release|x64.ActiveCfg = Release|x64 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Release|x64.ActiveCfg = Release|x64
{5A4EADF2-3237-457A-9DA8-BB9942A91019}.Release|x64.Build.0 = Release|x64 {47399D91-7EB9-41DE-B521-514BA5DB0C43}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -36,7 +36,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..\include;..\..\atlex\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\WinStd\include;..\..\atlex\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>

View File

@ -20,9 +20,10 @@
#pragma once #pragma once
#include <atlbase.h> #include <atlbase.h>
#include <atlcoll.h>
#include <atlfile.h> #include <atlfile.h>
#include <atlstr.h> #include <WinStd\Common.h>
#include <list>
#include <string>
#include <msi.h> #include <msi.h>
#include <mstask.h> #include <mstask.h>
#include <wincrypt.h> #include <wincrypt.h>
@ -109,7 +110,7 @@ public:
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSingleString &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSingleString &op);
protected: protected:
ATL::CAtlStringW m_sValue; std::wstring m_sValue;
}; };
@ -126,8 +127,8 @@ public:
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSrcDstString &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSrcDstString &op);
protected: protected:
ATL::CAtlStringW m_sValue1; std::wstring m_sValue1;
ATL::CAtlStringW m_sValue2; std::wstring m_sValue2;
}; };
@ -274,7 +275,7 @@ public:
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSingle &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSingle &op);
protected: protected:
ATL::CAtlStringW m_sValueName; std::wstring m_sValueName;
}; };
@ -291,8 +292,8 @@ public:
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSrcDst &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSrcDst &op);
protected: protected:
ATL::CAtlStringW m_sValueName1; std::wstring m_sValueName1;
ATL::CAtlStringW m_sValueName2; std::wstring m_sValueName2;
}; };
@ -315,10 +316,10 @@ public:
protected: protected:
DWORD m_dwType; DWORD m_dwType;
ATL::CAtlStringW m_sData; std::wstring m_sData;
ATL::CAtlArray<BYTE> m_binData; std::vector<BYTE> m_binData;
DWORD m_dwData; DWORD m_dwData;
ATL::CAtlArray<WCHAR> m_szData; std::vector<WCHAR> m_szData;
DWORDLONG m_qwData; DWORDLONG m_qwData;
}; };
@ -355,7 +356,6 @@ class COpTaskCreate : public COpTypeSingleString
{ {
public: public:
COpTaskCreate(LPCWSTR pszTaskName = L"", int iTicks = 0); COpTaskCreate(LPCWSTR pszTaskName = L"", int iTicks = 0);
virtual ~COpTaskCreate();
virtual HRESULT Execute(CSession *pSession); virtual HRESULT Execute(CSession *pSession);
UINT SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord); UINT SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord);
@ -365,20 +365,20 @@ public:
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskCreate &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskCreate &op);
protected: protected:
ATL::CAtlStringW m_sApplicationName; std::wstring m_sApplicationName;
ATL::CAtlStringW m_sParameters; std::wstring m_sParameters;
ATL::CAtlStringW m_sWorkingDirectory; std::wstring m_sWorkingDirectory;
ATL::CAtlStringW m_sAuthor; std::wstring m_sAuthor;
ATL::CAtlStringW m_sComment; std::wstring m_sComment;
DWORD m_dwFlags; DWORD m_dwFlags;
DWORD m_dwPriority; DWORD m_dwPriority;
ATL::CAtlStringW m_sAccountName; std::wstring m_sAccountName;
ATL::CAtlStringW m_sPassword; winstd::sanitizing_wstring m_sPassword;
WORD m_wIdleMinutes; WORD m_wIdleMinutes;
WORD m_wDeadlineMinutes; WORD m_wDeadlineMinutes;
DWORD m_dwMaxRuntimeMS; DWORD m_dwMaxRuntimeMS;
ATL::CAtlList<TASK_TRIGGER> m_lTriggers; std::list<TASK_TRIGGER> m_lTriggers;
}; };
@ -455,7 +455,7 @@ public:
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpCert &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpCert &op);
protected: protected:
ATL::CAtlArray<BYTE> m_binCert; std::vector<BYTE> m_binCert;
}; };
@ -588,7 +588,7 @@ public:
protected: protected:
DWORD m_dwFlags; DWORD m_dwFlags;
ATL::CAtlStringW m_sProfileXML; std::wstring m_sProfileXML;
}; };
@ -596,7 +596,7 @@ protected:
// COpList // COpList
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
class COpList : public COperation, public ATL::CAtlList<COperation*> class COpList : public COperation, public std::list<COperation*>
{ {
public: public:
COpList(int iTicks = 0); COpList(int iTicks = 0);
@ -637,7 +637,7 @@ protected:
protected: protected:
template <class T, enum OPERATION ID> inline static HRESULT Save(ATL::CAtlFile &f, const COperation *p); template <class T, enum OPERATION ID> inline static HRESULT Save(ATL::CAtlFile &f, const COperation *p);
template <class T> inline HRESULT LoadAndAddTail(ATL::CAtlFile &f); template <class T> inline HRESULT load_back(ATL::CAtlFile &f);
}; };
@ -679,12 +679,17 @@ UINT ExecuteSequence(MSIHANDLE hInstall);
#include <msiquery.h> #include <msiquery.h>
#include <mstask.h> #include <mstask.h>
#include <WinStd/MSI.h>
#include <memory>
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Inline helper functions // Inline helper functions
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
inline UINT MsiRecordFormatStringA(MSIHANDLE hInstall, MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringA &sValue) template<class _Elem, class _Traits, class _Ax>
inline UINT MsiRecordFormatStringA(MSIHANDLE hInstall, MSIHANDLE hRecord, unsigned int iField, std::basic_string<_Elem, _Traits, _Ax> &sValue)
{ {
UINT uiResult; UINT uiResult;
PMSIHANDLE hRecordEx; PMSIHANDLE hRecordEx;
@ -694,14 +699,14 @@ inline UINT MsiRecordFormatStringA(MSIHANDLE hInstall, MSIHANDLE hRecord, unsign
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
// If the string is empty, there's nothing left to do. // If the string is empty, there's nothing left to do.
if (sValue.IsEmpty()) return NO_ERROR; if (sValue.empty()) return NO_ERROR;
// Create a record. // Create a record.
hRecordEx = ::MsiCreateRecord(1); hRecordEx = ::MsiCreateRecord(1);
if (!hRecordEx) return ERROR_INVALID_HANDLE; if (!hRecordEx) return ERROR_INVALID_HANDLE;
// Populate record with data. // Populate record with data.
uiResult = ::MsiRecordSetStringA(hRecordEx, 0, sValue); uiResult = ::MsiRecordSetStringA(hRecordEx, 0, sValue.c_str());
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
// Do the formatting. // Do the formatting.
@ -709,7 +714,8 @@ inline UINT MsiRecordFormatStringA(MSIHANDLE hInstall, MSIHANDLE hRecord, unsign
} }
inline UINT MsiRecordFormatStringW(MSIHANDLE hInstall, MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringW &sValue) template<class _Elem, class _Traits, class _Ax>
inline UINT MsiRecordFormatStringW(MSIHANDLE hInstall, MSIHANDLE hRecord, unsigned int iField, std::basic_string<_Elem, _Traits, _Ax> &sValue)
{ {
UINT uiResult; UINT uiResult;
PMSIHANDLE hRecordEx; PMSIHANDLE hRecordEx;
@ -719,14 +725,14 @@ inline UINT MsiRecordFormatStringW(MSIHANDLE hInstall, MSIHANDLE hRecord, unsign
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
// If the string is empty, there's nothing left to do. // If the string is empty, there's nothing left to do.
if (sValue.IsEmpty()) return NO_ERROR; if (sValue.empty()) return NO_ERROR;
// Create a record. // Create a record.
hRecordEx = ::MsiCreateRecord(1); hRecordEx = ::MsiCreateRecord(1);
if (!hRecordEx) return ERROR_INVALID_HANDLE; if (!hRecordEx) return ERROR_INVALID_HANDLE;
// Populate record with data. // Populate record with data.
uiResult = ::MsiRecordSetStringW(hRecordEx, 0, sValue); uiResult = ::MsiRecordSetStringW(hRecordEx, 0, sValue.c_str());
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
// Do the formatting. // Do the formatting.
@ -806,120 +812,83 @@ inline HRESULT operator >>(ATL::CAtlFile &f, GUID &guid)
} }
template <class E> template <class _Ty, class _Ax>
inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlArray<E> &a) inline HRESULT operator <<(ATL::CAtlFile &f, const std::vector<_Ty, _Ax> &a)
{ {
HRESULT hr; HRESULT hr;
DWORD dwCount = (DWORD)a.GetCount(), dwWritten; size_t nCount = a.size();
DWORD dwWritten;
// Write element count. // Write element count.
hr = f.Write(&dwCount, sizeof(DWORD), &dwWritten); hr = f.Write(&nCount, sizeof(size_t), &dwWritten);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwWritten < sizeof(DWORD)) return E_FAIL; if (dwWritten < sizeof(size_t)) return E_FAIL;
// Write data. // Write data (opaque).
hr = f.Write(a.GetData(), sizeof(E) * dwCount, &dwWritten); hr = f.Write(a.data(), static_cast<DWORD>(sizeof(_Ty) * nCount), &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(E) * dwCount ? hr : E_FAIL : hr; return SUCCEEDED(hr) ? dwWritten == sizeof(_Ty) * nCount ? hr : E_FAIL : hr;
} }
template <class E> template <class _Ty, class _Ax>
inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlArray<E> &a) inline HRESULT operator >>(ATL::CAtlFile &f, std::vector<_Ty, _Ax> &a)
{ {
HRESULT hr; HRESULT hr;
DWORD dwCount, dwRead; size_t nCount;
DWORD dwRead;
// Read element count as 32-bit integer. // Read element count.
hr = f.Read(&dwCount, sizeof(DWORD), dwRead); hr = f.Read(&nCount, sizeof(size_t), dwRead);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwRead < sizeof(DWORD)) return E_FAIL; if (dwRead < sizeof(size_t)) return E_FAIL;
// Allocate the buffer. // Allocate the buffer.
if (!a.SetCount(dwCount)) return E_OUTOFMEMORY; a.resize(nCount);
// Read data. // Read data (opaque).
hr = f.Read(a.GetData(), sizeof(E) * dwCount, dwRead); hr = f.Read(a.data(), static_cast<DWORD>(sizeof(_Ty) * nCount), dwRead);
if (SUCCEEDED(hr)) a.SetCount(dwRead / sizeof(E)); if (SUCCEEDED(hr)) a.resize(dwRead / sizeof(_Ty));
return hr; return hr;
} }
inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlStringA &str) template<class _Elem, class _Traits, class _Ax>
inline HRESULT operator <<(ATL::CAtlFile &f, const std::basic_string<_Elem, _Traits, _Ax> &str)
{ {
HRESULT hr; HRESULT hr;
int iLength = str.GetLength(); size_t iLength = str.length();
DWORD dwWritten; DWORD dwWritten;
// Write string length (in characters) as 32-bit integer. // Write string length (in characters).
hr = f.Write(&iLength, sizeof(int), &dwWritten); hr = f.Write(&iLength, sizeof(size_t), &dwWritten);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwWritten < sizeof(int)) return E_FAIL; if (dwWritten < sizeof(size_t)) return E_FAIL;
// Write string data (without terminator). // Write string data (without terminator).
hr = f.Write((LPCSTR)str, sizeof(CHAR) * iLength, &dwWritten); hr = f.Write(str.c_str(), static_cast<DWORD>(sizeof(_Elem) * iLength), &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(CHAR) * iLength ? hr : E_FAIL : hr; return SUCCEEDED(hr) ? dwWritten == sizeof(_Elem) * iLength ? hr : E_FAIL : hr;
} }
inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlStringA &str) template<class _Elem, class _Traits, class _Ax>
inline HRESULT operator >>(ATL::CAtlFile &f, std::basic_string<_Elem, _Traits, _Ax> &str)
{ {
HRESULT hr; HRESULT hr;
int iLength; size_t iLength;
LPSTR buf;
DWORD dwRead; DWORD dwRead;
// Read string length (in characters) as 32-bit integer. // Read string length (in characters).
hr = f.Read(&iLength, sizeof(int), dwRead); hr = f.Read(&iLength, sizeof(size_t), dwRead);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwRead < sizeof(int)) return E_FAIL; if (dwRead < sizeof(size_t)) return E_FAIL;
// Allocate the buffer. // Allocate the buffer.
buf = str.GetBuffer(iLength); std::unique_ptr<_Elem[]> buf(new _Elem[iLength]);
if (!buf) return E_OUTOFMEMORY; if (!buf) return E_OUTOFMEMORY;
// Read string data (without terminator). // Read string data (without terminator).
hr = f.Read(buf, sizeof(CHAR) * iLength, dwRead); hr = f.Read(buf.get(), static_cast<DWORD>(sizeof(_Elem) * iLength), dwRead);
str.ReleaseBuffer(SUCCEEDED(hr) ? dwRead / sizeof(CHAR) : 0); str.assign(buf.get(), SUCCEEDED(hr) ? dwRead / sizeof(_Elem) : 0);
return hr;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlStringW &str)
{
HRESULT hr;
int iLength = str.GetLength();
DWORD dwWritten;
// Write string length (in characters) as 32-bit integer.
hr = f.Write(&iLength, sizeof(int), &dwWritten);
if (FAILED(hr)) return hr;
if (dwWritten < sizeof(int)) return E_FAIL;
// Write string data (without terminator).
hr = f.Write((LPCWSTR)str, sizeof(WCHAR) * iLength, &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(WCHAR) * iLength ? hr : E_FAIL : hr;
}
inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlStringW &str)
{
HRESULT hr;
int iLength;
LPWSTR buf;
DWORD dwRead;
// Read string length (in characters) as 32-bit integer.
hr = f.Read(&iLength, sizeof(int), dwRead);
if (FAILED(hr)) return hr;
if (dwRead < sizeof(int)) return E_FAIL;
// Allocate the buffer.
buf = str.GetBuffer(iLength);
if (!buf) return E_OUTOFMEMORY;
// Read string data (without terminator).
hr = f.Read(buf, sizeof(WCHAR) * iLength, dwRead);
str.ReleaseBuffer(SUCCEEDED(hr) ? dwRead / sizeof(WCHAR) : 0);
return hr; return hr;
} }
@ -1164,7 +1133,6 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueCreate &op)
inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op) inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op)
{ {
HRESULT hr; HRESULT hr;
POSITION pos;
hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr; hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f << op.m_sApplicationName; if (FAILED(hr)) return hr; hr = f << op.m_sApplicationName; if (FAILED(hr)) return hr;
@ -1178,9 +1146,9 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op)
hr = f << op.m_sPassword; if (FAILED(hr)) return hr; hr = f << op.m_sPassword; if (FAILED(hr)) return hr;
hr = f << (int)MAKELONG(op.m_wDeadlineMinutes, op.m_wIdleMinutes); if (FAILED(hr)) return hr; hr = f << (int)MAKELONG(op.m_wDeadlineMinutes, op.m_wIdleMinutes); if (FAILED(hr)) return hr;
hr = f << (int)(op.m_dwMaxRuntimeMS); if (FAILED(hr)) return hr; hr = f << (int)(op.m_dwMaxRuntimeMS); if (FAILED(hr)) return hr;
hr = f << (int)(op.m_lTriggers.GetCount()); if (FAILED(hr)) return hr; hr = f << (int)(op.m_lTriggers.size()); if (FAILED(hr)) return hr;
for (pos = op.m_lTriggers.GetHeadPosition(); pos;) { for (auto t = op.m_lTriggers.cbegin(), t_end = op.m_lTriggers.cend(); t != t_end; ++t) {
hr = f << op.m_lTriggers.GetNext(pos); hr = f << *t;
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
} }
@ -1210,7 +1178,7 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskCreate &op)
TASK_TRIGGER ttData; TASK_TRIGGER ttData;
hr = f >> ttData; hr = f >> ttData;
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
op.m_lTriggers.AddTail(ttData); op.m_lTriggers.push_back(ttData);
} }
return S_OK; return S_OK;
@ -1379,17 +1347,16 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpWLANProfileSet &op)
inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &list) inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &list)
{ {
POSITION pos;
HRESULT hr; HRESULT hr;
hr = f << (const COperation &)list; hr = f << (const COperation &)list;
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
hr = f << (int)(list.GetCount()); hr = f << (int)(list.size());
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
for (pos = list.GetHeadPosition(); pos;) { for (auto i = list.cbegin(), i_end = list.cend(); i != i_end; ++i) {
const COperation *pOp = list.GetNext(pos); const COperation *pOp = *i;
if (dynamic_cast<const COpRollbackEnable* >(pOp)) hr = list.Save<COpRollbackEnable, COpList::OP_ROLLBACK_ENABLE >(f, pOp); if (dynamic_cast<const COpRollbackEnable* >(pOp)) hr = list.Save<COpRollbackEnable, COpList::OP_ROLLBACK_ENABLE >(f, pOp);
else if (dynamic_cast<const COpFileDelete* >(pOp)) hr = list.Save<COpFileDelete, COpList::OP_FILE_DELETE >(f, pOp); else if (dynamic_cast<const COpFileDelete* >(pOp)) hr = list.Save<COpFileDelete, COpList::OP_FILE_DELETE >(f, pOp);
else if (dynamic_cast<const COpFileMove* >(pOp)) hr = list.Save<COpFileMove, COpList::OP_FILE_MOVE >(f, pOp); else if (dynamic_cast<const COpFileMove* >(pOp)) hr = list.Save<COpFileMove, COpList::OP_FILE_MOVE >(f, pOp);
@ -1441,27 +1408,27 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpList &list)
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
switch ((COpList::OPERATION)iTemp) { switch ((COpList::OPERATION)iTemp) {
case COpList::OP_ROLLBACK_ENABLE: hr = list.LoadAndAddTail<COpRollbackEnable >(f); break; case COpList::OP_ROLLBACK_ENABLE: hr = list.load_back<COpRollbackEnable >(f); break;
case COpList::OP_FILE_DELETE: hr = list.LoadAndAddTail<COpFileDelete >(f); break; case COpList::OP_FILE_DELETE: hr = list.load_back<COpFileDelete >(f); break;
case COpList::OP_FILE_MOVE: hr = list.LoadAndAddTail<COpFileMove >(f); break; case COpList::OP_FILE_MOVE: hr = list.load_back<COpFileMove >(f); break;
case COpList::OP_REG_KEY_CREATE: hr = list.LoadAndAddTail<COpRegKeyCreate >(f); break; case COpList::OP_REG_KEY_CREATE: hr = list.load_back<COpRegKeyCreate >(f); break;
case COpList::OP_REG_KEY_COPY: hr = list.LoadAndAddTail<COpRegKeyCopy >(f); break; case COpList::OP_REG_KEY_COPY: hr = list.load_back<COpRegKeyCopy >(f); break;
case COpList::OP_REG_KEY_DELETE: hr = list.LoadAndAddTail<COpRegKeyDelete >(f); break; case COpList::OP_REG_KEY_DELETE: hr = list.load_back<COpRegKeyDelete >(f); break;
case COpList::OP_REG_VALUE_CREATE: hr = list.LoadAndAddTail<COpRegValueCreate >(f); break; case COpList::OP_REG_VALUE_CREATE: hr = list.load_back<COpRegValueCreate >(f); break;
case COpList::OP_REG_VALUE_COPY: hr = list.LoadAndAddTail<COpRegValueCopy >(f); break; case COpList::OP_REG_VALUE_COPY: hr = list.load_back<COpRegValueCopy >(f); break;
case COpList::OP_REG_VALUE_DELETE: hr = list.LoadAndAddTail<COpRegValueDelete >(f); break; case COpList::OP_REG_VALUE_DELETE: hr = list.load_back<COpRegValueDelete >(f); break;
case COpList::OP_TASK_CREATE: hr = list.LoadAndAddTail<COpTaskCreate >(f); break; case COpList::OP_TASK_CREATE: hr = list.load_back<COpTaskCreate >(f); break;
case COpList::OP_TASK_DELETE: hr = list.LoadAndAddTail<COpTaskDelete >(f); break; case COpList::OP_TASK_DELETE: hr = list.load_back<COpTaskDelete >(f); break;
case COpList::OP_TASK_ENABLE: hr = list.LoadAndAddTail<COpTaskEnable >(f); break; case COpList::OP_TASK_ENABLE: hr = list.load_back<COpTaskEnable >(f); break;
case COpList::OP_TASK_COPY: hr = list.LoadAndAddTail<COpTaskCopy >(f); break; case COpList::OP_TASK_COPY: hr = list.load_back<COpTaskCopy >(f); break;
case COpList::OP_CERT_INSTALL: hr = list.LoadAndAddTail<COpCertInstall >(f); break; case COpList::OP_CERT_INSTALL: hr = list.load_back<COpCertInstall >(f); break;
case COpList::OP_CERT_REMOVE: hr = list.LoadAndAddTail<COpCertRemove >(f); break; case COpList::OP_CERT_REMOVE: hr = list.load_back<COpCertRemove >(f); break;
case COpList::OP_SVC_SET_START: hr = list.LoadAndAddTail<COpSvcSetStart >(f); break; case COpList::OP_SVC_SET_START: hr = list.load_back<COpSvcSetStart >(f); break;
case COpList::OP_SVC_START: hr = list.LoadAndAddTail<COpSvcStart >(f); break; case COpList::OP_SVC_START: hr = list.load_back<COpSvcStart >(f); break;
case COpList::OP_SVC_STOP: hr = list.LoadAndAddTail<COpSvcStop >(f); break; case COpList::OP_SVC_STOP: hr = list.load_back<COpSvcStop >(f); break;
case COpList::OP_WLAN_PROFILE_DELETE: hr = list.LoadAndAddTail<COpWLANProfileDelete>(f); break; case COpList::OP_WLAN_PROFILE_DELETE: hr = list.load_back<COpWLANProfileDelete>(f); break;
case COpList::OP_WLAN_PROFILE_SET: hr = list.LoadAndAddTail<COpWLANProfileSet >(f); break; case COpList::OP_WLAN_PROFILE_SET: hr = list.load_back<COpWLANProfileSet >(f); break;
case COpList::OP_SUBLIST: hr = list.LoadAndAddTail<COpList >(f); break; case COpList::OP_SUBLIST: hr = list.load_back<COpList >(f); break;
default: default:
// Unsupported type of operation. // Unsupported type of operation.
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
@ -1525,7 +1492,7 @@ template <class T, enum COpList::OPERATION ID> inline static HRESULT COpList::Sa
} }
template <class T> inline HRESULT COpList::LoadAndAddTail(ATL::CAtlFile &f) template <class T> inline HRESULT COpList::load_back(ATL::CAtlFile &f)
{ {
HRESULT hr; HRESULT hr;
@ -1541,7 +1508,7 @@ template <class T> inline HRESULT COpList::LoadAndAddTail(ATL::CAtlFile &f)
} }
// Add element. // Add element.
AddTail(p); push_back(p);
return S_OK; return S_OK;
} }

View File

@ -89,19 +89,15 @@ HRESULT COpRollbackEnable::Execute(CSession *pSession)
// COpList // COpList
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
COpList::COpList(int iTicks) : COpList::COpList(int iTicks) : COperation(iTicks)
COperation(iTicks),
ATL::CAtlList<COperation*>(sizeof(COperation*))
{ {
} }
void COpList::Free() void COpList::Free()
{ {
POSITION pos; for (auto i = begin(), i_end = end(); i != i_end; ++i) {
COperation *pOp = *i;
for (pos = GetHeadPosition(); pos;) {
COperation *pOp = GetNext(pos);
COpList *pOpList = dynamic_cast<COpList*>(pOp); COpList *pOpList = dynamic_cast<COpList*>(pOp);
if (pOpList) { if (pOpList) {
@ -111,7 +107,7 @@ void COpList::Free()
delete pOp; delete pOp;
} }
RemoveAll(); clear();
} }
@ -147,7 +143,6 @@ HRESULT COpList::SaveToFile(LPCTSTR pszFileName) const
HRESULT COpList::Execute(CSession *pSession) HRESULT COpList::Execute(CSession *pSession)
{ {
POSITION pos;
HRESULT hr; HRESULT hr;
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
@ -161,8 +156,8 @@ HRESULT COpList::Execute(CSession *pSession)
::MsiRecordSetInteger(hRecordProg, 1, 2); ::MsiRecordSetInteger(hRecordProg, 1, 2);
::MsiRecordSetInteger(hRecordProg, 3, 0); ::MsiRecordSetInteger(hRecordProg, 3, 0);
for (pos = GetHeadPosition(); pos;) { for (auto i = cbegin(), i_end = cend(); i != i_end; ++i) {
COperation *pOp = GetNext(pos); COperation *pOp = *i;
hr = pOp->Execute(pSession); hr = pOp->Execute(pSession);
if (!pSession->m_bContinueOnError && FAILED(hr)) { if (!pSession->m_bContinueOnError && FAILED(hr)) {
@ -210,7 +205,7 @@ UINT SaveSequence(MSIHANDLE hInstall, LPCTSTR szActionExecute, LPCTSTR szActionC
{ {
HRESULT hr; HRESULT hr;
UINT uiResult; UINT uiResult;
ATL::CAtlString sSequenceFilename; winstd::tstring sSequenceFilename;
ATL::CAtlFile fSequence; ATL::CAtlFile fSequence;
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
@ -218,25 +213,26 @@ UINT SaveSequence(MSIHANDLE hInstall, LPCTSTR szActionExecute, LPCTSTR szActionC
// The InstallCertificates is a deferred custom action, thus all this information will be unavailable to it. // The InstallCertificates is a deferred custom action, thus all this information will be unavailable to it.
// Therefore save all required info to file now. // Therefore save all required info to file now.
{ {
LPTSTR szBuffer = sSequenceFilename.GetBuffer(MAX_PATH); std::unique_ptr<TCHAR> szBuffer(new TCHAR[MAX_PATH]);
::GetTempPath(MAX_PATH, szBuffer); if (!szBuffer) return ERROR_OUTOFMEMORY;
::GetTempFileName(szBuffer, _T("MSICA"), 0, szBuffer); ::GetTempPath(MAX_PATH, szBuffer.get());
sSequenceFilename.ReleaseBuffer(); ::GetTempFileName(szBuffer.get(), _T("MSICA"), 0, szBuffer.get());
sSequenceFilename.assign(szBuffer.get(), wcsnlen(szBuffer.get(), MAX_PATH));
} }
// Save execute sequence to file. // Save execute sequence to file.
hr = olExecute.SaveToFile(sSequenceFilename); hr = olExecute.SaveToFile(sSequenceFilename.c_str());
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
// Store sequence script file names to properties for deferred custiom actions. // Store sequence script file names to properties for deferred custiom actions.
uiResult = ::MsiSetProperty(hInstall, szActionExecute, sSequenceFilename); uiResult = ::MsiSetProperty(hInstall, szActionExecute, sSequenceFilename.c_str());
if (uiResult == NO_ERROR) { if (uiResult == NO_ERROR) {
LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename.c_str());
ATL::CAtlString sSequenceFilename2; winstd::tstring sSequenceFilename2;
sSequenceFilename2.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); sprintf(sSequenceFilename2, _T("%.*ls-rb%ls"), pszExtension - sSequenceFilename.c_str(), sSequenceFilename.c_str(), pszExtension);
uiResult = ::MsiSetProperty(hInstall, szActionRollback, sSequenceFilename2); uiResult = ::MsiSetProperty(hInstall, szActionRollback, sSequenceFilename2.c_str());
if (uiResult == NO_ERROR) { if (uiResult == NO_ERROR) {
sSequenceFilename2.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); sprintf(sSequenceFilename2, _T("%.*ls-cm%ls"), pszExtension - sSequenceFilename.c_str(), sSequenceFilename.c_str(), pszExtension);
uiResult = ::MsiSetProperty(hInstall, szActionCommit, sSequenceFilename2); uiResult = ::MsiSetProperty(hInstall, szActionCommit, sSequenceFilename2.c_str());
if (uiResult != NO_ERROR) { if (uiResult != NO_ERROR) {
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET);
::MsiRecordSetString (hRecordProg, 2, szActionCommit ); ::MsiRecordSetString (hRecordProg, 2, szActionCommit );
@ -255,11 +251,11 @@ UINT SaveSequence(MSIHANDLE hInstall, LPCTSTR szActionExecute, LPCTSTR szActionC
::MsiRecordSetInteger(hRecordProg, 3, uiResult ); ::MsiRecordSetInteger(hRecordProg, 3, uiResult );
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
if (uiResult != NO_ERROR) ::DeleteFile(sSequenceFilename); if (uiResult != NO_ERROR) ::DeleteFile(sSequenceFilename.c_str());
} else { } else {
uiResult = ERROR_INSTALL_SCRIPT_WRITE; uiResult = ERROR_INSTALL_SCRIPT_WRITE;
::MsiRecordSetInteger(hRecordProg, 1, uiResult ); ::MsiRecordSetInteger(hRecordProg, 1, uiResult );
::MsiRecordSetString (hRecordProg, 2, sSequenceFilename); ::MsiRecordSetString (hRecordProg, 2, sSequenceFilename.c_str());
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
@ -273,7 +269,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
UINT uiResult; UINT uiResult;
HRESULT hr; HRESULT hr;
BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL)); BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL));
ATL::CAtlString sSequenceFilename; winstd::tstring sSequenceFilename;
uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename); uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename);
if (uiResult == NO_ERROR) { if (uiResult == NO_ERROR) {
@ -281,7 +277,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
BOOL bIsCleanup = ::MsiGetMode(hInstall, MSIRUNMODE_COMMIT) || ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK); BOOL bIsCleanup = ::MsiGetMode(hInstall, MSIRUNMODE_COMMIT) || ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK);
// Load operation sequence. // Load operation sequence.
hr = lstOperations.LoadFromFile(sSequenceFilename); hr = lstOperations.LoadFromFile(sSequenceFilename.c_str());
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
MSICA::CSession session; MSICA::CSession session;
@ -295,34 +291,34 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
if (!bIsCleanup) { if (!bIsCleanup) {
// Save cleanup scripts of delayed action regardless of action's execution status. // Save cleanup scripts of delayed action regardless of action's execution status.
// Rollback action MUST be scheduled in InstallExecuteSequence before this action! Otherwise cleanup won't be performed in case this action execution failed. // Rollback action MUST be scheduled in InstallExecuteSequence before this action! Otherwise cleanup won't be performed in case this action execution failed.
LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename.c_str());
ATL::CAtlString sSequenceFilenameCM, sSequenceFilenameRB; winstd::tstring sSequenceFilenameCM, sSequenceFilenameRB;
HRESULT hr; HRESULT hr;
sSequenceFilenameRB.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); sprintf(sSequenceFilenameRB, _T("%.*ls-rb%ls"), pszExtension - sSequenceFilename.c_str(), sSequenceFilename.c_str(), pszExtension);
sSequenceFilenameCM.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); sprintf(sSequenceFilenameCM, _T("%.*ls-cm%ls"), pszExtension - sSequenceFilename.c_str(), sSequenceFilename.c_str(), pszExtension);
// After commit, delete rollback file. After rollback, delete commit file. // After commit, delete rollback file. After rollback, delete commit file.
session.m_olCommit.AddTail(new MSICA::COpFileDelete( session.m_olCommit.push_back(new MSICA::COpFileDelete(
#ifdef _UNICODE #ifdef _UNICODE
sSequenceFilenameRB sSequenceFilenameRB.c_str()
#else #else
ATL::CAtlStringW(sSequenceFilenameRB) std::wstring(sSequenceFilenameRB)
#endif #endif
)); ));
session.m_olRollback.AddTail(new MSICA::COpFileDelete( session.m_olRollback.push_back(new MSICA::COpFileDelete(
#ifdef _UNICODE #ifdef _UNICODE
sSequenceFilenameCM sSequenceFilenameCM.c_str()
#else #else
ATL::CAtlStringW(sSequenceFilenameCM) std::wstring(sSequenceFilenameCM)
#endif #endif
)); ));
// Save commit file first. // Save commit file first.
hr = session.m_olCommit.SaveToFile(sSequenceFilenameCM); hr = session.m_olCommit.SaveToFile(sSequenceFilenameCM.c_str());
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
// Save rollback file next. // Save rollback file next.
hr = session.m_olRollback.SaveToFile(sSequenceFilenameRB); hr = session.m_olRollback.SaveToFile(sSequenceFilenameRB.c_str());
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
uiResult = NO_ERROR; uiResult = NO_ERROR;
} else { } else {
@ -330,7 +326,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
uiResult = ERROR_INSTALL_SCRIPT_WRITE; uiResult = ERROR_INSTALL_SCRIPT_WRITE;
::MsiRecordSetInteger(hRecordProg, 1, uiResult ); ::MsiRecordSetInteger(hRecordProg, 1, uiResult );
::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameRB); ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameRB.c_str());
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
@ -339,7 +335,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
uiResult = ERROR_INSTALL_SCRIPT_WRITE; uiResult = ERROR_INSTALL_SCRIPT_WRITE;
::MsiRecordSetInteger(hRecordProg, 1, uiResult ); ::MsiRecordSetInteger(hRecordProg, 1, uiResult );
::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameCM); ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameCM.c_str());
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
@ -349,7 +345,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
session.m_bContinueOnError = TRUE; session.m_bContinueOnError = TRUE;
session.m_bRollbackEnabled = FALSE; session.m_bRollbackEnabled = FALSE;
session.m_olRollback.Execute(&session); session.m_olRollback.Execute(&session);
::DeleteFile(sSequenceFilenameRB); ::DeleteFile(sSequenceFilenameRB.c_str());
} }
} else { } else {
// No cleanup after cleanup support. // No cleanup after cleanup support.
@ -361,7 +357,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
uiResult = HRESULT_CODE(hr); uiResult = HRESULT_CODE(hr);
} }
::DeleteFile(sSequenceFilename); ::DeleteFile(sSequenceFilename.c_str());
} else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && bIsCleanup) { } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && bIsCleanup) {
// Sequence file not found and this is rollback/commit action. Either of the following scenarios are possible: // Sequence file not found and this is rollback/commit action. Either of the following scenarios are possible:
// - The delayed action failed to save the rollback/commit file. The delayed action performed cleanup itself. No further action is required. // - The delayed action failed to save the rollback/commit file. The delayed action performed cleanup itself. No further action is required.
@ -372,7 +368,7 @@ UINT ExecuteSequence(MSIHANDLE hInstall)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
uiResult = ERROR_INSTALL_SCRIPT_READ; uiResult = ERROR_INSTALL_SCRIPT_READ;
::MsiRecordSetInteger(hRecordProg, 1, uiResult ); ::MsiRecordSetInteger(hRecordProg, 1, uiResult );
::MsiRecordSetString (hRecordProg, 2, sSequenceFilename); ::MsiRecordSetString (hRecordProg, 2, sSequenceFilename.c_str());
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }

View File

@ -41,10 +41,9 @@ COpCertStore::COpCertStore(LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
COpCert::COpCert(LPCVOID lpCert, SIZE_T nSize, LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags, int iTicks) : COpCert::COpCert(LPCVOID lpCert, SIZE_T nSize, LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags, int iTicks) :
m_binCert(reinterpret_cast<LPCBYTE>(lpCert), reinterpret_cast<LPCBYTE>(lpCert) + nSize),
COpCertStore(pszStore, dwEncodingType, dwFlags, iTicks) COpCertStore(pszStore, dwEncodingType, dwFlags, iTicks)
{ {
m_binCert.SetCount(nSize);
memcpy(m_binCert.GetData(), lpCert, nSize);
} }
@ -63,17 +62,17 @@ HRESULT COpCertInstall::Execute(CSession *pSession)
HCERTSTORE hCertStore; HCERTSTORE hCertStore;
// Open certificate store. // Open certificate store.
hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_W, m_dwEncodingType, NULL, m_dwFlags, m_sValue); hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_W, m_dwEncodingType, NULL, m_dwFlags, m_sValue.c_str());
if (hCertStore) { if (hCertStore) {
// Create certificate context. // Create certificate context.
PCCERT_CONTEXT pCertContext = ::CertCreateCertificateContext(m_dwEncodingType, m_binCert.GetData(), (DWORD)(m_binCert.GetCount())); PCCERT_CONTEXT pCertContext = ::CertCreateCertificateContext(m_dwEncodingType, m_binCert.data(), static_cast<DWORD>(m_binCert.size()));
if (pCertContext) { if (pCertContext) {
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1); PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
ATL::CAtlStringW sCertName; std::wstring sCertName;
// Display our custom message in the progress bar. // Display our custom message in the progress bar.
::CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, sCertName); ::CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, sCertName);
::MsiRecordSetStringW(hRecordMsg, 1, sCertName); ::MsiRecordSetStringW(hRecordMsg, 1, sCertName.c_str());
if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL) if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL)
return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT); return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT);
@ -81,7 +80,7 @@ HRESULT COpCertInstall::Execute(CSession *pSession)
if (::CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_NEW, NULL)) { if (::CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_NEW, NULL)) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the certificate. // Order rollback action to delete the certificate.
pSession->m_olRollback.AddHead(new COpCertRemove(m_binCert.GetData(), m_binCert.GetCount(), m_sValue, m_dwEncodingType, m_dwFlags)); pSession->m_olRollback.push_front(new COpCertRemove(m_binCert.data(), m_binCert.size(), m_sValue.c_str(), m_dwEncodingType, m_dwFlags));
} }
dwError = NO_ERROR; dwError = NO_ERROR;
} else { } else {
@ -103,7 +102,7 @@ HRESULT COpCertInstall::Execute(CSession *pSession)
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_CERT_INSTALL); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_CERT_INSTALL);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, dwError ); ::MsiRecordSetInteger(hRecordProg, 3, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);
@ -126,18 +125,18 @@ HRESULT COpCertRemove::Execute(CSession *pSession)
HCERTSTORE hCertStore; HCERTSTORE hCertStore;
// Open certificate store. // Open certificate store.
hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_W, m_dwEncodingType, NULL, m_dwFlags, m_sValue); hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_W, m_dwEncodingType, NULL, m_dwFlags, m_sValue.c_str());
if (hCertStore) { if (hCertStore) {
// Create certificate context. // Create certificate context.
PCCERT_CONTEXT pCertContext = ::CertCreateCertificateContext(m_dwEncodingType, m_binCert.GetData(), (DWORD)(m_binCert.GetCount())); PCCERT_CONTEXT pCertContext = ::CertCreateCertificateContext(m_dwEncodingType, m_binCert.data(), static_cast<DWORD>(m_binCert.size()));
if (pCertContext) { if (pCertContext) {
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1); PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
ATL::CAtlStringW sCertName; std::wstring sCertName;
PCCERT_CONTEXT pCertContextExisting; PCCERT_CONTEXT pCertContextExisting;
// Display our custom message in the progress bar. // Display our custom message in the progress bar.
::CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, sCertName); ::CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, sCertName);
::MsiRecordSetStringW(hRecordMsg, 1, sCertName); ::MsiRecordSetStringW(hRecordMsg, 1, sCertName.c_str());
if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL) if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL)
return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT); return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT);
@ -147,7 +146,7 @@ HRESULT COpCertRemove::Execute(CSession *pSession)
if (::CertDeleteCertificateFromStore(pCertContextExisting)) { if (::CertDeleteCertificateFromStore(pCertContextExisting)) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to reinstall the certificate. // Order rollback action to reinstall the certificate.
pSession->m_olRollback.AddHead(new COpCertInstall(m_binCert.GetData(), m_binCert.GetCount(), m_sValue, m_dwEncodingType, m_dwFlags)); pSession->m_olRollback.push_front(new COpCertInstall(m_binCert.data(), m_binCert.size(), m_sValue.c_str(), m_dwEncodingType, m_dwFlags));
} }
dwError = NO_ERROR; dwError = NO_ERROR;
} else { } else {
@ -170,7 +169,7 @@ HRESULT COpCertRemove::Execute(CSession *pSession)
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_CERT_REMOVE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_CERT_REMOVE);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, dwError ); ::MsiRecordSetInteger(hRecordProg, 3, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);

View File

@ -37,24 +37,24 @@ HRESULT COpFileDelete::Execute(CSession *pSession)
DWORD dwError; DWORD dwError;
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
ATL::CAtlStringW sBackupName; std::wstring sBackupName;
UINT uiCount = 0; UINT uiCount = 0;
do { do {
// Rename the file to make a backup. // Rename the file to make a backup.
sBackupName.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); sprintf(sBackupName, L"%ls (orig %u)", m_sValue.c_str(), ++uiCount);
dwError = ::MoveFileW(m_sValue, sBackupName) ? NO_ERROR : ::GetLastError(); dwError = ::MoveFileW(m_sValue.c_str(), sBackupName.c_str()) ? NO_ERROR : ::GetLastError();
} while (dwError == ERROR_ALREADY_EXISTS); } while (dwError == ERROR_ALREADY_EXISTS);
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
// Order rollback action to restore from backup copy. // Order rollback action to restore from backup copy.
pSession->m_olRollback.AddHead(new COpFileMove(sBackupName, m_sValue)); pSession->m_olRollback.push_front(new COpFileMove(sBackupName.c_str(), m_sValue.c_str()));
// Order commit action to delete backup copy. // Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpFileDelete(sBackupName)); pSession->m_olCommit.push_back(new COpFileDelete(sBackupName.c_str()));
} }
} else { } else {
// Delete the file. // Delete the file.
dwError = ::DeleteFileW(m_sValue) ? NO_ERROR : ::GetLastError(); dwError = ::DeleteFileW(m_sValue.c_str()) ? NO_ERROR : ::GetLastError();
} }
if (dwError == NO_ERROR || dwError == ERROR_FILE_NOT_FOUND) if (dwError == NO_ERROR || dwError == ERROR_FILE_NOT_FOUND)
@ -62,7 +62,7 @@ HRESULT COpFileDelete::Execute(CSession *pSession)
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_FILE_DELETE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_FILE_DELETE);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, dwError ); ::MsiRecordSetInteger(hRecordProg, 3, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);
@ -85,19 +85,19 @@ HRESULT COpFileMove::Execute(CSession *pSession)
DWORD dwError; DWORD dwError;
// Move the file. // Move the file.
dwError = ::MoveFileW(m_sValue1, m_sValue2) ? NO_ERROR : ::GetLastError(); dwError = ::MoveFileW(m_sValue1.c_str(), m_sValue2.c_str()) ? NO_ERROR : ::GetLastError();
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to move it back. // Order rollback action to move it back.
pSession->m_olRollback.AddHead(new COpFileMove(m_sValue2, m_sValue1)); pSession->m_olRollback.push_front(new COpFileMove(m_sValue2.c_str(), m_sValue1.c_str()));
} }
return S_OK; return S_OK;
} else { } else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_FILE_MOVE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_FILE_MOVE);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue1 ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue1.c_str() );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue2 ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue2.c_str() );
::MsiRecordSetInteger(hRecordProg, 4, dwError ); ::MsiRecordSetInteger(hRecordProg, 4, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);

View File

@ -58,8 +58,8 @@ HRESULT COpRegKeyCreate::Execute(CSession *pSession)
{ {
LONG lResult; LONG lResult;
REGSAM samAdditional = 0; REGSAM samAdditional = 0;
ATL::CAtlStringW sPartialName; std::wstring sPartialName;
int iStart = 0; size_t iStart = 0;
#ifndef _WIN64 #ifndef _WIN64
if (IsWow64Process()) { if (IsWow64Process()) {
@ -71,24 +71,24 @@ HRESULT COpRegKeyCreate::Execute(CSession *pSession)
for (;;) { for (;;) {
HKEY hKey; HKEY hKey;
int iStartNext = m_sValue.Find(L'\\', iStart); size_t iStartNext = m_sValue.find(L'\\', iStart);
if (iStartNext >= 0) if (iStartNext != std::wstring::npos)
sPartialName.SetString(m_sValue, iStartNext); sPartialName.assign(m_sValue.c_str(), iStartNext);
else else
sPartialName = m_sValue; sPartialName = m_sValue;
// Try to open the key, to see if it exists. // Try to open the key, to see if it exists.
lResult = ::RegOpenKeyExW(m_hKeyRoot, sPartialName, 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, sPartialName.c_str(), 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey);
if (lResult == ERROR_FILE_NOT_FOUND) { if (lResult == ERROR_FILE_NOT_FOUND) {
// The key doesn't exist yet. Create it. // The key doesn't exist yet. Create it.
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the key. ::RegCreateEx() might create a key but return failure. // Order rollback action to delete the key. ::RegCreateEx() might create a key but return failure.
pSession->m_olRollback.AddHead(new COpRegKeyDelete(m_hKeyRoot, sPartialName)); pSession->m_olRollback.push_front(new COpRegKeyDelete(m_hKeyRoot, sPartialName.c_str()));
} }
// Create the key. // Create the key.
lResult = ::RegCreateKeyExW(m_hKeyRoot, sPartialName, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ENUMERATE_SUB_KEYS | samAdditional, NULL, &hKey, NULL); lResult = ::RegCreateKeyExW(m_hKeyRoot, sPartialName.c_str(), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ENUMERATE_SUB_KEYS | samAdditional, NULL, &hKey, NULL);
if (lResult != NO_ERROR) break; if (lResult != NO_ERROR) break;
::RegCloseKey(hKey); ::RegCloseKey(hKey);
} else if (lResult == NO_ERROR) { } else if (lResult == NO_ERROR) {
@ -97,7 +97,7 @@ HRESULT COpRegKeyCreate::Execute(CSession *pSession)
} else } else
break; break;
if (iStartNext < 0) break; if (iStartNext == std::wstring::npos) break;
iStart = iStartNext + 1; iStart = iStartNext + 1;
} }
@ -107,7 +107,7 @@ HRESULT COpRegKeyCreate::Execute(CSession *pSession)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_CREATE ); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_CREATE );
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff);
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 4, lResult ); ::MsiRecordSetInteger(hRecordProg, 4, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);
@ -133,7 +133,7 @@ HRESULT COpRegKeyCopy::Execute(CSession *pSession)
// Delete existing destination key first. // Delete existing destination key first.
// Since deleting registry key is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since deleting registry key is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpRegKeyDelete::Execute() returns S_OK if key doesn't exist. // Don't worry, COpRegKeyDelete::Execute() returns S_OK if key doesn't exist.
COpRegKeyDelete opDelete(m_hKeyRoot, m_sValue2); COpRegKeyDelete opDelete(m_hKeyRoot, m_sValue2.c_str());
HRESULT hr = opDelete.Execute(pSession); HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
} }
@ -147,19 +147,19 @@ HRESULT COpRegKeyCopy::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the destination key. // Order rollback action to delete the destination key.
pSession->m_olRollback.AddHead(new COpRegKeyDelete(m_hKeyRoot, m_sValue2)); pSession->m_olRollback.push_front(new COpRegKeyDelete(m_hKeyRoot, m_sValue2.c_str()));
} }
// Copy the registry key. // Copy the registry key.
lResult = CopyKeyRecursively(m_hKeyRoot, m_sValue1, m_sValue2, samAdditional); lResult = CopyKeyRecursively(m_hKeyRoot, m_sValue1.c_str(), m_sValue2.c_str(), samAdditional);
if (lResult == NO_ERROR) if (lResult == NO_ERROR)
return S_OK; return S_OK;
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5); PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_COPY ); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_COPY );
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff);
::MsiRecordSetStringW(hRecordProg, 3, m_sValue1 ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue1.c_str() );
::MsiRecordSetStringW(hRecordProg, 4, m_sValue2 ); ::MsiRecordSetStringW(hRecordProg, 4, m_sValue2.c_str() );
::MsiRecordSetInteger(hRecordProg, 5, lResult ); ::MsiRecordSetInteger(hRecordProg, 5, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);
@ -179,29 +179,23 @@ LONG COpRegKeyCopy::CopyKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPC
{ {
DWORD dwSecurityDescriptorSize, dwClassLen = MAX_PATH; DWORD dwSecurityDescriptorSize, dwClassLen = MAX_PATH;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) }; SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
LPWSTR pszClass = new WCHAR[dwClassLen]; std::unique_ptr<WCHAR[]> pszClass(new WCHAR[dwClassLen]);
if (!pszClass) return ERROR_OUTOFMEMORY;
// Get source key class length and security descriptor size. // Get source key class length and security descriptor size.
lResult = ::RegQueryInfoKeyW(hKeySrc, pszClass, &dwClassLen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSecurityDescriptorSize, NULL); lResult = ::RegQueryInfoKeyW(hKeySrc, pszClass.get(), &dwClassLen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSecurityDescriptorSize, NULL);
if (lResult != NO_ERROR) { if (lResult != NO_ERROR) return lResult;
delete [] pszClass; pszClass.get()[dwClassLen] = 0;
return lResult;
}
pszClass[dwClassLen] = 0;
// Get source key security descriptor. // Get source key security descriptor.
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(new BYTE[dwSecurityDescriptorSize]); std::unique_ptr<BYTE[]> sd(new BYTE[dwSecurityDescriptorSize]);
if (!sd) return ERROR_OUTOFMEMORY;
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)sd.get();
lResult = ::RegGetKeySecurity(hKeySrc, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor, &dwSecurityDescriptorSize); lResult = ::RegGetKeySecurity(hKeySrc, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor, &dwSecurityDescriptorSize);
if (lResult != NO_ERROR) { if (lResult != NO_ERROR) return lResult;
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
delete [] pszClass;
return lResult;
}
// Create new destination key of the same class and security. // Create new destination key of the same class and security.
lResult = ::RegCreateKeyExW(hKeyRoot, pszKeyNameDst, 0, pszClass, REG_OPTION_NON_VOLATILE, KEY_WRITE | samAdditional, &sa, &hKeyDst, NULL); lResult = ::RegCreateKeyExW(hKeyRoot, pszKeyNameDst, 0, pszClass.get(), REG_OPTION_NON_VOLATILE, KEY_WRITE | samAdditional, &sa, &hKeyDst, NULL);
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
delete [] pszClass;
if (lResult != NO_ERROR) return lResult; if (lResult != NO_ERROR) return lResult;
} }
@ -214,57 +208,52 @@ LONG COpRegKeyCopy::CopyKeyRecursively(HKEY hKeySrc, HKEY hKeyDst, REGSAM samAdd
{ {
LONG lResult; LONG lResult;
DWORD dwMaxSubKeyLen, dwMaxValueNameLen, dwMaxClassLen, dwMaxDataSize, dwIndex; DWORD dwMaxSubKeyLen, dwMaxValueNameLen, dwMaxClassLen, dwMaxDataSize, dwIndex;
LPWSTR pszName, pszClass;
LPBYTE lpData;
// Query the source key. // Query the source key.
lResult = ::RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, NULL, &dwMaxSubKeyLen, &dwMaxClassLen, NULL, &dwMaxValueNameLen, &dwMaxDataSize, NULL, NULL); lResult = ::RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, NULL, &dwMaxSubKeyLen, &dwMaxClassLen, NULL, &dwMaxValueNameLen, &dwMaxDataSize, NULL, NULL);
if (lResult != NO_ERROR) return lResult; if (lResult != NO_ERROR) return lResult;
{
// Copy values first. // Copy values first.
dwMaxValueNameLen++; dwMaxValueNameLen++;
pszName = new WCHAR[dwMaxValueNameLen]; std::unique_ptr<WCHAR[]> pszName(new WCHAR[dwMaxValueNameLen]);
lpData = new BYTE[dwMaxDataSize]; if (!pszName) return ERROR_OUTOFMEMORY;
std::unique_ptr<BYTE[]> lpData(new BYTE[dwMaxDataSize]);
if (!lpData) return ERROR_OUTOFMEMORY;
for (dwIndex = 0; ; dwIndex++) { for (dwIndex = 0; ; dwIndex++) {
DWORD dwNameLen = dwMaxValueNameLen, dwType, dwValueSize = dwMaxDataSize; DWORD dwNameLen = dwMaxValueNameLen, dwType, dwValueSize = dwMaxDataSize;
// Read value. // Read value.
lResult = ::RegEnumValueW(hKeySrc, dwIndex, pszName, &dwNameLen, NULL, &dwType, lpData, &dwValueSize); lResult = ::RegEnumValueW(hKeySrc, dwIndex, pszName.get(), &dwNameLen, NULL, &dwType, lpData.get(), &dwValueSize);
if (lResult == ERROR_NO_MORE_ITEMS) { if (lResult == ERROR_NO_MORE_ITEMS) break;
lResult = NO_ERROR; else if (lResult != NO_ERROR ) return lResult;
break;
} else if (lResult != NO_ERROR)
break;
// Save value. // Save value.
lResult = ::RegSetValueExW(hKeyDst, pszName, 0, dwType, lpData, dwValueSize); lResult = ::RegSetValueExW(hKeyDst, pszName.get(), 0, dwType, lpData.get(), dwValueSize);
if (lResult != NO_ERROR)
break;
}
delete [] lpData;
delete [] pszName;
if (lResult != NO_ERROR) return lResult; if (lResult != NO_ERROR) return lResult;
}
}
{
// Iterate over all subkeys and copy them. // Iterate over all subkeys and copy them.
dwMaxSubKeyLen++; dwMaxSubKeyLen++;
pszName = new WCHAR[dwMaxSubKeyLen]; std::unique_ptr<WCHAR[]> pszName(new WCHAR[dwMaxSubKeyLen]);
if (!pszName) return ERROR_OUTOFMEMORY;
dwMaxClassLen++; dwMaxClassLen++;
pszClass = new WCHAR[dwMaxClassLen]; std::unique_ptr<WCHAR[]> pszClass(new WCHAR[dwMaxClassLen]);
if (!pszClass) return ERROR_OUTOFMEMORY;
for (dwIndex = 0; ; dwIndex++) { for (dwIndex = 0; ; dwIndex++) {
DWORD dwNameLen = dwMaxSubKeyLen, dwClassLen = dwMaxClassLen; DWORD dwNameLen = dwMaxSubKeyLen, dwClassLen = dwMaxClassLen;
HKEY hKeySrcSub, hKeyDstSub; HKEY hKeySrcSub, hKeyDstSub;
// Read subkey. // Read subkey.
lResult = ::RegEnumKeyExW(hKeySrc, dwIndex, pszName, &dwNameLen, NULL, pszClass, &dwClassLen, NULL); lResult = ::RegEnumKeyExW(hKeySrc, dwIndex, pszName.get(), &dwNameLen, NULL, pszClass.get(), &dwClassLen, NULL);
if (lResult == ERROR_NO_MORE_ITEMS) { if (lResult == ERROR_NO_MORE_ITEMS) break;
lResult = NO_ERROR; else if (lResult != NO_ERROR ) return lResult;
break;
} else if (lResult != NO_ERROR)
break;
// Open source subkey. // Open source subkey.
lResult = ::RegOpenKeyExW(hKeySrc, pszName, 0, READ_CONTROL | KEY_READ | samAdditional, &hKeySrcSub); lResult = ::RegOpenKeyExW(hKeySrc, pszName.get(), 0, READ_CONTROL | KEY_READ | samAdditional, &hKeySrcSub);
if (lResult != NO_ERROR) break; if (lResult != NO_ERROR) return lResult;
{ {
DWORD dwSecurityDescriptorSize; DWORD dwSecurityDescriptorSize;
@ -272,30 +261,27 @@ LONG COpRegKeyCopy::CopyKeyRecursively(HKEY hKeySrc, HKEY hKeyDst, REGSAM samAdd
// Get source subkey security descriptor size. // Get source subkey security descriptor size.
lResult = ::RegQueryInfoKeyW(hKeySrcSub, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSecurityDescriptorSize, NULL); lResult = ::RegQueryInfoKeyW(hKeySrcSub, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSecurityDescriptorSize, NULL);
if (lResult != NO_ERROR) break; if (lResult != NO_ERROR) return lResult;
// Get source subkey security descriptor. // Get source subkey security descriptor.
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(new BYTE[dwSecurityDescriptorSize]); std::unique_ptr<BYTE[]> sd(new BYTE[dwSecurityDescriptorSize]);
if (!sd) return ERROR_OUTOFMEMORY;
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)sd.get();
lResult = ::RegGetKeySecurity(hKeySrc, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor, &dwSecurityDescriptorSize); lResult = ::RegGetKeySecurity(hKeySrc, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor, &dwSecurityDescriptorSize);
if (lResult != NO_ERROR) { if (lResult != NO_ERROR) return lResult;
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
break;
}
// Create new destination subkey of the same class and security. // Create new destination subkey of the same class and security.
lResult = ::RegCreateKeyExW(hKeyDst, pszName, 0, pszClass, REG_OPTION_NON_VOLATILE, KEY_WRITE | samAdditional, &sa, &hKeyDstSub, NULL); lResult = ::RegCreateKeyExW(hKeyDst, pszName.get(), 0, pszClass.get(), REG_OPTION_NON_VOLATILE, KEY_WRITE | samAdditional, &sa, &hKeyDstSub, NULL);
delete [] (LPBYTE)(sa.lpSecurityDescriptor); if (lResult != NO_ERROR) return lResult;
if (lResult != NO_ERROR) break;
} }
// Copy subkey recursively. // Copy subkey recursively.
lResult = CopyKeyRecursively(hKeySrcSub, hKeyDstSub, samAdditional); lResult = CopyKeyRecursively(hKeySrcSub, hKeyDstSub, samAdditional);
if (lResult != NO_ERROR) break; if (lResult != NO_ERROR) return lResult;
}
} }
delete [] pszClass;
delete [] pszName;
return lResult; return NO_ERROR;
} }
@ -322,42 +308,42 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
#endif #endif
// Probe to see if the key exists. // Probe to see if the key exists.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, DELETE | samAdditional, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue.c_str(), 0, DELETE | samAdditional, &hKey);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
::RegCloseKey(hKey); ::RegCloseKey(hKey);
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Make a backup of the key first. // Make a backup of the key first.
ATL::CAtlStringW sBackupName; std::wstring sBackupName;
UINT uiCount = 0; UINT uiCount = 0;
int iLength = m_sValue.GetLength(); auto iLength = m_sValue.length();
// Trim trailing backslashes. // Trim trailing backslashes.
while (iLength && m_sValue.GetAt(iLength - 1) == L'\\') iLength--; while (iLength && m_sValue[iLength - 1] == L'\\') iLength--;
for (;;) { for (;;) {
HKEY hKey; HKEY hKey;
sBackupName.Format(L"%.*ls (orig %u)", iLength, (LPCWSTR)m_sValue, ++uiCount); sprintf(sBackupName, L"%.*ls (orig %u)", iLength, m_sValue.c_str(), ++uiCount);
lResult = ::RegOpenKeyExW(m_hKeyRoot, sBackupName, 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, sBackupName.c_str(), 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey);
if (lResult != NO_ERROR) break; if (lResult != NO_ERROR) break;
::RegCloseKey(hKey); ::RegCloseKey(hKey);
} }
if (lResult == ERROR_FILE_NOT_FOUND) { if (lResult == ERROR_FILE_NOT_FOUND) {
// Since copying registry key is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since copying registry key is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
COpRegKeyCopy opCopy(m_hKeyRoot, m_sValue, sBackupName); COpRegKeyCopy opCopy(m_hKeyRoot, m_sValue.c_str(), sBackupName.c_str());
HRESULT hr = opCopy.Execute(pSession); HRESULT hr = opCopy.Execute(pSession);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
// Order rollback action to restore the key from backup copy. // Order rollback action to restore the key from backup copy.
pSession->m_olRollback.AddHead(new COpRegKeyCopy(m_hKeyRoot, sBackupName, m_sValue)); pSession->m_olRollback.push_front(new COpRegKeyCopy(m_hKeyRoot, sBackupName.c_str(), m_sValue.c_str()));
// Order commit action to delete backup copy. // Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpRegKeyDelete(m_hKeyRoot, sBackupName)); pSession->m_olCommit.push_back(new COpRegKeyDelete(m_hKeyRoot, sBackupName.c_str()));
} else { } else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBING ); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBING );
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff);
::MsiRecordSetStringW(hRecordProg, 3, sBackupName ); ::MsiRecordSetStringW(hRecordProg, 3, sBackupName.c_str() );
::MsiRecordSetInteger(hRecordProg, 4, lResult ); ::MsiRecordSetInteger(hRecordProg, 4, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);
@ -365,7 +351,7 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
} }
// Delete the registry key. // Delete the registry key.
lResult = DeleteKeyRecursively(m_hKeyRoot, m_sValue, samAdditional); lResult = DeleteKeyRecursively(m_hKeyRoot, m_sValue.c_str(), samAdditional);
} }
if (lResult == NO_ERROR || lResult == ERROR_FILE_NOT_FOUND) if (lResult == NO_ERROR || lResult == ERROR_FILE_NOT_FOUND)
@ -374,7 +360,7 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_DELETE ); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_DELETE );
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff);
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 4, lResult ); ::MsiRecordSetInteger(hRecordProg, 4, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);
@ -395,20 +381,18 @@ LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, RE
// Determine the largest subkey name. // Determine the largest subkey name.
lResult = ::RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL); lResult = ::RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
LPWSTR pszSubKeyName;
// Prepare buffer to hold the subkey names (including zero terminator). // Prepare buffer to hold the subkey names (including zero terminator).
dwMaxSubKeyLen++; dwMaxSubKeyLen++;
pszSubKeyName = new WCHAR[dwMaxSubKeyLen]; std::unique_ptr<WCHAR[]> pszSubKeyName(new WCHAR[dwMaxSubKeyLen]);
if (pszSubKeyName) { if (pszSubKeyName) {
DWORD dwIndex; DWORD dwIndex;
// Iterate over all subkeys and delete them. Skip failed. // Iterate over all subkeys and delete them. Skip failed.
for (dwIndex = 0; ;) { for (dwIndex = 0; ;) {
DWORD dwNameLen = dwMaxSubKeyLen; DWORD dwNameLen = dwMaxSubKeyLen;
lResult = ::RegEnumKeyExW(hKey, dwIndex, pszSubKeyName, &dwNameLen, NULL, NULL, NULL, NULL); lResult = ::RegEnumKeyExW(hKey, dwIndex, pszSubKeyName.get(), &dwNameLen, NULL, NULL, NULL, NULL);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
lResult = DeleteKeyRecursively(hKey, pszSubKeyName, samAdditional); lResult = DeleteKeyRecursively(hKey, pszSubKeyName.get(), samAdditional);
if (lResult != NO_ERROR) if (lResult != NO_ERROR)
dwIndex++; dwIndex++;
} else if (lResult == ERROR_NO_MORE_ITEMS) { } else if (lResult == ERROR_NO_MORE_ITEMS) {
@ -417,8 +401,6 @@ LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, RE
} else } else
dwIndex++; dwIndex++;
} }
delete [] pszSubKeyName;
} else } else
lResult = ERROR_OUTOFMEMORY; lResult = ERROR_OUTOFMEMORY;
} }
@ -480,10 +462,9 @@ COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR
COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCVOID lpData, SIZE_T nSize, int iTicks) : COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCVOID lpData, SIZE_T nSize, int iTicks) :
m_dwType(REG_BINARY), m_dwType(REG_BINARY),
m_binData(reinterpret_cast<LPCBYTE>(lpData), reinterpret_cast<LPCBYTE>(lpData) + nSize),
COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks) COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{ {
m_binData.SetCount(nSize);
memcpy(m_binData.GetData(), lpData, nSize);
} }
@ -513,7 +494,7 @@ HRESULT COpRegValueCreate::Execute(CSession *pSession)
// Delete existing value first. // Delete existing value first.
// Since deleting registry value is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since deleting registry value is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpRegValueDelete::Execute() returns S_OK if key doesn't exist. // Don't worry, COpRegValueDelete::Execute() returns S_OK if key doesn't exist.
COpRegValueDelete opDelete(m_hKeyRoot, m_sValue, m_sValueName); COpRegValueDelete opDelete(m_hKeyRoot, m_sValue.c_str(), m_sValueName.c_str());
HRESULT hr = opDelete.Execute(pSession); HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
} }
@ -526,11 +507,11 @@ HRESULT COpRegValueCreate::Execute(CSession *pSession)
#endif #endif
// Open the key. // Open the key.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, sam, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue.c_str(), 0, sam, &hKey);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the value. // Order rollback action to delete the value.
pSession->m_olRollback.AddHead(new COpRegValueDelete(m_hKeyRoot, m_sValue, m_sValueName)); pSession->m_olRollback.push_front(new COpRegValueDelete(m_hKeyRoot, m_sValue.c_str(), m_sValueName.c_str()));
} }
// Set the registry value. // Set the registry value.
@ -538,23 +519,23 @@ HRESULT COpRegValueCreate::Execute(CSession *pSession)
case REG_SZ: case REG_SZ:
case REG_EXPAND_SZ: case REG_EXPAND_SZ:
case REG_LINK: case REG_LINK:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)(LPCWSTR)m_sData, (m_sData.GetLength() + 1) * sizeof(WCHAR)); break; lResult = ::RegSetValueExW(hKey, m_sValueName.c_str(), 0, m_dwType, (const BYTE*)m_sData.c_str(), static_cast<DWORD>((m_sData.length() + 1) * sizeof(WCHAR))); break;
break; break;
case REG_BINARY: case REG_BINARY:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, m_binData.GetData(), (DWORD)m_binData.GetCount() * sizeof(BYTE)); break; lResult = ::RegSetValueExW(hKey, m_sValueName.c_str(), 0, m_dwType, m_binData.data(), static_cast<DWORD>(m_binData.size() * sizeof(BYTE))); break;
case REG_DWORD_LITTLE_ENDIAN: case REG_DWORD_LITTLE_ENDIAN:
case REG_DWORD_BIG_ENDIAN: case REG_DWORD_BIG_ENDIAN:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)&m_dwData, sizeof(DWORD)); break; lResult = ::RegSetValueExW(hKey, m_sValueName.c_str(), 0, m_dwType, (const BYTE*)&m_dwData, sizeof(DWORD)); break;
break; break;
case REG_MULTI_SZ: case REG_MULTI_SZ:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)m_szData.GetData(), (DWORD)m_szData.GetCount() * sizeof(WCHAR)); break; lResult = ::RegSetValueExW(hKey, m_sValueName.c_str(), 0, m_dwType, (const BYTE*)m_szData.data(), static_cast<DWORD>(m_szData.size() * sizeof(WCHAR))); break;
break; break;
case REG_QWORD_LITTLE_ENDIAN: case REG_QWORD_LITTLE_ENDIAN:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)&m_qwData, sizeof(DWORDLONG)); break; lResult = ::RegSetValueExW(hKey, m_sValueName.c_str(), 0, m_dwType, (const BYTE*)&m_qwData, sizeof(DWORDLONG)); break;
break; break;
default: default:
@ -570,8 +551,8 @@ HRESULT COpRegValueCreate::Execute(CSession *pSession)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5); PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_SETVALUE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_SETVALUE);
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff);
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetStringW(hRecordProg, 4, m_sValueName ); ::MsiRecordSetStringW(hRecordProg, 4, m_sValueName.c_str() );
::MsiRecordSetInteger(hRecordProg, 5, lResult ); ::MsiRecordSetInteger(hRecordProg, 5, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);
@ -598,7 +579,7 @@ HRESULT COpRegValueCopy::Execute(CSession *pSession)
// Delete existing destination value first. // Delete existing destination value first.
// Since deleting registry value is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since deleting registry value is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpRegValueDelete::Execute() returns S_OK if key doesn't exist. // Don't worry, COpRegValueDelete::Execute() returns S_OK if key doesn't exist.
COpRegValueDelete opDelete(m_hKeyRoot, m_sValue, m_sValueName2); COpRegValueDelete opDelete(m_hKeyRoot, m_sValue.c_str(), m_sValueName2.c_str());
HRESULT hr = opDelete.Execute(pSession); HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
} }
@ -611,26 +592,28 @@ HRESULT COpRegValueCopy::Execute(CSession *pSession)
#endif #endif
// Open the key. // Open the key.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, sam, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue.c_str(), 0, sam, &hKey);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
DWORD dwType, dwSize; DWORD dwType, dwSize;
// Query the source registry value size. // Query the source registry value size.
lResult = ::RegQueryValueExW(hKey, m_sValueName1, 0, NULL, NULL, &dwSize); lResult = ::RegQueryValueExW(hKey, m_sValueName1.c_str(), 0, NULL, NULL, &dwSize);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
LPBYTE lpData = new BYTE[dwSize];
// Read the source registry value. // Read the source registry value.
lResult = ::RegQueryValueExW(hKey, m_sValueName1, 0, &dwType, lpData, &dwSize); std::unique_ptr<BYTE> lpData(new BYTE[dwSize]);
if (lpData) {
lResult = ::RegQueryValueExW(hKey, m_sValueName1.c_str(), 0, &dwType, lpData.get(), &dwSize);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the destination copy. // Order rollback action to delete the destination copy.
pSession->m_olRollback.AddHead(new COpRegValueDelete(m_hKeyRoot, m_sValue, m_sValueName2)); pSession->m_olRollback.push_front(new COpRegValueDelete(m_hKeyRoot, m_sValue.c_str(), m_sValueName2.c_str()));
} }
// Store the value to destination. // Store the value to destination.
lResult = ::RegSetValueExW(hKey, m_sValueName2, 0, dwType, lpData, dwSize); lResult = ::RegSetValueExW(hKey, m_sValueName2.c_str(), 0, dwType, lpData.get(), dwSize);
} }
delete [] lpData; } else
lResult = ERROR_OUTOFMEMORY;
} }
::RegCloseKey(hKey); ::RegCloseKey(hKey);
@ -642,9 +625,9 @@ HRESULT COpRegValueCopy::Execute(CSession *pSession)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(6); PMSIHANDLE hRecordProg = ::MsiCreateRecord(6);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_COPYVALUE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_COPYVALUE);
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetStringW(hRecordProg, 4, m_sValueName1 ); ::MsiRecordSetStringW(hRecordProg, 4, m_sValueName1.c_str() );
::MsiRecordSetStringW(hRecordProg, 5, m_sValueName2 ); ::MsiRecordSetStringW(hRecordProg, 5, m_sValueName2.c_str() );
::MsiRecordSetInteger(hRecordProg, 6, lResult ); ::MsiRecordSetInteger(hRecordProg, 6, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);
@ -675,26 +658,26 @@ HRESULT COpRegValueDelete::Execute(CSession *pSession)
#endif #endif
// Open the key. // Open the key.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, sam, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue.c_str(), 0, sam, &hKey);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
DWORD dwType; DWORD dwType;
// See if the value exists at all. // See if the value exists at all.
lResult = ::RegQueryValueExW(hKey, m_sValueName, 0, &dwType, NULL, NULL); lResult = ::RegQueryValueExW(hKey, m_sValueName.c_str(), 0, &dwType, NULL, NULL);
if (lResult == NO_ERROR) { if (lResult == NO_ERROR) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Make a backup of the value first. // Make a backup of the value first.
ATL::CAtlStringW sBackupName; std::wstring sBackupName;
UINT uiCount = 0; UINT uiCount = 0;
for (;;) { for (;;) {
sBackupName.Format(L"%ls (orig %u)", (LPCWSTR)m_sValueName, ++uiCount); sprintf(sBackupName, L"%ls (orig %u)", m_sValueName.c_str(), ++uiCount);
lResult = ::RegQueryValueExW(hKey, sBackupName, 0, &dwType, NULL, NULL); lResult = ::RegQueryValueExW(hKey, sBackupName.c_str(), 0, &dwType, NULL, NULL);
if (lResult != NO_ERROR) break; if (lResult != NO_ERROR) break;
} }
if (lResult == ERROR_FILE_NOT_FOUND) { if (lResult == ERROR_FILE_NOT_FOUND) {
// Since copying registry value is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since copying registry value is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
COpRegValueCopy opCopy(m_hKeyRoot, m_sValue, m_sValueName, sBackupName); COpRegValueCopy opCopy(m_hKeyRoot, m_sValue.c_str(), m_sValueName.c_str(), sBackupName.c_str());
HRESULT hr = opCopy.Execute(pSession); HRESULT hr = opCopy.Execute(pSession);
if (FAILED(hr)) { if (FAILED(hr)) {
::RegCloseKey(hKey); ::RegCloseKey(hKey);
@ -702,16 +685,16 @@ HRESULT COpRegValueDelete::Execute(CSession *pSession)
} }
// Order rollback action to restore the key from backup copy. // Order rollback action to restore the key from backup copy.
pSession->m_olRollback.AddHead(new COpRegValueCopy(m_hKeyRoot, m_sValue, sBackupName, m_sValueName)); pSession->m_olRollback.push_front(new COpRegValueCopy(m_hKeyRoot, m_sValue.c_str(), sBackupName.c_str(), m_sValueName.c_str()));
// Order commit action to delete backup copy. // Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpRegValueDelete(m_hKeyRoot, m_sValue, sBackupName)); pSession->m_olCommit.push_back(new COpRegValueDelete(m_hKeyRoot, m_sValue.c_str(), sBackupName.c_str()));
} else { } else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5); PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBINGVAL); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBINGVAL);
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetStringW(hRecordProg, 3, sBackupName ); ::MsiRecordSetStringW(hRecordProg, 3, sBackupName.c_str() );
::MsiRecordSetInteger(hRecordProg, 4, lResult ); ::MsiRecordSetInteger(hRecordProg, 4, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
::RegCloseKey(hKey); ::RegCloseKey(hKey);
@ -720,7 +703,7 @@ HRESULT COpRegValueDelete::Execute(CSession *pSession)
} }
// Delete the registry value. // Delete the registry value.
lResult = ::RegDeleteValueW(hKey, m_sValueName); lResult = ::RegDeleteValueW(hKey, m_sValueName.c_str());
} }
::RegCloseKey(hKey); ::RegCloseKey(hKey);
@ -732,8 +715,8 @@ HRESULT COpRegValueDelete::Execute(CSession *pSession)
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5); PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_DELETEVALUE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_DELETEVALUE);
::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ); ::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetStringW(hRecordProg, 4, m_sValueName ); ::MsiRecordSetStringW(hRecordProg, 4, m_sValueName.c_str() );
::MsiRecordSetInteger(hRecordProg, 5, lResult ); ::MsiRecordSetInteger(hRecordProg, 5, lResult );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult); return AtlHresultFromWin32(lResult);

View File

@ -46,7 +46,7 @@ HRESULT COpSvcSetStart::Execute(CSession *pSession)
SC_HANDLE hService; SC_HANDLE hService;
// Open the specified service. // Open the specified service.
hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG); hService = ::OpenServiceW(hSCM, m_sValue.c_str(), SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
if (hService) { if (hService) {
QUERY_SERVICE_CONFIG *sc; QUERY_SERVICE_CONFIG *sc;
DWORD dwSize; DWORD dwSize;
@ -62,7 +62,7 @@ HRESULT COpSvcSetStart::Execute(CSession *pSession)
if (::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, m_dwStartType, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { if (::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, m_dwStartType, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to revert the service start change. // Order rollback action to revert the service start change.
pSession->m_olRollback.AddHead(new COpSvcSetStart(m_sValue, sc->dwStartType)); pSession->m_olRollback.push_front(new COpSvcSetStart(m_sValue.c_str(), sc->dwStartType));
} }
dwError = NO_ERROR; dwError = NO_ERROR;
} else } else
@ -87,7 +87,7 @@ HRESULT COpSvcSetStart::Execute(CSession *pSession)
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_SVC_SET_START); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_SVC_SET_START);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, dwError ); ::MsiRecordSetInteger(hRecordProg, 3, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);
@ -164,14 +164,14 @@ HRESULT COpSvcStart::Execute(CSession *pSession)
SC_HANDLE hService; SC_HANDLE hService;
// Open the specified service. // Open the specified service.
hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_START | (m_bWait ? SERVICE_QUERY_STATUS : 0)); hService = ::OpenServiceW(hSCM, m_sValue.c_str(), SERVICE_START | (m_bWait ? SERVICE_QUERY_STATUS : 0));
if (hService) { if (hService) {
// Start the service. // Start the service.
if (::StartService(hService, 0, NULL)) { if (::StartService(hService, 0, NULL)) {
dwError = m_bWait ? WaitForState(pSession, hService, SERVICE_START_PENDING, SERVICE_RUNNING) : NO_ERROR; dwError = m_bWait ? WaitForState(pSession, hService, SERVICE_START_PENDING, SERVICE_RUNNING) : NO_ERROR;
if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) { if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
// Order rollback action to stop the service. // Order rollback action to stop the service.
pSession->m_olRollback.AddHead(new COpSvcStop(m_sValue)); pSession->m_olRollback.push_front(new COpSvcStop(m_sValue.c_str()));
} }
} else { } else {
dwError = ::GetLastError(); dwError = ::GetLastError();
@ -190,7 +190,7 @@ HRESULT COpSvcStart::Execute(CSession *pSession)
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_SVC_START); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_SVC_START);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, dwError ); ::MsiRecordSetInteger(hRecordProg, 3, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);
@ -218,7 +218,7 @@ HRESULT COpSvcStop::Execute(CSession *pSession)
SC_HANDLE hService; SC_HANDLE hService;
// Open the specified service. // Open the specified service.
hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_STOP | (m_bWait ? SERVICE_QUERY_STATUS : 0)); hService = ::OpenServiceW(hSCM, m_sValue.c_str(), SERVICE_STOP | (m_bWait ? SERVICE_QUERY_STATUS : 0));
if (hService) { if (hService) {
SERVICE_STATUS ss; SERVICE_STATUS ss;
// Stop the service. // Stop the service.
@ -226,7 +226,7 @@ HRESULT COpSvcStop::Execute(CSession *pSession)
dwError = m_bWait ? WaitForState(pSession, hService, SERVICE_STOP_PENDING, SERVICE_STOPPED) : NO_ERROR; dwError = m_bWait ? WaitForState(pSession, hService, SERVICE_STOP_PENDING, SERVICE_STOPPED) : NO_ERROR;
if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) { if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
// Order rollback action to start the service. // Order rollback action to start the service.
pSession->m_olRollback.AddHead(new COpSvcStart(m_sValue)); pSession->m_olRollback.push_front(new COpSvcStart(m_sValue.c_str()));
} }
} else { } else {
dwError = ::GetLastError(); dwError = ::GetLastError();
@ -245,7 +245,7 @@ HRESULT COpSvcStop::Execute(CSession *pSession)
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_SVC_STOP); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_SVC_STOP);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, dwError ); ::MsiRecordSetInteger(hRecordProg, 3, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);

View File

@ -40,24 +40,14 @@ COpTaskCreate::COpTaskCreate(LPCWSTR pszTaskName, int iTicks) :
} }
COpTaskCreate::~COpTaskCreate()
{
// Clear the password in memory.
int iLength = m_sPassword.GetLength();
::SecureZeroMemory(m_sPassword.GetBuffer(iLength), sizeof(WCHAR) * iLength);
m_sPassword.ReleaseBuffer(0);
}
HRESULT COpTaskCreate::Execute(CSession *pSession) HRESULT COpTaskCreate::Execute(CSession *pSession)
{ {
HRESULT hr; HRESULT hr;
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1); PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
CComPtr<ITaskService> pService; CComPtr<ITaskService> pService;
POSITION pos;
// Display our custom message in the progress bar. // Display our custom message in the progress bar.
::MsiRecordSetStringW(hRecordMsg, 1, m_sValue); ::MsiRecordSetStringW(hRecordMsg, 1, m_sValue.c_str());
if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL) if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL)
return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT); return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT);
@ -65,7 +55,7 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
// Delete existing task first. // Delete existing task first.
// Since task deleting is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since task deleting is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpTaskDelete::Execute() returns S_OK if task doesn't exist. // Don't worry, COpTaskDelete::Execute() returns S_OK if task doesn't exist.
COpTaskDelete opDelete(m_sValue); COpTaskDelete opDelete(m_sValue.c_str());
hr = opDelete.Execute(pSession); hr = opDelete.Execute(pSession);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
} }
@ -85,10 +75,10 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
CComPtr<ITriggerCollection> pTriggerCollection; CComPtr<ITriggerCollection> pTriggerCollection;
CComPtr<ITaskFolder> pTaskFolder; CComPtr<ITaskFolder> pTaskFolder;
CComPtr<IRegisteredTask> pTask; CComPtr<IRegisteredTask> pTask;
ATL::CAtlStringW str; std::wstring str;
UINT iTrigger; UINT iTrigger;
TASK_LOGON_TYPE logonType; TASK_LOGON_TYPE logonType;
CComBSTR bstrContext(L"Author"); winstd::bstr bstrContext(L"Author");
// Connect to local task service. // Connect to local task service.
hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty); hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty);
@ -106,7 +96,7 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) { if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) {
// The task is supposed to be enabled. // The task is supposed to be enabled.
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
pSession->m_olCommit.AddTail(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olCommit.push_back(new COpTaskEnable(m_sValue.c_str(), TRUE));
m_dwFlags |= TASK_FLAG_DISABLED; m_dwFlags |= TASK_FLAG_DISABLED;
} }
hr = pTaskSettings->put_Enabled(m_dwFlags & TASK_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE); if (FAILED(hr)) goto finish; hr = pTaskSettings->put_Enabled(m_dwFlags & TASK_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE); if (FAILED(hr)) goto finish;
@ -122,31 +112,24 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Configure the action. // Configure the action.
hr = pExecAction->put_Path (CComBSTR(m_sApplicationName )); if (FAILED(hr)) goto finish; hr = pExecAction->put_Path (winstd::bstr(m_sApplicationName )); if (FAILED(hr)) goto finish;
hr = pExecAction->put_Arguments (CComBSTR(m_sParameters )); if (FAILED(hr)) goto finish; hr = pExecAction->put_Arguments (winstd::bstr(m_sParameters )); if (FAILED(hr)) goto finish;
hr = pExecAction->put_WorkingDirectory(CComBSTR(m_sWorkingDirectory)); if (FAILED(hr)) goto finish; hr = pExecAction->put_WorkingDirectory(winstd::bstr(m_sWorkingDirectory)); if (FAILED(hr)) goto finish;
// Set task description. // Set task description.
hr = pTaskDefinition->get_RegistrationInfo(&pRegististrationInfo); hr = pTaskDefinition->get_RegistrationInfo(&pRegististrationInfo); if (FAILED(hr)) goto finish;
if (FAILED(hr)) goto finish; hr = pRegististrationInfo->put_Author(winstd::bstr(m_sAuthor)); if (FAILED(hr)) goto finish;
hr = pRegististrationInfo->put_Author(CComBSTR(m_sAuthor)); hr = pRegististrationInfo->put_Description(winstd::bstr(m_sComment)); if (FAILED(hr)) goto finish;
if (FAILED(hr)) goto finish;
hr = pRegististrationInfo->put_Description(CComBSTR(m_sComment));
if (FAILED(hr)) goto finish;
// Configure task "flags". // Configure task "flags".
if (m_dwFlags & TASK_FLAG_DELETE_WHEN_DONE) { if (m_dwFlags & TASK_FLAG_DELETE_WHEN_DONE) {
hr = pTaskSettings->put_DeleteExpiredTaskAfter(CComBSTR(L"PT24H")); hr = pTaskSettings->put_DeleteExpiredTaskAfter(winstd::bstr(L"PT24H"));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
} }
hr = pTaskSettings->put_Hidden(m_dwFlags & TASK_FLAG_HIDDEN ? VARIANT_TRUE : VARIANT_FALSE); hr = pTaskSettings->put_Hidden(m_dwFlags & TASK_FLAG_HIDDEN ? VARIANT_TRUE : VARIANT_FALSE); if (FAILED(hr)) goto finish;
if (FAILED(hr)) goto finish; hr = pTaskSettings->put_WakeToRun(m_dwFlags & TASK_FLAG_SYSTEM_REQUIRED ? VARIANT_TRUE : VARIANT_FALSE); if (FAILED(hr)) goto finish;
hr = pTaskSettings->put_WakeToRun(m_dwFlags & TASK_FLAG_SYSTEM_REQUIRED ? VARIANT_TRUE : VARIANT_FALSE); hr = pTaskSettings->put_DisallowStartIfOnBatteries(m_dwFlags & TASK_FLAG_DONT_START_IF_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE); if (FAILED(hr)) goto finish;
if (FAILED(hr)) goto finish; hr = pTaskSettings->put_StopIfGoingOnBatteries(m_dwFlags & TASK_FLAG_KILL_IF_GOING_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE); if (FAILED(hr)) goto finish;
hr = pTaskSettings->put_DisallowStartIfOnBatteries(m_dwFlags & TASK_FLAG_DONT_START_IF_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE);
if (FAILED(hr)) goto finish;
hr = pTaskSettings->put_StopIfGoingOnBatteries(m_dwFlags & TASK_FLAG_KILL_IF_GOING_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE);
if (FAILED(hr)) goto finish;
// Configure task priority. // Configure task priority.
hr = pTaskSettings->put_Priority( hr = pTaskSettings->put_Priority(
@ -162,10 +145,10 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
hr = pTaskDefinition->get_Principal(&pPrincipal); hr = pTaskDefinition->get_Principal(&pPrincipal);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
if (m_sAccountName.IsEmpty()) { if (m_sAccountName.empty()) {
logonType = TASK_LOGON_SERVICE_ACCOUNT; logonType = TASK_LOGON_SERVICE_ACCOUNT;
hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish; hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish;
hr = pPrincipal->put_UserId(CComBSTR(L"S-1-5-18")); if (FAILED(hr)) goto finish; hr = pPrincipal->put_UserId(winstd::bstr(L"S-1-5-18")); if (FAILED(hr)) goto finish;
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) goto finish; hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) goto finish;
} else if (m_dwFlags & TASK_FLAG_RUN_ONLY_IF_LOGGED_ON) { } else if (m_dwFlags & TASK_FLAG_RUN_ONLY_IF_LOGGED_ON) {
logonType = TASK_LOGON_INTERACTIVE_TOKEN; logonType = TASK_LOGON_INTERACTIVE_TOKEN;
@ -174,26 +157,24 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
} else { } else {
logonType = TASK_LOGON_PASSWORD; logonType = TASK_LOGON_PASSWORD;
hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish; hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish;
hr = pPrincipal->put_UserId(CComBSTR(m_sAccountName)); if (FAILED(hr)) goto finish; hr = pPrincipal->put_UserId(winstd::bstr(m_sAccountName)); if (FAILED(hr)) goto finish;
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) goto finish; hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) goto finish;
} }
// Connect principal and action collection. // Connect principal and action collection.
hr = pPrincipal->put_Id(bstrContext); hr = pPrincipal->put_Id(bstrContext); if (FAILED(hr)) goto finish;
if (FAILED(hr)) goto finish; hr = pActionCollection->put_Context(bstrContext); if (FAILED(hr)) goto finish;
hr = pActionCollection->put_Context(bstrContext);
if (FAILED(hr)) goto finish;
// Configure idle settings. // Configure idle settings.
hr = pTaskSettings->put_RunOnlyIfIdle(m_dwFlags & TASK_FLAG_START_ONLY_IF_IDLE ? VARIANT_TRUE : VARIANT_FALSE); hr = pTaskSettings->put_RunOnlyIfIdle(m_dwFlags & TASK_FLAG_START_ONLY_IF_IDLE ? VARIANT_TRUE : VARIANT_FALSE);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
hr = pTaskSettings->get_IdleSettings(&pIdleSettings); hr = pTaskSettings->get_IdleSettings(&pIdleSettings);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
str.Format(L"PT%uS", m_wIdleMinutes*60); sprintf(str, L"PT%uS", m_wIdleMinutes*60);
hr = pIdleSettings->put_IdleDuration(CComBSTR(str)); hr = pIdleSettings->put_IdleDuration(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
str.Format(L"PT%uS", m_wDeadlineMinutes*60); sprintf(str, L"PT%uS", m_wDeadlineMinutes*60);
hr = pIdleSettings->put_WaitTimeout(CComBSTR(str)); hr = pIdleSettings->put_WaitTimeout(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
hr = pIdleSettings->put_RestartOnIdle(m_dwFlags & TASK_FLAG_RESTART_ON_IDLE_RESUME ? VARIANT_TRUE : VARIANT_FALSE); hr = pIdleSettings->put_RestartOnIdle(m_dwFlags & TASK_FLAG_RESTART_ON_IDLE_RESUME ? VARIANT_TRUE : VARIANT_FALSE);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
@ -201,8 +182,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Configure task runtime limit. // Configure task runtime limit.
str.Format(L"PT%uS", m_dwMaxRuntimeMS != INFINITE ? (m_dwMaxRuntimeMS + 500) / 1000 : 0); sprintf(str, L"PT%uS", m_dwMaxRuntimeMS != INFINITE ? (m_dwMaxRuntimeMS + 500) / 1000 : 0);
hr = pTaskSettings->put_ExecutionTimeLimit(CComBSTR(str)); hr = pTaskSettings->put_ExecutionTimeLimit(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task trigger colection. // Get task trigger colection.
@ -210,17 +191,18 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Add triggers. // Add triggers.
for (pos = m_lTriggers.GetHeadPosition(), iTrigger = 0; pos; iTrigger++) { iTrigger = 0;
for (auto t = m_lTriggers.cbegin(), t_end = m_lTriggers.cend(); t != t_end; ++t, iTrigger++) {
CComPtr<ITrigger> pTrigger; CComPtr<ITrigger> pTrigger;
TASK_TRIGGER &ttData = m_lTriggers.GetNext(pos); const TASK_TRIGGER &ttData = *t;
switch (ttData.TriggerType) { switch (ttData.TriggerType) {
case TASK_TIME_TRIGGER_ONCE: { case TASK_TIME_TRIGGER_ONCE: {
CComPtr<ITimeTrigger> pTriggerTime; CComPtr<ITimeTrigger> pTriggerTime;
hr = pTriggerCollection->Create(TASK_TRIGGER_TIME, &pTrigger); if (FAILED(hr)) goto finish; hr = pTriggerCollection->Create(TASK_TRIGGER_TIME, &pTrigger); if (FAILED(hr)) goto finish;
hr = pTrigger.QueryInterface(&pTriggerTime); if (FAILED(hr)) goto finish; hr = pTrigger.QueryInterface(&pTriggerTime); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerTime->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerTime->put_RandomDelay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
@ -229,8 +211,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
hr = pTriggerCollection->Create(TASK_TRIGGER_DAILY, &pTrigger); if (FAILED(hr)) goto finish; hr = pTriggerCollection->Create(TASK_TRIGGER_DAILY, &pTrigger); if (FAILED(hr)) goto finish;
hr = pTrigger.QueryInterface(&pTriggerDaily); if (FAILED(hr)) goto finish; hr = pTrigger.QueryInterface(&pTriggerDaily); if (FAILED(hr)) goto finish;
hr = pTriggerDaily->put_DaysInterval(ttData.Type.Daily.DaysInterval); if (FAILED(hr)) goto finish; hr = pTriggerDaily->put_DaysInterval(ttData.Type.Daily.DaysInterval); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerDaily->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerDaily->put_RandomDelay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
@ -240,8 +222,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
hr = pTrigger.QueryInterface(&pTriggerWeekly); if (FAILED(hr)) goto finish; hr = pTrigger.QueryInterface(&pTriggerWeekly); if (FAILED(hr)) goto finish;
hr = pTriggerWeekly->put_WeeksInterval(ttData.Type.Weekly.WeeksInterval); if (FAILED(hr)) goto finish; hr = pTriggerWeekly->put_WeeksInterval(ttData.Type.Weekly.WeeksInterval); if (FAILED(hr)) goto finish;
hr = pTriggerWeekly->put_DaysOfWeek(ttData.Type.Weekly.rgfDaysOfTheWeek); if (FAILED(hr)) goto finish; hr = pTriggerWeekly->put_DaysOfWeek(ttData.Type.Weekly.rgfDaysOfTheWeek); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerWeekly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerWeekly->put_RandomDelay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
@ -251,8 +233,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
hr = pTrigger.QueryInterface(&pTriggerMonthly); if (FAILED(hr)) goto finish; hr = pTrigger.QueryInterface(&pTriggerMonthly); if (FAILED(hr)) goto finish;
hr = pTriggerMonthly->put_DaysOfMonth(ttData.Type.MonthlyDate.rgfDays); if (FAILED(hr)) goto finish; hr = pTriggerMonthly->put_DaysOfMonth(ttData.Type.MonthlyDate.rgfDays); if (FAILED(hr)) goto finish;
hr = pTriggerMonthly->put_MonthsOfYear(ttData.Type.MonthlyDate.rgfMonths); if (FAILED(hr)) goto finish; hr = pTriggerMonthly->put_MonthsOfYear(ttData.Type.MonthlyDate.rgfMonths); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerMonthly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerMonthly->put_RandomDelay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
@ -268,8 +250,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
ttData.Type.MonthlyDOW.wWhichWeek == TASK_LAST_WEEK ? 0x10 : 0x00); if (FAILED(hr)) goto finish; ttData.Type.MonthlyDOW.wWhichWeek == TASK_LAST_WEEK ? 0x10 : 0x00); if (FAILED(hr)) goto finish;
hr = pTriggerMonthlyDOW->put_DaysOfWeek(ttData.Type.MonthlyDOW.rgfDaysOfTheWeek); if (FAILED(hr)) goto finish; hr = pTriggerMonthlyDOW->put_DaysOfWeek(ttData.Type.MonthlyDOW.rgfDaysOfTheWeek); if (FAILED(hr)) goto finish;
hr = pTriggerMonthlyDOW->put_MonthsOfYear(ttData.Type.MonthlyDOW.rgfMonths); if (FAILED(hr)) goto finish; hr = pTriggerMonthlyDOW->put_MonthsOfYear(ttData.Type.MonthlyDOW.rgfMonths); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerMonthlyDOW->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerMonthlyDOW->put_RandomDelay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
@ -282,8 +264,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
CComPtr<IBootTrigger> pTriggerBoot; CComPtr<IBootTrigger> pTriggerBoot;
hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); if (FAILED(hr)) goto finish; hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); if (FAILED(hr)) goto finish;
hr = pTrigger.QueryInterface(&pTriggerBoot); if (FAILED(hr)) goto finish; hr = pTrigger.QueryInterface(&pTriggerBoot); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerBoot->put_Delay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerBoot->put_Delay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
@ -291,26 +273,26 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
CComPtr<ILogonTrigger> pTriggerLogon; CComPtr<ILogonTrigger> pTriggerLogon;
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); if (FAILED(hr)) goto finish; hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); if (FAILED(hr)) goto finish;
hr = pTrigger.QueryInterface(&pTriggerLogon); if (FAILED(hr)) goto finish; hr = pTrigger.QueryInterface(&pTriggerLogon); if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.wRandomMinutesInterval); sprintf(str, L"PT%uM", ttData.wRandomMinutesInterval);
hr = pTriggerLogon->put_Delay(CComBSTR(str)); if (FAILED(hr)) goto finish; hr = pTriggerLogon->put_Delay(winstd::bstr(str)); if (FAILED(hr)) goto finish;
break; break;
} }
} }
// Set trigger ID. // Set trigger ID.
str.Format(L"%u", iTrigger); sprintf(str, L"%u", iTrigger);
hr = pTrigger->put_Id(CComBSTR(str)); hr = pTrigger->put_Id(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Set trigger start date. // Set trigger start date.
str.Format(L"%04u-%02u-%02uT%02u:%02u:00", ttData.wBeginYear, ttData.wBeginMonth, ttData.wBeginDay, ttData.wStartHour, ttData.wStartMinute); sprintf(str, L"%04u-%02u-%02uT%02u:%02u:00", ttData.wBeginYear, ttData.wBeginMonth, ttData.wBeginDay, ttData.wStartHour, ttData.wStartMinute);
hr = pTrigger->put_StartBoundary(CComBSTR(str)); hr = pTrigger->put_StartBoundary(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
if (ttData.rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) { if (ttData.rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) {
// Set trigger end date. // Set trigger end date.
str.Format(L"%04u-%02u-%02u", ttData.wEndYear, ttData.wEndMonth, ttData.wEndDay); sprintf(str, L"%04u-%02u-%02u", ttData.wEndYear, ttData.wEndMonth, ttData.wEndDay);
hr = pTrigger->put_EndBoundary(CComBSTR(str)); hr = pTrigger->put_EndBoundary(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
} }
@ -320,11 +302,11 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
hr = pTrigger->get_Repetition(&pRepetitionPattern); hr = pTrigger->get_Repetition(&pRepetitionPattern);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.MinutesDuration); sprintf(str, L"PT%uM", ttData.MinutesDuration);
hr = pRepetitionPattern->put_Duration(CComBSTR(str)); hr = pRepetitionPattern->put_Duration(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
str.Format(L"PT%uM", ttData.MinutesInterval); sprintf(str, L"PT%uM", ttData.MinutesInterval);
hr = pRepetitionPattern->put_Interval(CComBSTR(str)); hr = pRepetitionPattern->put_Interval(winstd::bstr(str));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
hr = pRepetitionPattern->put_StopAtDurationEnd(ttData.rgFlags & TASK_TRIGGER_FLAG_KILL_AT_DURATION_END ? VARIANT_TRUE : VARIANT_FALSE); hr = pRepetitionPattern->put_StopAtDurationEnd(ttData.rgFlags & TASK_TRIGGER_FLAG_KILL_AT_DURATION_END ? VARIANT_TRUE : VARIANT_FALSE);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
@ -336,21 +318,21 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
} }
// Get the task folder. // Get the task folder.
hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); hr = pService->GetFolder(winstd::bstr(L"\\"), &pTaskFolder);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
#ifdef _DEBUG #ifdef _DEBUG
CComBSTR xml; winstd::bstr xml;
hr = pTaskDefinition->get_XmlText(&xml); hr = pTaskDefinition->get_XmlText(&xml);
#endif #endif
// Register the task. // Register the task.
hr = pTaskFolder->RegisterTaskDefinition( hr = pTaskFolder->RegisterTaskDefinition(
CComBSTR(m_sValue), // path winstd::bstr(m_sValue), // path
pTaskDefinition, // pDefinition pTaskDefinition, // pDefinition
TASK_CREATE, // flags TASK_CREATE, // flags
vEmpty, // userId vEmpty, // userId
logonType != TASK_LOGON_SERVICE_ACCOUNT && !m_sPassword.IsEmpty() ? CComVariant(m_sPassword) : vEmpty, // password logonType != TASK_LOGON_SERVICE_ACCOUNT && !m_sPassword.empty() ? CComVariant(m_sPassword.c_str()) : vEmpty, // password
logonType, // logonType logonType, // logonType
vEmpty, // sddl vEmpty, // sddl
&pTask); // ppTask &pTask); // ppTask
@ -364,41 +346,41 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Create the new task. // Create the new task.
hr = pTaskScheduler->NewWorkItem(m_sValue, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); hr = pTaskScheduler->NewWorkItem(m_sValue.c_str(), CLSID_CTask, IID_ITask, (IUnknown**)&pTask);
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the task. ITask::NewWorkItem() might made a blank task already. // Order rollback action to delete the task. ITask::NewWorkItem() might made a blank task already.
pSession->m_olRollback.AddHead(new COpTaskDelete(m_sValue)); pSession->m_olRollback.push_front(new COpTaskDelete(m_sValue.c_str()));
} }
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Set its properties. // Set its properties.
hr = pTask->SetApplicationName (m_sApplicationName ); if (FAILED(hr)) goto finish; hr = pTask->SetApplicationName (m_sApplicationName.c_str() ); if (FAILED(hr)) goto finish;
hr = pTask->SetParameters (m_sParameters ); if (FAILED(hr)) goto finish; hr = pTask->SetParameters (m_sParameters.c_str() ); if (FAILED(hr)) goto finish;
hr = pTask->SetWorkingDirectory(m_sWorkingDirectory); if (FAILED(hr)) goto finish; hr = pTask->SetWorkingDirectory(m_sWorkingDirectory.c_str()); if (FAILED(hr)) goto finish;
hr = pTask->SetComment (m_sComment ); if (FAILED(hr)) goto finish; hr = pTask->SetComment (m_sComment.c_str() ); if (FAILED(hr)) goto finish;
if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) { if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) {
// The task is supposed to be enabled. // The task is supposed to be enabled.
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
pSession->m_olCommit.AddTail(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olCommit.push_back(new COpTaskEnable(m_sValue.c_str(), TRUE));
m_dwFlags |= TASK_FLAG_DISABLED; m_dwFlags |= TASK_FLAG_DISABLED;
} }
hr = pTask->SetFlags (m_dwFlags ); if (FAILED(hr)) goto finish; hr = pTask->SetFlags (m_dwFlags ); if (FAILED(hr)) goto finish;
hr = pTask->SetPriority (m_dwPriority ); if (FAILED(hr)) goto finish; hr = pTask->SetPriority (m_dwPriority ); if (FAILED(hr)) goto finish;
// Set task credentials. // Set task credentials.
hr = m_sAccountName.IsEmpty() ? hr = m_sAccountName.empty() ?
pTask->SetAccountInformation(L"", NULL ) : pTask->SetAccountInformation(L"" , NULL ) :
pTask->SetAccountInformation(m_sAccountName, m_sPassword); pTask->SetAccountInformation(m_sAccountName.c_str(), m_sPassword.c_str());
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
hr = pTask->SetIdleWait (m_wIdleMinutes, m_wDeadlineMinutes); if (FAILED(hr)) goto finish; hr = pTask->SetIdleWait (m_wIdleMinutes, m_wDeadlineMinutes); if (FAILED(hr)) goto finish;
hr = pTask->SetMaxRunTime(m_dwMaxRuntimeMS ); if (FAILED(hr)) goto finish; hr = pTask->SetMaxRunTime(m_dwMaxRuntimeMS ); if (FAILED(hr)) goto finish;
// Add triggers. // Add triggers.
for (pos = m_lTriggers.GetHeadPosition(); pos;) { for (auto t = m_lTriggers.cbegin(), t_end = m_lTriggers.cend(); t != t_end; ++t) {
WORD wTriggerIdx; WORD wTriggerIdx;
CComPtr<ITaskTrigger> pTrigger; CComPtr<ITaskTrigger> pTrigger;
TASK_TRIGGER ttData = m_lTriggers.GetNext(pos); // Don't use reference! We don't want to modify original trigger data by adding random startup delay. TASK_TRIGGER ttData = *t; // Don't use reference! We don't want to modify original trigger data by adding random startup delay.
hr = pTask->CreateTrigger(&wTriggerIdx, &pTrigger); hr = pTask->CreateTrigger(&wTriggerIdx, &pTrigger);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
@ -426,8 +408,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
} }
// Convert numerical date to DMY (ULONGLONG -> FILETIME -> SYSTEMTIME). // Convert numerical date to DMY (ULONGLONG -> FILETIME -> SYSTEMTIME).
ftValue.dwHighDateTime = (DWORD)((ullValue >> 32) & 0xffffffff); ftValue.dwHighDateTime = static_cast<DWORD>((ullValue >> 32) & 0xffffffff);
ftValue.dwLowDateTime = (DWORD)( ullValue & 0xffffffff); ftValue.dwLowDateTime = static_cast<DWORD>( ullValue & 0xffffffff);
::FileTimeToSystemTime(&ftValue, &stValue); ::FileTimeToSystemTime(&ftValue, &stValue);
// Set new trigger date and time. // Set new trigger date and time.
@ -452,7 +434,7 @@ finish:
if (FAILED(hr)) { if (FAILED(hr)) {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_CREATE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_CREATE);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
@ -464,7 +446,7 @@ UINT COpTaskCreate::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord)
{ {
UINT uiResult; UINT uiResult;
int iValue; int iValue;
ATL::CAtlStringW sFolder; std::wstring sFolder;
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 3, m_sApplicationName); uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 3, m_sApplicationName);
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
@ -474,11 +456,11 @@ UINT COpTaskCreate::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord)
uiResult = ::MsiRecordGetStringW(hRecord, 5, sFolder); uiResult = ::MsiRecordGetStringW(hRecord, 5, sFolder);
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
uiResult = ::MsiGetTargetPathW(hInstall, sFolder, m_sWorkingDirectory); uiResult = ::MsiGetTargetPathW(hInstall, sFolder.c_str(), m_sWorkingDirectory);
if (uiResult != NO_ERROR) return uiResult; if (uiResult != NO_ERROR) return uiResult;
if (!m_sWorkingDirectory.IsEmpty() && m_sWorkingDirectory.GetAt(m_sWorkingDirectory.GetLength() - 1) == L'\\') { if (!m_sWorkingDirectory.empty() && m_sWorkingDirectory.back() == L'\\') {
// Trim trailing backslash. // Trim trailing backslash.
m_sWorkingDirectory.Truncate(m_sWorkingDirectory.GetLength() - 1); m_sWorkingDirectory.resize(m_sWorkingDirectory.length() - 1);
} }
uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 10, m_sAuthor); uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 10, m_sAuthor);
@ -532,8 +514,8 @@ UINT COpTaskCreate::SetTriggersFromView(MSIHANDLE hView)
iValue = ::MsiRecordGetInteger(hRecord, 2); iValue = ::MsiRecordGetInteger(hRecord, 2);
if (iValue == MSI_NULL_INTEGER) return ERROR_INVALID_FIELD; if (iValue == MSI_NULL_INTEGER) return ERROR_INVALID_FIELD;
ullValue = ((ULONGLONG)iValue + 138426) * 864000000000; ullValue = ((ULONGLONG)iValue + 138426) * 864000000000;
ftValue.dwHighDateTime = (DWORD)((ullValue >> 32) & 0xffffffff); ftValue.dwHighDateTime = static_cast<DWORD>((ullValue >> 32) & 0xffffffff);
ftValue.dwLowDateTime = (DWORD)( ullValue & 0xffffffff); ftValue.dwLowDateTime = static_cast<DWORD>( ullValue & 0xffffffff);
if (!::FileTimeToSystemTime(&ftValue, &stValue)) if (!::FileTimeToSystemTime(&ftValue, &stValue))
return ::GetLastError(); return ::GetLastError();
ttData.wBeginYear = stValue.wYear; ttData.wBeginYear = stValue.wYear;
@ -544,8 +526,8 @@ UINT COpTaskCreate::SetTriggersFromView(MSIHANDLE hView)
iValue = ::MsiRecordGetInteger(hRecord, 3); iValue = ::MsiRecordGetInteger(hRecord, 3);
if (iValue != MSI_NULL_INTEGER) { if (iValue != MSI_NULL_INTEGER) {
ullValue = ((ULONGLONG)iValue + 138426) * 864000000000; ullValue = ((ULONGLONG)iValue + 138426) * 864000000000;
ftValue.dwHighDateTime = (DWORD)((ullValue >> 32) & 0xffffffff); ftValue.dwHighDateTime = static_cast<DWORD>((ullValue >> 32) & 0xffffffff);
ftValue.dwLowDateTime = (DWORD)( ullValue & 0xffffffff); ftValue.dwLowDateTime = static_cast<DWORD>( ullValue & 0xffffffff);
if (!::FileTimeToSystemTime(&ftValue, &stValue)) if (!::FileTimeToSystemTime(&ftValue, &stValue))
return ::GetLastError(); return ::GetLastError();
ttData.wEndYear = stValue.wYear; ttData.wEndYear = stValue.wYear;
@ -632,7 +614,7 @@ UINT COpTaskCreate::SetTriggersFromView(MSIHANDLE hView)
break; break;
} }
m_lTriggers.AddTail(ttData); m_lTriggers.push_back(ttData);
} }
return NO_ERROR; return NO_ERROR;
@ -665,7 +647,7 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task folder. // Get task folder.
hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); hr = pService->GetFolder(winstd::bstr(L"\\"), &pTaskFolder);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
@ -674,13 +656,13 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
CComPtr<IPrincipal> pPrincipal; CComPtr<IPrincipal> pPrincipal;
VARIANT_BOOL bEnabled; VARIANT_BOOL bEnabled;
TASK_LOGON_TYPE logonType; TASK_LOGON_TYPE logonType;
CComBSTR sSSDL; winstd::bstr sSSDL;
CComVariant vSSDL; CComVariant vSSDL;
ATL::CAtlStringW sDisplayNameOrig; std::wstring sDisplayNameOrig;
UINT uiCount = 0; UINT uiCount = 0;
// Get the source task. // Get the source task.
hr = pTaskFolder->GetTask(CComBSTR(m_sValue), &pTask); hr = pTaskFolder->GetTask(winstd::bstr(m_sValue), &pTask);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; goto finish; } if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; goto finish; }
else if (FAILED(hr)) goto finish; else if (FAILED(hr)) goto finish;
@ -691,7 +673,7 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
// The task is enabled. // The task is enabled.
// In case the task disabling fails halfway, try to re-enable it anyway on rollback. // In case the task disabling fails halfway, try to re-enable it anyway on rollback.
pSession->m_olRollback.AddHead(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olRollback.push_front(new COpTaskEnable(m_sValue.c_str(), TRUE));
// Disable it. // Disable it.
hr = pTask->put_Enabled(VARIANT_FALSE); hr = pTask->put_Enabled(VARIANT_FALSE);
@ -716,14 +698,14 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
else if (FAILED(hr)) goto finish; else if (FAILED(hr)) goto finish;
else { else {
V_VT (&vSSDL) = VT_BSTR; V_VT (&vSSDL) = VT_BSTR;
V_BSTR(&vSSDL) = sSSDL.Detach(); V_BSTR(&vSSDL) = sSSDL.detach();
} }
// Register a backup copy of task. // Register a backup copy of task.
do { do {
sDisplayNameOrig.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); sprintf(sDisplayNameOrig, L"%ls (orig %u)", m_sValue.c_str(), ++uiCount);
hr = pTaskFolder->RegisterTaskDefinition( hr = pTaskFolder->RegisterTaskDefinition(
CComBSTR(sDisplayNameOrig), // path winstd::bstr(sDisplayNameOrig), // path
pTaskDefinition, // pDefinition pTaskDefinition, // pDefinition
TASK_CREATE, // flags TASK_CREATE, // flags
vEmpty, // userId vEmpty, // userId
@ -733,21 +715,21 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
&pTaskOrig); // ppTask &pTaskOrig); // ppTask
} while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); } while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS));
// In case the backup copy creation failed halfway, try to delete its remains anyway on rollback. // In case the backup copy creation failed halfway, try to delete its remains anyway on rollback.
pSession->m_olRollback.AddHead(new COpTaskDelete(sDisplayNameOrig)); pSession->m_olRollback.push_front(new COpTaskDelete(sDisplayNameOrig.c_str()));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Order rollback action to restore from backup copy. // Order rollback action to restore from backup copy.
pSession->m_olRollback.AddHead(new COpTaskCopy(sDisplayNameOrig, m_sValue)); pSession->m_olRollback.push_front(new COpTaskCopy(sDisplayNameOrig.c_str(), m_sValue.c_str()));
// Delete it. // Delete it.
hr = pTaskFolder->DeleteTask(CComBSTR(m_sValue), 0); hr = pTaskFolder->DeleteTask(winstd::bstr(m_sValue), 0);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Order commit action to delete backup copy. // Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpTaskDelete(sDisplayNameOrig)); pSession->m_olCommit.push_back(new COpTaskDelete(sDisplayNameOrig.c_str()));
} else { } else {
// Delete the task. // Delete the task.
hr = pTaskFolder->DeleteTask(CComBSTR(m_sValue), 0); hr = pTaskFolder->DeleteTask(winstd::bstr(m_sValue), 0);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hr = S_OK; if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hr = S_OK;
} }
} else { } else {
@ -761,11 +743,11 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
CComPtr<ITask> pTask; CComPtr<ITask> pTask;
DWORD dwFlags; DWORD dwFlags;
ATL::CAtlStringW sDisplayNameOrig; std::wstring sDisplayNameOrig;
UINT uiCount = 0; UINT uiCount = 0;
// Load the task. // Load the task.
hr = pTaskScheduler->Activate(m_sValue, IID_ITask, (IUnknown**)&pTask); hr = pTaskScheduler->Activate(m_sValue.c_str(), IID_ITask, (IUnknown**)&pTask);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; goto finish; } if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; goto finish; }
else if (FAILED(hr)) goto finish; else if (FAILED(hr)) goto finish;
@ -776,7 +758,7 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
// The task is enabled. // The task is enabled.
// In case the task disabling fails halfway, try to re-enable it anyway on rollback. // In case the task disabling fails halfway, try to re-enable it anyway on rollback.
pSession->m_olRollback.AddHead(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olRollback.push_front(new COpTaskEnable(m_sValue.c_str(), TRUE));
// Disable it. // Disable it.
dwFlags |= TASK_FLAG_DISABLED; dwFlags |= TASK_FLAG_DISABLED;
@ -786,11 +768,11 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
// Prepare a backup copy of task. // Prepare a backup copy of task.
do { do {
sDisplayNameOrig.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); sprintf(sDisplayNameOrig, L"%ls (orig %u)", m_sValue.c_str(), ++uiCount);
hr = pTaskScheduler->AddWorkItem(sDisplayNameOrig, pTask); hr = pTaskScheduler->AddWorkItem(sDisplayNameOrig.c_str(), pTask);
} while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); } while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS));
// In case the backup copy creation failed halfway, try to delete its remains anyway on rollback. // In case the backup copy creation failed halfway, try to delete its remains anyway on rollback.
pSession->m_olRollback.AddHead(new COpTaskDelete(sDisplayNameOrig)); pSession->m_olRollback.push_front(new COpTaskDelete(sDisplayNameOrig.c_str()));
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Save the backup copy. // Save the backup copy.
@ -800,17 +782,17 @@ HRESULT COpTaskDelete::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Order rollback action to restore from backup copy. // Order rollback action to restore from backup copy.
pSession->m_olRollback.AddHead(new COpTaskCopy(sDisplayNameOrig, m_sValue)); pSession->m_olRollback.push_front(new COpTaskCopy(sDisplayNameOrig.c_str(), m_sValue.c_str()));
// Delete it. // Delete it.
hr = pTaskScheduler->Delete(m_sValue); hr = pTaskScheduler->Delete(m_sValue.c_str());
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Order commit action to delete backup copy. // Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpTaskDelete(sDisplayNameOrig)); pSession->m_olCommit.push_back(new COpTaskDelete(sDisplayNameOrig.c_str()));
} else { } else {
// Delete the task. // Delete the task.
hr = pTaskScheduler->Delete(m_sValue); hr = pTaskScheduler->Delete(m_sValue.c_str());
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hr = S_OK; if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hr = S_OK;
} }
} }
@ -819,7 +801,7 @@ finish:
if (FAILED(hr)) { if (FAILED(hr)) {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_DELETE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_DELETE);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
@ -856,11 +838,11 @@ HRESULT COpTaskEnable::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task folder. // Get task folder.
hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); hr = pService->GetFolder(winstd::bstr(L"\\"), &pTaskFolder);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task. // Get task.
hr = pTaskFolder->GetTask(CComBSTR(m_sValue), &pTask); hr = pTaskFolder->GetTask(winstd::bstr(m_sValue), &pTask);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get currently enabled state. // Get currently enabled state.
@ -872,7 +854,7 @@ HRESULT COpTaskEnable::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled && !bEnabled) { if (pSession->m_bRollbackEnabled && !bEnabled) {
// The task is disabled and supposed to be enabled. // The task is disabled and supposed to be enabled.
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
pSession->m_olCommit.AddTail(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olCommit.push_back(new COpTaskEnable(m_sValue.c_str(), TRUE));
hr = S_OK; goto finish; hr = S_OK; goto finish;
} else } else
bEnabled = VARIANT_TRUE; bEnabled = VARIANT_TRUE;
@ -880,7 +862,7 @@ HRESULT COpTaskEnable::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled && bEnabled) { if (pSession->m_bRollbackEnabled && bEnabled) {
// The task is enabled and we will disable it now. // The task is enabled and we will disable it now.
// Order rollback to re-enable it. // Order rollback to re-enable it.
pSession->m_olRollback.AddHead(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olRollback.push_front(new COpTaskEnable(m_sValue.c_str(), TRUE));
} }
bEnabled = VARIANT_FALSE; bEnabled = VARIANT_FALSE;
} }
@ -899,7 +881,7 @@ HRESULT COpTaskEnable::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Load the task. // Load the task.
hr = pTaskScheduler->Activate(m_sValue, IID_ITask, (IUnknown**)&pTask); hr = pTaskScheduler->Activate(m_sValue.c_str(), IID_ITask, (IUnknown**)&pTask);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task's current flags. // Get task's current flags.
@ -911,7 +893,7 @@ HRESULT COpTaskEnable::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled && (dwFlags & TASK_FLAG_DISABLED)) { if (pSession->m_bRollbackEnabled && (dwFlags & TASK_FLAG_DISABLED)) {
// The task is disabled and supposed to be enabled. // The task is disabled and supposed to be enabled.
// However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase.
pSession->m_olCommit.AddTail(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olCommit.push_back(new COpTaskEnable(m_sValue.c_str(), TRUE));
hr = S_OK; goto finish; hr = S_OK; goto finish;
} else } else
dwFlags &= ~TASK_FLAG_DISABLED; dwFlags &= ~TASK_FLAG_DISABLED;
@ -919,7 +901,7 @@ HRESULT COpTaskEnable::Execute(CSession *pSession)
if (pSession->m_bRollbackEnabled && !(dwFlags & TASK_FLAG_DISABLED)) { if (pSession->m_bRollbackEnabled && !(dwFlags & TASK_FLAG_DISABLED)) {
// The task is enabled and we will disable it now. // The task is enabled and we will disable it now.
// Order rollback to re-enable it. // Order rollback to re-enable it.
pSession->m_olRollback.AddHead(new COpTaskEnable(m_sValue, TRUE)); pSession->m_olRollback.push_front(new COpTaskEnable(m_sValue.c_str(), TRUE));
} }
dwFlags |= TASK_FLAG_DISABLED; dwFlags |= TASK_FLAG_DISABLED;
} }
@ -939,7 +921,7 @@ finish:
if (FAILED(hr)) { if (FAILED(hr)) {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_ENABLE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_ENABLE);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue.c_str() );
::MsiRecordSetInteger(hRecordProg, 3, hr ); ::MsiRecordSetInteger(hRecordProg, 3, hr );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }
@ -971,18 +953,18 @@ HRESULT COpTaskCopy::Execute(CSession *pSession)
CComPtr<ITaskDefinition> pTaskDefinition; CComPtr<ITaskDefinition> pTaskDefinition;
CComPtr<IPrincipal> pPrincipal; CComPtr<IPrincipal> pPrincipal;
TASK_LOGON_TYPE logonType; TASK_LOGON_TYPE logonType;
CComBSTR sSSDL; winstd::bstr sSSDL;
// Connect to local task service. // Connect to local task service.
hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty); hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task folder. // Get task folder.
hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); hr = pService->GetFolder(winstd::bstr(L"\\"), &pTaskFolder);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get the source task. // Get the source task.
hr = pTaskFolder->GetTask(CComBSTR(m_sValue1), &pTask); hr = pTaskFolder->GetTask(winstd::bstr(m_sValue1), &pTask);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Get task's definition. // Get task's definition.
@ -1003,7 +985,7 @@ HRESULT COpTaskCopy::Execute(CSession *pSession)
// Register a new task. // Register a new task.
hr = pTaskFolder->RegisterTaskDefinition( hr = pTaskFolder->RegisterTaskDefinition(
CComBSTR(m_sValue2), // path winstd::bstr(m_sValue2), // path
pTaskDefinition, // pDefinition pTaskDefinition, // pDefinition
TASK_CREATE, // flags TASK_CREATE, // flags
vEmpty, // userId vEmpty, // userId
@ -1022,14 +1004,14 @@ HRESULT COpTaskCopy::Execute(CSession *pSession)
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Load the source task. // Load the source task.
hr = pTaskScheduler->Activate(m_sValue1, IID_ITask, (IUnknown**)&pTask); hr = pTaskScheduler->Activate(m_sValue1.c_str(), IID_ITask, (IUnknown**)&pTask);
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
// Add with different name. // Add with different name.
hr = pTaskScheduler->AddWorkItem(m_sValue2, pTask); hr = pTaskScheduler->AddWorkItem(m_sValue2.c_str(), pTask);
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the new copy. ITask::AddWorkItem() might made a blank task already. // Order rollback action to delete the new copy. ITask::AddWorkItem() might made a blank task already.
pSession->m_olRollback.AddHead(new COpTaskDelete(m_sValue2)); pSession->m_olRollback.push_front(new COpTaskDelete(m_sValue2.c_str()));
} }
if (FAILED(hr)) goto finish; if (FAILED(hr)) goto finish;
@ -1044,8 +1026,8 @@ finish:
if (FAILED(hr)) { if (FAILED(hr)) {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_COPY); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_COPY);
::MsiRecordSetStringW(hRecordProg, 2, m_sValue1 ); ::MsiRecordSetStringW(hRecordProg, 2, m_sValue1.c_str() );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue2 ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue2.c_str() );
::MsiRecordSetInteger(hRecordProg, 4, hr ); ::MsiRecordSetInteger(hRecordProg, 4, hr );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
} }

View File

@ -55,19 +55,19 @@ HRESULT COpWLANProfileDelete::Execute(CSession *pSession)
DWORD dwFlags = 0, dwGrantedAccess = 0; DWORD dwFlags = 0, dwGrantedAccess = 0;
// Get profile settings as XML first. // Get profile settings as XML first.
dwError = ::pfnWlanGetProfile(hClientHandle, &m_guidInterface, m_sValue, NULL, &pszProfileXML, &dwFlags, &dwGrantedAccess); dwError = ::pfnWlanGetProfile(hClientHandle, &m_guidInterface, m_sValue.c_str(), NULL, &pszProfileXML, &dwFlags, &dwGrantedAccess);
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
// Delete the profile. // Delete the profile.
dwError = ::pfnWlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue, NULL); dwError = ::pfnWlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue.c_str(), NULL);
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
// Order rollback action to recreate it. // Order rollback action to recreate it.
pSession->m_olRollback.AddHead(new COpWLANProfileSet(m_guidInterface, dwFlags, m_sValue, pszProfileXML)); pSession->m_olRollback.push_front(new COpWLANProfileSet(m_guidInterface, dwFlags, m_sValue.c_str(), pszProfileXML));
} }
::pfnWlanFreeMemory(pszProfileXML); ::pfnWlanFreeMemory(pszProfileXML);
} }
} else { } else {
// Delete the profile. // Delete the profile.
dwError = ::pfnWlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue, NULL); dwError = ::pfnWlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue.c_str(), NULL);
} }
::pfnWlanCloseHandle(hClientHandle, NULL); ::pfnWlanCloseHandle(hClientHandle, NULL);
} }
@ -76,11 +76,9 @@ HRESULT COpWLANProfileDelete::Execute(CSession *pSession)
return S_OK; return S_OK;
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
ATL::CAtlStringW sGUID; ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_DELETE );
GuidToString(&m_guidInterface, sGUID); ::MsiRecordSetStringW(hRecordProg, 2, winstd::wstring_guid(m_guidInterface).c_str());
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_DELETE); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetStringW(hRecordProg, 2, sGUID );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue );
::MsiRecordSetInteger(hRecordProg, 4, dwError ); ::MsiRecordSetInteger(hRecordProg, 4, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);
@ -117,7 +115,7 @@ HRESULT COpWLANProfileSet::Execute(CSession *pSession)
// Delete existing profile first. // Delete existing profile first.
// Since deleting a profile is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since deleting a profile is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpWLANProfileDelete::Execute() returns S_OK if profile doesn't exist. // Don't worry, COpWLANProfileDelete::Execute() returns S_OK if profile doesn't exist.
COpWLANProfileDelete opDelete(m_guidInterface, m_sValue); COpWLANProfileDelete opDelete(m_guidInterface, m_sValue.c_str());
HRESULT hr = opDelete.Execute(pSession); HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
} }
@ -125,10 +123,10 @@ HRESULT COpWLANProfileSet::Execute(CSession *pSession)
dwError = ::pfnWlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle); dwError = ::pfnWlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle);
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
// Set the profile. // Set the profile.
dwError = ::pfnWlanSetProfile(hClientHandle, &m_guidInterface, m_dwFlags, m_sProfileXML, NULL, TRUE, NULL, &wlrc); dwError = ::pfnWlanSetProfile(hClientHandle, &m_guidInterface, m_dwFlags, m_sProfileXML.c_str(), NULL, TRUE, NULL, &wlrc);
if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) { if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
// Order rollback action to delete it. // Order rollback action to delete it.
pSession->m_olRollback.AddHead(new COpWLANProfileDelete(m_guidInterface, m_sValue)); pSession->m_olRollback.push_front(new COpWLANProfileDelete(m_guidInterface, m_sValue.c_str()));
} }
::pfnWlanCloseHandle(hClientHandle, NULL); ::pfnWlanCloseHandle(hClientHandle, NULL);
} }
@ -137,19 +135,17 @@ HRESULT COpWLANProfileSet::Execute(CSession *pSession)
return S_OK; return S_OK;
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5); PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
ATL::CAtlStringW sGUID, sReason; std::wstring sReason;
DWORD dwSize = 1024, dwResult; std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[1024]);
LPWSTR szBuffer = sReason.GetBuffer(dwSize); if (szBuffer && ::pfnWlanReasonCodeToString(wlrc, 1024, szBuffer.get(), NULL) == NO_ERROR)
sReason.assign(szBuffer.get(), wcsnlen(szBuffer.get(), 1024));
GuidToString(&m_guidInterface, sGUID); else
dwResult = ::pfnWlanReasonCodeToString(wlrc, dwSize, szBuffer, NULL); sprintf(sReason, L"0x%x", wlrc);
sReason.ReleaseBuffer(dwSize);
if (dwResult != NO_ERROR) sReason.Format(L"0x%x", wlrc);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_SET); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_SET);
::MsiRecordSetStringW(hRecordProg, 2, sGUID ); ::MsiRecordSetStringW(hRecordProg, 2, winstd::wstring_guid(m_guidInterface).c_str());
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue.c_str() );
::MsiRecordSetStringW(hRecordProg, 4, sReason ); ::MsiRecordSetStringW(hRecordProg, 4, sReason.c_str() );
::MsiRecordSetInteger(hRecordProg, 5, dwError ); ::MsiRecordSetInteger(hRecordProg, 5, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return AtlHresultFromWin32(dwError);

View File

@ -21,6 +21,9 @@
#include <MSICALib.h> #include <MSICALib.h>
#include <WinStd/COM.h>
#include <WinStd/Crypt.h>
#include <atlex/atlcrypt.h> #include <atlex/atlcrypt.h>
#include <atlex/atlwin.h> #include <atlex/atlwin.h>