You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2309 lines
78 KiB
2309 lines
78 KiB
/*++
|
|
|
|
Copyright (C) 1996-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
IMPORT.CPP
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <StdIo.h>
|
|
#include <ConIo.h>
|
|
#include <wbemint.h>
|
|
#include <WbemUtil.h>
|
|
#include <corex.h>
|
|
#include "upgrade.h"
|
|
#include "Import.h"
|
|
#include "export.h"
|
|
#include "reg.h"
|
|
|
|
|
|
template <class T> class CMyRelMe
|
|
{
|
|
T m_p;
|
|
public:
|
|
CMyRelMe(T p) : m_p(p) {};
|
|
~CMyRelMe() { if (m_p) m_p->Release(); }
|
|
void Set(T p) { m_p = p; }
|
|
};
|
|
|
|
class CSysFreeMe
|
|
{
|
|
protected:
|
|
BSTR m_str;
|
|
|
|
public:
|
|
CSysFreeMe(BSTR str) : m_str(str){}
|
|
~CSysFreeMe() {SysFreeString(m_str);}
|
|
};
|
|
|
|
bool CRepImporter::CheckOldSecurityClass(const wchar_t* wszClass)
|
|
{
|
|
// check whether it is an old security class
|
|
bool bOldSecurityClass = false;
|
|
if(m_bSecurityMode)
|
|
{
|
|
if(!_wcsicmp(wszClass, L"__SecurityRelatedClass"))
|
|
bOldSecurityClass = true;
|
|
else if(!_wcsicmp(wszClass, L"__Subject"))
|
|
bOldSecurityClass = true;
|
|
else if(!_wcsicmp(wszClass, L"__User"))
|
|
bOldSecurityClass = true;
|
|
else if(!_wcsicmp(wszClass, L"__NTLMUser"))
|
|
bOldSecurityClass = true;
|
|
else if(!_wcsicmp(wszClass, L"__Group"))
|
|
bOldSecurityClass = true;
|
|
else if(!_wcsicmp(wszClass, L"__NTLMGroup"))
|
|
bOldSecurityClass = true;
|
|
}
|
|
return bOldSecurityClass;
|
|
}
|
|
|
|
void CRepImporter::DecodeTrailer()
|
|
{
|
|
DWORD dwTrailerSize = 0;
|
|
DWORD dwTrailer[4];
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(m_hFile, &dwTrailerSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to read a block trailer size.");
|
|
throw FAILURE_READ;
|
|
}
|
|
if (dwTrailerSize != REP_EXPORT_END_TAG_SIZE)
|
|
{
|
|
LogMessage(MSG_ERROR, "Block trailer size is invalid.");
|
|
throw FAILURE_INVALID_TRAILER;
|
|
}
|
|
if ((ReadFile(m_hFile, dwTrailer, REP_EXPORT_END_TAG_SIZE, &dwSize, NULL) == 0) || (dwSize != REP_EXPORT_END_TAG_SIZE))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to read a block trailer.");
|
|
throw FAILURE_READ;
|
|
}
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (dwTrailer[i] != REP_EXPORT_FILE_END_TAG)
|
|
{
|
|
LogMessage(MSG_ERROR, "Block trailer has invalid contents.");
|
|
throw FAILURE_INVALID_TRAILER;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CRepImporter::DecodeInstanceInt(IWbemServices* pNamespace, const wchar_t *wszFullPath, const wchar_t *pszParentClass, _IWmiObject* pOldParentClass, _IWmiObject *pNewParentClass)
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
//Read the key and object size
|
|
INT_PTR dwKey = 0;
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(m_hFile, &dwKey, sizeof(INT_PTR), &dwSize, NULL) == 0) || (dwSize != sizeof(INT_PTR)))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance key for class %S. (i)", pszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
DWORD dwHeader;
|
|
if ((ReadFile(m_hFile, &dwHeader, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance object size for class %S. (i)", pszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
char *pObjectBlob = new char[dwHeader];
|
|
if (pObjectBlob == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<char> delMe(pObjectBlob);
|
|
|
|
//Read the blob
|
|
if ((ReadFile(m_hFile, pObjectBlob, dwHeader, &dwSize, NULL) == 0) || (dwSize != dwHeader))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance information for class %S. (i)", pszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
if (pNewParentClass == (_IWmiObject*)-1)
|
|
{
|
|
//We are working with a class which has problems... we need to ignore this instance...
|
|
return;
|
|
}
|
|
|
|
// create old Nova-style instance
|
|
HRESULT hr;
|
|
_IWmiObject* pOldInstance = 0;
|
|
CMyRelMe<_IWmiObject*> relMe(pOldInstance);
|
|
_IWmiObject* pNewInstance = 0;
|
|
CMyRelMe<_IWmiObject*> relMe2(pNewInstance);
|
|
|
|
hr = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE, dwSize, pObjectBlob, &pOldInstance);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to merge old instance (i); HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_MERGE_INSTANCE;
|
|
}
|
|
if (pOldInstance == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe.Set(pOldInstance);
|
|
|
|
// put the new instance into the repository
|
|
hr = pNamespace->PutInstance(pOldInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
|
|
// Original put failed, so we will try to upgrade the instance and retry the put
|
|
// upgrade to new Whistler instance
|
|
hr = pOldInstance->Upgrade(pNewParentClass, 0L, &pNewInstance);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to upgrade to new instance (i); HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_UPGRADE_INSTANCE;
|
|
}
|
|
if (pNewInstance == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe2.Set(pNewInstance);
|
|
|
|
hr = pNamespace->PutInstance(pNewInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
|
|
|
|
if ( FAILED(hr))
|
|
{
|
|
if (!CheckOldSecurityClass(pszParentClass))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance %S.%d in repository. (i); HRESULT = %#lx", pszParentClass, dwKey, hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_INSTANCE;
|
|
}
|
|
else
|
|
{
|
|
// This is an old Win9x security class, but it can't be put yet because the win9x users haven't been migrated at this point in setup.
|
|
// Instead, write it out to the win9x security blob file so it can be processed later after setup is completed
|
|
if (!AppendWin9xBlobFile(wszFullPath, pszParentClass, pNewInstance))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to write Win9x security class to file for instance %S.%d", pszParentClass, dwKey);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void CRepImporter::DecodeInstanceString(IWbemServices* pNamespace, const wchar_t *wszFullPath, const wchar_t *pszParentClass, _IWmiObject* pOldParentClass, _IWmiObject *pNewParentClass)
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
//Read the key and object size
|
|
DWORD dwKeySize;
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(m_hFile, &dwKeySize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance key size for class %S. (s)", pszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
wchar_t *wszKey = new wchar_t[dwKeySize];
|
|
if (wszKey == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<wchar_t> delMe(wszKey);
|
|
if ((ReadFile(m_hFile, wszKey, dwKeySize, &dwSize, NULL) == 0) || (dwSize != dwKeySize))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance key for class %S. (s)", pszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
DWORD dwBlobSize;
|
|
if ((ReadFile(m_hFile, &dwBlobSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance object size for %S.%S from import file. (s)", pszParentClass, wszKey);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
char *pObjectBlob = new char[dwBlobSize];
|
|
if (pObjectBlob == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<char> delMe2(pObjectBlob);
|
|
|
|
//Read the blob
|
|
if ((ReadFile(m_hFile, pObjectBlob, dwBlobSize, &dwSize, NULL) == 0) || (dwSize != dwBlobSize))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance %S.%S from import file. (s)", pszParentClass, wszKey);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
if (pNewParentClass == (_IWmiObject*)-1)
|
|
{
|
|
//We are working with a class which has problems... we need to ignore this instance...
|
|
return;
|
|
}
|
|
|
|
// create old Nova-style instance
|
|
HRESULT hr;
|
|
_IWmiObject* pOldInstance = 0;
|
|
CMyRelMe<_IWmiObject*> relMe(pOldInstance);
|
|
_IWmiObject* pNewInstance = 0;
|
|
CMyRelMe<_IWmiObject*> relMe2(pNewInstance);
|
|
|
|
hr = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE, dwSize, pObjectBlob, &pOldInstance);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to merge old instance (s); HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_MERGE_INSTANCE;
|
|
}
|
|
if (pOldInstance == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe.Set(pOldInstance);
|
|
|
|
// put the instance into the repository
|
|
// if this fails, upgrade and retry
|
|
hr = pNamespace->PutInstance(pOldInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
|
|
// upgrade to new Whistler instance
|
|
hr = pOldInstance->Upgrade(pNewParentClass, 0L, &pNewInstance);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to upgrade to new instance (s); HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_UPGRADE_INSTANCE;
|
|
}
|
|
if (pNewInstance == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe2.Set(pNewInstance);
|
|
|
|
hr = pNamespace->PutInstance(pNewInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
|
|
|
|
if ( FAILED(hr))
|
|
{
|
|
if (!CheckOldSecurityClass(pszParentClass))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance %S.%S in repository. (s); HRESULT = %#lx", pszParentClass, wszKey, hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_INSTANCE;
|
|
}
|
|
else
|
|
{
|
|
// This is an old Win9x security class, but it can't be put yet because the win9x users haven't been migrated at this point in setup.
|
|
// Instead, write it out to the win9x security blob file so it can be processed later after setup is completed
|
|
if (!AppendWin9xBlobFile(wszFullPath, pszParentClass, pNewInstance))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to write Win9x security class to file for instance %S.%S", pszParentClass, wszKey);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CRepImporter::DecodeClass(IWbemServices* pNamespace, const wchar_t *wszFullPath, const wchar_t *wszParentClass, _IWmiObject* pOldParentClass, _IWmiObject *pNewParentClass)
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
//Read our current class from the file...
|
|
HRESULT hr;
|
|
DWORD dwClassSize = 0;
|
|
DWORD dwSize = 0;
|
|
_IWmiObject* pOldClass = 0;
|
|
CMyRelMe<_IWmiObject*> relMe(pOldClass);
|
|
_IWmiObject* pNewClass = 0;
|
|
CMyRelMe<_IWmiObject*> relMe2(pNewClass);
|
|
|
|
if ((ReadFile(m_hFile, &dwClassSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class size for class with parent class %S.", wszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
wchar_t *wszClass = new wchar_t[dwClassSize];
|
|
if (wszClass == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<wchar_t> delMe(wszClass);
|
|
if ((ReadFile(m_hFile, wszClass, dwClassSize, &dwSize, NULL) == 0) || (dwSize != dwClassSize))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class information for class with parent class %S.", wszParentClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
//Now we have the class blob...
|
|
if ((ReadFile(m_hFile, &dwClassSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class size for class %S.", wszClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
if (dwClassSize)
|
|
{
|
|
char *pClassBlob = new char[dwClassSize];
|
|
if (pClassBlob == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<char> delMe2(pClassBlob);
|
|
if ((ReadFile(m_hFile, pClassBlob, dwClassSize, &dwSize, NULL) == 0) || (dwSize != dwClassSize))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class information for class %S.", wszClass);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
if (pNewParentClass == (_IWmiObject*)-1)
|
|
{
|
|
// parent class was bad, so don't process this class
|
|
pNewClass = (_IWmiObject*)-1;
|
|
}
|
|
else
|
|
{
|
|
// create old Nova-style class
|
|
hr = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_CLASS, dwSize, pClassBlob, &pOldClass);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to merge old class; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_MERGE_CLASS;
|
|
}
|
|
if (pOldClass == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe.Set(pOldClass);
|
|
|
|
//If the class is a system class then we do not write it... it may have changed for starters,
|
|
//but also we create all system classes when a new database/namespace is created...
|
|
if (_wcsnicmp(wszClass, L"__", 2) != 0)
|
|
{
|
|
// put the class into the repository
|
|
// if this fails, upgrade it and retry
|
|
hr = pNamespace->PutClass(pOldClass, WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_UPDATE_FORCE_MODE, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
|
|
// upgrade to new Whistler class (note: pNewParentClass will be NULL for base classes)
|
|
hr = pOldClass->Upgrade(pNewParentClass, 0L, &pNewClass);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to upgrade to new class; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_UPGRADE_CLASS;
|
|
}
|
|
if (pNewClass == 0)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe2.Set(pNewClass);
|
|
|
|
// retry the put
|
|
hr = pNamespace->PutClass(pNewClass, WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_UPDATE_FORCE_MODE, NULL, NULL);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create class for class %S; HRESULT = %#lx", wszClass, hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_CLASS;
|
|
}
|
|
}
|
|
}
|
|
|
|
// We need to re-get the class as class comparisons may fail to see
|
|
// that this class is in fact the same as the one in the database!
|
|
if ( NULL != pNewClass )
|
|
{
|
|
pNewClass->Release();
|
|
pNewClass = 0;
|
|
relMe2.Set(NULL);
|
|
}
|
|
|
|
BSTR bstrClassName = SysAllocString(wszClass);
|
|
if (!bstrClassName)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrClassName);
|
|
hr = pNamespace->GetObject(bstrClassName, 0L, NULL, (IWbemClassObject**) &pNewClass, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
if (_wcsnicmp(wszClass, L"__", 2) != 0)
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class %S from the repository after creating it; HRESULT = %#lx", wszClass, hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_GET_PARENT_CLASS;
|
|
}
|
|
else
|
|
{
|
|
if (_wcsicmp(wszClass, L"__CIMOMIdentification") != 0) // we don't want to warn about failures to retrieve this class
|
|
{
|
|
// couldn't get the system class
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve system class %S from the repository; HRESULT = %#lx", wszClass, hr);
|
|
LogMessage(MSG_WARNING, szMsg);
|
|
}
|
|
|
|
// set pointer to -1 and continue processing file
|
|
// old comment said: If this does not exist then it cannot be important!
|
|
pNewClass = (_IWmiObject*)-1;
|
|
}
|
|
}
|
|
else
|
|
relMe2.Set(pNewClass);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This is a situation where we have a class in the export file,
|
|
// but the size is zero, so we just get the class from the repository.
|
|
|
|
// ***** So what do we do about pOldClass? At this point it is NULL. *****
|
|
// ***** We need the old class to be able to upgrade child classes properly. *****
|
|
|
|
if (pNewParentClass == (_IWmiObject*)-1)
|
|
{
|
|
// parent class was bad, so don't process this class
|
|
pNewClass = (_IWmiObject*)-1;
|
|
}
|
|
else
|
|
{
|
|
// get the class from the repository
|
|
BSTR bstrClassName = SysAllocString(wszClass);
|
|
if (!bstrClassName)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrClassName);
|
|
hr = pNamespace->GetObject(bstrClassName, 0L, NULL, (IWbemClassObject**) &pNewClass, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class %S from the repository; HRESULT = %#lx", wszClass, hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_GET_PARENT_CLASS;
|
|
}
|
|
relMe2.Set(pNewClass);
|
|
}
|
|
}
|
|
|
|
//Now we iterate through all child classes and instances until we get an end of class marker...
|
|
while (1)
|
|
{
|
|
DWORD dwType = 0;
|
|
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to read next block type from import file.");
|
|
throw FAILURE_READ;
|
|
}
|
|
if (dwType == REP_EXPORT_CLASS_TAG)
|
|
{
|
|
DecodeClass(pNamespace, wszFullPath, wszClass, pOldClass, pNewClass);
|
|
}
|
|
else if (dwType == REP_EXPORT_INST_INT_TAG)
|
|
{
|
|
DecodeInstanceInt(pNamespace, wszFullPath, wszClass, pOldClass, pNewClass);
|
|
}
|
|
else if (dwType == REP_EXPORT_INST_STR_TAG)
|
|
{
|
|
DecodeInstanceString(pNamespace, wszFullPath, wszClass, pOldClass, pNewClass);
|
|
}
|
|
else if (dwType == REP_EXPORT_CLASS_END_TAG)
|
|
{
|
|
//That's the end of this class...
|
|
DecodeTrailer();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
LogMessage(MSG_ERROR, "Next block type in import file is invalid.");
|
|
throw FAILURE_INVALID_TYPE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CRepImporter::DecodeNamespace(IWbemServices* pParentNamespace, const wchar_t *wszParentNamespace)
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
//Read our current namespace from the file...
|
|
DWORD dwNsSize = 0;
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(m_hFile, &dwNsSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace whose parent namespace is %S.", wszParentNamespace);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
wchar_t *wszNs = new wchar_t[dwNsSize];
|
|
if (wszNs == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<wchar_t> delMe(wszNs);
|
|
if ((ReadFile(m_hFile, wszNs, dwNsSize, &dwSize, NULL) == 0) || (dwSize != dwNsSize))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace whose parent namespace is %S.", wszParentNamespace);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
if (wbem_wcsicmp(wszNs, L"security") == 0)
|
|
{
|
|
m_bSecurityMode = true;
|
|
}
|
|
|
|
wchar_t *wszFullPath = new wchar_t[wcslen(wszParentNamespace) + 1 + wcslen(wszNs) + 1];
|
|
if (wszFullPath == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<wchar_t> delMe2(wszFullPath);
|
|
StringCchCopyW(wszFullPath, MAX_MSG_TEXT_LENGTH, wszParentNamespace);
|
|
if (wcslen(wszParentNamespace) != 0)
|
|
{
|
|
StringCchCatW(wszFullPath, MAX_MSG_TEXT_LENGTH, L"\\");
|
|
}
|
|
StringCchCatW(wszFullPath, MAX_MSG_TEXT_LENGTH, wszNs);
|
|
|
|
// open the namespace
|
|
IWbemServices* pNamespace = NULL;
|
|
CMyRelMe<IWbemServices*> relMe2(pNamespace);
|
|
HRESULT hr;
|
|
|
|
if (pParentNamespace)
|
|
{
|
|
BSTR bstrNamespace = SysAllocString(wszNs);
|
|
if (!bstrNamespace)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrNamespace);
|
|
hr = pParentNamespace->OpenNamespace(bstrNamespace, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, NULL, &pNamespace, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve namespace %S from the repository; HRESULT = %#lx", wszFullPath, hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_FIND_NAMESPACE;
|
|
}
|
|
}
|
|
else // special start case for root
|
|
{
|
|
IWbemLocator* pLocator = NULL;
|
|
CMyRelMe<IWbemLocator*> relMe(pLocator);
|
|
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_IWbemLocator, (void**) &pLocator);
|
|
if(FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWbemLocator; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_IWBEMLOCATOR;
|
|
}
|
|
else
|
|
{
|
|
relMe.Set(pLocator);
|
|
BSTR bstrNamespace = SysAllocString(L"root");
|
|
if (!bstrNamespace)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrNamespace);
|
|
hr = pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, NULL, NULL, &pNamespace);
|
|
if (FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to connect server; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CONNECT_SERVER;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pNamespace == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe2.Set(pNamespace);
|
|
|
|
//Get and set the namespace security...
|
|
DWORD dwBuffer[2];
|
|
if ((ReadFile(m_hFile, dwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace security header for namespace %S.", wszFullPath);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
if (dwBuffer[0] != REP_EXPORT_NAMESPACE_SEC_TAG)
|
|
{
|
|
LogMessage(MSG_ERROR, "Expecting a namespace security blob and did not find it.");
|
|
throw FAILURE_INVALID_TYPE;
|
|
}
|
|
if (dwBuffer[1] != 0)
|
|
{
|
|
char *pNsSecurity = new char[dwBuffer[1]];
|
|
CVectorDeleteMe<char> delMe3(pNsSecurity);
|
|
|
|
if (pNsSecurity == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
if ((ReadFile(m_hFile, pNsSecurity, dwBuffer[1], &dwSize, NULL) == 0) || (dwSize != dwBuffer[1]))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace security blob for namespace %S.", wszFullPath);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_READ;
|
|
}
|
|
|
|
// we have the security blob, now set the SECURITY_DESCRIPTOR property in the namespace
|
|
DecodeNamespaceSecurity(pNamespace, pParentNamespace, pNsSecurity, dwBuffer[1], wszFullPath);
|
|
}
|
|
|
|
// create empty Nova-style class object for use in decoding base classes
|
|
_IWmiObjectFactory* pObjFactory = NULL;
|
|
CMyRelMe<_IWmiObjectFactory*> relMe3(pObjFactory);
|
|
hr = CoCreateInstance(CLSID__WmiObjectFactory, NULL, CLSCTX_ALL, IID__IWmiObjectFactory, (void**) &pObjFactory);
|
|
if(FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWmiObjectFactory; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_OBJECTFACTORY;
|
|
}
|
|
if (pObjFactory == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe3.Set(pObjFactory);
|
|
|
|
_IWmiObject* pBaseObject = NULL;
|
|
CMyRelMe<_IWmiObject*> relMe4(pBaseObject);
|
|
hr = pObjFactory->Create(NULL, 0L, CLSID__WbemEmptyClassObject, IID__IWmiObject, (void**) &pBaseObject);
|
|
if(FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWmiObject; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_IWMIOBJECT;
|
|
}
|
|
if (pBaseObject == NULL)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
relMe4.Set(pBaseObject);
|
|
|
|
//Now we need to iterate through the next set of blocks of namespace or class
|
|
//until we get to an end of NS marker
|
|
while (1)
|
|
{
|
|
DWORD dwType = 0;
|
|
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to read next block type (namespace/class) from import file.");
|
|
throw FAILURE_READ;
|
|
}
|
|
if (dwType == REP_EXPORT_NAMESPACE_TAG)
|
|
{
|
|
DecodeNamespace(pNamespace, wszFullPath);
|
|
}
|
|
else if (dwType == REP_EXPORT_CLASS_TAG)
|
|
{
|
|
DecodeClass(pNamespace, wszFullPath, L"", pBaseObject, NULL);
|
|
}
|
|
else if (dwType == REP_EXPORT_NAMESPACE_END_TAG)
|
|
{
|
|
//That's the end of this namespace...
|
|
DecodeTrailer();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
LogMessage(MSG_ERROR, "Next block type (namespace/class) in import file is invalid.");
|
|
throw FAILURE_INVALID_TYPE;
|
|
}
|
|
}
|
|
|
|
m_bSecurityMode = false;
|
|
}
|
|
|
|
void CRepImporter::DecodeNamespaceSecurity(IWbemServices* pNamespace, IWbemServices* pParentNamespace, const char* pNsSecurity, DWORD dwSize, const wchar_t* wszFullPath)
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
// determine whether we have an old Win9x pseudo-blob
|
|
DWORD dwStoredAsNT = 0;
|
|
if (pNsSecurity)
|
|
{
|
|
DWORD* pdwData = (DWORD*)pNsSecurity;
|
|
DWORD dwBlobSize = *pdwData;
|
|
pdwData++;
|
|
DWORD dwVersion = *pdwData;
|
|
if(dwVersion != 1 || dwBlobSize == 0 || dwBlobSize > 64000)
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Invalid namespace security blob header for namespace %S.", wszFullPath);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
return;
|
|
}
|
|
|
|
pdwData++;
|
|
dwStoredAsNT = *pdwData;
|
|
}
|
|
|
|
if (!dwStoredAsNT)
|
|
{
|
|
// Do not process Win9x security blobs, because Win9x users haven't been migrated over yet at this point in setup.
|
|
// Instead, write them out to a file to be processed after setup is complete.
|
|
|
|
if (!AppendWin9xBlobFile(wszFullPath, dwSize, pNsSecurity))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to write Win9x security blob to file for namespace %S.", wszFullPath);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// now transform the old security blob that consisted of a header and array of ACE's
|
|
// into a proper Security Descriptor that can be stored in the property
|
|
|
|
CNtSecurityDescriptor mmfNsSD;
|
|
if (!TransformBlobToSD(pParentNamespace, pNsSecurity, dwStoredAsNT, mmfNsSD))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to convert security blob to SD for namespace %S.", wszFullPath);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
return;
|
|
}
|
|
|
|
// now set the security
|
|
if (!SetNamespaceSecurity(pNamespace, mmfNsSD))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to set namespace security for namespace %S.", wszFullPath);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void CRepImporter::Decode()
|
|
{
|
|
char pszBuff[7];
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(m_hFile, pszBuff, 7, &dwSize, NULL) == 0) || (dwSize != 7))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to retrieve the import file header information.");
|
|
throw FAILURE_READ;
|
|
}
|
|
if (strncmp(pszBuff, REP_EXPORT_FILE_START_TAG, 7) != 0)
|
|
{
|
|
LogMessage(MSG_ERROR, "The import file specified is not an import file.");
|
|
throw FAILURE_INVALID_FILE;
|
|
}
|
|
|
|
//We should have a tag for a namespace...
|
|
DWORD dwType = 0;
|
|
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to read next block type from import file.");
|
|
throw FAILURE_READ;
|
|
}
|
|
if (dwType != REP_EXPORT_NAMESPACE_TAG)
|
|
{
|
|
LogMessage(MSG_ERROR, "Next block type in import file is invalid.");
|
|
throw FAILURE_INVALID_TYPE;
|
|
}
|
|
DecodeNamespace(NULL, L"");
|
|
|
|
// if we opened a Win9x security blob upgrade file, close it
|
|
CloseWin9xBlobFile();
|
|
|
|
// force ROOT\DEFAULT and ROOT\SECURITY namespaces to inherit their inheritable security settings
|
|
ForceInherit();
|
|
|
|
//Now we should have the file trailer
|
|
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to read next block type (trailer) from import file.");
|
|
throw FAILURE_READ;
|
|
}
|
|
if (dwType != REP_EXPORT_FILE_END_TAG)
|
|
{
|
|
LogMessage(MSG_ERROR, "Next block type (trailer) in import file is invalid.");
|
|
throw FAILURE_INVALID_TYPE;
|
|
}
|
|
DecodeTrailer();
|
|
}
|
|
|
|
int CRepImporter::ImportRepository(const TCHAR *pszFromFile)
|
|
{
|
|
LogMessage(MSG_INFO, "Beginning ImportRepository");
|
|
|
|
int nRet = no_error;
|
|
m_hFile = CreateFile(pszFromFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
try
|
|
{
|
|
Decode();
|
|
}
|
|
catch (CX_MemoryException)
|
|
{
|
|
LogMessage(MSG_ERROR, "Memory Exception.");
|
|
nRet = out_of_memory;
|
|
}
|
|
catch (...)
|
|
{
|
|
LogMessage(MSG_ERROR, "Traversal of import file failed.");
|
|
nRet = critical_error;
|
|
}
|
|
CloseHandle(m_hFile);
|
|
}
|
|
else
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Could not open the import file \"%s\" for reading.", pszFromFile);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
nRet = critical_error;
|
|
}
|
|
|
|
if (nRet == no_error)
|
|
LogMessage(MSG_INFO, "ImportRepository completed successfully.");
|
|
else
|
|
LogMessage(MSG_ERROR, "ImportRepository failed to complete.");
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//
|
|
// Helper functions for DecodeNamespaceSecurity
|
|
//
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
bool CRepImporter::TransformBlobToSD(IWbemServices* pParentNamespace, const char* pNsSecurity, DWORD dwStoredAsNT, CNtSecurityDescriptor& mmfNsSD)
|
|
{
|
|
// now transform the old security blob that consisted of a header and array of ACE's
|
|
// into a proper Security Descriptor that can be stored in the property
|
|
|
|
// build up an ACL from our blob, if we have one
|
|
CNtAcl acl;
|
|
|
|
if (pNsSecurity)
|
|
{
|
|
DWORD* pdwData = (DWORD*) pNsSecurity;
|
|
pdwData += 3;
|
|
int iAceCount = (int)*pdwData;
|
|
pdwData += 2;
|
|
BYTE* pAceData = (BYTE*)pdwData;
|
|
|
|
PGENERIC_ACE pAce = NULL;
|
|
for (int iCnt = 0; iCnt < iAceCount; iCnt++)
|
|
{
|
|
pAce = (PGENERIC_ACE)pAceData;
|
|
if (!pAce)
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to access GENERIC_ACE within security blob");
|
|
return false;
|
|
}
|
|
|
|
CNtAce ace(pAce);
|
|
if(ace.GetStatus() != 0)
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to construct CNtAce from GENERIC_ACE");
|
|
return false;
|
|
}
|
|
|
|
acl.AddAce(&ace);
|
|
if (acl.GetStatus() != 0)
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to add ACE to ACL");
|
|
return false;
|
|
}
|
|
|
|
pAceData += ace.GetSize();
|
|
}
|
|
}
|
|
|
|
// a real SD was constructed and passed in by reference, now set it up properly
|
|
SetOwnerAndGroup(mmfNsSD);
|
|
mmfNsSD.SetDacl(&acl);
|
|
if (mmfNsSD.GetStatus() != 0)
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to convert namespace security blob to SD");
|
|
return false;
|
|
}
|
|
|
|
// add in the parent's inheritable aces, if this is not ROOT
|
|
if (pParentNamespace)
|
|
{
|
|
if (!GetParentsInheritableAces(pParentNamespace, mmfNsSD))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to inherit parent's inheritable ACE's");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CRepImporter::SetNamespaceSecurity(IWbemServices* pNamespace, CNtSecurityDescriptor& mmfNsSD)
|
|
{
|
|
// now set the security
|
|
|
|
if (!pNamespace)
|
|
return false;
|
|
|
|
IWbemClassObject* pThisNamespace = NULL;
|
|
BSTR bstrNamespace = SysAllocString(L"__thisnamespace=@");
|
|
if (!bstrNamespace)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrNamespace);
|
|
HRESULT hr = pNamespace->GetObject(bstrNamespace, 0, NULL, &pThisNamespace, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to get singleton namespace object");
|
|
return false;
|
|
}
|
|
CMyRelMe<IWbemClassObject*> relMe(pThisNamespace);
|
|
|
|
|
|
//
|
|
// Check to see if namespace contains any ALLOW or DENY ACEs for NETWORK/LOCAL SERVICE
|
|
// If they do exist, we leave them as is, otherwise we want to add them to the SD.
|
|
//
|
|
if ( CheckNetworkLocalService ( mmfNsSD ) == false )
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to add NETWORK/LOCAL service ACEs");
|
|
return false;
|
|
}
|
|
|
|
SAFEARRAY FAR* psa;
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
rgsabound[0].lLbound = 0;
|
|
rgsabound[0].cElements = mmfNsSD.GetSize();
|
|
psa = SafeArrayCreate( VT_UI1, 1 , rgsabound );
|
|
if (!psa)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
|
|
char* pData = NULL;
|
|
hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pData);
|
|
if (FAILED(hr))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed SafeArrayAccessData");
|
|
return false;
|
|
}
|
|
memcpy(pData, mmfNsSD.GetPtr(), mmfNsSD.GetSize());
|
|
hr = SafeArrayUnaccessData(psa);
|
|
if (FAILED(hr))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed SafeArrayUnaccessData");
|
|
return false;
|
|
}
|
|
pData = NULL;
|
|
|
|
VARIANT var;
|
|
var.vt = VT_UI1|VT_ARRAY;
|
|
var.parray = psa;
|
|
hr = pThisNamespace->Put(L"SECURITY_DESCRIPTOR" , 0, &var, 0);
|
|
VariantClear(&var);
|
|
if (FAILED(hr))
|
|
{
|
|
if (hr == WBEM_E_OUT_OF_MEMORY)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to put SECURITY_DESCRIPTOR property");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
hr = pNamespace->PutInstance(pThisNamespace, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
if (hr == WBEM_E_OUT_OF_MEMORY)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to put back singleton instance");
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
--------------------------------------------------------------------------
|
|
|
|
|
| Checks to see if the namespace had a previous ACE with NETWORK or LOCAL
|
|
| service accounts. If so, it simply leaves them, otherwise, it adds a
|
|
| ACE with default settings for these accounts. The default settings are:
|
|
| WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER
|
|
| The characteristics of the ACE is irrelevant. Only SID comparison applies.
|
|
|
|
|
--------------------------------------------------------------------------
|
|
*/
|
|
bool CRepImporter::CheckNetworkLocalService ( CNtSecurityDescriptor& mmfNsSD )
|
|
{
|
|
DWORD dwAccessMaskNetworkLocalService = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER ;
|
|
PSID pRawSid = NULL ;
|
|
SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
|
|
BOOL bStatus = TRUE ;
|
|
BYTE flags = 0 ;
|
|
|
|
CNtAcl* pAcl = mmfNsSD.GetDacl ( ) ;
|
|
CDeleteMe<CNtAcl> AclDelete ( pAcl ) ;
|
|
|
|
//
|
|
// Start with NETWORK_SERVICE account
|
|
//
|
|
if(AllocateAndInitializeSid( &id, 1,
|
|
SECURITY_NETWORK_SERVICE_RID,0,0,0,0,0,0,0,&pRawSid))
|
|
{
|
|
CNtSid SidNetworkService (pRawSid);
|
|
FreeSid(pRawSid);
|
|
|
|
{
|
|
CNtAce * pace = new CNtAce(dwAccessMaskNetworkLocalService,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE,
|
|
SidNetworkService );
|
|
if ( NULL == pace )
|
|
{
|
|
bStatus = FALSE ;
|
|
}
|
|
else
|
|
{
|
|
CDeleteMe<CNtAce> dm(pace);
|
|
pAcl->AddAce(pace);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Next, LOCAL_SERVICE account
|
|
//
|
|
if ( bStatus == TRUE )
|
|
{
|
|
pRawSid = NULL ;
|
|
if(AllocateAndInitializeSid( &id, 1,
|
|
SECURITY_LOCAL_SERVICE_RID,0,0,0,0,0,0,0,&pRawSid))
|
|
{
|
|
CNtSid SidLocalService (pRawSid);
|
|
FreeSid(pRawSid);
|
|
|
|
{
|
|
CNtAce * pace = new CNtAce(dwAccessMaskNetworkLocalService,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE,
|
|
SidLocalService );
|
|
if ( NULL == pace )
|
|
{
|
|
bStatus = FALSE ;
|
|
}
|
|
else
|
|
{
|
|
CDeleteMe<CNtAce> dm(pace);
|
|
pAcl->AddAce(pace);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( bStatus == TRUE )
|
|
{
|
|
mmfNsSD.SetDacl ( pAcl ) ;
|
|
}
|
|
return bStatus ? true : false ;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CRepImporter::GetParentsInheritableAces(IWbemServices* pParentNamespace, CNtSecurityDescriptor &sd)
|
|
{
|
|
if (!pParentNamespace)
|
|
return false;
|
|
|
|
// Get the parent namespace's SD
|
|
CNtSecurityDescriptor sdParent;
|
|
if (!GetSDFromNamespace(pParentNamespace, sdParent))
|
|
return false;
|
|
|
|
// strip out the inherited aces so we have a consistent SD
|
|
if (!StripOutInheritedAces(sd))
|
|
return false;
|
|
|
|
// Go through the parents dacl and add any inheritable aces to ours.
|
|
if (!CopyInheritAces(sd, sdParent))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CRepImporter::GetSDFromNamespace(IWbemServices* pNamespace, CNtSecurityDescriptor& sd)
|
|
{
|
|
if (!pNamespace)
|
|
return false;
|
|
|
|
// get the singleton object
|
|
IWbemClassObject* pThisNamespace = NULL;
|
|
BSTR bstrNamespace = SysAllocString(L"__thisnamespace=@");
|
|
if (!bstrNamespace)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrNamespace);
|
|
HRESULT hr = pNamespace->GetObject(bstrNamespace, 0, NULL, &pThisNamespace, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
LogMessage(MSG_ERROR, "Failed to get singleton namespace object");
|
|
return false;
|
|
}
|
|
CMyRelMe<IWbemClassObject*> relMe(pThisNamespace);
|
|
|
|
// Get the security descriptor argument
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hr = pThisNamespace->Get(L"SECURITY_DESCRIPTOR", 0, &var, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
VariantClear(&var);
|
|
LogMessage(MSG_ERROR, "Failed to get SECURITY_DESCRIPTOR property");
|
|
return false;
|
|
}
|
|
|
|
if(var.vt != (VT_ARRAY | VT_UI1))
|
|
{
|
|
VariantClear(&var);
|
|
LogMessage(MSG_ERROR, "Failed to get SECURITY_DESCRIPTOR property due to incorrect variant type");
|
|
return false;
|
|
}
|
|
|
|
SAFEARRAY* psa = var.parray;
|
|
PSECURITY_DESCRIPTOR pSD;
|
|
hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pSD);
|
|
if (FAILED(hr))
|
|
{
|
|
VariantClear(&var);
|
|
LogMessage(MSG_ERROR, "GetSDFromNamespace failed SafeArrayAccessData");
|
|
return false;
|
|
}
|
|
|
|
BOOL bValid = IsValidSecurityDescriptor(pSD);
|
|
if (!bValid)
|
|
{
|
|
VariantClear(&var);
|
|
LogMessage(MSG_ERROR, "GetSDFromNamespace retrieved an invalid security descriptor");
|
|
return false;
|
|
}
|
|
|
|
CNtSecurityDescriptor sdNew(pSD);
|
|
|
|
// Check to make sure the owner and group is not NULL!!!!
|
|
CNtSid *pTmpSid = sdNew.GetOwner();
|
|
if (pTmpSid == NULL)
|
|
{
|
|
LogMessage(MSG_ERROR, "Security descriptor was retrieved and it had no owner");
|
|
}
|
|
delete pTmpSid;
|
|
|
|
pTmpSid = sdNew.GetGroup();
|
|
if (pTmpSid == NULL)
|
|
{
|
|
LogMessage(MSG_ERROR, "Security descriptor was retrieved and it had no group");
|
|
}
|
|
delete pTmpSid;
|
|
|
|
sd = sdNew;
|
|
SafeArrayUnaccessData(psa);
|
|
VariantClear(&var);
|
|
return true;
|
|
}
|
|
|
|
bool CRepImporter::StripOutInheritedAces(CNtSecurityDescriptor &sd)
|
|
{
|
|
// Get the DACL
|
|
CNtAcl* pAcl;
|
|
pAcl = sd.GetDacl();
|
|
if(!pAcl)
|
|
return false;
|
|
CDeleteMe<CNtAcl> dm(pAcl);
|
|
|
|
// enumerate through the aces
|
|
DWORD dwNumAces = pAcl->GetNumAces();
|
|
BOOL bChanged = FALSE;
|
|
for(long nIndex = (long)dwNumAces-1; nIndex >= 0; nIndex--)
|
|
{
|
|
CNtAce *pAce = pAcl->GetAce(nIndex);
|
|
if(pAce)
|
|
{
|
|
long lFlags = pAce->GetFlags();
|
|
if(lFlags & INHERITED_ACE)
|
|
{
|
|
pAcl->DeleteAce(nIndex);
|
|
bChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if(bChanged)
|
|
sd.SetDacl(pAcl);
|
|
return true;
|
|
}
|
|
|
|
bool CRepImporter::CopyInheritAces(CNtSecurityDescriptor& sd, CNtSecurityDescriptor& sdParent)
|
|
{
|
|
// Get the acl list for both SDs
|
|
|
|
CNtAcl * pacl = sd.GetDacl();
|
|
if(pacl == NULL)
|
|
return false;
|
|
CDeleteMe<CNtAcl> dm0(pacl);
|
|
|
|
CNtAcl * paclParent = sdParent.GetDacl();
|
|
if(paclParent == NULL)
|
|
return false;
|
|
CDeleteMe<CNtAcl> dm1(paclParent);
|
|
|
|
int iNumParent = paclParent->GetNumAces();
|
|
for(int iCnt = 0; iCnt < iNumParent; iCnt++)
|
|
{
|
|
CNtAce *pParentAce = paclParent->GetAce(iCnt);
|
|
CDeleteMe<CNtAce> dm2(pParentAce);
|
|
|
|
long lFlags = pParentAce->GetFlags();
|
|
if(lFlags & CONTAINER_INHERIT_ACE)
|
|
{
|
|
|
|
if(lFlags & NO_PROPAGATE_INHERIT_ACE)
|
|
lFlags ^= CONTAINER_INHERIT_ACE;
|
|
lFlags |= INHERITED_ACE;
|
|
|
|
// If this is an inherit only ace we need to clear this
|
|
// in the children.
|
|
// NT RAID: 161761 [marioh]
|
|
if ( lFlags & INHERIT_ONLY_ACE )
|
|
lFlags ^= INHERIT_ONLY_ACE;
|
|
|
|
pParentAce->SetFlags(lFlags);
|
|
pacl->AddAce(pParentAce);
|
|
}
|
|
}
|
|
sd.SetDacl(pacl);
|
|
return true;
|
|
}
|
|
|
|
BOOL CRepImporter::SetOwnerAndGroup(CNtSecurityDescriptor &sd)
|
|
{
|
|
PSID pRawSid;
|
|
BOOL bRet = FALSE;
|
|
|
|
SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
|
|
if(AllocateAndInitializeSid( &id, 2,
|
|
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
|
|
0,0,0,0,0,0,&pRawSid))
|
|
{
|
|
CNtSid SidAdmins(pRawSid);
|
|
bRet = sd.SetGroup(&SidAdmins); // Access check doesn't really care what you put,
|
|
// so long as you put something for the owner
|
|
if(bRet)
|
|
bRet = sd.SetOwner(&SidAdmins);
|
|
FreeSid(pRawSid);
|
|
return bRet;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void CRepImporter::ForceInherit()
|
|
{
|
|
// force ROOT\DEFAULT and ROOT\SECURITY namespaces to inherit their inheritable security settings
|
|
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
IWbemLocator* pLocator = NULL;
|
|
HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_IWbemLocator, (void**) &pLocator);
|
|
if(FAILED(hr))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWbemLocator; HRESULT = %#lx", hr);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CREATE_IWBEMLOCATOR;
|
|
}
|
|
CMyRelMe<IWbemLocator*> relMe1(pLocator);
|
|
|
|
IWbemServices* pRootNamespace = NULL;
|
|
ConnectNamespace(pLocator, L"root", &pRootNamespace);
|
|
CMyRelMe<IWbemServices*> relMe2(pRootNamespace);
|
|
|
|
if (!InheritSecurity(pLocator, pRootNamespace, L"root\\default"))
|
|
LogMessage(MSG_ERROR, "Failed to force inherit for root\\default");
|
|
|
|
if (!InheritSecurity(pLocator, pRootNamespace, L"root\\security"))
|
|
LogMessage(MSG_ERROR, "Failed to force inherit for root\\security");
|
|
}
|
|
|
|
bool CRepImporter::InheritSecurity(IWbemLocator* pLocator, IWbemServices* pRootNamespace, const wchar_t* wszNamespace)
|
|
{
|
|
IWbemServices* pNamespace = NULL;
|
|
ConnectNamespace(pLocator, wszNamespace, &pNamespace);
|
|
CMyRelMe<IWbemServices*> relMe(pNamespace);
|
|
|
|
CNtSecurityDescriptor sdNamespace;
|
|
if (!GetSDFromNamespace(pNamespace, sdNamespace))
|
|
return false;
|
|
|
|
if (!GetParentsInheritableAces(pRootNamespace, sdNamespace))
|
|
return false;
|
|
|
|
if (!SetNamespaceSecurity(pNamespace, sdNamespace))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CRepImporter::ConnectNamespace(IWbemLocator* pLocator, const wchar_t* wszNamespaceName, IWbemServices** ppNamespace)
|
|
{
|
|
char szMsg[MAX_MSG_TEXT_LENGTH];
|
|
|
|
// get the namespace
|
|
BSTR bstrNamespace = SysAllocString(wszNamespaceName);
|
|
if (!bstrNamespace)
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
CSysFreeMe fm(bstrNamespace);
|
|
|
|
HRESULT hres = pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, NULL, NULL, ppNamespace);
|
|
if (FAILED(hres))
|
|
{
|
|
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to connect server for namespace %S; HRESULT = %#lx", wszNamespaceName, hres);
|
|
LogMessage(MSG_ERROR, szMsg);
|
|
throw FAILURE_CANNOT_CONNECT_SERVER;
|
|
}
|
|
if (!*ppNamespace)
|
|
{
|
|
throw FAILURE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//
|
|
// Helper functions for Win9x security processing
|
|
//
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
bool CRepImporter::AppendWin9xBlobFile(const wchar_t* wszFullPath, DWORD dwBlobSize, const char* pNsSecurity)
|
|
{
|
|
// check whether we need to create the blob file
|
|
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
if (!CreateWin9xBlobFile())
|
|
return false;
|
|
}
|
|
|
|
// write the blob header containing the type, namespace name size, and blob size to the file
|
|
BLOB9X_SPACER header;
|
|
header.dwSpacerType = BLOB9X_TYPE_SECURITY_BLOB;
|
|
header.dwNamespaceNameSize = (wcslen(wszFullPath)+1)*sizeof(wchar_t);
|
|
header.dwParentClassNameSize = 0;
|
|
header.dwBlobSize = dwBlobSize;
|
|
DWORD dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) && (dwSize == sizeof(header)))
|
|
{
|
|
// write the namespace name to the file
|
|
dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, wszFullPath, header.dwNamespaceNameSize, &dwSize, NULL) && (dwSize == header.dwNamespaceNameSize))
|
|
{
|
|
// write the blob to the file
|
|
dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, pNsSecurity, dwBlobSize, &dwSize, NULL) && (dwSize == dwBlobSize))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// if we failed to write to the file, something is wrong with the file, so close and delete it
|
|
DeleteWin9xBlobFile();
|
|
return false;
|
|
}
|
|
|
|
bool CRepImporter::AppendWin9xBlobFile(const wchar_t* wszFullPath, const wchar_t* wszParentClass, _IWmiObject* pInstance)
|
|
{
|
|
// check whether we need to create the blob file
|
|
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
if (!CreateWin9xBlobFile())
|
|
return false;
|
|
}
|
|
|
|
//Get the size of the object
|
|
DWORD dwObjPartLen = 0;
|
|
HRESULT hRes = pInstance->Unmerge(0, 0, &dwObjPartLen, 0);
|
|
|
|
//Allocate the size of the object
|
|
BYTE *pObjPart = NULL;
|
|
if (hRes == WBEM_E_BUFFER_TOO_SMALL)
|
|
{
|
|
hRes = WBEM_S_NO_ERROR;
|
|
pObjPart = new BYTE[dwObjPartLen];
|
|
}
|
|
|
|
if (pObjPart)
|
|
{
|
|
CVectorDeleteMe<BYTE> delMe(pObjPart);
|
|
|
|
//retrieve the object blob
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
DWORD dwLen;
|
|
hRes = pInstance->Unmerge(0, dwObjPartLen, &dwLen, pObjPart);
|
|
}
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// write the blob header containing the type, namespace name size, parent class name size, and blob size to the file
|
|
BLOB9X_SPACER header;
|
|
header.dwSpacerType = BLOB9X_TYPE_SECURITY_INSTANCE;
|
|
header.dwNamespaceNameSize = (wcslen(wszFullPath)+1)*sizeof(wchar_t);
|
|
header.dwParentClassNameSize = (wcslen(wszParentClass)+1)*sizeof(wchar_t);
|
|
header.dwBlobSize = dwObjPartLen;
|
|
DWORD dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) && (dwSize == sizeof(header)))
|
|
{
|
|
// write the namespace name to the file
|
|
dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, wszFullPath, header.dwNamespaceNameSize, &dwSize, NULL) && (dwSize == header.dwNamespaceNameSize))
|
|
{
|
|
// write the parent class name to the file
|
|
dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, wszParentClass, header.dwParentClassNameSize, &dwSize, NULL) && (dwSize == header.dwParentClassNameSize))
|
|
{
|
|
// write the blob to the file
|
|
dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, pObjPart, dwObjPartLen, &dwSize, NULL) && (dwSize == dwObjPartLen))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if we failed to write to the file, something is wrong with the file, so close and delete it
|
|
DeleteWin9xBlobFile();
|
|
return false;
|
|
}
|
|
|
|
bool CRepImporter::CreateWin9xBlobFile()
|
|
{
|
|
// get the root directory of the repository
|
|
wchar_t wszFilePath[MAX_PATH+1];
|
|
if (!GetRepositoryDirectory(wszFilePath))
|
|
return false;
|
|
|
|
// append blob file name
|
|
StringCchCatW(wszFilePath, MAX_PATH+1, BLOB9X_FILENAME);
|
|
|
|
// create a new file in which to store blob info
|
|
m_h9xBlobFile = CreateFileW(wszFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
|
|
return false;
|
|
|
|
// write the blob file header
|
|
BLOB9X_HEADER header;
|
|
StringCchCopyA(header.szSignature, sizeof(header.szSignature)/sizeof(char), BLOB9X_SIGNATURE);
|
|
DWORD dwSize = 0;
|
|
if (WriteFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) && (dwSize == sizeof(header)))
|
|
return true;
|
|
|
|
// if we failed to write to the file we should close the handle and delete the file
|
|
CloseHandle(m_h9xBlobFile);
|
|
DeleteFileW(wszFilePath);
|
|
m_h9xBlobFile = INVALID_HANDLE_VALUE;
|
|
return false;
|
|
}
|
|
|
|
void CRepImporter::DeleteWin9xBlobFile()
|
|
{
|
|
// close and invalidate the handle if necessary
|
|
if (m_h9xBlobFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(m_h9xBlobFile);
|
|
m_h9xBlobFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
// delete the file
|
|
wchar_t wszFilePath[MAX_PATH+1];
|
|
if (GetRepositoryDirectory(wszFilePath))
|
|
{
|
|
StringCchCatW(wszFilePath, MAX_PATH+1, BLOB9X_FILENAME);
|
|
DeleteFileW(wszFilePath);
|
|
}
|
|
}
|
|
|
|
bool CRepImporter::GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1])
|
|
{
|
|
HKEY hKey;
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ, &hKey))
|
|
return false;
|
|
|
|
wchar_t wszTmp[MAX_PATH + 1];
|
|
DWORD dwLen = (MAX_PATH + 1) * sizeof(wchar_t);
|
|
long lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL, (LPBYTE)wszTmp, &dwLen);
|
|
RegCloseKey(hKey);
|
|
if(lRes)
|
|
return false;
|
|
|
|
if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CRepImporter::CloseWin9xBlobFile()
|
|
{
|
|
// if no valid handle, then we don't have a file to close, return success
|
|
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
|
|
return true;
|
|
|
|
// write the end of blob file marker
|
|
BLOB9X_SPACER trailer;
|
|
trailer.dwSpacerType = BLOB9X_TYPE_END_OF_FILE;
|
|
trailer.dwNamespaceNameSize = 0;
|
|
trailer.dwParentClassNameSize = 0;
|
|
trailer.dwBlobSize = 0;
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(m_h9xBlobFile, &trailer, sizeof(trailer), &dwSize, NULL) == 0) || (dwSize != sizeof(trailer)))
|
|
{
|
|
// if we failed to write the trailer, something is wrong with the file, so close and delete it
|
|
DeleteWin9xBlobFile();
|
|
return false;
|
|
}
|
|
|
|
CloseHandle(m_h9xBlobFile);
|
|
m_h9xBlobFile = INVALID_HANDLE_VALUE;
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
extern HRESULT Traverse (
|
|
|
|
IWbemServices *a_Service ,
|
|
BSTR a_Namespace
|
|
) ;
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
PSID g_NetworkServiceSid = NULL ;
|
|
PSID g_LocalServiceSid = NULL ;
|
|
|
|
ACCESS_ALLOWED_ACE *g_NetworkService_Ace = NULL ;
|
|
WORD g_NetworkService_AceSize = 0 ;
|
|
|
|
ACCESS_ALLOWED_ACE *g_LocalService_Ace = NULL ;
|
|
WORD g_LocalService_AceSize = 0 ;
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT TraverseSetSecurity ( IWbemServices *a_Service )
|
|
{
|
|
IClientSecurity *t_Security = NULL ;
|
|
HRESULT t_Result = a_Service->QueryInterface ( IID_IClientSecurity , ( void ** ) & t_Security ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Result = t_Security->SetBlanket (
|
|
a_Service ,
|
|
RPC_C_AUTHN_WINNT,
|
|
RPC_C_AUTHZ_NONE,
|
|
NULL,
|
|
RPC_C_AUTHN_LEVEL_DEFAULT ,
|
|
RPC_C_IMP_LEVEL_IDENTIFY,
|
|
NULL,
|
|
EOAC_NONE
|
|
) ;
|
|
|
|
t_Security->Release () ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT InsertServiceAccess (
|
|
|
|
SAFEARRAY *a_Array ,
|
|
SAFEARRAY *&a_NewArray
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( SafeArrayGetDim ( a_Array ) == 1 )
|
|
{
|
|
LONG t_Dimension = 1 ;
|
|
|
|
LONG t_Lower ;
|
|
SafeArrayGetLBound ( a_Array , t_Dimension , & t_Lower ) ;
|
|
|
|
LONG t_Upper ;
|
|
SafeArrayGetUBound ( a_Array , t_Dimension , & t_Upper ) ;
|
|
|
|
LONG t_Count = ( t_Upper - t_Lower ) + 1 ;
|
|
|
|
BYTE *t_SecurityDescriptor = new BYTE [ t_Count ] ;
|
|
if ( t_SecurityDescriptor )
|
|
{
|
|
if ( t_Count )
|
|
{
|
|
for ( LONG t_ElementIndex = t_Lower ; t_ElementIndex <= t_Upper ; t_ElementIndex ++ )
|
|
{
|
|
BYTE t_Element ;
|
|
if ( SUCCEEDED ( SafeArrayGetElement ( a_Array , & t_ElementIndex , & t_Element ) ) )
|
|
{
|
|
t_SecurityDescriptor [ t_ElementIndex - t_Lower ] = t_Element ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
if ( IsValidSecurityDescriptor ( t_SecurityDescriptor ) == FALSE )
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
}
|
|
|
|
bool t_NetworkServicePresent = false ;
|
|
bool t_LocalServicePresent = false ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
BOOL t_AclPresent = FALSE ;
|
|
BOOL t_AclDefaulted = FALSE ;
|
|
ACL *t_Dacl = NULL ;
|
|
|
|
BOOL t_Status = GetSecurityDescriptorDacl (t_SecurityDescriptor ,& t_AclPresent ,& t_Dacl ,& t_AclDefaulted) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
DWORD SidNetworkSvcSize = GetLengthSid(g_NetworkServiceSid);
|
|
DWORD SidLocalSvcSize = GetLengthSid(g_LocalServiceSid);
|
|
|
|
ACCESS_ALLOWED_ACE * pACE = (ACCESS_ALLOWED_ACE *)(t_Dacl+1);
|
|
for (USHORT i=0;i<t_Dacl->AceCount;i++)
|
|
{
|
|
DWORD sidSize = GetLengthSid((PSID)&pACE->SidStart);
|
|
if ((sidSize == SidNetworkSvcSize) &&
|
|
(0 == memcmp(&pACE->SidStart,g_NetworkServiceSid,sidSize)))
|
|
{
|
|
t_NetworkServicePresent = true;
|
|
}
|
|
|
|
if ((sidSize == SidLocalSvcSize) &&
|
|
(0 == memcmp(&pACE->SidStart,g_LocalServiceSid,sidSize)))
|
|
{
|
|
t_LocalServicePresent = true;
|
|
}
|
|
|
|
pACE = (ACCESS_ALLOWED_ACE *)((BYTE *)pACE + pACE->Header.AceSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
SECURITY_DESCRIPTOR *t_AbsoluteSecurityDescriptor = NULL ;
|
|
DWORD t_AbsoluteSecurityDescriptorSize = sizeof ( SECURITY_DESCRIPTOR ) ;
|
|
|
|
PACL t_Dacl = NULL ;
|
|
PACL t_Sacl = NULL ;
|
|
PSID t_Owner = NULL ;
|
|
PSID t_PrimaryGroup = NULL ;
|
|
|
|
DWORD t_DaclSize = 0 ;
|
|
DWORD t_SaclSize = 0 ;
|
|
DWORD t_OwnerSize = 0 ;
|
|
DWORD t_PrimaryGroupSize = 0 ;
|
|
|
|
BOOL t_Status = MakeAbsoluteSD (t_SecurityDescriptor ,t_AbsoluteSecurityDescriptor ,& t_AbsoluteSecurityDescriptorSize ,
|
|
t_Dacl,& t_DaclSize,t_Sacl,& t_SaclSize,t_Owner,& t_OwnerSize,t_PrimaryGroup,& t_PrimaryGroupSize) ;
|
|
|
|
if ( ( t_Status == FALSE ) && GetLastError () == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
WORD t_Extra = 0 ;
|
|
if ( t_NetworkServicePresent == false )
|
|
{
|
|
t_Extra = t_Extra + g_NetworkService_AceSize ;
|
|
}
|
|
|
|
if ( t_LocalServicePresent == false )
|
|
{
|
|
t_Extra = t_Extra + g_LocalService_AceSize ;
|
|
}
|
|
|
|
t_DaclSize = t_DaclSize + t_Extra ;
|
|
|
|
t_Dacl = ( PACL ) new BYTE [ t_DaclSize ] ;
|
|
t_Sacl = ( PACL ) new BYTE [ t_SaclSize ] ;
|
|
t_Owner = ( PSID ) new BYTE [ t_OwnerSize ] ;
|
|
t_PrimaryGroup = ( PSID ) new BYTE [ t_PrimaryGroupSize ] ;
|
|
|
|
t_AbsoluteSecurityDescriptor = ( SECURITY_DESCRIPTOR * ) new BYTE [ t_AbsoluteSecurityDescriptorSize ] ;
|
|
|
|
if ( t_AbsoluteSecurityDescriptor && t_Dacl && t_Sacl && t_Owner && t_PrimaryGroup )
|
|
{
|
|
BOOL t_Status = InitializeSecurityDescriptor ( t_AbsoluteSecurityDescriptor , SECURITY_DESCRIPTOR_REVISION ) ;
|
|
if ( t_Status )
|
|
{
|
|
t_Status = MakeAbsoluteSD (t_SecurityDescriptor ,t_AbsoluteSecurityDescriptor ,& t_AbsoluteSecurityDescriptorSize ,
|
|
t_Dacl ,& t_DaclSize ,t_Sacl,& t_SaclSize,t_Owner,& t_OwnerSize,t_PrimaryGroup,& t_PrimaryGroupSize
|
|
) ;
|
|
|
|
WORD t_AceCount = t_Dacl->AceCount ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Dacl->AclSize = ( WORD ) t_DaclSize ;
|
|
|
|
if ( t_NetworkServicePresent == false )
|
|
{
|
|
t_Status = AddAce ( t_Dacl , ACL_REVISION, t_AceCount ++ , g_NetworkService_Ace , g_NetworkService_AceSize) ;
|
|
}
|
|
}
|
|
|
|
if ( t_Status )
|
|
{
|
|
if ( t_LocalServicePresent == false )
|
|
{
|
|
t_Status = AddAce ( t_Dacl , ACL_REVISION, t_AceCount ++ , g_LocalService_Ace , g_LocalService_AceSize) ;
|
|
}
|
|
}
|
|
|
|
if ( t_Status == FALSE )
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
SECURITY_DESCRIPTOR *t_SecurityDescriptorRelative = NULL ;
|
|
DWORD t_FinalLength = 0 ;
|
|
|
|
t_Status = MakeSelfRelativeSD (t_AbsoluteSecurityDescriptor ,t_SecurityDescriptorRelative ,& t_FinalLength ) ;
|
|
|
|
if ( t_Status == FALSE && GetLastError () == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
t_SecurityDescriptorRelative = ( SECURITY_DESCRIPTOR * ) new BYTE [ t_FinalLength ] ;
|
|
if ( t_SecurityDescriptorRelative )
|
|
{
|
|
t_Status = InitializeSecurityDescriptor ( t_SecurityDescriptorRelative , SECURITY_DESCRIPTOR_REVISION ) ;
|
|
if ( t_Status )
|
|
{
|
|
t_Status = MakeSelfRelativeSD (t_AbsoluteSecurityDescriptor ,t_SecurityDescriptorRelative ,& t_FinalLength ) ;
|
|
|
|
if ( t_Status == FALSE )
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
SAFEARRAYBOUND t_Bounds ;
|
|
t_Bounds.lLbound = 0;
|
|
t_Bounds.cElements = t_FinalLength ;
|
|
|
|
a_NewArray = SafeArrayCreate ( VT_UI1 , 1 , & t_Bounds ) ;
|
|
if ( a_NewArray )
|
|
{
|
|
for ( LONG t_Index = 0 ; ( ( ULONG ) t_Index ) < t_FinalLength ; t_Index ++ )
|
|
{
|
|
BYTE t_Byte = * ( ( ( BYTE * ) t_SecurityDescriptorRelative ) + t_Index ) ;
|
|
t_Result = SafeArrayPutElement ( a_NewArray , & t_Index , & t_Byte ) ;
|
|
if ( FAILED ( t_Result ) )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
|
|
delete [] ( BYTE * ) t_SecurityDescriptorRelative ;
|
|
}
|
|
|
|
delete [] ( BYTE * ) t_Dacl ;
|
|
delete [] ( BYTE * ) t_Sacl ;
|
|
delete [] ( BYTE * ) t_Owner ;
|
|
delete [] ( BYTE * ) t_PrimaryGroup ;
|
|
}
|
|
|
|
delete [] t_SecurityDescriptor ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT ConfigureSecurity (
|
|
|
|
IWbemServices *a_Service
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
BSTR t_ObjectPath = SysAllocString ( L"__SystemSecurity" ) ;
|
|
BSTR t_MethodName = SysAllocString ( L"GetSD" ) ;
|
|
if ( t_ObjectPath && t_MethodName )
|
|
{
|
|
IWbemClassObject *t_Object = NULL ;
|
|
|
|
t_Result = a_Service->ExecMethod (t_ObjectPath ,t_MethodName ,0 ,NULL ,NULL ,& t_Object ,NULL);
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
VARIANT t_Variant ;
|
|
VariantInit ( & t_Variant ) ;
|
|
|
|
LONG t_VarType = 0 ;
|
|
LONG t_Flavour = 0 ;
|
|
|
|
HRESULT t_Result = t_Object->Get ( L"SD" , 0 , & t_Variant , & t_VarType , & t_Flavour ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
if ( t_Variant.vt == ( VT_UI1 | VT_ARRAY ) )
|
|
{
|
|
SAFEARRAY *t_Array = t_Variant.parray ;
|
|
SAFEARRAY *t_NewArray = NULL ;
|
|
|
|
t_Result = InsertServiceAccess (t_Array ,t_NewArray ) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
BSTR t_Class = SysAllocString ( L"__SystemSecurity" ) ;
|
|
if ( t_Class )
|
|
{
|
|
IWbemClassObject *t_InObject = NULL ;
|
|
t_Result = a_Service->GetObject (t_Class ,0 , NULL , & t_InObject ,NULL ) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
BSTR t_SetMethodName = SysAllocString ( L"SetSD" ) ;
|
|
if ( t_SetMethodName )
|
|
{
|
|
IWbemClassObject *t_InArgsClass = NULL ;
|
|
t_Result = t_InObject->GetMethod (t_SetMethodName ,0 ,& t_InArgsClass ,NULL ) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
IWbemClassObject *t_InArgs = NULL ;
|
|
|
|
t_Result = t_InArgsClass->SpawnInstance ( 0 , & t_InArgs ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
VARIANT t_Variant ;
|
|
VariantInit ( & t_Variant ) ;
|
|
t_Variant.vt = VT_UI1 | VT_ARRAY ;
|
|
t_Variant.parray = t_NewArray ;
|
|
|
|
t_Result = t_InArgs->Put ( L"SD" ,0 ,& t_Variant ,CIM_UINT8 | CIM_FLAG_ARRAY) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
IWbemClassObject *t_OutArgs = NULL ;
|
|
a_Service->ExecMethod (t_ObjectPath ,t_SetMethodName ,0 ,NULL ,t_InArgs ,& t_OutArgs ,NULL ) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
if ( t_OutArgs )
|
|
{
|
|
t_OutArgs->Release () ;
|
|
}
|
|
}
|
|
}
|
|
|
|
t_InArgs->Release () ;
|
|
}
|
|
|
|
t_InArgsClass->Release () ;
|
|
}
|
|
|
|
SysFreeString ( t_SetMethodName ) ;
|
|
}
|
|
|
|
t_InObject->Release () ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
SafeArrayDestroy ( t_NewArray ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
VariantClear ( & t_Variant ) ;
|
|
}
|
|
|
|
t_Object->Release () ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
SysFreeString ( t_ObjectPath ) ;
|
|
SysFreeString ( t_MethodName ) ;
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT Traverse (
|
|
IWbemServices *a_Service ,
|
|
BSTR a_Namespace
|
|
)
|
|
{
|
|
if ( wcslen ( a_Namespace ) < ( MAX_MSG_TEXT_LENGTH >> 1 ) )
|
|
{
|
|
char t_Buffer [ MAX_MSG_TEXT_LENGTH ] ;
|
|
StringCchPrintfA ( t_Buffer , MAX_MSG_TEXT_LENGTH, "\nTraversing [%S]" , a_Namespace ) ;
|
|
LogMessage(MSG_INFO, t_Buffer);
|
|
}
|
|
|
|
HRESULT t_Result = ConfigureSecurity (a_Service ) ;
|
|
|
|
if ( FAILED ( t_Result ) )
|
|
{
|
|
char t_Buffer [ MAX_MSG_TEXT_LENGTH ] ;
|
|
StringCchPrintfA ( t_Buffer, MAX_MSG_TEXT_LENGTH , "\nConfiguration of Security failed [%lx]" , t_Result ) ;
|
|
LogMessage(MSG_INFO, t_Buffer);
|
|
}
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT ConfigureServiceSecurity ()
|
|
{
|
|
IWbemLocator *t_Locator = NULL ;
|
|
HRESULT t_Result = CoCreateInstance (CLSID_WbemLocator ,NULL ,CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER ,
|
|
IID_IUnknown ,( void ** ) & t_Locator);
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
BSTR t_Root = SysAllocString ( L"root" ) ;
|
|
if ( t_Root )
|
|
{
|
|
IWbemServices *t_Service = NULL ;
|
|
HRESULT t_Result = t_Locator->ConnectServer (t_Root ,NULL ,NULL,NULL ,0 ,NULL,NULL,&t_Service) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Result = TraverseSetSecurity ( t_Service ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Result = Traverse (t_Service ,t_Root ) ;
|
|
}
|
|
|
|
t_Service->Release () ;
|
|
}
|
|
else
|
|
{
|
|
char t_Buffer [ MAX_MSG_TEXT_LENGTH ] ;
|
|
StringCchPrintfA ( t_Buffer , MAX_MSG_TEXT_LENGTH, "\nFailing Connecting to Namespace [%s] with result [%lx]" , t_Root , t_Result ) ;
|
|
LogMessage(MSG_INFO, t_Buffer);
|
|
}
|
|
|
|
SysFreeString ( t_Root ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
t_Locator->Release () ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT InitializeConstants ()
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
SID_IDENTIFIER_AUTHORITY t_NtAuthoritySid = SECURITY_NT_AUTHORITY ;
|
|
|
|
BOOL t_Status = AllocateAndInitializeSid (& t_NtAuthoritySid ,1 ,SECURITY_NETWORK_SERVICE_RID,0,0,0,0,0,0,0,& g_NetworkServiceSid) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
DWORD t_SidLength = :: GetLengthSid ( g_NetworkServiceSid );
|
|
g_NetworkService_AceSize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
|
|
g_NetworkService_Ace = (ACCESS_ALLOWED_ACE*) new BYTE [ g_NetworkService_AceSize ] ;
|
|
if ( g_NetworkService_Ace )
|
|
{
|
|
CopySid ( t_SidLength, (PSID) & g_NetworkService_Ace->SidStart, g_NetworkServiceSid ) ;
|
|
g_NetworkService_Ace->Mask = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER ;
|
|
g_NetworkService_Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE ;
|
|
g_NetworkService_Ace->Header.AceFlags = CONTAINER_INHERIT_ACE ;
|
|
g_NetworkService_Ace->Header.AceSize = g_NetworkService_AceSize ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Status = AllocateAndInitializeSid (& t_NtAuthoritySid ,1 ,SECURITY_LOCAL_SERVICE_RID,0,0,0,0,0,0,0,& g_LocalServiceSid) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
DWORD t_SidLength = :: GetLengthSid ( g_LocalServiceSid );
|
|
g_LocalService_AceSize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
|
|
g_LocalService_Ace = (ACCESS_ALLOWED_ACE*) new BYTE [ g_LocalService_AceSize ] ;
|
|
if ( g_LocalService_Ace )
|
|
{
|
|
CopySid ( t_SidLength, (PSID) & g_LocalService_Ace->SidStart, g_LocalServiceSid ) ;
|
|
g_LocalService_Ace->Mask = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER ;
|
|
g_LocalService_Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE ;
|
|
g_LocalService_Ace->Header.AceFlags = CONTAINER_INHERIT_ACE ;
|
|
g_LocalService_Ace->Header.AceSize = g_LocalService_AceSize ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT UnInitializeConstants ()
|
|
{
|
|
FreeSid ( g_NetworkServiceSid ) ;
|
|
FreeSid ( g_LocalServiceSid ) ;
|
|
|
|
delete [] ( ( BYTE * ) g_NetworkService_Ace ) ;
|
|
delete [] ( ( BYTE * ) g_LocalService_Ace ) ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT UpdateServiceSecurity ()
|
|
{
|
|
HRESULT t_Result = InitializeConstants () ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Result = ConfigureServiceSecurity () ;
|
|
|
|
UnInitializeConstants () ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CheckForServiceSecurity ()
|
|
{
|
|
Registry r(WBEM_REG_WBEM);
|
|
if (r.GetStatus() != no_error)
|
|
{
|
|
LogMessage(MSG_ERROR, "Unable to access registry for UpdateServiceSecurity.");
|
|
return WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
char *t_BuildVersion = NULL ;
|
|
if ( r.GetStr ("Build", & t_BuildVersion ) )
|
|
{
|
|
LogMessage(MSG_ERROR, "Unable to get build version number for UpdateServiceSecurity.");
|
|
return WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
if ( strlen ( t_BuildVersion ) >= 4 )
|
|
{
|
|
t_BuildVersion [ 4 ] = 0 ;
|
|
}
|
|
else
|
|
{
|
|
LogMessage(MSG_ERROR, "Unexpected build version number for UpdateServiceSecurity.");
|
|
return WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
DWORD t_BuildVersionNumber = 0 ;
|
|
if ( sscanf ( t_BuildVersion , "%lu" , & t_BuildVersionNumber ) == NULL )
|
|
{
|
|
LogMessage(MSG_ERROR, "Unable to convert build version number for UpdateServiceSecurity.");
|
|
return WBEM_E_CRITICAL_ERROR ;
|
|
}
|
|
|
|
if ( t_BuildVersionNumber < 2600 )
|
|
{
|
|
LogMessage(MSG_INFO, "Operating System Version < WindowsXP (2600) UpdateServiceSecurity.");
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
return S_FALSE ;
|
|
}
|
|
}
|