diff --git a/atl.vcxproj b/atl.vcxproj
new file mode 100644
index 0000000..70a1826
--- /dev/null
+++ b/atl.vcxproj
@@ -0,0 +1,119 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ libatl
+ {5A4EADF2-3237-457A-9DA8-BB9942A91019}
+ libatl
+ Win32Proj
+
+
+
+ StaticLibrary
+ Unicode
+
+
+ StaticLibrary
+ Unicode
+
+
+ StaticLibrary
+ Unicode
+
+
+ StaticLibrary
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.40219.1
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+
+
+ X64
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/atl.vcxproj.filters b/atl.vcxproj.filters
new file mode 100644
index 0000000..f305a55
--- /dev/null
+++ b/atl.vcxproj.filters
@@ -0,0 +1,47 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/atlcrypt.h b/atlcrypt.h
new file mode 100644
index 0000000..5d08c36
--- /dev/null
+++ b/atlcrypt.h
@@ -0,0 +1,311 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include "atlex.h"
+#include
+#include
+#include
+
+
+inline DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, ATL::CAtlStringA &sNameString)
+{
+ // Query the final string length first.
+ DWORD dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
+
+ // Prepare the buffer to format the string data into and read it.
+ LPSTR szBuffer = sNameString.GetBuffer(dwSize);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, szBuffer, dwSize);
+ sNameString.ReleaseBuffer(dwSize);
+ return dwSize;
+}
+
+
+inline DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, ATL::CAtlStringW &sNameString)
+{
+ // Query the final string length first.
+ DWORD dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
+
+ // Prepare the buffer to format the string data into and read it.
+ LPWSTR szBuffer = sNameString.GetBuffer(dwSize);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, szBuffer, dwSize);
+ sNameString.ReleaseBuffer(dwSize);
+ return dwSize;
+}
+
+
+inline BOOL CryptGetHashParam(__in HCRYPTHASH hHash, __in DWORD dwParam, __out ATL::CAtlArray &aData, __in DWORD dwFlags)
+{
+ DWORD dwHashSize;
+
+ if (CryptGetHashParam(hHash, dwParam, NULL, &dwHashSize, dwFlags)) {
+ if (aData.SetCount(dwHashSize)) {
+ if (CryptGetHashParam(hHash, dwParam, aData.GetData(), &dwHashSize, dwFlags)) {
+ return TRUE;
+ } else {
+ aData.SetCount(0);
+ return FALSE;
+ }
+ } else {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ } else
+ return FALSE;
+}
+
+
+inline BOOL CryptExportKey(__in HCRYPTKEY hKey, __in HCRYPTKEY hExpKey, __in DWORD dwBlobType, __in DWORD dwFlags, __out ATL::CAtlArray &aData)
+{
+ DWORD dwKeyBLOBSize;
+
+ if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, NULL, &dwKeyBLOBSize)) {
+ if (aData.SetCount(dwKeyBLOBSize)) {
+ if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, aData.GetData(), &dwKeyBLOBSize)) {
+ return TRUE;
+ } else {
+ aData.SetCount(0);
+ return FALSE;
+ }
+ } else {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ } else
+ return FALSE;
+}
+
+
+namespace ATL
+{
+ namespace Crypt
+ {
+ //
+ // CCertContext
+ //
+ class CCertContext : public ATL::CObjectWithHandleDuplT
+ {
+ public:
+ virtual ~CCertContext() throw()
+ {
+ if (m_h)
+ CertFreeCertificateContext(m_h);
+ }
+
+ inline BOOL Create(_In_ DWORD dwCertEncodingType, _In_ const BYTE *pbCertEncoded, _In_ DWORD cbCertEncoded) throw()
+ {
+ HANDLE h = CertCreateCertificateContext(dwCertEncodingType, pbCertEncoded, cbCertEncoded);
+ if (h) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ CertFreeCertificateContext(m_h);
+ }
+
+ virtual HANDLE InternalDuplicate(HANDLE h) const
+ {
+ return CertDuplicateCertificateContext(h);
+ }
+ };
+
+
+ //
+ // CCertChainContext
+ //
+ class CCertChainContext : public ATL::CObjectWithHandleDuplT
+ {
+ public:
+ virtual ~CCertChainContext() throw()
+ {
+ if (m_h)
+ CertFreeCertificateChain(m_h);
+ }
+
+ inline BOOL Create(__in_opt HCERTCHAINENGINE hChainEngine, __in PCCERT_CONTEXT pCertContext, __in_opt LPFILETIME pTime, __in_opt HCERTSTORE hAdditionalStore, __in PCERT_CHAIN_PARA pChainPara, __in DWORD dwFlags, __reserved LPVOID pvReserved) throw()
+ {
+ HANDLE h;
+ if (CertGetCertificateChain(hChainEngine, pCertContext, pTime, hAdditionalStore, pChainPara, dwFlags, pvReserved, &h)) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ CertFreeCertificateChain(m_h);
+ }
+
+ virtual HANDLE InternalDuplicate(HANDLE h) const
+ {
+ return CertDuplicateCertificateChain(h);
+ }
+ };
+
+
+ //
+ // CCertStore
+ //
+ class CCertStore : public ATL::CObjectWithHandleT
+ {
+ public:
+ virtual ~CCertStore() throw()
+ {
+ if (m_h)
+ CertCloseStore(m_h, 0);
+ }
+
+ inline BOOL Create(__in LPCSTR lpszStoreProvider, __in DWORD dwEncodingType, __in_opt HCRYPTPROV_LEGACY hCryptProv, __in DWORD dwFlags, __in_opt const void *pvPara) throw()
+ {
+ HANDLE h = CertOpenStore(lpszStoreProvider, dwEncodingType, hCryptProv, dwFlags, pvPara);
+ if (h) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ CertCloseStore(m_h, 0);
+ }
+ };
+
+
+ //
+ // CContext
+ //
+ class CContext : public ATL::CObjectWithHandleT
+ {
+ public:
+ virtual ~CContext() throw()
+ {
+ if (m_h)
+ CryptReleaseContext(m_h, 0);
+ }
+
+ inline BOOL Create(__in_opt LPCTSTR szContainer, __in_opt LPCTSTR szProvider, __in DWORD dwProvType, __in DWORD dwFlags) throw()
+ {
+ HANDLE h;
+ if (CryptAcquireContext(&h, szContainer, szProvider, dwProvType, dwFlags)) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ CryptReleaseContext(m_h, 0);
+ }
+ };
+
+
+ //
+ // CHash
+ //
+ class CHash : public ATL::CObjectWithHandleT
+ {
+ public:
+ virtual ~CHash() throw()
+ {
+ if (m_h)
+ CryptDestroyHash(m_h);
+ }
+
+ inline BOOL Create(__in HCRYPTPROV hProv, __in ALG_ID Algid, __in HCRYPTKEY hKey, __in DWORD dwFlags) throw()
+ {
+ HANDLE h;
+ if (CryptCreateHash(hProv, Algid, hKey, dwFlags, &h)) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ CryptDestroyHash(m_h);
+ }
+ };
+
+
+ //
+ // CKey
+ //
+ class CKey : public ATL::CObjectWithHandleT
+ {
+ public:
+ virtual ~CKey() throw()
+ {
+ if (m_h)
+ CryptDestroyKey(m_h);
+ }
+
+ inline BOOL Generate(__in HCRYPTPROV hProv, __in ALG_ID Algid, __in DWORD dwFlags) throw()
+ {
+ HANDLE h;
+ if (CryptGenKey(hProv, Algid, dwFlags, &h)) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ inline BOOL Import(__in HCRYPTPROV hProv, __in_bcount(dwDataLen) CONST BYTE *pbData, __in DWORD dwDataLen, __in HCRYPTKEY hPubKey, __in DWORD dwFlags) throw()
+ {
+ HANDLE h;
+ if (CryptImportKey(hProv, pbData, dwDataLen, hPubKey, dwFlags, &h)) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ inline BOOL ImportPublic(__in HCRYPTPROV hCryptProv, __in DWORD dwCertEncodingType, __in PCERT_PUBLIC_KEY_INFO pInfo) throw()
+ {
+ HANDLE h;
+ if (CryptImportPublicKeyInfo(hCryptProv, dwCertEncodingType, pInfo, &h)) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ CryptDestroyKey(m_h);
+ }
+ };
+ }
+}
diff --git a/atleap.h b/atleap.h
new file mode 100644
index 0000000..5951c70
--- /dev/null
+++ b/atleap.h
@@ -0,0 +1,46 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include
+
+
+namespace ATL
+{
+ namespace EAP
+ {
+ class CEAPAttribute : public EAP_ATTRIBUTE
+ {
+ public:
+ CEAPAttribute()
+ {
+ eaType = eatReserved;
+ dwLength = 0;
+ pValue = NULL;
+ }
+
+ ~CEAPAttribute()
+ {
+ if (pValue)
+ delete pValue;
+ }
+ };
+ }
+}
diff --git a/atlex.h b/atlex.h
new file mode 100644
index 0000000..adf0e93
--- /dev/null
+++ b/atlex.h
@@ -0,0 +1,324 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+#include
+
+
+namespace ATL
+{
+ //
+ // CObjectWithHandleT
+ //
+ template
+ class CObjectWithHandleT
+ {
+ public:
+ typedef T HANDLE;
+
+ inline CObjectWithHandleT() throw() : m_h(NULL)
+ {
+ }
+
+ inline CObjectWithHandleT(HANDLE h) throw() : m_h(h)
+ {
+ }
+
+ inline operator HANDLE() const throw()
+ {
+ return m_h;
+ }
+
+ inline HANDLE*& operator*() const
+ {
+ ATLENSURE(m_h != NULL);
+ return *m_h;
+ }
+
+ inline HANDLE* operator&() throw()
+ {
+ ATLASSERT(m_h == NULL);
+ return &m_h;
+ }
+
+ inline HANDLE operator->() const throw()
+ {
+ ATLASSERT(m_h != NULL);
+ return m_h;
+ }
+
+ inline bool operator!() const throw()
+ {
+ return m_h == NULL;
+ }
+
+ inline bool operator<(_In_opt_ HANDLE h) const throw()
+ {
+ return m_h < h;
+ }
+
+ inline bool operator!=(_In_opt_ HANDLE h) const
+ {
+ return !operator==(h);
+ }
+
+ inline bool operator==(_In_opt_ HANDLE h) const throw()
+ {
+ return m_h == h;
+ }
+
+ inline void Attach(_In_opt_ HANDLE h) throw()
+ {
+ if (m_h)
+ InternalFree();
+ m_h = h;
+ }
+
+ inline HANDLE Detach() throw()
+ {
+ HANDLE h = m_h;
+ m_h = NULL;
+ return h;
+ }
+
+ inline void Free() throw()
+ {
+ if (m_h) {
+ InternalFree();
+ m_h = NULL;
+ }
+ }
+
+ protected:
+ virtual void InternalFree() = 0;
+
+ protected:
+ HANDLE m_h;
+ };
+
+
+ //
+ // CObjectWithHandleDuplT
+ //
+ template
+ class CObjectWithHandleDuplT : public CObjectWithHandleT
+ {
+ public:
+ inline HANDLE GetDuplicate() const
+ {
+ return m_h ? InternalDuplicate(m_h) : NULL;
+ }
+
+ inline BOOL DuplicateAndAttach(_In_opt_ HANDLE h) throw()
+ {
+ if (m_h)
+ InternalFree();
+
+ return h ? (m_h = InternalDuplicate(h)) != NULL : (m_h = NULL, TRUE);
+ }
+
+ //
+ // Do not allow = operators. They are semantically ambigious:
+ // Do they attach the class to the existing instance of object, or do they duplicate it?
+ // To avoid confusion, user should use Attach() and Duplicate() methods explicitly.
+ //
+ //inline const CObjectWithHandleDuplT& operator=(_In_ const HANDLE src)
+ //{
+ // Attach(src ? InternalDuplicate(src) : NULL);
+ // return *this;
+ //}
+
+ //inline const CObjectWithHandleDuplT& operator=(_In_ const CObjectWithHandleDuplT &src)
+ //{
+ // Attach(src.m_h ? InternalDuplicate(src.m_h) : NULL);
+ // return *this;
+ //}
+
+ protected:
+ virtual HANDLE InternalDuplicate(HANDLE h) const = 0;
+ };
+
+
+ //
+ // CStrFormatT, CStrFormatW, CStrFormatA, CStrFormat
+ //
+ template
+ class CStrFormatT : public CStringT
+ {
+ public:
+ CStrFormatT(_In_z_ _FormatMessage_format_string_ PCXSTR pszFormat, ...)
+ {
+ ATLASSERT(AtlIsValidString(pszFormat));
+
+ va_list argList;
+ va_start(argList, pszFormat);
+ FormatV(pszFormat, argList);
+ va_end(argList);
+ }
+
+ CStrFormatT(_In_ _FormatMessage_format_string_ UINT nFormatID, ...)
+ {
+ CStringT strFormat(GetManager());
+ ATLENSURE(strFormat.LoadString(nFormatID));
+
+ va_list argList;
+ va_start(argList, nFormatID);
+ FormatV(strFormat, argList);
+ va_end(argList);
+ }
+
+ CStrFormatT(_In_ HINSTANCE hInstance, _In_ _FormatMessage_format_string_ UINT nFormatID, ...)
+ {
+ CStringT strFormat(GetManager());
+ ATLENSURE(strFormat.LoadString(hInstance, nFormatID));
+
+ va_list argList;
+ va_start(argList, nFormatID);
+ FormatV(strFormat, argList);
+ va_end(argList);
+ }
+
+ CStrFormatT(_In_ HINSTANCE hInstance, _In_ WORD wLanguageID, _In_ _FormatMessage_format_string_ UINT nFormatID, ...)
+ {
+ CStringT strFormat(GetManager());
+ ATLENSURE(strFormat.LoadString(hInstance, nFormatID, wLanguageID));
+
+ va_list argList;
+ va_start(argList, nFormatID);
+ FormatV(strFormat, argList);
+ va_end(argList);
+ }
+ };
+
+ typedef CStrFormatT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT< wchar_t > > > CStrFormatW;
+ typedef CStrFormatT< char, StrTraitATL< char, ChTraitsCRT< char > > > CStrFormatA;
+ typedef CStrFormatT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > > CStrFormat;
+
+
+ //
+ // CStrFormatMsgT, CStrFormatMsgW, CStrFormatMsgA, CStrFormatMsg
+ //
+ template
+ class CStrFormatMsgT : public CStringT
+ {
+ public:
+ CStrFormatMsgT(_In_z_ _FormatMessage_format_string_ PCXSTR pszFormat, ...)
+ {
+ ATLASSERT(AtlIsValidString(pszFormat));
+
+ va_list argList;
+ va_start(argList, pszFormat);
+ FormatMessageV(pszFormat, &argList);
+ va_end(argList);
+ }
+
+ CStrFormatMsgT(_In_ _FormatMessage_format_string_ UINT nFormatID, ...)
+ {
+ CStringT strFormat(GetManager());
+ ATLENSURE(strFormat.LoadString(nFormatID));
+
+ va_list argList;
+ va_start(argList, nFormatID);
+ FormatMessageV(strFormat, &argList);
+ va_end(argList);
+ }
+
+ CStrFormatMsgT(_In_ HINSTANCE hInstance, _In_ _FormatMessage_format_string_ UINT nFormatID, ...)
+ {
+ CStringT strFormat(GetManager());
+ ATLENSURE(strFormat.LoadString(hInstance, nFormatID));
+
+ va_list argList;
+ va_start(argList, nFormatID);
+ FormatMessageV(strFormat, &argList);
+ va_end(argList);
+ }
+
+ CStrFormatMsgT(_In_ HINSTANCE hInstance, _In_ WORD wLanguageID, _In_ _FormatMessage_format_string_ UINT nFormatID, ...)
+ {
+ CStringT strFormat(GetManager());
+ ATLENSURE(strFormat.LoadString(hInstance, nFormatID, wLanguageID));
+
+ va_list argList;
+ va_start(argList, nFormatID);
+ FormatMessageV(strFormat, &argList);
+ va_end(argList);
+ }
+ };
+
+ typedef CStrFormatMsgT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT< wchar_t > > > CStrFormatMsgW;
+ typedef CStrFormatMsgT< char, StrTraitATL< char, ChTraitsCRT< char > > > CStrFormatMsgA;
+ typedef CStrFormatMsgT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > > CStrFormatMsg;
+
+
+ //
+ // CParanoidHeap
+ //
+ template
+ class CParanoidHeap : public BaseHeap {
+ public:
+ virtual void Free(_In_opt_ void* p) throw()
+ {
+ // Sanitize then free.
+ SecureZeroMemory(p, GetSize(p));
+ BaseHeap::Free(p);
+ }
+
+ _Ret_opt_bytecap_(nBytes) virtual void* Reallocate(_In_opt_ void* p, _In_ size_t nBytes) throw()
+ {
+ // Create a new sized copy.
+ void *pNew = Allocate(nBytes);
+ size_t nSizePrev = GetSize(p);
+ memcpy(pNew, p, nSizePrev);
+
+ // Sanitize the old data then free.
+ SecureZeroMemory(p, nSizePrev);
+ Free(p);
+
+ return pNew;
+ }
+ };
+
+
+ //
+ // CW2AParanoidEX
+ //
+ template
+ class CW2AParanoidEX : public CW2AEX {
+ public:
+ CW2AParanoidEX(_In_z_ LPCWSTR psz) throw(...) : CW2AEX(psz) {}
+ CW2AParanoidEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage) throw(...) : CW2AEX(psz, nCodePage) {}
+ ~CW2AParanoidEX() throw()
+ {
+ // Sanitize before free.
+ if (m_psz != m_szBuffer)
+ SecureZeroMemory(m_psz, _msize(m_psz));
+ else
+ SecureZeroMemory(m_szBuffer, sizeof(m_szBuffer));
+ }
+ };
+
+ //
+ // CW2AParanoid
+ //
+ typedef CW2AParanoidEX<> CW2AParanoid;
+}
diff --git a/atlmsi.h b/atlmsi.h
new file mode 100644
index 0000000..875d44e
--- /dev/null
+++ b/atlmsi.h
@@ -0,0 +1,241 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+#include
+
+
+inline UINT MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, ATL::CAtlStringA &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the actual string length first.
+ uiResult = ::MsiGetPropertyA(hInstall, szName, "", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to read the string data into and read it.
+ LPSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiGetPropertyA(hInstall, szName, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The string in database is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, ATL::CAtlStringW &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the actual string length first.
+ uiResult = ::MsiGetPropertyW(hInstall, szName, L"", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to read the string data into and read it.
+ LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiGetPropertyW(hInstall, szName, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The string in database is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiRecordGetStringA(MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringA &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the actual string length first.
+ uiResult = ::MsiRecordGetStringA(hRecord, iField, "", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to read the string data into and read it.
+ LPSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiRecordGetStringA(hRecord, iField, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The string in database is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiRecordGetStringW(MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringW &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the actual string length first.
+ uiResult = ::MsiRecordGetStringW(hRecord, iField, L"", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to read the string data into and read it.
+ LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiRecordGetStringW(hRecord, iField, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The string in database is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringA &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the final string length first.
+ uiResult = ::MsiFormatRecordA(hInstall, hRecord, "", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to format the string data into and read it.
+ LPSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiFormatRecordA(hInstall, hRecord, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The result is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringW &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the final string length first.
+ uiResult = ::MsiFormatRecordW(hInstall, hRecord, L"", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to format the string data into and read it.
+ LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiFormatRecordW(hInstall, hRecord, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The result is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiRecordReadStream(MSIHANDLE hRecord, unsigned int iField, ATL::CAtlArray &binData)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the actual data length first.
+ uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
+ if (uiResult == NO_ERROR) {
+ if (!binData.SetCount(dwSize)) return ERROR_OUTOFMEMORY;
+ return ::MsiRecordReadStream(hRecord, iField, (char*)binData.GetData(), &dwSize);
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiGetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder, ATL::CAtlStringA &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the final string length first.
+ uiResult = ::MsiGetTargetPathA(hInstall, szFolder, "", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to format the string data into and read it.
+ LPSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The result is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
+
+
+inline UINT MsiGetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, ATL::CAtlStringW &sValue)
+{
+ DWORD dwSize = 0;
+ UINT uiResult;
+
+ // Query the final string length first.
+ uiResult = ::MsiGetTargetPathW(hInstall, szFolder, L"", &dwSize);
+ if (uiResult == ERROR_MORE_DATA) {
+ // Prepare the buffer to format the string data into and read it.
+ LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szBuffer, &dwSize);
+ sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
+ return uiResult;
+ } else if (uiResult == NO_ERROR) {
+ // The result is empty.
+ sValue.Empty();
+ return NO_ERROR;
+ } else {
+ // Return error code.
+ return uiResult;
+ }
+}
diff --git a/atlsec.h b/atlsec.h
new file mode 100644
index 0000000..78a1e9d
--- /dev/null
+++ b/atlsec.h
@@ -0,0 +1,84 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#include
+
+
+BOOLEAN GetUserNameExA(__in EXTENDED_NAME_FORMAT NameFormat, __out ATL::CAtlStringA &sName)
+{
+ ULONG ulSize = 0;
+
+ // Query the final string length first.
+ if (!::GetUserNameExA(NameFormat, NULL, &ulSize)) {
+ if (::GetLastError() == ERROR_MORE_DATA) {
+ // Prepare the buffer and retry.
+ LPSTR szBuffer = sName.GetBuffer(ulSize - 1);
+ if (!szBuffer) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ if (::GetUserNameExA(NameFormat, szBuffer, &ulSize)) {
+ sName.ReleaseBuffer(ulSize);
+ return TRUE;
+ } else {
+ sName.ReleaseBuffer(0);
+ return FALSE;
+ }
+ } else {
+ // Return error.
+ return FALSE;
+ }
+ } else {
+ // The result is empty.
+ sName.Empty();
+ return NO_ERROR;
+ }
+}
+
+
+BOOLEAN GetUserNameExW(__in EXTENDED_NAME_FORMAT NameFormat, __out ATL::CAtlStringW &sName)
+{
+ ULONG ulSize = 0;
+
+ // Query the final string length first.
+ if (!::GetUserNameExW(NameFormat, NULL, &ulSize)) {
+ if (::GetLastError() == ERROR_MORE_DATA) {
+ // Prepare the buffer and retry.
+ LPWSTR szBuffer = sName.GetBuffer(ulSize - 1);
+ if (!szBuffer) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ if (::GetUserNameExW(NameFormat, szBuffer, &ulSize)) {
+ sName.ReleaseBuffer(ulSize);
+ return TRUE;
+ } else {
+ sName.ReleaseBuffer(0);
+ return FALSE;
+ }
+ } else {
+ // Return error.
+ return FALSE;
+ }
+ } else {
+ // The result is empty.
+ sName.Empty();
+ return NO_ERROR;
+ }
+}
diff --git a/atlshlwapi.h b/atlshlwapi.h
new file mode 100644
index 0000000..4b4dcfa
--- /dev/null
+++ b/atlshlwapi.h
@@ -0,0 +1,53 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+
+
+inline BOOL PathCanonicalizeA(__out ATL::CAtlStringA &sValue, __in LPCSTR pszPath)
+{
+ // Prepare the buffer data and read into it.
+ LPSTR szBuffer = sValue.GetBuffer(MAX_PATH);
+ if (!szBuffer) {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ BOOL bResult = ::PathCanonicalizeA(szBuffer, pszPath);
+ sValue.ReleaseBuffer(bResult ? (int)strnlen(szBuffer, MAX_PATH) : 0);
+ sValue.FreeExtra();
+ return bResult;
+}
+
+
+inline BOOL PathCanonicalizeW(__out ATL::CAtlStringW &sValue, __in LPCWSTR pszPath)
+{
+ // Prepare the buffer data and read into it.
+ LPWSTR szBuffer = sValue.GetBuffer(MAX_PATH);
+ if (!szBuffer) {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath);
+ sValue.ReleaseBuffer(bResult ? (int)wcsnlen(szBuffer, MAX_PATH) : 0);
+ sValue.FreeExtra();
+ return bResult;
+}
diff --git a/atlwin.h b/atlwin.h
new file mode 100644
index 0000000..f4056de
--- /dev/null
+++ b/atlwin.h
@@ -0,0 +1,423 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include "atlex.h"
+#include
+#include
+#include
+
+
+inline DWORD GetModuleFileNameA(__in_opt HMODULE hModule, __out ATL::CAtlStringA &sValue)
+{
+ DWORD dwSize = 0;
+
+ for (;;) {
+ // Increment size and allocate buffer.
+ LPSTR szBuffer = sValue.GetBuffer(dwSize += 1024);
+ if (!szBuffer) {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+ }
+
+ // Try!
+ DWORD dwResult = ::GetModuleFileNameA(hModule, szBuffer, dwSize);
+ if (dwResult == 0) {
+ // Error.
+ sValue.ReleaseBuffer(0);
+ return 0;
+ } else if (dwResult < dwSize) {
+ DWORD dwLength = (DWORD)strnlen(szBuffer, dwSize);
+ sValue.ReleaseBuffer(dwLength++);
+ if (dwLength == dwSize) {
+ // Buffer was long exactly enough.
+ return dwResult;
+ } if (dwLength < dwSize) {
+ // Buffer was long enough to get entire string, and has some extra space left.
+ sValue.FreeExtra();
+ return dwResult;
+ }
+ }
+ }
+}
+
+
+inline DWORD GetModuleFileNameW(__in_opt HMODULE hModule, __out ATL::CAtlStringW &sValue)
+{
+ DWORD dwSize = 0;
+
+ for (;;) {
+ // Increment size and allocate buffer.
+ LPWSTR szBuffer = sValue.GetBuffer(dwSize += 1024);
+ if (!szBuffer) {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+ }
+
+ // Try!
+ DWORD dwResult = ::GetModuleFileNameW(hModule, szBuffer, dwSize);
+ if (dwResult == 0) {
+ // Error.
+ sValue.ReleaseBuffer(0);
+ return 0;
+ } else if (dwResult < dwSize) {
+ DWORD dwLength = (DWORD)wcsnlen(szBuffer, dwSize);
+ sValue.ReleaseBuffer(dwLength++);
+ if (dwLength == dwSize) {
+ // Buffer was long exactly enough.
+ return dwResult;
+ } if (dwLength < dwSize) {
+ // Buffer was long enough to get entire string, and has some extra space left.
+ sValue.FreeExtra();
+ return dwResult;
+ }
+ }
+ }
+}
+
+
+inline int GetWindowTextA(__in HWND hWnd, __out ATL::CAtlStringA &sValue)
+{
+ int iResult;
+
+ // Query the final string length first.
+ iResult = ::GetWindowTextLengthA(hWnd);
+ if (iResult > 0) {
+ // Prepare the buffer and read the string data into it.
+ LPSTR szBuffer = sValue.GetBuffer(iResult++);
+ if (!szBuffer) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+ }
+ iResult = ::GetWindowTextA(hWnd, szBuffer, iResult);
+ sValue.ReleaseBuffer(iResult);
+ return iResult;
+ } else {
+ // The result is empty.
+ sValue.Empty();
+ return 0;
+ }
+}
+
+
+inline int GetWindowTextW(__in HWND hWnd, __out ATL::CAtlStringW &sValue)
+{
+ int iResult;
+
+ // Query the final string length first.
+ iResult = ::GetWindowTextLengthW(hWnd);
+ if (iResult > 0) {
+ // Prepare the buffer and read the string data into it.
+ LPWSTR szBuffer = sValue.GetBuffer(iResult++);
+ if (!szBuffer) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+ }
+ iResult = ::GetWindowTextW(hWnd, szBuffer, iResult);
+ sValue.ReleaseBuffer(iResult);
+ return iResult;
+ } else {
+ // The result is empty.
+ sValue.Empty();
+ return 0;
+ }
+}
+
+
+inline BOOL GetFileVersionInfoA(__in LPCSTR lptstrFilename, __reserved DWORD dwHandle, __out ATL::CAtlArray &aValue)
+{
+ // Get version info size.
+ DWORD dwVerInfoSize = ::GetFileVersionInfoSizeA(lptstrFilename, &dwHandle);
+ if (dwVerInfoSize != 0) {
+ if (aValue.SetCount(dwVerInfoSize)) {
+ // Read version info.
+ return ::GetFileVersionInfoA(lptstrFilename, dwHandle, dwVerInfoSize, aValue.GetData());
+ } else {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ } else
+ return FALSE;
+}
+
+
+inline BOOL GetFileVersionInfoW(__in LPCWSTR lptstrFilename, __reserved DWORD dwHandle, __out ATL::CAtlArray &aValue)
+{
+ // Get version info size.
+ DWORD dwVerInfoSize = ::GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
+ if (dwVerInfoSize != 0) {
+ if (aValue.SetCount(dwVerInfoSize)) {
+ // Read version info.
+ return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwVerInfoSize, aValue.GetData());
+ } else {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ } else
+ return FALSE;
+}
+
+
+inline DWORD ExpandEnvironmentStringsA(__in LPCSTR lpSrc, ATL::CAtlStringA &sValue)
+{
+ DWORD dwBufferSizeEst = (DWORD)strlen(lpSrc) + 0x100; // Initial estimate
+
+ for (;;) {
+ DWORD dwBufferSize = dwBufferSizeEst;
+ LPSTR szBuffer = sValue.GetBuffer(dwBufferSize);
+ if (!szBuffer) {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ dwBufferSizeEst = ::ExpandEnvironmentStringsA(lpSrc, szBuffer, dwBufferSize);
+ if (dwBufferSizeEst > dwBufferSize) {
+ // The buffer was to small. Repeat with a bigger one.
+ sValue.ReleaseBuffer(0);
+ } else if (dwBufferSizeEst == 0) {
+ // Error.
+ sValue.ReleaseBuffer(0);
+ return 0;
+ } else {
+ // The buffer was sufficient. Break.
+ sValue.ReleaseBuffer();
+ sValue.FreeExtra();
+ return dwBufferSizeEst;
+ }
+ }
+}
+
+
+inline DWORD ExpandEnvironmentStringsW(__in LPCWSTR lpSrc, ATL::CAtlStringW &sValue)
+{
+ DWORD dwBufferSizeEst = (DWORD)wcslen(lpSrc) + 0x100; // Initial estimate
+
+ for (;;) {
+ DWORD dwBufferSize = dwBufferSizeEst;
+ LPWSTR szBuffer = sValue.GetBuffer(dwBufferSize);
+ if (!szBuffer) {
+ ::SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ dwBufferSizeEst = ::ExpandEnvironmentStringsW(lpSrc, szBuffer, dwBufferSize);
+ if (dwBufferSizeEst > dwBufferSize) {
+ // The buffer was to small. Repeat with a bigger one.
+ sValue.ReleaseBuffer(0);
+ } else if (dwBufferSizeEst == 0) {
+ // Error.
+ sValue.ReleaseBuffer(0);
+ return 0;
+ } else {
+ // The buffer was sufficient. Break.
+ sValue.ReleaseBuffer();
+ sValue.FreeExtra();
+ return dwBufferSizeEst;
+ }
+ }
+}
+
+
+inline VOID GuidToString(_In_ LPCGUID lpGuid, ATL::CAtlStringA &str)
+{
+ str.Format("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ lpGuid->Data1,
+ lpGuid->Data2,
+ lpGuid->Data3,
+ lpGuid->Data4[0], lpGuid->Data4[1],
+ lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
+}
+
+
+inline VOID GuidToString(_In_ LPCGUID lpGuid, ATL::CAtlStringW &str)
+{
+ str.Format(L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ lpGuid->Data1,
+ lpGuid->Data2,
+ lpGuid->Data3,
+ lpGuid->Data4[0], lpGuid->Data4[1],
+ lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
+}
+
+
+inline LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ ATL::CAtlStringA &sValue)
+{
+ LSTATUS lResult;
+ DWORD dwSize = 0, dwType;
+
+ // Determine the type and size first.
+ if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, NULL, &dwSize)) == ERROR_SUCCESS) {
+ if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
+ // The value is REG_SZ or REG_MULTI_SZ. Read it now.
+ LPSTR szTemp = sValue.GetBuffer(dwSize / sizeof(TCHAR));
+ if (!szTemp) return ERROR_OUTOFMEMORY;
+ if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, (LPBYTE)szTemp, &dwSize)) == ERROR_SUCCESS) {
+ sValue.ReleaseBuffer();
+ } else {
+ // Reading of the value failed.
+ sValue.ReleaseBuffer(0);
+ }
+ } else if (dwType == REG_EXPAND_SZ) {
+ // The value is REG_EXPAND_SZ. Read it and expand environment variables.
+ ATL::CTempBuffer sTemp(dwSize / sizeof(CHAR));
+ if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, (LPBYTE)(CHAR*)sTemp, &dwSize)) == ERROR_SUCCESS)
+ if (::ExpandEnvironmentStringsA((const CHAR*)sTemp, sValue) == 0)
+ lResult = ::GetLastError();
+ } else {
+ // The value is not a string type.
+ lResult = ERROR_INVALID_DATA;
+ }
+ }
+
+ return lResult;
+}
+
+
+inline LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ ATL::CAtlStringW &sValue)
+{
+ LSTATUS lResult;
+ DWORD dwSize = 0, dwType;
+
+ // Determine the type and size first.
+ if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, NULL, &dwSize)) == ERROR_SUCCESS) {
+ if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
+ // The value is REG_SZ or REG_MULTI_SZ. Read it now.
+ LPWSTR szTemp = sValue.GetBuffer(dwSize / sizeof(TCHAR));
+ if (!szTemp) return ERROR_OUTOFMEMORY;
+ if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, (LPBYTE)szTemp, &dwSize)) == ERROR_SUCCESS) {
+ sValue.ReleaseBuffer();
+ } else {
+ // Reading of the value failed.
+ sValue.ReleaseBuffer(0);
+ }
+ } else if (dwType == REG_EXPAND_SZ) {
+ // The value is REG_EXPAND_SZ. Read it and expand environment variables.
+ ATL::CTempBuffer sTemp(dwSize / sizeof(WCHAR));
+ if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, (LPBYTE)(WCHAR*)sTemp, &dwSize)) == ERROR_SUCCESS)
+ if (::ExpandEnvironmentStringsW((const WCHAR*)sTemp, sValue) == 0)
+ lResult = ::GetLastError();
+ } else {
+ // The value is not a string type.
+ lResult = ERROR_INVALID_DATA;
+ }
+ }
+
+ return lResult;
+}
+
+
+inline LSTATUS RegQueryValueExA(__in HKEY hKey, __in_opt LPCSTR lpValueName, __reserved LPDWORD lpReserved, __out_opt LPDWORD lpType, __out ATL::CAtlArray &aData)
+{
+ LSTATUS lResult;
+ DWORD dwDataSize;
+
+ if ((lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, NULL, &dwDataSize)) == ERROR_SUCCESS) {
+ if (!aData.SetCount(dwDataSize)) return ERROR_OUTOFMEMORY;
+ if ((lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aData.GetData(), &dwDataSize)) != ERROR_SUCCESS)
+ aData.SetCount(0);
+ }
+
+ return lResult;
+}
+
+
+inline LSTATUS RegQueryValueExW(__in HKEY hKey, __in_opt LPCWSTR lpValueName, __reserved LPDWORD lpReserved, __out_opt LPDWORD lpType, __out ATL::CAtlArray &aData)
+{
+ LSTATUS lResult;
+ DWORD dwDataSize;
+
+ if ((lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, NULL, &dwDataSize)) == ERROR_SUCCESS) {
+ if (!aData.SetCount(dwDataSize)) return ERROR_OUTOFMEMORY;
+ if ((lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aData.GetData(), &dwDataSize)) != ERROR_SUCCESS)
+ aData.SetCount(0);
+ }
+
+ return lResult;
+}
+
+
+#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+
+inline LSTATUS RegLoadMUIStringA(__in HKEY hKey, __in_opt LPCSTR pszValue, __out ATL::CAtlStringA &sOut, __in DWORD Flags, __in_opt LPCSTR pszDirectory)
+{
+ LSTATUS lResult;
+ DWORD dwSize;
+
+ Flags &= ~REG_MUI_STRING_TRUNCATE;
+
+ lResult = RegLoadMUIStringA(hKey, pszValue, NULL, 0, &dwSize, Flags, pszDirectory);
+ if (lResult == ERROR_MORE_DATA) {
+ LPSTR szBuffer = sOut.GetBuffer(dwSize - 1);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ sOut.ReleaseBuffer((lResult = RegLoadMUIStringA(hKey, pszValue, szBuffer, dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? dwSize - 1 : 0);
+ } else if (lResult == ERROR_SUCCESS)
+ sOut.Empty();
+
+ return lResult;
+}
+
+
+inline LSTATUS RegLoadMUIStringW(__in HKEY hKey, __in_opt LPCWSTR pszValue, __out ATL::CAtlStringW &sOut, __in DWORD Flags, __in_opt LPCWSTR pszDirectory)
+{
+ LSTATUS lResult;
+ DWORD dwSize;
+
+ Flags &= ~REG_MUI_STRING_TRUNCATE;
+
+ lResult = RegLoadMUIStringW(hKey, pszValue, NULL, 0, &dwSize, Flags, pszDirectory);
+ if (lResult == ERROR_MORE_DATA) {
+ LPWSTR szBuffer = sOut.GetBuffer(dwSize - 1);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+ sOut.ReleaseBuffer((lResult = RegLoadMUIStringW(hKey, pszValue, szBuffer, dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? dwSize - 1 : 0);
+ } else if (lResult == ERROR_SUCCESS)
+ sOut.Empty();
+
+ return lResult;
+}
+
+#endif
+
+
+namespace ATL
+{
+ class CAtlLibrary : public CObjectWithHandleT
+ {
+ public:
+ virtual ~CAtlLibrary() throw()
+ {
+ if (m_h)
+ FreeLibrary(m_h);
+ }
+
+ inline BOOL Load(__in LPCTSTR lpFileName, __reserved HANDLE hFile, __in DWORD dwFlags) throw()
+ {
+ HANDLE h = LoadLibraryEx(lpFileName, hFile, dwFlags);
+ if (h) {
+ Attach(h);
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ protected:
+ virtual void InternalFree()
+ {
+ FreeLibrary(m_h);
+ }
+ };
+}
diff --git a/atlwlan.h b/atlwlan.h
new file mode 100644
index 0000000..3d5be95
--- /dev/null
+++ b/atlwlan.h
@@ -0,0 +1,54 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+
+
+inline DWORD WlanReasonCodeToString(__in DWORD dwReasonCode, __out ATL::CAtlStringW &sValue, __reserved PVOID pReserved)
+{
+ DWORD dwSize = 0;
+
+ for (;;) {
+ // Increment size and allocate buffer.
+ LPWSTR szBuffer = sValue.GetBuffer(dwSize += 1024);
+ if (!szBuffer) return ERROR_OUTOFMEMORY;
+
+ // Try!
+ DWORD dwResult = ::WlanReasonCodeToString(dwReasonCode, dwSize, szBuffer, pReserved);
+ if (dwResult == NO_ERROR) {
+ DWORD dwLength = (DWORD)wcsnlen(szBuffer, dwSize);
+ sValue.ReleaseBuffer(dwLength++);
+ if (dwLength == dwSize) {
+ // Buffer was long exactly enough.
+ return NO_ERROR;
+ } else if (dwLength < dwSize) {
+ // Buffer was long enough to get entire string, and has some extra space left.
+ sValue.FreeExtra();
+ return NO_ERROR;
+ }
+ } else {
+ // Return error code.
+ sValue.ReleaseBuffer(0);
+ return dwResult;
+ }
+ }
+}
diff --git a/stdafx.cpp b/stdafx.cpp
new file mode 100644
index 0000000..81111ac
--- /dev/null
+++ b/stdafx.cpp
@@ -0,0 +1,20 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#include "stdafx.h"
diff --git a/stdafx.h b/stdafx.h
new file mode 100644
index 0000000..99c70cc
--- /dev/null
+++ b/stdafx.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 1991-2015 Amebis
+
+ This file is part of libatl.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#pragma once
+
+#include "atlwin.h"
+
+#include "atlcrypt.h"
+#include "atleap.h"
+#include "atlex.h"
+#include "atlmsi.h"
+#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL) || defined(SECURITY_MAC)
+#include "atlsec.h"
+#endif
+#include "atlshlwapi.h"
+#include "atlwin.h"
+#include "atlwlan.h"