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.
731 lines
22 KiB
731 lines
22 KiB
#include "precomp.h"
|
|
#include <stdio.h>
|
|
#include <io.h>
|
|
#include <wbemutil.h>
|
|
#include <GroupsForUser.h>
|
|
#include <ArrTempl.h>
|
|
#include <GenUtils.h>
|
|
#include <ErrorObj.h>
|
|
#include "logfile.h"
|
|
#include <sync.h>
|
|
#include <statsync.h>
|
|
#include <errno.h>
|
|
#include <strsafe.h>
|
|
|
|
#define LOGFILE_PROPNAME_FILENAME L"Filename"
|
|
#define LOGFILE_PROPNAME_TEXT L"Text"
|
|
#define LOGFILE_PROPNAME_MAX_SIZE L"MaximumFileSize"
|
|
#define LOGFILE_PROPNAME_IS_UNICODE L"IsUnicode"
|
|
|
|
const char ByteOrderMark[2] = {'\xFF','\xFE'};
|
|
|
|
CStaticCritSec fileLock;
|
|
|
|
HRESULT STDMETHODCALLTYPE CLogFileConsumer::XProvider::FindConsumer(
|
|
IWbemClassObject* pLogicalConsumer,
|
|
IWbemUnboundObjectSink** ppConsumer)
|
|
{
|
|
// Create a new sink
|
|
// =================
|
|
|
|
CLogFileSink* pSink = new CLogFileSink(m_pObject->m_pControl);
|
|
if (!pSink)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
// Initialize it
|
|
// =============
|
|
|
|
HRESULT hres = pSink->Initialize(pLogicalConsumer);
|
|
if(FAILED(hres))
|
|
{
|
|
delete pSink;
|
|
*ppConsumer = NULL;
|
|
return hres;
|
|
}
|
|
|
|
// return it
|
|
|
|
else return pSink->QueryInterface(IID_IWbemUnboundObjectSink,
|
|
(void**)ppConsumer);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CLogFileConsumer::XInit::Initialize(
|
|
LPWSTR, LONG, LPWSTR, LPWSTR, IWbemServices*, IWbemContext*,
|
|
IWbemProviderInitSink* pSink)
|
|
{
|
|
pSink->SetStatus(0, 0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void* CLogFileConsumer::GetInterface(REFIID riid)
|
|
{
|
|
if(riid == IID_IWbemEventConsumerProvider)
|
|
return &m_XProvider;
|
|
else if(riid == IID_IWbemProviderInit)
|
|
return &m_XInit;
|
|
else return NULL;
|
|
}
|
|
|
|
CLogFileSink::~CLogFileSink()
|
|
{
|
|
if(m_hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(m_hFile);
|
|
|
|
if (m_pErrorObj)
|
|
m_pErrorObj->Release();
|
|
}
|
|
|
|
// determine whether file needs to be backed up
|
|
// returns false if we are not expected to back up file
|
|
bool CLogFileSink::IsFileTooBig(UINT64 maxFileSize, HANDLE hFile)
|
|
{
|
|
bool bRet = false;
|
|
|
|
// zero is interpreted to mean 'Let it grow without bounds'
|
|
if (maxFileSize > 0)
|
|
{
|
|
LARGE_INTEGER size;
|
|
|
|
if (GetFileSizeEx(hFile, &size))
|
|
bRet = size.QuadPart > maxFileSize;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
bool CLogFileSink::IsFileTooBig(UINT64 maxFileSize, WString& fileName)
|
|
{
|
|
bool bRet = false;
|
|
|
|
// zero is interpreted to mean 'Let it grow without bounds'
|
|
if (maxFileSize > 0)
|
|
{
|
|
struct _wfinddatai64_t foundData;
|
|
|
|
__int64 handle;
|
|
handle = _wfindfirsti64( (wchar_t *)fileName, &foundData);
|
|
if (handle != -1l)
|
|
{
|
|
bRet = foundData.size >= maxFileSize;
|
|
_findclose(handle);
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
bool CLogFileSink::GetNumericExtension(WCHAR* pName, int& foundNumber)
|
|
{
|
|
WCHAR foundExtension[_MAX_EXT];
|
|
_wsplitpath(pName, NULL, NULL, NULL, foundExtension);
|
|
|
|
return (swscanf(foundExtension, L".%d", &foundNumber) == 1);
|
|
}
|
|
|
|
// makes backup of file
|
|
// file must be closed when this is called
|
|
HRESULT CLogFileSink::ArchiveFile(WString& fullName)
|
|
{
|
|
// first, let's make sure the dang file actually exists...
|
|
struct _wfinddatai64_t foundData;
|
|
__int64 findHandle;
|
|
if ((findHandle = _wfindfirsti64( fullName, &foundData)) == -1i64)
|
|
{
|
|
if (GetLastError() == ENOENT)
|
|
return WBEM_S_NO_ERROR;
|
|
else
|
|
return WBEM_E_FAILED;
|
|
}
|
|
else
|
|
_findclose(findHandle);
|
|
|
|
|
|
WCHAR drive[_MAX_DRIVE];
|
|
WCHAR dir[_MAX_DIR];
|
|
WCHAR fname[_MAX_FNAME];
|
|
WCHAR ext[_MAX_EXT];
|
|
|
|
// warning: reused, it'll be the mask for the lookup
|
|
// then it'll be the new file name.
|
|
WCHAR pathBuf[MAX_PATH +1];
|
|
|
|
_wsplitpath( (const wchar_t *)fullName, drive, dir, fname, ext );
|
|
|
|
bool bItEightDotThree = (wcslen(fname) <= 8) && (wcslen(ext) <= 4);
|
|
// eightdot three file names are backed up to name.###
|
|
// NON eight dotthree are backed up to name.ext.###
|
|
|
|
// build mask for lookup
|
|
StringCchCopyW(pathBuf, MAX_PATH+1, drive);
|
|
StringCchCatW(pathBuf, MAX_PATH+1, dir);
|
|
StringCchCatW(pathBuf, MAX_PATH+1, fname);
|
|
|
|
if (!bItEightDotThree)
|
|
{
|
|
// there's a possibility that the filename would be too long
|
|
// if we appended four chars. Will trunc if needed
|
|
if ((wcslen(pathBuf) + wcslen(ext) + 4) > MAX_PATH)
|
|
{
|
|
// see if we can get away with just dropping the ext
|
|
if ((wcslen(pathBuf) + 4) > MAX_PATH)
|
|
pathBuf[MAX_PATH -4] = L'\0';
|
|
}
|
|
else
|
|
// everything fits, no trunc needed
|
|
StringCchCatW(pathBuf, MAX_PATH+1, ext);
|
|
}
|
|
// and the dotstar goes on the end, no matter what.
|
|
StringCchCatW(pathBuf, MAX_PATH+1, L".*");
|
|
|
|
// pathbuf is now the proper mask to lookup stuff.
|
|
int biggestOne = 0;
|
|
bool foundOne = false;
|
|
bool foundOnes[1000];
|
|
// keep track of which ones we found
|
|
// just in case we have to go back & find a hole
|
|
// using 1000 so I don't have to convert all the time.
|
|
ZeroMemory(foundOnes, sizeof(bool) * 1000);
|
|
|
|
if ((findHandle = _wfindfirsti64( pathBuf, &foundData)) != -1i64)
|
|
{
|
|
int latestOne;
|
|
|
|
if (foundOne = GetNumericExtension(foundData.name, latestOne))
|
|
{
|
|
if (latestOne <= 999)
|
|
{
|
|
foundOnes[latestOne] = true;
|
|
if (latestOne > biggestOne)
|
|
biggestOne = latestOne;
|
|
}
|
|
}
|
|
|
|
while (0 == _wfindnexti64(findHandle, &foundData))
|
|
{
|
|
if (GetNumericExtension(foundData.name, latestOne) && (latestOne <= 999))
|
|
{
|
|
foundOne = true;
|
|
foundOnes[latestOne] = true;
|
|
if (latestOne > biggestOne)
|
|
biggestOne = latestOne;
|
|
}
|
|
}
|
|
|
|
_findclose(findHandle);
|
|
}
|
|
|
|
int newExt = -1;
|
|
|
|
if (foundOne)
|
|
if (biggestOne < 999)
|
|
newExt = biggestOne + 1;
|
|
else
|
|
{
|
|
newExt = -1;
|
|
|
|
// see if there's a hole somewhere
|
|
for (int i = 1; i <= 999; i++)
|
|
if (!foundOnes[i])
|
|
{
|
|
newExt = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
WCHAR *pTok;
|
|
pTok = wcschr(pathBuf, L'*');
|
|
|
|
// "can't happen" - the asterisk is added approximately 60 lines up
|
|
// however, we'll go ahead & do the check - will make PREFIX happy if nothing else.
|
|
if (!pTok)
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
if (newExt != -1)
|
|
{
|
|
// calc how much buffer we have past the end of pTok...
|
|
int nTokStrLen = MAX_PATH - (pTok - pathBuf) -1;
|
|
|
|
// construct new name
|
|
// we want to replace the * with ###
|
|
StringCchPrintf(pTok, nTokStrLen, L"%03d", newExt);
|
|
//swprintf(pTok, L"%03d", newExt);
|
|
}
|
|
else
|
|
// okay, we'll hammer an old file
|
|
{
|
|
// calc how much buffer we have past the end of pTok...
|
|
int nTokStrLen = MAX_PATH - (pTok - pathBuf) -1;
|
|
StringCchCopy(pTok, nTokStrLen, L"001");
|
|
|
|
_wremove(pathBuf);
|
|
}
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
BOOL bRet;
|
|
//int retval = _wrename(fullName, pathBuf);
|
|
{
|
|
bRet = MoveFile(fullName, pathBuf);
|
|
}
|
|
|
|
if (!bRet)
|
|
{
|
|
DWORD err = GetLastError();
|
|
m_pErrorObj->ReportError(L"MoveFile", fullName, NULL, err, true);
|
|
|
|
ERRORTRACE((LOG_ESS, "MoveFile failed 0x%08X\n", err));
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// determines whether file is too large, archives old if needed
|
|
// use this function rather than accessing the file pointer directly
|
|
HRESULT CLogFileSink::GetFileHandle(HANDLE& handle)
|
|
{
|
|
CInCritSec lockMe(&fileLock);
|
|
|
|
// assume the worst
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
handle = INVALID_HANDLE_VALUE;
|
|
|
|
// check for whether we have to archive file
|
|
// (use handle if open, else use filename)
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
|
|
if (IsFileTooBig(m_maxFileSize, m_hFile))
|
|
{
|
|
// two possibilities: we have ahold of logfile.log OR we've got logfile.001
|
|
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
|
|
hr = WBEM_S_NO_ERROR;
|
|
if (IsFileTooBig(m_maxFileSize, m_wsFile))
|
|
hr = ArchiveFile(m_wsFile);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (IsFileTooBig(m_maxFileSize, m_wsFile))
|
|
{
|
|
hr = ArchiveFile(m_wsFile);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
// got a good file, we're good to go
|
|
handle = m_hFile;
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
// Open the file
|
|
|
|
// we'll try opening an existing file first
|
|
|
|
m_hFile = CreateFile(m_wsFile, GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
|
|
|
|
|
|
if(m_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (FILE_TYPE_DISK != GetFileType(m_hFile))
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
m_pErrorObj->ReportError(L"CreateFile", m_wsFile, NULL, WBEM_E_ACCESS_DENIED, false);
|
|
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
// now, take a looksee and determine whether the existing file is unicode
|
|
// *regardless* of what the flag says
|
|
char readbuf[2] = {'\0','\0'};
|
|
DWORD bytesRead;
|
|
|
|
// if (fread(&readbuf, sizeof(WCHAR), 1, m_pFile) > 0)
|
|
if (ReadFile(m_hFile, &readbuf, sizeof(WCHAR), &bytesRead, NULL) &&
|
|
(bytesRead == sizeof(WCHAR)))
|
|
{
|
|
// only interesting cases are those where the flag
|
|
// doesn't match what's in the file...
|
|
if ((readbuf[0] == ByteOrderMark[0]) && (readbuf[1] == ByteOrderMark[1])
|
|
&& !m_bUnicode)
|
|
m_bUnicode = true;
|
|
else if (((readbuf[0] != ByteOrderMark[0]) || (readbuf[1] != ByteOrderMark[1])) && m_bUnicode)
|
|
m_bUnicode = false;
|
|
}
|
|
|
|
// line up at the end of the file
|
|
SetFilePointer(m_hFile, 0,0, FILE_END);
|
|
|
|
handle = m_hFile;
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
// ahhh - it wasn't there, for whatever reason.
|
|
m_hFile = CreateFile(m_wsFile, GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (FILE_TYPE_DISK != GetFileType(m_hFile))
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
m_pErrorObj->ReportError(L"CreateFile", m_wsFile, NULL, WBEM_E_ACCESS_DENIED, false);
|
|
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
DWORD bytesWryt;
|
|
if (m_bUnicode)
|
|
{
|
|
if (0 == WriteFile(m_hFile, (LPCVOID)ByteOrderMark, 2, &bytesWryt, NULL))
|
|
ERRORTRACE((LOG_ESS, "Failed to write byte order mark to log file 0x%08X\n", GetLastError()));
|
|
}
|
|
|
|
handle = m_hFile;
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
}
|
|
else
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
m_pErrorObj->ReportError(L"CreateFile", m_wsFile, NULL, dwError, true);
|
|
|
|
ERRORTRACE((LOG_ESS, "Unable to open log file %S, [0x%X]\n", (LPWSTR)m_wsFile, dwError));
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// initialize members, do security check.
|
|
// a tidier programmer would probably move the security check to a separate function
|
|
HRESULT CLogFileSink::Initialize(IWbemClassObject* pLogicalConsumer)
|
|
{
|
|
// this is actually a pointer to a static object
|
|
// if it fails, something is Very, Very Wrong.
|
|
m_pErrorObj = ErrorObj::GetErrorObj();
|
|
if (!m_pErrorObj)
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
|
|
// Get the information
|
|
// ===================
|
|
|
|
HRESULT hres;
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
hres = pLogicalConsumer->Get(LOGFILE_PROPNAME_FILENAME, 0, &v, NULL, NULL);
|
|
if (FAILED(hres) || (V_VT(&v) != VT_BSTR) || (v.bstrVal == NULL))
|
|
{
|
|
VariantClear(&v);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
size_t length;
|
|
length = wcslen(v.bstrVal);
|
|
if ((length > MAX_PATH) || (length == 0))
|
|
{
|
|
VariantClear(&v);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
m_wsFile = V_BSTR(&v);
|
|
|
|
// check for disallowed filenames
|
|
VariantClear(&v);
|
|
m_wsFile.StripWs(WString::leading);
|
|
if (m_wsFile.Length() == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// UNC global file names: no-no.
|
|
if (wcsstr(m_wsFile, L"\\\\.")
|
|
||
|
|
wcsstr(m_wsFile, L"//.")
|
|
||
|
|
wcsstr(m_wsFile, L"\\\\??")
|
|
||
|
|
wcsstr(m_wsFile, L"//??"))
|
|
{
|
|
m_pErrorObj->ReportError(L"CLogFileSink::Initialize", m_wsFile, L"Filename", WBEM_E_ACCESS_DENIED, true);
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
hres = pLogicalConsumer->Get(LOGFILE_PROPNAME_TEXT, 0, &v, NULL, NULL);
|
|
if(FAILED(hres) || V_VT(&v) != VT_BSTR)
|
|
{
|
|
VariantClear(&v);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
m_Template.SetTemplate(V_BSTR(&v));
|
|
VariantClear(&v);
|
|
|
|
hres = pLogicalConsumer->Get(LOGFILE_PROPNAME_IS_UNICODE, 0, &v, NULL, NULL);
|
|
if(FAILED(hres))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
else if (V_VT(&v) == VT_BOOL)
|
|
m_bUnicode = v.boolVal == VARIANT_TRUE;
|
|
else if (V_VT(&v) == VT_NULL)
|
|
m_bUnicode = false;
|
|
else
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
VariantClear(&v);
|
|
|
|
hres = pLogicalConsumer->Get(LOGFILE_PROPNAME_MAX_SIZE, 0, &v, NULL, NULL);
|
|
|
|
if (FAILED(hres))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
else if (V_VT(&v) == VT_BSTR)
|
|
{
|
|
if (!ReadUI64(V_BSTR(&v), m_maxFileSize))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
else if (V_VT(&v) == VT_NULL)
|
|
m_maxFileSize = 65535;
|
|
else
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
VariantClear(&v);
|
|
|
|
// Determine whether user has rights to file
|
|
// =========================================
|
|
// first determine who is our creator...
|
|
hres = pLogicalConsumer->Get(L"CreatorSid", 0, &v,
|
|
NULL, NULL);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
HRESULT hDebug = WBEM_E_FAILED;
|
|
long ubound = 0;
|
|
PSID pSidCreator = NULL;
|
|
PVOID pVoid = NULL;
|
|
|
|
hDebug = SafeArrayGetUBound(V_ARRAY(&v), 1, &ubound);
|
|
if(FAILED(hDebug)) return hDebug;
|
|
|
|
hDebug = SafeArrayAccessData(V_ARRAY(&v), &pVoid);
|
|
if(FAILED(hDebug)) return hDebug;
|
|
|
|
pSidCreator = new BYTE[ubound +1];
|
|
if (pSidCreator)
|
|
memcpy(pSidCreator, pVoid, ubound + 1);
|
|
else
|
|
{
|
|
VariantClear(&v);
|
|
SafeArrayUnaccessData(V_ARRAY(&v));
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
CDeleteMe<BYTE> deleteTheCreator((BYTE*)pSidCreator);
|
|
SafeArrayUnaccessData(V_ARRAY(&v));
|
|
|
|
VariantClear(&v);
|
|
|
|
BOOL bIsSystem;
|
|
// check to see if the creator is The System
|
|
{
|
|
PSID pSidSystem;
|
|
SID_IDENTIFIER_AUTHORITY sa = SECURITY_NT_AUTHORITY;
|
|
if (AllocateAndInitializeSid(&sa, 1, SECURITY_LOCAL_SYSTEM_RID, 0,0,0,0,0,0,0, &pSidSystem))
|
|
{
|
|
bIsSystem = EqualSid(pSidCreator, pSidSystem);
|
|
FreeSid(pSidSystem);
|
|
}
|
|
else
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
if (bIsSystem)
|
|
// creator is local system, let him in.
|
|
hres = WBEM_S_NO_ERROR;
|
|
else
|
|
{
|
|
DWORD dwSize;
|
|
WString fNameForCheck = m_wsFile;
|
|
// call once to see how big a buffer we might need
|
|
GetFileSecurityW(fNameForCheck, DACL_SECURITY_INFORMATION, NULL, 0, &dwSize);
|
|
DWORD dwErr = GetLastError();
|
|
if (dwErr == ERROR_INVALID_NAME)
|
|
{
|
|
m_pErrorObj->ReportError(L"GetFileSecurity", (WCHAR*)fNameForCheck, NULL, dwErr, true);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
else if (dwErr == ERROR_FILE_NOT_FOUND)
|
|
// no file - see if directory exists
|
|
{
|
|
WCHAR drive[_MAX_DRIVE];
|
|
WCHAR dir[_MAX_DIR];
|
|
_wsplitpath( m_wsFile,drive, dir, NULL, NULL);
|
|
WCHAR path[MAX_PATH];
|
|
StringCchCopy(path, MAX_PATH, drive);
|
|
StringCchCat(path, MAX_PATH, dir);
|
|
|
|
fNameForCheck = path;
|
|
GetFileSecurityW(fNameForCheck, DACL_SECURITY_INFORMATION, NULL, 0, &dwSize);
|
|
dwErr = GetLastError();
|
|
}
|
|
// we don't bother trying to create the directory.
|
|
if ((dwErr == ERROR_FILE_NOT_FOUND) || (dwErr == ERROR_PATH_NOT_FOUND) || (dwErr == ERROR_INVALID_NAME))
|
|
{
|
|
m_pErrorObj->ReportError(L"GetFileSecurity", m_wsFile, NULL, dwErr, true);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
if (dwErr != ERROR_INSUFFICIENT_BUFFER)
|
|
return WBEM_E_FAILED;
|
|
|
|
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) new BYTE[dwSize];
|
|
if (!psd)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
CDeleteMe<BYTE> delSD((BYTE *)psd);
|
|
|
|
|
|
PACL pDacl = NULL;
|
|
BOOL bDaclPresent, bDaclDefaulted;
|
|
// retrieve file's security, if any
|
|
if (GetFileSecurityW(fNameForCheck, DACL_SECURITY_INFORMATION, psd, dwSize, &dwSize) &&
|
|
GetSecurityDescriptorDacl(psd, &bDaclPresent, &pDacl, &bDaclDefaulted))
|
|
{
|
|
if (bDaclPresent && pDacl)
|
|
{
|
|
DWORD accessMask;
|
|
if (S_OK == GetAccessMask(pSidCreator, pDacl, &accessMask))
|
|
{
|
|
DWORD rightAccess = FILE_WRITE_DATA;
|
|
|
|
if (accessMask & rightAccess)
|
|
hres = WBEM_S_NO_ERROR;
|
|
else
|
|
hres = WBEM_E_ACCESS_DENIED;
|
|
}
|
|
else
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
}
|
|
else
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CLogFileSink::XSink::IndicateToConsumer(
|
|
IWbemClassObject* pLogicalConsumer, long lNumObjects,
|
|
IWbemClassObject** apObjects)
|
|
{
|
|
for(int i = 0; i < lNumObjects; i++)
|
|
{
|
|
// Apply the template to the event
|
|
// ===============================
|
|
BSTR strText = m_pObject->m_Template.Apply(apObjects[i]);
|
|
if(strText == NULL)
|
|
strText = SysAllocString(L"invalid log entry");
|
|
if (strText == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
CSysFreeMe freeString(strText);
|
|
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
HRESULT hr = m_pObject->GetFileHandle(hFile);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (m_pObject->m_bUnicode)
|
|
{
|
|
CInCritSec lockMe(&fileLock);
|
|
WCHAR EOL[] = L"\r\n";
|
|
|
|
// make sure we're at the end, in case of multiple writers
|
|
SetFilePointer(hFile, 0,0, FILE_END);
|
|
|
|
DWORD bitzwritz;
|
|
if (!WriteFile(hFile, strText, wcslen(strText) *2, &bitzwritz, NULL) ||
|
|
!WriteFile(hFile, EOL, wcslen(EOL) *2, &bitzwritz, NULL))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
m_pObject->m_pErrorObj->ReportError(L"WriteFile", strText, NULL, dwErr, true);
|
|
ERRORTRACE((LOG_ESS, "LOGFILE: Failed to write to file, 0x%08X\n", dwErr));
|
|
|
|
return WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// convert to mbcs
|
|
char* pStr = new char[wcslen(strText) *2 +1];
|
|
|
|
if (!pStr)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
// else...
|
|
CDeleteMe<char> delStr(pStr);
|
|
|
|
|
|
if (0 == WideCharToMultiByte(CP_THREAD_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, strText, -1, pStr, wcslen(strText) *2 +1, NULL, NULL))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "LOGFILE: Unable to convert \"%S\" to MBCS, failing\n", strText));
|
|
return WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
CInCritSec lockMe(&fileLock);
|
|
|
|
char EOL[] = "\r\n";
|
|
|
|
// make sure we're at the end, in case of multiple writers
|
|
SetFilePointer(hFile, 0,0, FILE_END);
|
|
|
|
DWORD bitzwritz;
|
|
if (!WriteFile(hFile, pStr, strlen(pStr), &bitzwritz, NULL) ||
|
|
!WriteFile(hFile, EOL, strlen(EOL), &bitzwritz, NULL))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
m_pObject->m_pErrorObj->ReportError(L"WriteFile", strText, NULL, dwErr, true);
|
|
ERRORTRACE((LOG_ESS, "LOGFILE: Failed to write to file, 0x%08X\n", dwErr));
|
|
|
|
return WBEM_E_FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return hr;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
void* CLogFileSink::GetInterface(REFIID riid)
|
|
{
|
|
if(riid == IID_IWbemUnboundObjectSink)
|
|
return &m_XSink;
|
|
else return NULL;
|
|
}
|
|
|