Do konca sem usposobil podporo za delo z registrom.

Nekaj skupnih sporočil o napakah sem preselil iz MSITSCA sem.

Branje in zapisovanje na tok podatkov ATL::CAtlFile zdaj preverja dolžino prebranih/zapisanih podatkov.

Estetski popravki.

Verzijo sem nastavil na 1.0.1.
This commit is contained in:
Simon Rozman 2013-06-08 06:10:26 +00:00
parent 12a8cbd84e
commit bb0d512b51
6 changed files with 934 additions and 160 deletions

View File

@ -5,13 +5,13 @@
// Version // Version
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
#define AMSICA_VERSION 0x01000000 #define AMSICA_VERSION 0x01000100
#define AMSICA_VERSION_MAJ 1 #define AMSICA_VERSION_MAJ 1
#define AMSICA_VERSION_MIN 0 #define AMSICA_VERSION_MIN 0
#define AMSICA_VERSION_REV 0 #define AMSICA_VERSION_REV 1
#define AMSICA_VERSION_STR "1.0" #define AMSICA_VERSION_STR "1.0.1"
#if !defined(RC_INVOKED) && !defined(MIDL_PASS) #if !defined(RC_INVOKED) && !defined(MIDL_PASS)
@ -26,26 +26,30 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Error codes (next unused 2565L) // Error codes (next unused 2569L)
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#define ERROR_INSTALL_DATABASE_OPEN 2550L
#define ERROR_INSTALL_PROPERTY_SET 2553L
#define ERROR_INSTALL_SCRIPT_WRITE 2552L
#define ERROR_INSTALL_SCRIPT_READ 2560L
#define ERROR_INSTALL_FILE_DELETE_FAILED 2554L #define ERROR_INSTALL_FILE_DELETE_FAILED 2554L
#define ERROR_INSTALL_FILE_MOVE_FAILED 2555L #define ERROR_INSTALL_FILE_MOVE_FAILED 2555L
#define ERROR_INSTALL_REGKEY_CREATE_FAILED 2561L #define ERROR_INSTALL_REGKEY_CREATE_FAILED 2561L
#define ERROR_INSTALL_REGKEY_COPY_FAILED 2562L #define ERROR_INSTALL_REGKEY_COPY_FAILED 2562L
#define ERROR_INSTALL_REGKEY_PROBING_FAILED 2563L #define ERROR_INSTALL_REGKEY_PROBING_FAILED 2563L
#define ERROR_INSTALL_REGKEY_DELETE_FAILED 2564L #define ERROR_INSTALL_REGKEY_DELETE_FAILED 2564L
#define ERROR_INSTALL_REGKEY_SETVALUE_FAILED 2565L
#define ERROR_INSTALL_REGKEY_DELETEVALUE_FAILED 2567L
#define ERROR_INSTALL_REGKEY_COPYVALUE_FAILED 2568L
#define ERROR_INSTALL_REGKEY_PROBINGVAL_FAILED 2566L
#define ERROR_INSTALL_TASK_CREATE_FAILED 2556L #define ERROR_INSTALL_TASK_CREATE_FAILED 2556L
#define ERROR_INSTALL_TASK_DELETE_FAILED 2557L #define ERROR_INSTALL_TASK_DELETE_FAILED 2557L
#define ERROR_INSTALL_TASK_ENABLE_FAILED 2558L #define ERROR_INSTALL_TASK_ENABLE_FAILED 2558L
#define ERROR_INSTALL_TASK_COPY_FAILED 2559L #define ERROR_INSTALL_TASK_COPY_FAILED 2559L
// Errors reported by MSITSCA // Errors reported by MSITSCA
#define ERROR_INSTALL_SCHEDULED_TASKS_DATABASE_OPEN 2550L
#define ERROR_INSTALL_SCHEDULED_TASKS_OPLIST_CREATE 2551L #define ERROR_INSTALL_SCHEDULED_TASKS_OPLIST_CREATE 2551L
#define ERROR_INSTALL_SCHEDULED_TASKS_SCRIPT_WRITE 2552L
#define ERROR_INSTALL_SCHEDULED_TASKS_SCRIPT_READ 2560L
#define ERROR_INSTALL_SCHEDULED_TASKS_PROPERTY_SET 2553L
namespace AMSICA { namespace AMSICA {
@ -96,7 +100,7 @@ protected:
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// COpDoubleStringOperation // COpTypeSrcDstString
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
class COpTypeSrcDstString : public COperation class COpTypeSrcDstString : public COperation
@ -219,11 +223,12 @@ public:
class COpRegKeyCopy : public COpRegKeySrcDst class COpRegKeyCopy : public COpRegKeySrcDst
{ {
public: public:
COpRegKeyCopy(HKEY hKey = NULL, LPCWSTR pszKeyNameSrc = L"", LPCWSTR pszKeyNameDst = L"", int iTicks = 0); COpRegKeyCopy(HKEY hKeyRoot = NULL, LPCWSTR pszKeyNameSrc = L"", LPCWSTR pszKeyNameDst = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession); virtual HRESULT Execute(CSession *pSession);
private: private:
static LONG CopyKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPCWSTR pszKeyNameDst, REGSAM samAdditional); static LONG CopyKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPCWSTR pszKeyNameDst, REGSAM samAdditional);
static LONG CopyKeyRecursively(HKEY hKeySrc, HKEY hKeyDst, REGSAM samAdditional);
}; };
@ -234,11 +239,97 @@ private:
class COpRegKeyDelete : public COpRegKeySingle class COpRegKeyDelete : public COpRegKeySingle
{ {
public: public:
COpRegKeyDelete(HKEY hKey = NULL, LPCWSTR pszKeyName = L"", int iTicks = 0); COpRegKeyDelete(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession); virtual HRESULT Execute(CSession *pSession);
private: private:
static LONG DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM sam); static LONG DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM samAdditional);
};
////////////////////////////////////////////////////////////////////////////
// COpRegValueSingle
////////////////////////////////////////////////////////////////////////////
class COpRegValueSingle : public COpRegKeySingle
{
public:
COpRegValueSingle(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueName = L"", int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSingle &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSingle &op);
protected:
ATL::CAtlStringW m_sValueName;
};
////////////////////////////////////////////////////////////////////////////
// COpRegValueSrcDst
////////////////////////////////////////////////////////////////////////////
class COpRegValueSrcDst : public COpRegKeySingle
{
public:
COpRegValueSrcDst(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueNameSrc = L"", LPCWSTR pszValueNameDst = L"", int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSrcDst &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSrcDst &op);
protected:
ATL::CAtlStringW m_sValueName1;
ATL::CAtlStringW m_sValueName2;
};
////////////////////////////////////////////////////////////////////////////
// COpRegValueCreate
////////////////////////////////////////////////////////////////////////////
class COpRegValueCreate : public COpRegValueSingle
{
public:
COpRegValueCreate(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueName = L"", int iTicks = 0);
COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, DWORD dwData, int iTicks = 0);
COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCVOID lpData, SIZE_T nSize, int iTicks = 0);
COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCWSTR pszData, int iTicks = 0);
COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, DWORDLONG qwData, int iTicks = 0);
virtual HRESULT Execute(CSession *pSession);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueCreate &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueCreate &op);
protected:
DWORD m_dwType;
ATL::CAtlStringW m_sData;
ATL::CAtlArray<BYTE> m_binData;
DWORD m_dwData;
ATL::CAtlArray<WCHAR> m_szData;
DWORDLONG m_qwData;
};
////////////////////////////////////////////////////////////////////////////
// COpRegValueCopy
////////////////////////////////////////////////////////////////////////////
class COpRegValueCopy : public COpRegValueSrcDst
{
public:
COpRegValueCopy(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueNameSrc = L"", LPCWSTR pszValueNameDst = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// COpRegValueDelete
////////////////////////////////////////////////////////////////////////////
class COpRegValueDelete : public COpRegValueSingle
{
public:
COpRegValueDelete(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueName = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession);
}; };
@ -339,18 +430,24 @@ public:
protected: protected:
enum OPERATION { enum OPERATION {
OPERATION_ENABLE_ROLLBACK = 1, OP_ROLLBACK_ENABLE = 1,
OPERATION_DELETE_FILE, OP_FILE_DELETE,
OPERATION_MOVE_FILE, OP_FILE_MOVE,
OPERATION_CREATE_TASK, OP_REG_KEY_CREATE,
OPERATION_DELETE_TASK, OP_REG_KEY_COPY,
OPERATION_ENABLE_TASK, OP_REG_KEY_DELETE,
OPERATION_COPY_TASK, OP_REG_VALUE_CREATE,
OPERATION_SUBLIST OP_REG_VALUE_COPY,
OP_REG_VALUE_DELETE,
OP_TASK_CREATE,
OP_TASK_DELETE,
OP_TASK_ENABLE,
OP_TASK_COPY,
OP_SUBLIST
}; };
protected: protected:
template <class T, int 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 LoadAndAddTail(ATL::CAtlFile &f);
}; };
@ -653,13 +750,81 @@ namespace AMSICA {
inline HRESULT operator <<(ATL::CAtlFile &f, int i) inline HRESULT operator <<(ATL::CAtlFile &f, int i)
{ {
return f.Write(&i, sizeof(int)); HRESULT hr;
DWORD dwWritten;
hr = f.Write(&i, sizeof(int), &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(int) ? hr : E_FAIL : hr;
} }
inline HRESULT operator >>(ATL::CAtlFile &f, int &i) inline HRESULT operator >>(ATL::CAtlFile &f, int &i)
{ {
return f.Read(&i, sizeof(int)); HRESULT hr;
DWORD dwRead;
hr = f.Read(&i, sizeof(int), dwRead);
return SUCCEEDED(hr) ? dwRead == sizeof(int) ? hr : E_FAIL : hr;
}
inline HRESULT operator <<(ATL::CAtlFile &f, DWORDLONG i)
{
HRESULT hr;
DWORD dwWritten;
hr = f.Write(&i, sizeof(DWORDLONG), &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(DWORDLONG) ? hr : E_FAIL : hr;
}
inline HRESULT operator >>(ATL::CAtlFile &f, DWORDLONG &i)
{
HRESULT hr;
DWORD dwRead;
hr = f.Read(&i, sizeof(DWORDLONG), dwRead);
return SUCCEEDED(hr) ? dwRead == sizeof(DWORDLONG) ? hr : E_FAIL : hr;
}
template <class E>
inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlArray<E> &a)
{
assert(a.GetCount() <= INT_MAX);
HRESULT hr;
DWORD dwCount = (DWORD)a.GetCount(), dwWritten;
// Write element count.
hr = f.Write(&dwCount, sizeof(DWORD), &dwWritten);
if (FAILED(hr)) return hr;
if (dwWritten < sizeof(DWORD)) return E_FAIL;
// Write data.
hr = f.Write(a.GetData(), sizeof(E) * dwCount, &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(E) * dwCount ? hr : E_FAIL : hr;
}
template <class E>
inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlArray<E> &a)
{
HRESULT hr;
DWORD dwCount, dwRead;
// Read element count as 32-bit integer.
hr = f.Read(&dwCount, sizeof(DWORD), dwRead);
if (FAILED(hr)) return hr;
if (dwRead < sizeof(DWORD)) return E_FAIL;
// Allocate the buffer.
if (!a.SetCount(dwCount)) return E_OUTOFMEMORY;
// Read data.
hr = f.Read(a.GetData(), sizeof(E) * dwCount, dwRead);
if (SUCCEEDED(hr)) a.SetCount(dwRead / sizeof(E));
return hr;
} }
@ -667,13 +832,16 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlStringA &str)
{ {
HRESULT hr; HRESULT hr;
int iLength = str.GetLength(); int iLength = str.GetLength();
DWORD dwWritten;
// Write string length (in characters) as 32-bit integer. // Write string length (in characters) as 32-bit integer.
hr = f.Write(&iLength, sizeof(int)); hr = f.Write(&iLength, sizeof(int), &dwWritten);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwWritten < sizeof(int)) return E_FAIL;
// Write string data (without terminator). // Write string data (without terminator).
return f.Write((LPCSTR)str, sizeof(CHAR) * iLength); hr = f.Write((LPCSTR)str, sizeof(CHAR) * iLength, &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(CHAR) * iLength ? hr : E_FAIL : hr;
} }
@ -682,18 +850,20 @@ inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlStringA &str)
HRESULT hr; HRESULT hr;
int iLength; int iLength;
LPSTR buf; LPSTR buf;
DWORD dwRead;
// Read string length (in characters) as 32-bit integer. // Read string length (in characters) as 32-bit integer.
hr = f.Read(&iLength, sizeof(int)); hr = f.Read(&iLength, sizeof(int), dwRead);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwRead < sizeof(int)) return E_FAIL;
// Allocate the buffer. // Allocate the buffer.
buf = str.GetBuffer(iLength); buf = str.GetBuffer(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); hr = f.Read(buf, sizeof(CHAR) * iLength, dwRead);
str.ReleaseBuffer(SUCCEEDED(hr) ? iLength : 0); str.ReleaseBuffer(SUCCEEDED(hr) ? dwRead / sizeof(CHAR) : 0);
return hr; return hr;
} }
@ -702,13 +872,16 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlStringW &str)
{ {
HRESULT hr; HRESULT hr;
int iLength = str.GetLength(); int iLength = str.GetLength();
DWORD dwWritten;
// Write string length (in characters) as 32-bit integer. // Write string length (in characters) as 32-bit integer.
hr = f.Write(&iLength, sizeof(int)); hr = f.Write(&iLength, sizeof(int), &dwWritten);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwWritten < sizeof(int)) return E_FAIL;
// Write string data (without terminator). // Write string data (without terminator).
return f.Write((LPCWSTR)str, sizeof(WCHAR) * iLength); hr = f.Write((LPCWSTR)str, sizeof(WCHAR) * iLength, &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(WCHAR) * iLength ? hr : E_FAIL : hr;
} }
@ -717,31 +890,41 @@ inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlStringW &str)
HRESULT hr; HRESULT hr;
int iLength; int iLength;
LPWSTR buf; LPWSTR buf;
DWORD dwRead;
// Read string length (in characters) as 32-bit integer. // Read string length (in characters) as 32-bit integer.
hr = f.Read(&iLength, sizeof(int)); hr = f.Read(&iLength, sizeof(int), dwRead);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (dwRead < sizeof(int)) return E_FAIL;
// Allocate the buffer. // Allocate the buffer.
buf = str.GetBuffer(iLength); buf = str.GetBuffer(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(WCHAR) * iLength); hr = f.Read(buf, sizeof(WCHAR) * iLength, dwRead);
str.ReleaseBuffer(SUCCEEDED(hr) ? iLength : 0); str.ReleaseBuffer(SUCCEEDED(hr) ? dwRead / sizeof(WCHAR) : 0);
return hr; return hr;
} }
inline HRESULT operator <<(ATL::CAtlFile &f, const TASK_TRIGGER &ttData) inline HRESULT operator <<(ATL::CAtlFile &f, const TASK_TRIGGER &ttData)
{ {
return f.Write(&ttData, sizeof(TASK_TRIGGER)); HRESULT hr;
DWORD dwWritten;
hr = f.Write(&ttData, sizeof(TASK_TRIGGER), &dwWritten);
return SUCCEEDED(hr) ? dwWritten == sizeof(TASK_TRIGGER) ? hr : E_FAIL : hr;
} }
inline HRESULT operator >>(ATL::CAtlFile &f, TASK_TRIGGER &ttData) inline HRESULT operator >>(ATL::CAtlFile &f, TASK_TRIGGER &ttData)
{ {
return f.Read(&ttData, sizeof(TASK_TRIGGER)); HRESULT hr;
DWORD dwRead;
hr = f.Read(&ttData, sizeof(TASK_TRIGGER), dwRead);
return SUCCEEDED(hr) ? dwRead == sizeof(TASK_TRIGGER) ? hr : E_FAIL : hr;
} }
@ -761,10 +944,10 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSingleString &op)
{ {
HRESULT hr; HRESULT hr;
hr = f << (const COperation &)op; hr = f << (const COperation &)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f << op.m_sValue; if (FAILED(hr)) return hr;
return f << op.m_sValue; return S_OK;
} }
@ -772,10 +955,10 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSingleString &op)
{ {
HRESULT hr; HRESULT hr;
hr = f >> (COperation &)op; hr = f >> (COperation &)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f >> op.m_sValue; if (FAILED(hr)) return hr;
return f >> op.m_sValue; return S_OK;
} }
@ -783,13 +966,11 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSrcDstString &op)
{ {
HRESULT hr; HRESULT hr;
hr = f << (const COperation &)op; hr = f << (const COperation &)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f << op.m_sValue1; if (FAILED(hr)) return hr;
hr = f << op.m_sValue2; if (FAILED(hr)) return hr;
hr = f << op.m_sValue1; return S_OK;
if (FAILED(hr)) return hr;
return f << op.m_sValue2;
} }
@ -797,13 +978,11 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSrcDstString &op)
{ {
HRESULT hr; HRESULT hr;
hr = f >> (COperation &)op; hr = f >> (COperation &)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f >> op.m_sValue1; if (FAILED(hr)) return hr;
hr = f >> op.m_sValue2; if (FAILED(hr)) return hr;
hr = f >> op.m_sValue1; return S_OK;
if (FAILED(hr)) return hr;
return f >> op.m_sValue2;
} }
@ -811,10 +990,10 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeBoolean &op)
{ {
HRESULT hr; HRESULT hr;
hr = f << (const COperation &)op; hr = f << (const COperation &)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f << (int)(op.m_bValue); if (FAILED(hr)) return hr;
return f << (int)op.m_bValue; return S_OK;
} }
@ -823,18 +1002,13 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeBoolean &op)
HRESULT hr; HRESULT hr;
int iValue; int iValue;
hr = f >> (COperation &)op; hr = f >> (COperation &)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f >> iValue; if (FAILED(hr)) return hr; op.m_bValue = iValue ? TRUE : FALSE;
hr = f >> iValue;
if (FAILED(hr)) return hr;
op.m_bValue = iValue ? TRUE : FALSE;
return S_OK; return S_OK;
} }
inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegKeySingle &op) inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegKeySingle &op)
{ {
HRESULT hr; HRESULT hr;
@ -881,6 +1055,96 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpRegKeySrcDst &op)
} }
inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSingle &op)
{
HRESULT hr;
hr = f << (const COpRegKeySingle &)op; if (FAILED(hr)) return hr;
hr = f << op.m_sValueName; if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSingle &op)
{
HRESULT hr;
hr = f >> (COpRegKeySingle &)op; if (FAILED(hr)) return hr;
hr = f >> op.m_sValueName; if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSrcDst &op)
{
HRESULT hr;
hr = f << (const COpRegKeySingle &)op; if (FAILED(hr)) return hr;
hr = f << op.m_sValueName1; if (FAILED(hr)) return hr;
hr = f << op.m_sValueName2; if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSrcDst &op)
{
HRESULT hr;
hr = f >> (COpRegKeySingle &)op; if (FAILED(hr)) return hr;
hr = f >> op.m_sValueName1; if (FAILED(hr)) return hr;
hr = f >> op.m_sValueName2; if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueCreate &op)
{
HRESULT hr;
hr = f << (const COpRegValueSingle &)op; if (FAILED(hr)) return hr;
hr = f << (int)(op.m_dwType); if (FAILED(hr)) return hr;
switch (op.m_dwType) {
case REG_SZ:
case REG_EXPAND_SZ:
case REG_LINK: hr = f << op.m_sData; if (FAILED(hr)) return hr; break;
case REG_BINARY: hr = f << op.m_binData; if (FAILED(hr)) return hr; break;
case REG_DWORD_LITTLE_ENDIAN:
case REG_DWORD_BIG_ENDIAN: hr = f << (int)(op.m_dwData); if (FAILED(hr)) return hr; break;
case REG_MULTI_SZ: hr = f << op.m_szData; if (FAILED(hr)) return hr; break;
case REG_QWORD_LITTLE_ENDIAN: hr = f << op.m_qwData; if (FAILED(hr)) return hr; break;
default: assert(0); return E_UNEXPECTED;
}
return S_OK;
}
inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueCreate &op)
{
HRESULT hr;
hr = f >> (COpRegValueSingle &)op; if (FAILED(hr)) return hr;
hr = f >> (int&)(op.m_dwType); if (FAILED(hr)) return hr;
switch (op.m_dwType) {
case REG_SZ:
case REG_EXPAND_SZ:
case REG_LINK: hr = f >> op.m_sData; if (FAILED(hr)) return hr; break;
case REG_BINARY: hr = f >> op.m_binData; if (FAILED(hr)) return hr; break;
case REG_DWORD_LITTLE_ENDIAN:
case REG_DWORD_BIG_ENDIAN: hr = f >> (int&)(op.m_dwData); if (FAILED(hr)) return hr; break;
case REG_MULTI_SZ: hr = f >> op.m_szData; if (FAILED(hr)) return hr; break;
case REG_QWORD_LITTLE_ENDIAN: hr = f >> op.m_qwData; if (FAILED(hr)) return hr; break;
default: assert(0); return E_UNEXPECTED;
}
return S_OK;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op) inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op)
{ {
HRESULT hr; HRESULT hr;
@ -892,13 +1156,13 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op)
hr = f << op.m_sWorkingDirectory; if (FAILED(hr)) return hr; hr = f << op.m_sWorkingDirectory; if (FAILED(hr)) return hr;
hr = f << op.m_sAuthor; if (FAILED(hr)) return hr; hr = f << op.m_sAuthor; if (FAILED(hr)) return hr;
hr = f << op.m_sComment; if (FAILED(hr)) return hr; hr = f << op.m_sComment; if (FAILED(hr)) return hr;
hr = f << (int)op.m_dwFlags; if (FAILED(hr)) return hr; hr = f << (int)(op.m_dwFlags); if (FAILED(hr)) return hr;
hr = f << (int)op.m_dwPriority; if (FAILED(hr)) return hr; hr = f << (int)(op.m_dwPriority); if (FAILED(hr)) return hr;
hr = f << op.m_sAccountName; if (FAILED(hr)) return hr; hr = f << op.m_sAccountName; if (FAILED(hr)) return hr;
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.GetCount()); if (FAILED(hr)) return hr;
for (pos = op.m_lTriggers.GetHeadPosition(); pos;) { for (pos = op.m_lTriggers.GetHeadPosition(); pos;) {
hr = f << op.m_lTriggers.GetNext(pos); hr = f << op.m_lTriggers.GetNext(pos);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
@ -941,10 +1205,10 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskEnable &op)
{ {
HRESULT hr; HRESULT hr;
hr = f << (const COpTypeSingleString&)op; hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f << (int)(op.m_bEnable); if (FAILED(hr)) return hr;
return f << (int)op.m_bEnable; return S_OK;
} }
@ -953,12 +1217,8 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskEnable &op)
HRESULT hr; HRESULT hr;
int iTemp; int iTemp;
hr = f >> (COpTypeSingleString&)op; hr = f >> (COpTypeSingleString&)op; if (FAILED(hr)) return hr;
if (FAILED(hr)) return hr; hr = f >> iTemp; if (FAILED(hr)) return hr; op.m_bEnable = iTemp ? TRUE : FALSE;
hr = f >> iTemp;
if (FAILED(hr)) return hr;
op.m_bEnable = iTemp ? TRUE : FALSE;
return S_OK; return S_OK;
} }
@ -972,27 +1232,39 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &list)
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.GetCount());
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
for (pos = list.GetHeadPosition(); pos;) { for (pos = list.GetHeadPosition(); pos;) {
const COperation *pOp = list.GetNext(pos); const COperation *pOp = list.GetNext(pos);
if (dynamic_cast<const COpRollbackEnable*>(pOp)) if (dynamic_cast<const COpRollbackEnable*>(pOp))
hr = list.Save<COpRollbackEnable, COpList::OPERATION_ENABLE_ROLLBACK>(f, pOp); hr = list.Save<COpRollbackEnable, COpList::OP_ROLLBACK_ENABLE>(f, pOp);
else if (dynamic_cast<const COpFileDelete*>(pOp)) else if (dynamic_cast<const COpFileDelete*>(pOp))
hr = list.Save<COpFileDelete, COpList::OPERATION_DELETE_FILE>(f, pOp); hr = list.Save<COpFileDelete, COpList::OP_FILE_DELETE>(f, pOp);
else if (dynamic_cast<const COpFileMove*>(pOp)) else if (dynamic_cast<const COpFileMove*>(pOp))
hr = list.Save<COpFileMove, COpList::OPERATION_MOVE_FILE>(f, pOp); hr = list.Save<COpFileMove, COpList::OP_FILE_MOVE>(f, pOp);
else if (dynamic_cast<const COpRegKeyCreate*>(pOp))
hr = list.Save<COpRegKeyCreate, COpList::OP_REG_KEY_CREATE>(f, pOp);
else if (dynamic_cast<const COpRegKeyCopy*>(pOp))
hr = list.Save<COpRegKeyCopy, COpList::OP_REG_KEY_COPY>(f, pOp);
else if (dynamic_cast<const COpRegKeyDelete*>(pOp))
hr = list.Save<COpRegKeyDelete, COpList::OP_REG_KEY_DELETE>(f, pOp);
else if (dynamic_cast<const COpRegValueCreate*>(pOp))
hr = list.Save<COpRegValueCreate, COpList::OP_REG_VALUE_CREATE>(f, pOp);
else if (dynamic_cast<const COpRegValueCopy*>(pOp))
hr = list.Save<COpRegValueCopy, COpList::OP_REG_VALUE_COPY>(f, pOp);
else if (dynamic_cast<const COpRegValueDelete*>(pOp))
hr = list.Save<COpRegValueDelete, COpList::OP_REG_VALUE_DELETE>(f, pOp);
else if (dynamic_cast<const COpTaskCreate*>(pOp)) else if (dynamic_cast<const COpTaskCreate*>(pOp))
hr = list.Save<COpTaskCreate, COpList::OPERATION_CREATE_TASK>(f, pOp); hr = list.Save<COpTaskCreate, COpList::OP_TASK_CREATE>(f, pOp);
else if (dynamic_cast<const COpTaskDelete*>(pOp)) else if (dynamic_cast<const COpTaskDelete*>(pOp))
hr = list.Save<COpTaskDelete, COpList::OPERATION_DELETE_TASK>(f, pOp); hr = list.Save<COpTaskDelete, COpList::OP_TASK_DELETE>(f, pOp);
else if (dynamic_cast<const COpTaskEnable*>(pOp)) else if (dynamic_cast<const COpTaskEnable*>(pOp))
hr = list.Save<COpTaskEnable, COpList::OPERATION_ENABLE_TASK>(f, pOp); hr = list.Save<COpTaskEnable, COpList::OP_TASK_ENABLE>(f, pOp);
else if (dynamic_cast<const COpTaskCopy*>(pOp)) else if (dynamic_cast<const COpTaskCopy*>(pOp))
hr = list.Save<COpTaskCopy, COpList::OPERATION_COPY_TASK>(f, pOp); hr = list.Save<COpTaskCopy, COpList::OP_TASK_COPY>(f, pOp);
else if (dynamic_cast<const COpList*>(pOp)) else if (dynamic_cast<const COpList*>(pOp))
hr = list.Save<COpList, COpList::OPERATION_SUBLIST>(f, pOp); hr = list.Save<COpList, COpList::OP_SUBLIST>(f, pOp);
else { else {
// Unsupported type of operation. // Unsupported type of operation.
assert(0); assert(0);
@ -1009,43 +1281,61 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &list)
inline HRESULT operator >>(ATL::CAtlFile &f, COpList &list) inline HRESULT operator >>(ATL::CAtlFile &f, COpList &list)
{ {
HRESULT hr; HRESULT hr;
DWORD dwCount; int iCount;
hr = f >> (COperation &)list; hr = f >> (COperation &)list;
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
hr = f >> (int&)dwCount; hr = f >> iCount;
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
while (dwCount--) { while (iCount--) {
int iTemp; int iTemp;
hr = f >> iTemp; hr = f >> iTemp;
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
switch ((COpList::OPERATION)iTemp) { switch ((COpList::OPERATION)iTemp) {
case COpList::OPERATION_ENABLE_ROLLBACK: case COpList::OP_ROLLBACK_ENABLE:
hr = list.LoadAndAddTail<COpRollbackEnable>(f); hr = list.LoadAndAddTail<COpRollbackEnable>(f);
break; break;
case COpList::OPERATION_DELETE_FILE: case COpList::OP_FILE_DELETE:
hr = list.LoadAndAddTail<COpFileDelete>(f); hr = list.LoadAndAddTail<COpFileDelete>(f);
break; break;
case COpList::OPERATION_MOVE_FILE: case COpList::OP_FILE_MOVE:
hr = list.LoadAndAddTail<COpFileMove>(f); hr = list.LoadAndAddTail<COpFileMove>(f);
break; break;
case COpList::OPERATION_CREATE_TASK: case COpList::OP_REG_KEY_CREATE:
hr = list.LoadAndAddTail<COpRegKeyCreate>(f);
break;
case COpList::OP_REG_KEY_COPY:
hr = list.LoadAndAddTail<COpRegKeyCopy>(f);
break;
case COpList::OP_REG_KEY_DELETE:
hr = list.LoadAndAddTail<COpRegKeyDelete>(f);
break;
case COpList::OP_REG_VALUE_CREATE:
hr = list.LoadAndAddTail<COpRegValueCreate>(f);
break;
case COpList::OP_REG_VALUE_COPY:
hr = list.LoadAndAddTail<COpRegValueCopy>(f);
break;
case COpList::OP_REG_VALUE_DELETE:
hr = list.LoadAndAddTail<COpRegValueDelete>(f);
break;
case COpList::OP_TASK_CREATE:
hr = list.LoadAndAddTail<COpTaskCreate>(f); hr = list.LoadAndAddTail<COpTaskCreate>(f);
break; break;
case COpList::OPERATION_DELETE_TASK: case COpList::OP_TASK_DELETE:
hr = list.LoadAndAddTail<COpTaskDelete>(f); hr = list.LoadAndAddTail<COpTaskDelete>(f);
break; break;
case COpList::OPERATION_ENABLE_TASK: case COpList::OP_TASK_ENABLE:
hr = list.LoadAndAddTail<COpTaskEnable>(f); hr = list.LoadAndAddTail<COpTaskEnable>(f);
break; break;
case COpList::OPERATION_COPY_TASK: case COpList::OP_TASK_COPY:
hr = list.LoadAndAddTail<COpTaskCopy>(f); hr = list.LoadAndAddTail<COpTaskCopy>(f);
break; break;
case COpList::OPERATION_SUBLIST: case COpList::OP_SUBLIST:
hr = list.LoadAndAddTail<COpList>(f); hr = list.LoadAndAddTail<COpList>(f);
break; break;
default: default:
@ -1103,7 +1393,7 @@ inline BOOL IsWow64Process()
// Inline methods // Inline methods
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
template <class T, int ID> inline static HRESULT COpList::Save(ATL::CAtlFile &f, const COperation *p) template <class T, enum COpList::OPERATION ID> inline static HRESULT COpList::Save(ATL::CAtlFile &f, const COperation *p)
{ {
assert(p); assert(p);
HRESULT hr; HRESULT hr;

View File

@ -31,6 +31,10 @@ Error Error
Error Message Error Message
i2 L0 i2 L0
1250 Error Error 1250 Error Error
2550 Pri odpiranju namestitvenega paketa je prišlo do napake. Obrnite se na svojo tehnično službo.
2552 Pri pisanju v datoteko seznama opravil »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo.
2560 Pri branju iz datoteke seznama opravil »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo.
2553 Pri nastavljanju parametra »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo.
2554 Pri brisanju datoteke »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. 2554 Pri brisanju datoteke »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo.
2555 Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na svojo tehnično službo. 2555 Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na svojo tehnično službo.
2556 Pri ustvarjanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. 2556 Pri ustvarjanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo.

View File

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: MSITSCA\n" "Project-Id-Version: MSITSCA\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-04-26 11:07+0100\n" "POT-Creation-Date: 2013-06-07 21:16+0100\n"
"PO-Revision-Date: \n" "PO-Revision-Date: \n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n" "Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Amebis, d. o. o., Kamnik <simon.rozman@amebis.si>\n" "Language-Team: Amebis, d. o. o., Kamnik <simon.rozman@amebis.si>\n"
@ -19,20 +19,25 @@ msgstr ""
# Privzeta kodna stran ANSI za ta jezik (desetiško) # Privzeta kodna stran ANSI za ta jezik (desetiško)
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:3 ..\msm/Sl.DebugU.x64.Error-2.idtx:3 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:3 ..\msm/Sl.DebugU.x64.Error-2.idtx:3
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:3
msgid "1250" msgid "1250"
msgstr "1252" msgstr "1252"
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:4 ..\msm/Sl.DebugU.x64.Error-2.idtx:4 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:6 ..\msm/Sl.DebugU.x64.Error-2.idtx:6
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:4 msgid ""
"Pri branju iz datoteke seznama opravil »[2]« je prišlo do napake [3]. "
"Obrnite se na svojo tehnično službo."
msgstr ""
"Error [3] reading from \"[2]\" task list file. Please, contact your support "
"personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:8 ..\msm/Sl.DebugU.x64.Error-2.idtx:8
msgid "" msgid ""
"Pri brisanju datoteke »[2]« je prišlo do napake [3]. Obrnite se na svojo " "Pri brisanju datoteke »[2]« je prišlo do napake [3]. Obrnite se na svojo "
"tehnično službo." "tehnično službo."
msgstr "" msgstr ""
"Error [3] deleting \"[2]\" file. Please, contact your support personnel." "Error [3] deleting \"[2]\" file. Please, contact your support personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:7 ..\msm/Sl.DebugU.x64.Error-2.idtx:7 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:11 ..\msm/Sl.DebugU.x64.Error-2.idtx:11
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:7
msgid "" msgid ""
"Pri brisanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite " "Pri brisanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite "
"se na svojo tehnično službo." "se na svojo tehnično službo."
@ -40,8 +45,7 @@ msgstr ""
"Error [3] deleting \"[2]\" scheduled task. Please, contact your support " "Error [3] deleting \"[2]\" scheduled task. Please, contact your support "
"personnel." "personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:9 ..\msm/Sl.DebugU.x64.Error-2.idtx:9 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:13 ..\msm/Sl.DebugU.x64.Error-2.idtx:13
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:9
msgid "" msgid ""
"Pri kopiranju razporejenega opravila »[2]« v »[3]« je prišlo do napake [4]. " "Pri kopiranju razporejenega opravila »[2]« v »[3]« je prišlo do napake [4]. "
"Obrnite se na svojo tehnično službo." "Obrnite se na svojo tehnično službo."
@ -49,8 +53,14 @@ msgstr ""
"Error [4] copying \"[2]\" scheduled task to \"[3]\". Please, contact your " "Error [4] copying \"[2]\" scheduled task to \"[3]\". Please, contact your "
"support personnel." "support personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:8 ..\msm/Sl.DebugU.x64.Error-2.idtx:8 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:7 ..\msm/Sl.DebugU.x64.Error-2.idtx:7
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:8 msgid ""
"Pri nastavljanju parametra »[2]« je prišlo do napake [3]. Obrnite se na "
"svojo tehnično službo."
msgstr ""
"Error [3] setting \"[2]\" parameter. Please, contact your support personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:12 ..\msm/Sl.DebugU.x64.Error-2.idtx:12
msgid "" msgid ""
"Pri o(ne)mogočanju razporejenega opravila »[2]« je prišlo do napake [3]. " "Pri o(ne)mogočanju razporejenega opravila »[2]« je prišlo do napake [3]. "
"Obrnite se na svojo tehnično službo." "Obrnite se na svojo tehnično službo."
@ -58,8 +68,22 @@ msgstr ""
"Error [3] enabling/disabling \"[2]\" scheduled task. Please, contact your " "Error [3] enabling/disabling \"[2]\" scheduled task. Please, contact your "
"support personnel." "support personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:4 ..\msm/Sl.DebugU.x64.Error-2.idtx:4
msgid ""
"Pri odpiranju namestitvenega paketa je prišlo do napake. Obrnite se na svojo "
"tehnično službo."
msgstr ""
"Error opening installation package. Please, contact your support personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:5 ..\msm/Sl.DebugU.x64.Error-2.idtx:5 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:5 ..\msm/Sl.DebugU.x64.Error-2.idtx:5
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:5 msgid ""
"Pri pisanju v datoteko seznama opravil »[2]« je prišlo do napake [3]. "
"Obrnite se na svojo tehnično službo."
msgstr ""
"Error [3] writing to \"[2]\" task list file. Please, contact your support "
"personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:9 ..\msm/Sl.DebugU.x64.Error-2.idtx:9
msgid "" msgid ""
"Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na " "Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na "
"svojo tehnično službo." "svojo tehnično službo."
@ -67,8 +91,7 @@ msgstr ""
"Error [4] moving \"[2]\" file to \"[3]\". Please, contact your support " "Error [4] moving \"[2]\" file to \"[3]\". Please, contact your support "
"personnel." "personnel."
#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:6 ..\msm/Sl.DebugU.x64.Error-2.idtx:6 #: ..\msm/Sl.DebugU.Win32.Error-2.idtx:10 ..\msm/Sl.DebugU.x64.Error-2.idtx:10
#: ..\msm/Sl.ReleaseU.Win32.Error-2.idtx:6
msgid "" msgid ""
"Pri ustvarjanju razporejenega opravila »[2]« je prišlo do napake [3]. " "Pri ustvarjanju razporejenega opravila »[2]« je prišlo do napake [3]. "
"Obrnite se na svojo tehnično službo." "Obrnite se na svojo tehnično službo."

View File

@ -1,5 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#pragma comment(lib, "msi.lib")
namespace AMSICA { namespace AMSICA {
@ -25,7 +27,7 @@ COpTypeSingleString::COpTypeSingleString(LPCWSTR pszValue, int iTicks) :
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// COpDoubleStringOperation // COpTypeSrcDstString
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
COpTypeSrcDstString::COpTypeSrcDstString(LPCWSTR pszValue1, LPCWSTR pszValue2, int iTicks) : COpTypeSrcDstString::COpTypeSrcDstString(LPCWSTR pszValue1, LPCWSTR pszValue2, int iTicks) :

View File

@ -1,5 +1,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#pragma comment(lib, "mstask.lib")
#pragma comment(lib, "taskschd.lib") #pragma comment(lib, "taskschd.lib")

View File

@ -43,8 +43,6 @@ HRESULT COpRegKeyCreate::Execute(CSession *pSession)
ATL::CAtlStringW sPartialName; ATL::CAtlStringW sPartialName;
int iStart = 0; int iStart = 0;
assert(0); // TODO: Preizkusi ta del kode.
#ifndef _WIN64 #ifndef _WIN64
if (IsWow64Process()) { if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too. // 32-bit processes run as WOW64 should use 64-bit registry too.
@ -114,8 +112,6 @@ HRESULT COpRegKeyCopy::Execute(CSession *pSession)
LONG lResult; LONG lResult;
REGSAM samAdditional = 0; REGSAM samAdditional = 0;
assert(0); // TODO: Preizkusi ta del kode.
{ {
// 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.
@ -154,11 +150,143 @@ HRESULT COpRegKeyCopy::Execute(CSession *pSession)
} }
LONG COpRegKeyCopy::CopyKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPCWSTR pszKeyNameDst, REGSAM samAdditional)
{
LONG lResult;
HKEY hKeySrc, hKeyDst;
// Open source key.
lResult = ::RegOpenKeyExW(hKeyRoot, pszKeyNameSrc, 0, READ_CONTROL | KEY_READ | samAdditional, &hKeySrc);
if (lResult != ERROR_SUCCESS) return lResult;
{
DWORD dwSecurityDescriptorSize, dwClassLen = MAX_PATH;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
LPWSTR pszClass = new WCHAR[dwClassLen];
// Get source key class length and security descriptor size.
lResult = ::RegQueryInfoKeyW(hKeySrc, pszClass, &dwClassLen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSecurityDescriptorSize, NULL);
if (lResult != ERROR_SUCCESS) {
delete [] pszClass;
return lResult;
}
pszClass[dwClassLen] = 0;
// Get source key security descriptor.
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(new BYTE[dwSecurityDescriptorSize]);
lResult = ::RegGetKeySecurity(hKeySrc, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor, &dwSecurityDescriptorSize);
if (lResult != ERROR_SUCCESS) {
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
delete [] pszClass;
return lResult;
}
// 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);
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
delete [] pszClass;
if (lResult != ERROR_SUCCESS) return lResult;
}
// Copy subkey recursively.
return CopyKeyRecursively(hKeySrc, hKeyDst, samAdditional);
}
LONG COpRegKeyCopy::CopyKeyRecursively(HKEY hKeySrc, HKEY hKeyDst, REGSAM samAdditional)
{
LONG lResult;
DWORD dwMaxSubKeyLen, dwMaxValueNameLen, dwMaxClassLen, dwMaxDataSize, dwIndex;
LPWSTR pszName, pszClass;
LPBYTE lpData;
// Query the source key.
lResult = ::RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, NULL, &dwMaxSubKeyLen, &dwMaxClassLen, NULL, &dwMaxValueNameLen, &dwMaxDataSize, NULL, NULL);
if (lResult != ERROR_SUCCESS) return lResult;
// Copy values first.
dwMaxValueNameLen++;
pszName = new WCHAR[dwMaxValueNameLen];
lpData = new BYTE[dwMaxDataSize];
for (dwIndex = 0; ; dwIndex++) {
DWORD dwNameLen = dwMaxValueNameLen, dwType, dwValueSize = dwMaxDataSize;
// Read value.
lResult = ::RegEnumValueW(hKeySrc, dwIndex, pszName, &dwNameLen, NULL, &dwType, lpData, &dwValueSize);
if (lResult == ERROR_NO_MORE_ITEMS) {
lResult = ERROR_SUCCESS;
break;
} else if (lResult != ERROR_SUCCESS)
break;
// Save value.
lResult = ::RegSetValueExW(hKeyDst, pszName, 0, dwType, lpData, dwValueSize);
if (lResult != ERROR_SUCCESS)
break;
}
delete [] lpData;
delete [] pszName;
if (lResult != ERROR_SUCCESS) return lResult;
// Iterate over all subkeys and copy them.
dwMaxSubKeyLen++;
pszName = new WCHAR[dwMaxSubKeyLen];
dwMaxClassLen++;
pszClass = new WCHAR[dwMaxClassLen];
for (dwIndex = 0; ; dwIndex++) {
DWORD dwNameLen = dwMaxSubKeyLen, dwClassLen = dwMaxClassLen;
HKEY hKeySrcSub, hKeyDstSub;
// Read subkey.
lResult = ::RegEnumKeyExW(hKeySrc, dwIndex, pszName, &dwNameLen, NULL, pszClass, &dwClassLen, NULL);
if (lResult == ERROR_NO_MORE_ITEMS) {
lResult = ERROR_SUCCESS;
break;
} else if (lResult != ERROR_SUCCESS)
break;
// Open source subkey.
lResult = ::RegOpenKeyExW(hKeySrc, pszName, 0, READ_CONTROL | KEY_READ | samAdditional, &hKeySrcSub);
if (lResult != ERROR_SUCCESS) break;
{
DWORD dwSecurityDescriptorSize;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
// Get source subkey security descriptor size.
lResult = ::RegQueryInfoKeyW(hKeySrcSub, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSecurityDescriptorSize, NULL);
if (lResult != ERROR_SUCCESS) break;
// Get source subkey security descriptor.
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(new BYTE[dwSecurityDescriptorSize]);
lResult = ::RegGetKeySecurity(hKeySrc, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor, &dwSecurityDescriptorSize);
if (lResult != ERROR_SUCCESS) {
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
break;
}
// 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);
delete [] (LPBYTE)(sa.lpSecurityDescriptor);
if (lResult != ERROR_SUCCESS) break;
}
// Copy subkey recursively.
lResult = CopyKeyRecursively(hKeySrcSub, hKeyDstSub, samAdditional);
if (lResult != ERROR_SUCCESS) break;
}
delete [] pszClass;
delete [] pszName;
return lResult;
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// COpRegKeyDelete // COpRegKeyDelete
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
COpRegKeyDelete::COpRegKeyDelete(HKEY hKeyRoot, LPCWSTR m_hKeyRoot, int iTicks) : COpRegKeySingle(hKeyRoot, m_hKeyRoot, iTicks) COpRegKeyDelete::COpRegKeyDelete(HKEY hKey, LPCWSTR pszKeyName, int iTicks) : COpRegKeySingle(hKey, pszKeyName, iTicks)
{ {
} }
@ -167,10 +295,9 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
{ {
assert(pSession); assert(pSession);
LONG lResult; LONG lResult;
HKEY hKey;
REGSAM samAdditional = 0; REGSAM samAdditional = 0;
assert(0); // TODO: Preizkusi ta del kode.
#ifndef _WIN64 #ifndef _WIN64
if (IsWow64Process()) { if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too. // 32-bit processes run as WOW64 should use 64-bit registry too.
@ -178,17 +305,26 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
} }
#endif #endif
// Probe to see if the key exists.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, DELETE | samAdditional, &hKey);
if (lResult == ERROR_SUCCESS) {
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
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; ATL::CAtlStringW sBackupName;
UINT uiCount = 0; UINT uiCount = 0;
int iLength = m_sValue.GetLength();
// Trim trailing backslashes.
while (iLength && m_sValue.GetAt(iLength - 1) == L'\\') iLength--;
for (;;) { for (;;) {
HKEY hKey; HKEY hKey;
sBackupName.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); sBackupName.Format(L"%.*ls (orig %u)", iLength, (LPCWSTR)m_sValue, ++uiCount);
lResult = ::RegOpenKeyExW(m_hKeyRoot, sBackupName, 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey); lResult = ::RegOpenKeyExW(m_hKeyRoot, sBackupName, 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey);
if (lResult != ERROR_SUCCESS) break; if (lResult != ERROR_SUCCESS) break;
verify(::RegCloseKey(hKey)); verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
} }
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.
@ -200,7 +336,7 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
pSession->m_olRollback.AddHead(new COpRegKeyCopy(m_hKeyRoot, sBackupName, m_sValue)); pSession->m_olRollback.AddHead(new COpRegKeyCopy(m_hKeyRoot, sBackupName, m_sValue));
// Order commit action to delete backup copy. // Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpRegKeyDelete(m_hKeyRoot, sBackupName, TRUE)); pSession->m_olCommit.AddTail(new COpRegKeyDelete(m_hKeyRoot, sBackupName));
} else { } else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBING_FAILED) == ERROR_SUCCESS); verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBING_FAILED) == ERROR_SUCCESS);
@ -213,8 +349,10 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
} }
// Delete the registry key. // Delete the registry key.
lResult = DeleteKeyRecursively(m_hKeyRoot, m_sValue, KEY_ENUMERATE_SUB_KEYS | samAdditional); lResult = DeleteKeyRecursively(m_hKeyRoot, m_sValue, samAdditional);
if (lResult == ERROR_SUCCESS) }
if (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND)
return S_OK; return S_OK;
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
@ -228,33 +366,39 @@ HRESULT COpRegKeyDelete::Execute(CSession *pSession)
} }
LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM sam) LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM samAdditional)
{ {
HKEY hKey; HKEY hKey;
LONG lResult; LONG lResult;
// Open the key. // Open the key.
lResult = ::RegOpenKeyEx(hKeyRoot, pszKeyName, 0, sam, &hKey); lResult = ::RegOpenKeyExW(hKeyRoot, pszKeyName, 0, DELETE | KEY_READ | samAdditional, &hKey);
if (lResult == ERROR_SUCCESS) { if (lResult == ERROR_SUCCESS) {
DWORD dwMaxSubKeyLen; DWORD dwMaxSubKeyLen;
// Determine the largest subkey name. // Determine the largest subkey name.
lResult = ::RegQueryInfoKey(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 == ERROR_SUCCESS) { if (lResult == ERROR_SUCCESS) {
LPWSTR pszSubKeyName; 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 TCHAR[dwMaxSubKeyLen]; 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; lResult != ERROR_NO_MORE_ITEMS ;) { for (dwIndex = 0; ;) {
lResult = ::RegEnumKeyEx(hKey, dwIndex, pszSubKeyName, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL); DWORD dwNameLen = dwMaxSubKeyLen;
if (lResult == ERROR_SUCCESS) lResult = ::RegEnumKeyExW(hKey, dwIndex, pszSubKeyName, &dwNameLen, NULL, NULL, NULL, NULL);
lResult = DeleteKeyRecursively(hKey, pszSubKeyName, sam); if (lResult == ERROR_SUCCESS) {
else lResult = DeleteKeyRecursively(hKey, pszSubKeyName, samAdditional);
if (lResult != ERROR_SUCCESS)
dwIndex++;
} else if (lResult == ERROR_NO_MORE_ITEMS) {
lResult = ERROR_SUCCESS;
break;
} else
dwIndex++; dwIndex++;
} }
@ -266,7 +410,7 @@ LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, RE
verify(::RegCloseKey(hKey) == ERROR_SUCCESS); verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
// Finally try to delete the key. // Finally try to delete the key.
lResult = ::RegDeleteKeyW(hKeyRoot, pszKeyName); lResult = ::RegDeleteKeyExW(hKeyRoot, pszKeyName, samAdditional, 0);
} else if (lResult == ERROR_FILE_NOT_FOUND) { } else if (lResult == ERROR_FILE_NOT_FOUND) {
// The key doesn't exist. Not really an error in this case. // The key doesn't exist. Not really an error in this case.
lResult = ERROR_SUCCESS; lResult = ERROR_SUCCESS;
@ -276,4 +420,314 @@ LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, RE
} }
////////////////////////////////////////////////////////////////////////////
// COpRegValueSingle
////////////////////////////////////////////////////////////////////////////
COpRegValueSingle::COpRegValueSingle(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, int iTicks) :
m_sValueName(pszValueName),
COpRegKeySingle(hKeyRoot, pszKeyName, iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpRegValueSrcDst
////////////////////////////////////////////////////////////////////////////
COpRegValueSrcDst::COpRegValueSrcDst(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueNameSrc, LPCWSTR pszValueNameDst, int iTicks) :
m_sValueName1(pszValueNameSrc),
m_sValueName2(pszValueNameDst),
COpRegKeySingle(hKeyRoot, pszKeyName, iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpRegValueCreate
////////////////////////////////////////////////////////////////////////////
COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, int iTicks) :
m_dwType(REG_NONE),
COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{
}
COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, DWORD dwData, int iTicks) :
m_dwType(REG_DWORD),
m_dwData(dwData),
COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{
}
COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCVOID lpData, SIZE_T nSize, int iTicks) :
m_dwType(REG_BINARY),
COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{
assert(lpData || !nSize);
verify(m_binData.SetCount(nSize));
memcpy(m_binData.GetData(), lpData, nSize);
}
COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCWSTR pszData, int iTicks) :
m_dwType(REG_SZ),
m_sData(pszData),
COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{
}
COpRegValueCreate::COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, DWORDLONG qwData, int iTicks) :
m_dwType(REG_QWORD),
m_qwData(qwData),
COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{
}
HRESULT COpRegValueCreate::Execute(CSession *pSession)
{
assert(pSession);
LONG lResult;
REGSAM sam = KEY_QUERY_VALUE | STANDARD_RIGHTS_WRITE | KEY_SET_VALUE;
HKEY hKey;
{
// 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.
// Don't worry, COpRegValueDelete::Execute() returns S_OK if key doesn't exist.
COpRegValueDelete opDelete(m_hKeyRoot, m_sValue, m_sValueName);
HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr;
}
#ifndef _WIN64
if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too.
sam |= KEY_WOW64_64KEY;
}
#endif
// Open the key.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, sam, &hKey);
if (lResult == ERROR_SUCCESS) {
if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the value.
pSession->m_olRollback.AddHead(new COpRegValueDelete(m_hKeyRoot, m_sValue, m_sValueName));
}
// Set the registry value.
switch (m_dwType) {
case REG_SZ:
case REG_EXPAND_SZ:
case REG_LINK:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)(LPCWSTR)m_sData, (m_sData.GetLength() + 1) * sizeof(WCHAR)); break;
break;
case REG_BINARY:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, m_binData.GetData(), (DWORD)m_binData.GetCount() * sizeof(BYTE)); break;
case REG_DWORD_LITTLE_ENDIAN:
case REG_DWORD_BIG_ENDIAN:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)&m_dwData, sizeof(DWORD)); break;
break;
case REG_MULTI_SZ:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)m_szData.GetData(), (DWORD)m_szData.GetCount() * sizeof(WCHAR)); break;
break;
case REG_QWORD_LITTLE_ENDIAN:
lResult = ::RegSetValueExW(hKey, m_sValueName, 0, m_dwType, (const BYTE*)&m_qwData, sizeof(DWORDLONG)); break;
break;
default:
assert(0);
lResult = ERROR_UNSUPPORTED_TYPE;
}
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
}
if (lResult == ERROR_SUCCESS)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_SETVALUE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 4, m_sValueName ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 5, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
////////////////////////////////////////////////////////////////////////////
// COpRegValueCopy
////////////////////////////////////////////////////////////////////////////
COpRegValueCopy::COpRegValueCopy(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueNameSrc, LPCWSTR pszValueNameDst, int iTicks) : COpRegValueSrcDst(hKeyRoot, pszKeyName, pszValueNameSrc, pszValueNameDst, iTicks)
{
}
HRESULT COpRegValueCopy::Execute(CSession *pSession)
{
assert(pSession);
LONG lResult;
REGSAM sam = KEY_QUERY_VALUE | KEY_SET_VALUE;
HKEY hKey;
{
// 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.
// Don't worry, COpRegValueDelete::Execute() returns S_OK if key doesn't exist.
COpRegValueDelete opDelete(m_hKeyRoot, m_sValue, m_sValueName2);
HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr;
}
#ifndef _WIN64
if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too.
sam |= KEY_WOW64_64KEY;
}
#endif
// Open the key.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, sam, &hKey);
if (lResult == ERROR_SUCCESS) {
DWORD dwType, dwSize;
// Query the source registry value size.
lResult = ::RegQueryValueExW(hKey, m_sValueName1, 0, NULL, NULL, &dwSize);
if (lResult == ERROR_SUCCESS) {
LPBYTE lpData = new BYTE[dwSize];
assert(lpData);
// Read the source registry value.
lResult = ::RegQueryValueExW(hKey, m_sValueName1, 0, &dwType, lpData, &dwSize);
if (lResult == ERROR_SUCCESS) {
if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the destination copy.
pSession->m_olRollback.AddHead(new COpRegValueDelete(m_hKeyRoot, m_sValue, m_sValueName2));
}
// Store the value to destination.
lResult = ::RegSetValueExW(hKey, m_sValueName2, 0, dwType, lpData, dwSize);
}
delete [] lpData;
}
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
}
if (lResult == ERROR_SUCCESS)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(6);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_COPYVALUE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 4, m_sValueName1 ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 5, m_sValueName2 ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 6, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
////////////////////////////////////////////////////////////////////////////
// COpRegValueDelete
////////////////////////////////////////////////////////////////////////////
COpRegValueDelete::COpRegValueDelete(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, int iTicks) : COpRegValueSingle(hKeyRoot, pszKeyName, pszValueName, iTicks)
{
}
HRESULT COpRegValueDelete::Execute(CSession *pSession)
{
assert(pSession);
LONG lResult;
REGSAM sam = KEY_QUERY_VALUE | KEY_SET_VALUE;
HKEY hKey;
#ifndef _WIN64
if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too.
sam |= KEY_WOW64_64KEY;
}
#endif
// Open the key.
lResult = ::RegOpenKeyExW(m_hKeyRoot, m_sValue, 0, sam, &hKey);
if (lResult == ERROR_SUCCESS) {
DWORD dwType;
// See if the value exists at all.
lResult = ::RegQueryValueExW(hKey, m_sValueName, 0, &dwType, NULL, NULL);
if (lResult == ERROR_SUCCESS) {
if (pSession->m_bRollbackEnabled) {
// Make a backup of the value first.
ATL::CAtlStringW sBackupName;
UINT uiCount = 0;
for (;;) {
sBackupName.Format(L"%ls (orig %u)", (LPCWSTR)m_sValueName, ++uiCount);
lResult = ::RegQueryValueExW(hKey, sBackupName, 0, &dwType, NULL, NULL);
if (lResult != ERROR_SUCCESS) break;
}
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.
COpRegValueCopy opCopy(m_hKeyRoot, m_sValue, m_sValueName, sBackupName);
HRESULT hr = opCopy.Execute(pSession);
if (FAILED(hr)) {
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
return hr;
}
// Order rollback action to restore the key from backup copy.
pSession->m_olRollback.AddHead(new COpRegValueCopy(m_hKeyRoot, m_sValue, sBackupName, m_sValueName));
// Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpRegValueDelete(m_hKeyRoot, m_sValue, sBackupName));
} else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBINGVAL_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, sBackupName ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 4, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
return AtlHresultFromWin32(lResult);
}
}
// Delete the registry value.
lResult = ::RegDeleteValueW(hKey, m_sValueName);
}
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
}
if (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_DELETEVALUE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 4, m_sValueName ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 5, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
} // namespace AMSICA } // namespace AMSICA