1710 lines
52 KiB
C++
1710 lines
52 KiB
C++
#include "StdAfx.h"
|
||
#include "resource.h"
|
||
#include "errno.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
|
||
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"), WsbGuidAsString(guid) ) );
|
||
} else {
|
||
// ID already exists so set it and blast the SettingId
|
||
WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), WsbGuidAsString(guid)));
|
||
WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), WsbGuidAsString(guid)));
|
||
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));
|
||
WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), WsbGuidAsString(*pGuid)));
|
||
WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), WsbGuidAsString(*pGuid)));
|
||
} 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;
|
||
|
||
try {
|
||
|
||
WsbAssertPointer(serviceName);
|
||
|
||
WsbAffirmHr(WsbGetMetaDataPath(rsPath));
|
||
|
||
// NOTE: Might want to check for errors, and ignore the directory already existing. Since I don't know
|
||
// what the error is, so we'll ignore this for now.
|
||
tmpString = rsPath;
|
||
WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\")));
|
||
CreateDirectory(tmpString, 0);
|
||
|
||
// 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);
|
||
|
||
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;
|
||
|
||
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;
|
||
WsbAffirmStatus( CheckTokenMembership( 0, psid, &pMember ) );
|
||
|
||
if( !pMember ) {
|
||
|
||
WsbThrow( E_ACCESSDENIED );
|
||
|
||
}
|
||
|
||
} WsbCatch( hr );
|
||
|
||
if( psid ) FreeSid( psid );
|
||
|
||
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 ) {
|
||
|
||
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
|
||
//
|
||
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 );
|
||
} |