You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1828 lines
57 KiB
1828 lines
57 KiB
#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 );
|
|
}
|