|
|
#include "StdAfx.h"
#include "resource.h"
#include "errno.h"
#include "aclapi.h"
#include "Wsb.h"
#include "rpfilt.h"
// File/Directory
// Create a directory and all the parent directories necessary for this directory to
// exist.
HRESULT WsbCreateAllDirectories(OLECHAR* path) { HRESULT hr = S_OK; CWsbBstrPtr win32Path; CWsbBstrPtr parentPath;
try {
// Convert the path to the win32 style path (to handle long file names), and
// then try to create the directory.
WsbAffirmHr(WsbGetWin32PathAsBstr(path, &win32Path)); if (CreateDirectory(win32Path, 0) == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); }
// There are 4 possibilities:
// 1) it worked (we are done)
// 2) the directory already exists (we are done)
// 3) the directory doesn't exist, so try again after creating the parent
// 4) some other error occurred, so quit
if (FAILED(hr)) {
if ((HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) || (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)) { hr = S_OK; } else if ((HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) || (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)) {
// Create the parent directory and try again.
WsbAffirmHr(WsbCreateAllDirectoriesForFile(path));
if (CreateDirectory(win32Path, 0) == 0) { hr = HRESULT_FROM_WIN32(GetLastError());
if ((HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)) { hr = S_OK; } } else { hr = S_OK; } } }
} WsbCatch(hr);
return(hr); }
// Create a all the parent directories necessary for this file to exist.
HRESULT WsbCreateAllDirectoriesForFile(OLECHAR* path) { HRESULT hr = S_OK; CWsbBstrPtr parentPath; OLECHAR* slashPtr = 0; OLECHAR* pathStart = 0;
try {
// Find out where the relative portion of the path starts, since we don't need to try
// to create the root directory.
parentPath = path; if ((parentPath[0] == L'\\') && (parentPath[1] == L'\\')) { pathStart = wcschr(&parentPath[2], L'\\'); WsbAffirm(pathStart != 0, E_INVALIDARG); pathStart = wcschr(++pathStart, L'\\'); WsbAffirm(pathStart != 0, E_INVALIDARG); } else if (parentPath[1] == L':') { pathStart = &parentPath[2]; } else { WsbAssert(FALSE, E_INVALIDARG); }
WsbAffirm(*pathStart != 0, E_INVALIDARG);
// Create the path to the parent directory and use the create all to create it.
slashPtr = wcsrchr(pathStart, L'\\'); if ((slashPtr != 0) && (slashPtr != pathStart)) { *slashPtr = 0;
WsbAffirmHr(WsbCreateAllDirectories(parentPath)); }
} WsbCatch(hr);
return(hr); }
// Convert a normal path (UNC or drive letter) to the internal format that is needed by
// win32 to deal with long paths and special characters.
HRESULT WsbGetWin32PathAsBstr(OLECHAR* path, BSTR* pWin32Path) { HRESULT hr = S_OK; CWsbBstrPtr win32Path;
try {
WsbAssert(0 != pWin32Path, E_POINTER);
// Is it a UNC or a drive letter base path?
if ((path[0] == L'\\') && (path[1] == L'\\')) { // UNC Paths must be preceeded with '\\?\UNC', but the then should only be
// followed by one '\' not two.
win32Path = L"\\\\?\\UNC"; WsbAffirmHr(win32Path.Append(&path[1]));
} else if (path[1] == L':') {
// Drive letter based paths need to be preceeded by \\?\.
win32Path = L"\\\\?\\"; WsbAffirmHr(win32Path.Append(path)); } else { WsbThrow(E_INVALIDARG); }
WsbAffirmHr(win32Path.CopyToBstr(pWin32Path));
} WsbCatch(hr);
return(hr); }
// Convert the internal format that is needed by win32 to deal with long paths and
// special characters to a normal path (UNC or drive letter).
HRESULT WsbGetPathFromWin32AsBstr(OLECHAR* win32Path, BSTR* pPath) { HRESULT hr = S_OK; CWsbBstrPtr path;
try {
WsbAssert(0 != pPath, E_POINTER);
// Is it a UNC or a drive letter base path?
if (_wcsnicmp(win32Path, L"\\\\?\\", 4) == 0) { path = &win32Path[4]; } else if (_wcsnicmp(win32Path, L"\\\\?\\UNC", 7) == 0) { path = "\\"; WsbAffirmHr(path.Append(&path[7])); } else { WsbThrow(E_INVALIDARG); }
WsbAffirmHr(path.CopyToBstr(pPath));
} WsbCatch(hr);
return(hr); }
// String & Buffer Copy
HRESULT WsbGetComBuffer(OLECHAR** pDest, ULONG requestedSize, ULONG neededSize, BOOL* pWasAllocated) { HRESULT hr = S_OK; // If they didn't give us a buffer, then let them know that we
// had to allocate one for them.
if (pWasAllocated != NULL) { if (*pDest == NULL) { *pWasAllocated = TRUE; } else { *pWasAllocated = FALSE; } }
// If they gave us the size they wanted (or have) for the
// buffer, then it better be big enough.
if (requestedSize != 0) { if (requestedSize < neededSize) { hr = E_INVALIDARG; } else if (*pDest == NULL) { *pDest = (OLECHAR*)WsbAlloc(requestedSize);
if (*pDest == NULL) { hr = E_OUTOFMEMORY; } } }
// If we control the size of the buffer, then make sure it is
// the right size.
//
// NOTE: This may move the buffer!
else { LPVOID pTemp = WsbRealloc(*pDest, neededSize); if (pTemp == NULL) { hr = E_OUTOFMEMORY; } else { *pDest = (OLECHAR *) pTemp; } }
return(hr); }
HRESULT WsbAllocAndCopyComString(OLECHAR** pszDest, OLECHAR* szSrc, ULONG bufferSize) { return(WsbAllocAndCopyComString2(pszDest, szSrc, bufferSize, TRUE)); }
HRESULT WsbAllocAndCopyComString2(OLECHAR** pszDest, OLECHAR* szSrc, ULONG bufferSize, BOOL bInOrder) { HRESULT hr = S_OK; ULONG ulStringSize; BOOL bWasAllocated; BOOL bCopyFailed = FALSE;
// Determine how big a buffer we need to store the string.
// NOTE: If we given a NULL pointer, then assume a "" will
// be created.
if (szSrc == NULL) { ulStringSize = sizeof(OLECHAR); } else { ulStringSize = (wcslen(szSrc) + 1) * sizeof(OLECHAR); }
// Make sure that we have a buffer that we can use, and also
// remember if we created it (so that we can free it on failure).
hr = WsbGetComBuffer(pszDest, bufferSize, ulStringSize, &bWasAllocated);
// If we have a valid buffer, then copy the string.
if (SUCCEEDED(hr)) {
if (szSrc == NULL) { *pszDest[0] = 0; }
else if (bInOrder) { if (wcscpy(*pszDest, szSrc) != *pszDest) { bCopyFailed = TRUE; } } else { int i,j;
for (i = 0, j = (ulStringSize / sizeof(OLECHAR)) - 2; j >= 0; i++, j--) { (*pszDest)[i] = szSrc[j]; } (*pszDest)[i] = OLECHAR( '\0' ); }
if (bCopyFailed) { // If the copy failed then free the buffer and
// return an error.
if (bWasAllocated) { WsbFree(*pszDest); *pszDest = NULL; }
hr = E_FAIL; } } return(hr); }
HRESULT WsbLoadComString(HINSTANCE hInstance, UINT uID, OLECHAR** pszDest, ULONG bufferSize) { HRESULT hr = S_OK; HRSRC hResource; ULONG ulStringSize; BOOL bWasAllocated = FALSE;
// Find the resource requested. This requires converting the resource
// identifier into a string.
//
// NOTE: Strings are not number individually, but in groups of 16!! This throws
// off the latter size calculation, and some other strategy might be better
// here (e.g. load to a fixed size and then allocate again if too small).
hResource = FindResource(hInstance, MAKEINTRESOURCE((uID/16) + 1), RT_STRING); if (hResource == NULL) { hr = E_FAIL; } else {
// How big is the string?
ulStringSize = SizeofResource(hInstance, hResource); if (ulStringSize == 0) { hr = E_FAIL; } else { // Get the right sized buffer.
hr = WsbGetComBuffer(pszDest, bufferSize, ulStringSize, &bWasAllocated); if (SUCCEEDED(hr)) {
// Load the string into the buffer.
if (LoadString(hInstance, uID, (LPTSTR) *pszDest, ulStringSize) == 0) { // If we couldn't load the string, then free the buffer that
// if we allocated it.
if (bWasAllocated) { WsbFree(*pszDest); } hr = E_FAIL; } } } }
return(hr); }
HRESULT WsbMatchComString(OLECHAR* szEnd, UINT uId, USHORT usChecks, UINT* uIdMatch) { HRESULT hr = S_FALSE; HRESULT hr2; OLECHAR* szDest = NULL;
// Initialize the return value.
*uIdMatch = 0;
// Check each resource string mention and see if it is the same as
// the string provided.
for (UINT uIdTest = uId; ((uIdTest < (uId + usChecks)) && (hr == S_FALSE)); uIdTest++) {
hr2 = WsbLoadComString(_Module.m_hInst, uIdTest, &szDest, 0);
if (SUCCEEDED(hr2)) { if (wcscmp(szDest, szEnd) == 0) { *uIdMatch = uIdTest; } } else { hr =hr2; } }
// If we allocated a buffer, then we need to free it.
if (szDest != NULL) { WsbFree(szDest); }
return(hr); }
// Type Conversion
void WsbLLtoHL(LONGLONG ll, LONG* pHigh, LONG* pLow) {
*pHigh = (DWORD) (ll >> 32); *pLow = (DWORD) (ll & 0x00000000ffffffff); }
LONGLONG WsbHLtoLL(LONG high, LONG low) { LONGLONG ll;
ll = ((LONGLONG) high) << 32; ll += (LONGLONG) (ULONG) low;
return(ll); }
FILETIME WsbLLtoFT(LONGLONG ll) { FILETIME ft;
WsbLLtoHL(ll, (LONG*) &ft.dwHighDateTime, (LONG*) &ft.dwLowDateTime);
return(ft); }
LONGLONG WsbFTtoLL(FILETIME ft) { LONGLONG ll;
ll = WsbHLtoLL((LONG) ft.dwHighDateTime, (LONG) ft.dwLowDateTime);
return(ll); }
HRESULT WsbFTtoWCS(BOOL isRelative, FILETIME ft, OLECHAR** pszA, ULONG bufferSize) { SYSTEMTIME st; HRESULT hr = S_OK; BOOL bWasAllocated = FALSE; LONGLONG llIn = WsbFTtoLL(ft);
WsbTraceIn(OLESTR("WsbFTtoWCS"), OLESTR("isRelative = %ls, ft = %I64x"), WsbQuickString(WsbBoolAsString(isRelative)), ft);
// If this is a relative time, then FT is just ticks.
if (isRelative) { LONGLONG llTicks=0; UINT uId=0;
// Try to find a scale that works (i.e. the largest one with
// no remainder.
if (llIn == 0) { llTicks = 0; uId = IDS_WSB_FT_TYPE_SECOND; }
else if ((llIn % WSB_FT_TICKS_PER_YEAR) == 0) { llTicks = llIn / WSB_FT_TICKS_PER_YEAR; uId = IDS_WSB_FT_TYPE_YEAR; }
else if ((llIn % WSB_FT_TICKS_PER_MONTH) == 0) { llTicks = llIn / WSB_FT_TICKS_PER_MONTH; uId = IDS_WSB_FT_TYPE_MONTH; }
else if ((llIn % WSB_FT_TICKS_PER_DAY) == 0) { llTicks = llIn / WSB_FT_TICKS_PER_DAY; uId = IDS_WSB_FT_TYPE_DAY; }
else if ((llIn % WSB_FT_TICKS_PER_HOUR) == 0) { llTicks = llIn / WSB_FT_TICKS_PER_HOUR; uId = IDS_WSB_FT_TYPE_HOUR; }
else if ((llIn % WSB_FT_TICKS_PER_MINUTE) == 0) { llTicks = llIn / WSB_FT_TICKS_PER_MINUTE; uId = IDS_WSB_FT_TYPE_MINUTE; }
else if ((llIn % WSB_FT_TICKS_PER_SECOND) == 0) { llTicks = llIn / WSB_FT_TICKS_PER_SECOND; uId = IDS_WSB_FT_TYPE_SECOND; }
else { hr = E_INVALIDARG; }
// If we found a scale, then form the proper string.
if (SUCCEEDED(hr)) { OLECHAR* szTmp1 = NULL; OLECHAR* szTmp2 = NULL;
// Get the string corresponding to the time period selected.
hr = WsbLoadComString(_Module.m_hInst, uId, &szTmp1, 0);
if (SUCCEEDED(hr)) { hr = WsbLLtoWCS(llTicks, &szTmp2, 0);
if (SUCCEEDED(hr)) { hr = WsbGetComBuffer(pszA, bufferSize, (wcslen(szTmp1) + wcslen(szTmp2) + 2) * sizeof(OLECHAR), NULL); if (SUCCEEDED(hr)) { swprintf( *pszA, OLESTR("%ls %ls"), szTmp2, szTmp1); }
WsbFree(szTmp2); }
WsbFree(szTmp1); } } }
// Otherwise it is absolute and converts to a specific date and time.
else { // Convert the filetime to a system time.
if (!FileTimeToSystemTime(&ft, &st)) { hr = E_FAIL; }
else {
// Get a buffer for the time string.
hr = WsbGetComBuffer(pszA, bufferSize, WSB_FT_TO_WCS_ABS_STRLEN * sizeof(OLECHAR), &bWasAllocated);
if (SUCCEEDED(hr)) { // Print the time in the buffer according to the standard
// format mm/dd/yy @ hh:mm:ss.
swprintf( *pszA, OLESTR("%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d"), st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond); } } }
WsbTraceOut(OLESTR("WsbFTtoWCS"), OLESTR("pszA = %ls"), *pszA);
return(hr); }
HRESULT WsbLLtoWCS(LONGLONG ll, OLECHAR** pszA, ULONG bufferSize) { OLECHAR szTmp[80]; HRESULT hr = S_OK; int i = 0; LONGLONG value = ll; BOOL bIsNegative = FALSE;
// First check to see if ll is negative
if (value < 0) { bIsNegative = TRUE; value *= -1; }
// This builds the string in reverse, but we'll change the order
// again we we copy it to a buffer.
do { szTmp[i++] = (OLECHAR) ('0' + (value % 10)); value /= 10; } while (value > 0); // Add the negative symbol is negative just before terminating NULL
if (bIsNegative) { szTmp[i] = OLECHAR('-'); i++; }
// Add a terminating NULL
szTmp[i] = OLECHAR( '\0' );
// Now vopy the string into the target buffer.
hr = WsbAllocAndCopyComString2(pszA, szTmp, bufferSize, FALSE);
return(hr); }
HRESULT WsbWCStoFT(OLECHAR* szA, BOOL* pisRelative, FILETIME* pft) { HRESULT hr = S_OK; OLECHAR* szEnd;
// Is this an absolute time (i.e. a date and time) or a relative
// time (e.g. 6 days, ...). This is determined by seeing a / in the
// string, which should only be present in absolute times. (Input
// format expected for an absolute time is either "mm/dd/yyyy hh:mm:ss"
// or "mm/dd/yyyy". If no time is input for an absolute time (i.e.,
// the "mm/dd/yyyy" format), then the current local time will be
// filled in for the user.
// Note that no millisecond info is to be included, since we supply
// a 'ticks' field as a separate parameter whenever we work at the
// millisecond/fraction of millisecond level.)
szEnd = wcschr(szA, '/');
// Is it a relative time (i.e. no '/')?
if (szEnd == NULL) { LONGLONG llValue;
*pisRelative = TRUE;
// The first token should be a number, so convert the string to
// a number.
llValue = wcstoul(szA, &szEnd, 10);
if (errno == ERANGE) { hr = E_INVALIDARG; }
else { UINT uId;
// The second token should be a type (i.e. second, hour, minute, ...).
hr = WsbMatchComString(szEnd, IDS_WSB_FT_TYPE_YEAR, WSB_FT_TYPES_MAX, &uId); if (S_OK == hr) {
switch (uId) { case IDS_WSB_FT_TYPE_YEAR: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_YEAR); break;
case IDS_WSB_FT_TYPE_MONTH: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_MONTH); break;
case IDS_WSB_FT_TYPE_WEEK: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_WEEK); break;
case IDS_WSB_FT_TYPE_DAY: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_DAY); break;
case IDS_WSB_FT_TYPE_HOUR: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_HOUR); break;
case IDS_WSB_FT_TYPE_MINUTE: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_MINUTE); break;
case IDS_WSB_FT_TYPE_SECOND: *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_SECOND); break;
default: hr = E_INVALIDARG; break; } } } }
// It is an absolute time.
else { SYSTEMTIME st; BOOL timeWasInput = TRUE; OLECHAR* szSearchString; // The first number should represent the month.
st.wMonth = (USHORT) wcstoul(szA, &szEnd, 10); // test resultant month within range, and that the format of the input
// absolute date/time is valid (i.e., the character which stopped the
// above conversion is the slash between the month and day digits)
if ((st.wMonth < 1) || (st.wMonth > 12) || (*szEnd != ((OLECHAR) '/'))) { hr = E_INVALIDARG; }
// The next number should represent the day.
if (SUCCEEDED(hr)) { // set szSearchString to 1 character beyond the character that
// stopped the above 'wcstoul' conversion
szSearchString = szEnd + 1; st.wDay = (USHORT) wcstoul(szSearchString, &szEnd, 10); if ((st.wDay < 1) || (st.wDay > 31) || (*szEnd != ((OLECHAR) '/'))) { hr = E_INVALIDARG; } }
// The next number should represent the year.
if (SUCCEEDED(hr)) { szSearchString = szEnd + 1; st.wYear = (USHORT) wcstoul(szSearchString, &szEnd, 10); // test resultant year equal to at least 1601, since NT records
// time and date starting from 12:00am, January 1, 1601. This
// test also is used to enforce that a 4 digit year was entered.
if ((st.wYear < 1601) || (*szEnd != ((OLECHAR) ' '))) { if (( st.wYear >= 1601 ) && ( szEnd[0] == 0 )) { SYSTEMTIME now; GetLocalTime ( &now ); st.wHour = now.wHour; st.wMinute = now.wMinute; st.wSecond = now.wSecond; timeWasInput = FALSE; } else { hr = E_INVALIDARG; } } }
// The next number should represent the hour.
if ( timeWasInput ) { if (SUCCEEDED(hr)) { szSearchString = szEnd + 1; st.wHour = (USHORT) wcstoul(szSearchString, &szEnd, 10); if ((st.wHour > 23) || (*szEnd != ((OLECHAR) ':'))) { hr = E_INVALIDARG; } } }
// The next number should represent the minutes.
if ( timeWasInput ) { if (SUCCEEDED(hr)) { szSearchString = szEnd + 1; st.wMinute = (USHORT) wcstoul(szSearchString, &szEnd, 10); if ((st.wMinute > 59) || (*szEnd != ((OLECHAR) ':'))) { hr = E_INVALIDARG; } } }
// The next number should represent the seconds.
if ( timeWasInput ) { if (SUCCEEDED(hr)) { szSearchString = szEnd + 1; st.wSecond = (USHORT) wcstoul(szSearchString, &szEnd, 10); if ((st.wSecond > 59) || (szEnd[0] != 0)) { hr = E_INVALIDARG; } } }
// NOTE: Although the SYSTEMTIME structure contains a milliseconds field,
// it can only express milliseconds as whole numbers, so this function
// does not support any way to specify the number of milliseconds. If
// millisecond/fraction of milliseconds are necessary, after this function
// returns add in the NT-supported 'number of 100 nanosecond 'ticks'' to
// the FILETIME result output by this function. The number of
// ticks is used to represent both milliseconds and fractions thereof.
// initialize the millisecond field before converting SystemTime to FileTime
st.wMilliseconds = 0;
// If we properly converted the string, then convert the
// system time into a file time.
if (SUCCEEDED(hr)) { if ( SystemTimeToFileTime(&st, pft) == FALSE) { hr = E_FAIL; } } }
return(hr); }
HRESULT WsbWCStoLL(OLECHAR* szA, LONGLONG* pll) { HRESULT hr = S_OK; LONGLONG llFactor = 1; size_t ulLength = wcslen(szA);
// It is an error not to have any digits.
if (ulLength == 0) { hr = E_INVALIDARG; }
else { int i; // Step through character by character.
for (i = ulLength, *pll = 0; ((i > 0) && (SUCCEEDED(hr))); i--) { if (iswalpha(szA[i-1])) { (*pll) += llFactor * ((LONGLONG) (szA[i-1] - ((OLECHAR) '0'))); llFactor *= 10; } else { hr = E_INVALIDARG; } } }
return(hr); }
HRESULT WsbDatetoFT(DATE date, LONG ticks, FILETIME* pFt) { HRESULT hr = S_OK; SYSTEMTIME st;
try {
WsbAssert(0 != pFt, E_POINTER);
// Do the basic date conversion
WsbAffirmHr(VariantTimeToSystemTime(date, &st)); WsbAffirmStatus(SystemTimeToFileTime(&st, pFt));
// Variant DATE field only tracks time and date down to seconds.
// FILETIMEs are kept using a 64 bit value specifying the number
// of 100-nanosecond intervals that have elapsed since 12:00am
// January 1, 1601. Since our 'ticks' value represents milliseconds
// and fractions of milliseconds using the same 100-nanosecond interval
// units, to add in milliseconds add in the ticks. But since FILETIME
// is actually a structure of 2 DWORDs, we must use some conversions.
LONGLONG FTasLL; FTasLL = WsbFTtoLL ( *pFt );
FTasLL += (LONGLONG) ticks;
*pFt = WsbLLtoFT ( FTasLL );
} WsbCatch(hr); return(hr); }
HRESULT WsbFTtoDate(FILETIME ft, DATE* pDate, LONG* pTicks) { HRESULT hr = S_OK; SYSTEMTIME st; FILETIME ft2;
try { WsbAssert(0 != pDate, E_POINTER); WsbAssert(0 != pTicks, E_POINTER);
// Do the basic time conversion.
WsbAffirmStatus(FileTimeToSystemTime(&ft, &st)); WsbAffirmStatus(SystemTimeToVariantTime(&st, pDate));
// Now convert back what we have and figure out how many ticks got lost.
WsbAffirmHr(WsbDatetoFT(*pDate, 0, &ft2)); *pTicks = (LONG) (WsbFTtoLL(ft) - WsbFTtoLL(ft2));
} WsbCatch(hr)
return(hr); }
HRESULT WsbLocalDateTicktoUTCFT(DATE date, LONG ticks, FILETIME* pFT) { // This routine converts a VARIANT DATE field (expressed in local time)
// and a 'number of 100 nanosecond intervals' ticks field to a FILETIME
// in UTC format. This is the format that file timestamps are kept in.
// The result of this call is suitable for use in setting a file's timestamp.
HRESULT hr = S_OK; FILETIME localFTHolder;
try {
WsbAssert(0 != pFT, E_POINTER);
// Do the basic date conversion which yields a FILETIME in local time
WsbAffirmHr(WsbDatetoFT(date, ticks, &localFTHolder));
// Now convert the local time to UTC format FILETIME
WsbAffirmStatus(LocalFileTimeToFileTime(&localFTHolder, pFT));
} WsbCatch(hr); return(hr); }
HRESULT WsbUTCFTtoLocalDateTick(FILETIME ft, DATE* pDate, LONG* pTicks) { // This routine converts a FILETIME field (expressed in UTC format - which
// is the format file timestamps are stored in) to a VARIANT DATE field
// (expressed in local time) and a Ticks field. The Ticks field represents
// a 'number of 100 nanosecond intervals' which represents the 'milliseconds
// and fractions of a millisecond' that was contained in the UTC formatted
// FILETIME.
HRESULT hr = S_OK; FILETIME localFT;
try { WsbAssert(0 != pDate, E_POINTER); WsbAssert(0 != pTicks, E_POINTER);
// First convert the UTC format FILETIME to one in Local Time
WsbAffirmStatus(FileTimeToLocalFileTime(&ft, &localFT)); // Do the basic time conversion.
WsbAffirmHr(WsbFTtoDate(localFT, pDate, pTicks));
} WsbCatch(hr)
return(hr); }
HRESULT WsbDateToString(DATE date, OLECHAR** string) { // NOTE: the caller owns the memory occupied by 'string' when this
// helper function returns. Since 'string''s buffer is allocated
// by WsbAlloc/Realloc(), memory needs to be freed via
// WsbFree()
HRESULT hr = S_OK; SYSTEMTIME systime; BOOL wasBufferAllocated;
try { // convert the VARIANT Date to a system time
WsbAffirmHr ( VariantTimeToSystemTime ( date, &systime ) );
// create a COM buffer (meaning it was allocated with
// WsbAlloc/Realloc()) to hold the date/time string which this method
// will return. The buffer, passed back as 'string', will need to be freed
// with WsbFree() by the caller. Note that passing a 'requested size'
// (2nd arg) of zero forces a realloc of the 'string' buffer.
WsbAffirmHr ( WsbGetComBuffer ( string, 0, (WSB_VDATE_TO_WCS_ABS_STRLEN * sizeof (OLECHAR)), &wasBufferAllocated ) );
// load the buffer with the date and time using the standard
// format: mm/dd/yyyy hh:mm:ss. Note that milliseconds are
// not represented since a VARIANT Date field can only track
// time to second granularity.
swprintf ( *string, L"%2.2d/%2.2d/%2.4d %2.2d:%2.2d:%2.2d", systime.wMonth, systime.wDay, systime.wYear, systime.wHour, systime.wMinute, systime.wSecond );
} WsbCatch ( hr )
return ( hr ); }
HRESULT WsbStringToDate(OLECHAR* string, DATE* date) { HRESULT conversionHR = S_OK; BOOL isRelative; FILETIME holdFT; SYSTEMTIME holdST;
try { // convert input wide char string to a FILETIME. Throw hr as
// exception if not successful.
WsbAffirmHr ( WsbWCStoFT ( string, &isRelative, &holdFT ) );
// convert FILETIME result from above to SYSTEMTIME. If this
// Boolean call fails, get Last Error, convert to hr and throw it.
WsbAffirmStatus ( FileTimeToSystemTime ( &holdFT, &holdST ) );
// finally, convert SYSTEMTIME result from above to VARIANT Date
WsbAffirmHr ( SystemTimeToVariantTime ( &holdST, date ) );
} WsbCatch ( conversionHR )
return ( conversionHR ); }
// Filetime Manipulations
FILETIME WsbFtSubFt(FILETIME ft1, FILETIME ft2) { return(WsbLLtoFT(WsbFTtoLL(ft1) - WsbFTtoLL(ft2))); }
SHORT WsbCompareFileTimes(FILETIME ft1, FILETIME ft2, BOOL isRelative, BOOL isNewer) { SHORT result = 0; LONGLONG ll1; LONGLONG ll2; LONGLONG tmp; FILETIME ftNow; LONGLONG llNow;
WsbTraceIn(OLESTR("WsbCompareFileTimes"), OLESTR("ft1 = %ls, ft2 = %ls, isRelative = %ls, isNewer = %ls"), WsbQuickString(WsbFiletimeAsString(FALSE, ft1)), WsbQuickString(WsbFiletimeAsString(isRelative, ft2)), WsbQuickString(WsbBoolAsString(isRelative)), WsbQuickString(WsbBoolAsString(isRelative)));
ll1 = WsbFTtoLL(ft1); ll2 = WsbFTtoLL(ft2);
if (isRelative) { GetSystemTimeAsFileTime(&ftNow); WsbTrace(OLESTR("WsbCompareFileTimes: ftNow = %ls\n"), WsbFiletimeAsString(FALSE, ftNow)); llNow = WsbFTtoLL(ftNow);
if (isNewer) { tmp = ll1 - llNow; } else { tmp = llNow - ll1; }
if (tmp > ll2) { result = 1; } if (tmp < ll2) { result = -1; } } else {
if (ll1 > ll2) { result = 1; } if (ll1 < ll2) { result = -1; }
if (!isNewer) { result *= -1; } }
WsbTraceOut(OLESTR("WsbCompareFileTimes"), OLESTR("result = %hd"), result); return(result); }
// GUID Manipulations
int WsbCompareGuid(REFGUID guid1, REFGUID guid2) { return(memcmp(&guid1, &guid2, sizeof(GUID))); }
HRESULT WsbStringFromGuid(REFGUID rguid, OLECHAR* sz) { int returnCount = StringFromGUID2(rguid, sz, WSB_GUID_STRING_SIZE);
return ( ( returnCount > 0) ? S_OK : E_FAIL ); }
HRESULT WsbGuidFromString(const OLECHAR* sz, GUID * pguid) { return CLSIDFromString((OLECHAR*)sz, pguid); }
HRESULT WsbGetServiceId(OLECHAR* serviceName, GUID* pGuid ) { HRESULT hr = S_OK; DWORD sizeGot; CWsbStringPtr outString; CWsbStringPtr tmpString;
try {
// Look in the registry to see if this service has already created itself and has
// a GUID registered.
tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\"); WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(tmpString.Append(serviceName)); WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(outString.Alloc(256));
// if the SettingId value is there then we tell caller there is none
// clean up the registry ?????
if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), outString, 256, &sizeGot) == S_OK) { // if the Id is there remove it first
if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) == S_OK) { WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("Id") ) ); } // Remove the SettingId value last
WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("SettingId") ) ); *pGuid = GUID_NULL ; WsbThrow( WSB_E_NOTFOUND );
// if it is not there we return GUID_NULL
} else if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) != S_OK) { *pGuid = GUID_NULL ; WsbThrow( WSB_E_NOTFOUND );
// verify that the Id value is really there
} else { WsbAffirmHr(IIDFromString(outString, (IID *)pGuid)); }
} WsbCatch(hr);
return(hr); }
HRESULT WsbSetServiceId(OLECHAR* serviceName, GUID guid ) { HRESULT hr = S_OK; DWORD sizeGot; CWsbStringPtr outString; CWsbStringPtr tmpString;
try {
// Look in the registry to see if this service has already created itself and has
// a GUID registered.
tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\"); WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(tmpString.Append(serviceName)); WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(outString.Alloc(256));
// If the Id string is not there then set it
CWsbStringPtr strGuid; WsbAffirmHr(WsbSafeGuidAsString(guid, strGuid)); if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) != S_OK) { // if there is a SettingId then we have something wrong in here so throw an error
if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), outString, 256, &sizeGot) == S_OK) { WsbThrow( WSB_E_INVALID_DATA ); } WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), strGuid ) ); } else { // ID already exists so set it and blast the SettingId
WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), strGuid)); WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), strGuid)); WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("SettingId") ) ); }
} WsbCatch(hr);
return(hr); } HRESULT WsbCreateServiceId(OLECHAR* serviceName, GUID* pGuid ) { HRESULT hr = S_OK; DWORD sizeGot; CWsbStringPtr outString; CWsbStringPtr tmpString;
try {
// Look in the registry to see if this service has already created itself and has
// a GUID registered.
tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\"); WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(tmpString.Append(serviceName)); WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(outString.Alloc(256));
if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) != S_OK) { WsbAffirmHr(CoCreateGuid(pGuid)); CWsbStringPtr strGuid; WsbAffirmHr(WsbSafeGuidAsString(*pGuid, strGuid)); WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), strGuid)); WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), strGuid)); } else { WsbThrow( WSB_E_INVALID_DATA ); }
} WsbCatch(hr);
return(hr); } HRESULT WsbConfirmServiceId(OLECHAR* serviceName, GUID guidConfirm ) { HRESULT hr = S_OK; DWORD sizeGot; CWsbStringPtr outString; CWsbStringPtr tmpString; GUID guid;
try {
// Look in the registry to see if this service has already created itself and has
// a GUID registered.
tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\"); WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(tmpString.Append(serviceName)); WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(outString.Alloc(256));
// verify that the Id value is really there
WsbAffirmHr( WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) ) ; WsbAffirmHr( IIDFromString( outString, (IID *)&guid ) ); WsbAffirm( guid == guidConfirm, WSB_E_INVALID_DATA );
// verify that the SettingId value is really there and the same
WsbAffirmHr( WsbGetRegistryValueString( NULL, tmpString, OLESTR("SettingId"), outString, 256, &sizeGot ) ) ; WsbAffirmHr( IIDFromString( outString, (IID *)&guid ) ); WsbAffirm( guid == guidConfirm, WSB_E_INVALID_DATA );
// remove the flag value
WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("SettingId") ) );
} WsbCatch(hr);
return(hr); }
HRESULT WsbGetMetaDataPath(OUT CWsbStringPtr & Path) { HRESULT hr = S_OK; DWORD sizeGot; try {
// Find out where they have NT installed, and make sure that our subdirectory exists.
WsbAffirmHr(Path.Alloc(256)); //
// Use the relocatable meta-data path if it's available,
// otherwise default to the %SystemRoot%\System32\RemoteStorage
//
hr = WsbCheckIfRegistryKeyExists(NULL, WSB_CONTROL_REGISTRY_KEY); if (hr == S_OK) { WsbAffirmHr(WsbGetRegistryValueString(NULL, WSB_CONTROL_REGISTRY_KEY, WSB_METADATA_REGISTRY_VALUE, Path, 256, &sizeGot));
} else { WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, WSB_CURRENT_VERSION_REGISTRY_KEY)); WsbAffirmHr(WsbGetRegistryValueString(NULL, WSB_CURRENT_VERSION_REGISTRY_KEY, WSB_SYSTEM_ROOT_REGISTRY_VALUE, Path, 256, &sizeGot)); WsbAffirmHr(Path.Append(OLESTR("\\system32\\RemoteStorage"))); } } WsbCatchAndDo(hr, Path.Free(); );
return(hr); }
HRESULT WsbGetServiceTraceDefaults(OLECHAR* serviceName, OLECHAR* traceFile, IUnknown* pUnk) { HRESULT hr = S_OK; DWORD sizeGot; CWsbStringPtr pathString; CWsbStringPtr outString; CWsbStringPtr rsPath; CWsbStringPtr tmpString; CComPtr<IWsbTrace> pTrace; OLECHAR* lastSlash; PSID pSystemSID = NULL; PSID pAdminSID = NULL; PSID pBackupOpSID = NULL; PACL pACL = NULL; #define METADATA_DIR_NUM_ACE 3
EXPLICIT_ACCESS ea[METADATA_DIR_NUM_ACE]; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
try {
WsbAssertPointer(serviceName);
WsbAffirmHr(WsbGetMetaDataPath(rsPath));
// Create metadata directory
tmpString = rsPath; WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\"))); if (! CreateDirectory(tmpString, 0)) { // Directory already exists is expected
DWORD status = GetLastError(); if ((status == ERROR_ALREADY_EXISTS) || (status == ERROR_FILE_EXISTS)) { status = NO_ERROR; } WsbAffirmNoError(status); }
// Set strong ACL on the RSS metadata directory
// Note: In order to handle the upgrade case as well, we need to set the ACL even if
// the directory exists. Another option would be:
// 1. Set it here only if directory doesn't exist
// 2. Then set ACL in CHsmServer::Load or in the Setup-upgrade code where there is
// a dedicated code for the Win2K upgrade case
// Prepare security attribute for admin only access:
memset(ea, 0, sizeof(EXPLICIT_ACCESS) * METADATA_DIR_NUM_ACE);
// Create a SID for the local system account
WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSID) );
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE allows the Administrators group full access to the directory
ea[0].grfAccessPermissions = FILE_ALL_ACCESS; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea[0].Trustee.pMultipleTrustee = NULL; ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; ea[0].Trustee.ptstrName = (LPTSTR) pSystemSID;
// Create a SID for the Administrators group.
WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID) );
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE allows the Administrators group full access to the directory
ea[1].grfAccessPermissions = FILE_ALL_ACCESS; ea[1].grfAccessMode = SET_ACCESS; ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea[1].Trustee.pMultipleTrustee = NULL; ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;
// Create a SID for the BackupOp group.
WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS, 0, 0, 0, 0, 0, 0, &pBackupOpSID) );
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE allows the BackupOps group read access to the directory
ea[2].grfAccessPermissions = (FILE_GENERIC_READ | FILE_TRAVERSE); ea[2].grfAccessMode = SET_ACCESS; ea[2].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea[2].Trustee.pMultipleTrustee = NULL; ea[2].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[2].Trustee.ptstrName = (LPTSTR) pBackupOpSID;
// Create a new ACL that contains the ACEs.
WsbAffirmNoError( SetEntriesInAcl(METADATA_DIR_NUM_ACE, ea, NULL, &pACL));
// Set the ACL on the directory
WsbAffirmWin32(SetNamedSecurityInfo(tmpString, SE_FILE_OBJECT, (DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION), NULL, NULL, pACL, NULL) );
// Look in the registry to see if this service has already created itself and has
// a GUID registered.
tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\"); WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString)); WsbAffirmHr(tmpString.Append(serviceName)); WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters"))); WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
WsbAffirmHr(outString.Alloc(256));
// We also want to put the path where the trce file should go.
if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("WsbTraceFileName"), outString, 256, &sizeGot) != S_OK) { outString = rsPath; WsbAffirmHr(outString.Append(OLESTR("\\Trace\\"))); WsbAffirmHr(outString.Append(traceFile)); WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("WsbTraceFileName"), outString)); }
// Try a little to make sure the trace directory exists.
lastSlash = wcsrchr(outString, L'\\'); if ((0 != lastSlash) && (lastSlash != outString)) { *lastSlash = 0; CreateDirectory(outString, 0); }
// Turn tracing on, if requested.
if (0 != pUnk) { WsbAffirmHr(pUnk->QueryInterface(IID_IWsbTrace, (void**) &pTrace)); WsbAffirmHr(pTrace->SetRegistryEntry(tmpString)); WsbAffirmHr(pTrace->LoadFromRegistry()); }
} WsbCatch(hr);
// Cleanup security allocations
if (pSystemSID) FreeSid(pSystemSID); if (pAdminSID) FreeSid(pAdminSID); if (pBackupOpSID) FreeSid(pBackupOpSID); if (pACL) LocalFree(pACL);
return(hr); }
HRESULT WsbRegisterEventLogSource( IN const WCHAR * LogName, IN const WCHAR * SourceName, IN DWORD CategoryCount, IN const WCHAR * CategoryMsgFile OPTIONAL, IN const WCHAR * MsgFiles )
/*++
Routine Description:
Registers the given event source in the event log. We have to do the event log registration outside the rgs files since event log viewer insists on REG_EXPAND_SZ type values (which cannot be done via rgs).
Arguments:
None.
Return Value:
S_OK - Service Registered and everything is set
--*/
{
CWsbStringPtr rpPath; HRESULT hr = S_OK;
try {
CWsbStringPtr regPath; DWORD types = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
//
// Everything goes into HKLM\SYSTEM\CurrentControlSet\Services\EventLog\<LogName>\<SourceName>
//
regPath.Printf( OLESTR("%ls\\%ls\\%ls"), WSB_LOG_BASE, LogName, SourceName ); WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, regPath ) );
//
// See if we have Categories within this source. Register if so
//
if( CategoryCount ) {
WsbAffirmHr( WsbSetRegistryValueDWORD( 0, regPath, WSB_LOG_CAT_COUNT, CategoryCount ) ); WsbAffirmHr( WsbSetRegistryValueString( 0, regPath, WSB_LOG_CAT_FILE, CategoryMsgFile, REG_EXPAND_SZ ) );
}
//
// Register the message source and types of events
//
WsbAffirmHr( WsbSetRegistryValueString( 0, regPath, WSB_LOG_MESSAGE_FILE, MsgFiles, REG_EXPAND_SZ ) ); WsbAffirmHr( WsbSetRegistryValueDWORD( 0, regPath, WSB_LOG_TYPES, types ) );
} WsbCatch( hr );
return ( hr ); }
HRESULT WsbUnregisterEventLogSource( IN const WCHAR * LogName, IN const WCHAR * SourceName )
/*++
Routine Description:
Registers the given event source in the event log.
Arguments:
None.
Return Value:
S_OK - Service Registered and everything is set
--*/
{
CWsbStringPtr rpPath; HRESULT hr = S_OK;
try {
CWsbStringPtr regPath;
//
// Everything goes into HKLM\SYSTEM\CurrentControlSet\Services\EventLog\<LogName>\<SourceName>
//
regPath.Printf( OLESTR("%ls\\%ls\\%ls"), WSB_LOG_BASE, LogName, SourceName );
//
// Some of these may not exist, so don't check return value
//
WsbRemoveRegistryValue( 0, regPath, WSB_LOG_CAT_COUNT ); WsbRemoveRegistryValue( 0, regPath, WSB_LOG_CAT_FILE ); WsbRemoveRegistryValue( 0, regPath, WSB_LOG_MESSAGE_FILE ); WsbRemoveRegistryValue( 0, regPath, WSB_LOG_TYPES );
regPath.Printf( OLESTR("%ls\\%ls"), WSB_LOG_BASE, LogName ); WsbAffirmHr( WsbRemoveRegistryKey( 0, regPath, SourceName ) );
} WsbCatch( hr );
return ( hr ); }
HRESULT WsbRegisterRsFilter ( BOOL bDisplay )
/*++
Routine Description:
Registers the RsFilter for use by the system. We assume that the filter is already in the system32\driver directory.
Arguments:
None.
Return Value:
S_OK - Service Registered and everything is set
ERROR_SERVICE_EXISTS - service already exists
ERROR_DUP_NAME - The display name already exists in teh SCM as a service name or a display name --*/
{
CWsbStringPtr rpPath; CWsbStringPtr rpDescription; SC_HANDLE hService; SC_HANDLE hSCM = NULL; HRESULT hr = S_OK; DWORD rpTag = 0;
try { rpPath.Printf( OLESTR("%%SystemRoot%%\\System32\\drivers\\%ls%ls"), TEXT(RSFILTER_APPNAME), TEXT(RSFILTER_EXTENSION) );
//
// First make sure not already installed
//
hSCM = OpenSCManager( 0, 0, GENERIC_READ | GENERIC_WRITE ); WsbAffirmPointer( hSCM );
//
// and install it
//
hService = CreateService( hSCM, // SCManager database
TEXT(RSFILTER_SERVICENAME), // Service name
TEXT(RSFILTER_DISPLAYNAME), // Display name
SERVICE_ALL_ACCESS, // desired access
SERVICE_FILE_SYSTEM_DRIVER, // service type
SERVICE_BOOT_START, // start type
SERVICE_ERROR_NORMAL, // error control type
rpPath, // Executable location
TEXT(RSFILTER_GROUP), // group
&rpTag, // Set tag to zero so we are loaded first in the filter group.
TEXT(RSFILTER_DEPENDENCIES), NULL, NULL); WsbAffirmStatus( 0 != hService );
rpDescription.LoadFromRsc(_Module.m_hInst, IDS_WSBSVC_DESC ); SERVICE_DESCRIPTION svcDesc; svcDesc.lpDescription = rpDescription; ChangeServiceConfig2( hService, SERVICE_CONFIG_DESCRIPTION, &svcDesc );
CloseServiceHandle( hService );
//
// Add event logging entries
//
WsbAffirmHr( WsbRegisterEventLogSource( WSB_LOG_SYS, WSB_LOG_FILTER_NAME, 0, 0, TEXT(RSFILTER_FULLPATH) ) );
//
// Make sure params Key exists
//
CWsbStringPtr regPath; regPath.Printf( OLESTR("%ls\\%ls\\Parameters"), WSB_SVC_BASE, TEXT(RSFILTER_SERVICENAME) ); WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, regPath ) );
} WsbCatchAndDo( hr,
// If the caller wants error messages then give a message
if ( bDisplay ) MessageBox(NULL, WsbHrAsString( hr ), WSB_FACILITY_PLATFORM_NAME, MB_OK);
);
if( hSCM ) {
CloseServiceHandle( hSCM ); hSCM = NULL;
}
return ( hr ); }
HRESULT WsbUnregisterRsFilter ( BOOL bDisplay )
/*++
Routine Description:
Registers the RsFilter for use by the system.
Arguments:
None.
Return Value:
S_OK - Service Registered and everything is set
ERROR_SERVICE_EXISTS - service already exists
ERROR_DUP_NAME - The display name already exists in teh SCM as a service name or a display name --*/
{ SC_HANDLE hSCM = NULL; SC_HANDLE hService = NULL; HRESULT hr = S_OK;
try { //
// First connect with the Service Control Manager
//
hSCM = OpenSCManager( 0, 0, GENERIC_READ | GENERIC_WRITE ); WsbAffirmPointer( hSCM );
//
// Open the service
//
hService = OpenService( hSCM, TEXT(RSFILTER_SERVICENAME), SERVICE_ALL_ACCESS ); //
// if the handle is NULL then there is a problem and need to call GetLastError to get error code
//
WsbAffirmStatus( 0 != hService );
//
// Delete the service - if it does not work then return the error
//
WsbAffirmStatus( DeleteService( hService ) );
//
// Remove the registry values
//
WsbAffirmHr( WsbUnregisterEventLogSource( WSB_LOG_SYS, WSB_LOG_FILTER_NAME ) ); } WsbCatchAndDo( hr, // If the caller wants error messages then give a message
if ( bDisplay ) MessageBox(NULL, WsbHrAsString( hr ), WSB_FACILITY_PLATFORM_NAME, MB_OK); );
if ( hService ){ CloseServiceHandle( hService ); hService = NULL; } if( hSCM ) { CloseServiceHandle( hSCM ); hSCM = NULL; }
return ( hr ); }
STDAPI DllRegisterRsFilter ( void ) { return( WsbRegisterRsFilter( FALSE ) ) ; }
STDAPI DllUnregisterRsFilter ( void ) { return( WsbUnregisterRsFilter( FALSE ) ) ; }
HRESULT WsbCheckAccess( WSB_ACCESS_TYPE AccessType ) { HRESULT hr = S_OK; PSID psid = 0;
HANDLE hToken = NULL;
try {
//
// Set up the SID to check against
//
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; switch( AccessType ) { case WSB_ACCESS_TYPE_ADMINISTRATOR: WsbAffirmStatus( AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psid ) ); break;
case WSB_ACCESS_TYPE_OPERATOR: WsbAffirmStatus( AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS, 0, 0, 0, 0, 0, 0, &psid ) ); break;
case WSB_ACCESS_TYPE_USER: WsbAffirmStatus( AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &psid ) ); break;
case WSB_ACCESS_TYPE_ALL: WsbThrow( S_OK ); break;
default: WsbThrow( E_INVALIDARG );
}
//
// Check for membership
//
BOOL pMember = FALSE; if (! CheckTokenMembership( 0, psid, &pMember ) ) { // Check if this is an impersonation level problem, if so,
// get the thread impersonation token and try again
DWORD dwErr1 = GetLastError(); if (dwErr1 == ERROR_BAD_IMPERSONATION_LEVEL) { // Get thread token
HANDLE hThread = GetCurrentThread(); // No need to call CloseHandle here
WsbAffirmStatus(OpenThreadToken(hThread, TOKEN_QUERY, TRUE, &hToken)); WsbAffirmStatus( CheckTokenMembership( hToken, psid, &pMember ) ); } else { // Other error - throw
WsbAffirmNoError(dwErr1); } }
if( !pMember ) {
WsbThrow( E_ACCESSDENIED ); } } WsbCatch( hr ); if( psid ) FreeSid( psid );
if (hToken != NULL) CloseHandle(hToken);
return( hr ); }
HRESULT CWsbSecurityDescriptor::AllowRid( DWORD Rid, DWORD dwAccessMask ) { HRESULT hr = S_OK; PSID pSid = 0; PACL newACL = 0;
try {
//
// First, create the SID from Rid
//
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; WsbAffirmStatus( AllocateAndInitializeSid( &sia, 2, SECURITY_BUILTIN_DOMAIN_RID, Rid, 0, 0, 0, 0, 0, 0, &pSid ) );
//
// Construct new ACL
//
ACL_SIZE_INFORMATION aclSizeInfo; int aclSize; PACL oldACL;
aclSizeInfo.AclBytesInUse = 0; oldACL = m_pDACL; if( oldACL ) {
WsbAffirmStatus(GetAclInformation( oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
}
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid( pSid ) - sizeof(DWORD);
WsbAffirmAlloc( newACL = (PACL)( new BYTE[aclSize] ) ); WsbAffirmStatus( InitializeAcl( newACL, aclSize, ACL_REVISION ) ); WsbAffirmHr( CopyACL( newACL, oldACL ) );
WsbAffirmStatus( AddAccessAllowedAce( newACL, ACL_REVISION2, dwAccessMask, pSid ) );
//
// Swap over to new ACL
//
m_pDACL = newACL; newACL = 0;
if( oldACL ) {
delete( oldACL );
}
//
// Update the security descriptor
//
WsbAffirmStatus(SetSecurityDescriptorDacl( m_pSD, TRUE, m_pDACL, FALSE ));
} WsbCatch( hr );
if( pSid ) FreeSid( pSid ); if( newACL ) delete( newACL ); return( hr ); }
HRESULT WsbGetResourceString( ULONG id, WCHAR **ppString ) { HRESULT hr = S_OK; try { WsbAssert(ppString != 0, E_INVALIDARG);
*ppString = NULL;
// Let our srting class to do the work...
CWsbStringPtr loader; WsbAffirmHr(loader.LoadFromRsc(_Module.m_hInst, id));
*ppString = *(&loader); *(&loader) = NULL; } WsbCatch( hr );
return( hr ); }
|