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.
1242 lines
28 KiB
1242 lines
28 KiB
//
|
|
// global.cpp
|
|
//
|
|
|
|
#include "StdAfx.h"
|
|
#include <sddl.h>
|
|
#include "global.h"
|
|
#include "util.h"
|
|
#include "SSRLog.h"
|
|
|
|
|
|
CFBLogMgr g_fblog;
|
|
|
|
WCHAR g_wszSsrRoot[MAX_PATH + 1];
|
|
DWORD g_dwSsrRootLen = 0;
|
|
|
|
LPCWSTR g_pwszSSRRootToExpand = L"%windir%\\Security\\SSR";
|
|
|
|
//
|
|
// this is our ACL list
|
|
//
|
|
|
|
//LPCWSTR g_pwszSsrDCOMSecDescripACL = L"D:(A;;GA;;;SY)(A;;GA;;;BA)";
|
|
|
|
LPCWSTR g_pwszAppID = L"SOFTWARE\\Classes\\APPID\\{3f2db10f-6368-4702-a4b1-e5149d931370}";
|
|
LPCWSTR g_pwszAccessPermission = L"AccessPermission";
|
|
LPCWSTR g_pwszLaunchPermission = L"LaunchPermission";
|
|
|
|
//
|
|
// registry's SSR root
|
|
//
|
|
|
|
LPCWSTR g_pwszSSRRegRoot = L"Software\\Microsoft\\Security\\SSR";
|
|
|
|
LPCWSTR g_pwszSSR = L"SSR";
|
|
LPCWSTR g_pwszLogs = L"Logs";
|
|
|
|
//
|
|
// The following are reserved action verbs
|
|
//
|
|
|
|
CComBSTR g_bstrConfigure(L"Configure");
|
|
CComBSTR g_bstrRollback(L"Rollback");
|
|
CComBSTR g_bstrReport(L"Report");
|
|
|
|
//
|
|
// the following are reserved file-usage values
|
|
//
|
|
|
|
CComBSTR g_bstrLaunch(L"Launch");
|
|
CComBSTR g_bstrResult(L"Result");
|
|
|
|
//
|
|
// the following is the reserved action data's names
|
|
//
|
|
|
|
LPCWSTR g_pwszCurrSecurityPolicy = L"CurrSecurityPolicy";
|
|
LPCWSTR g_pwszTransformFiles = L"TransformFiles";
|
|
LPCWSTR g_pwszScriptFiles = L"ScriptFiles";
|
|
|
|
|
|
//
|
|
// the following are element tag names
|
|
//
|
|
|
|
CComBSTR g_bstrSsrMemberInfo(L"SsrMemberInfo");
|
|
CComBSTR g_bstrDescription(L"Description");
|
|
CComBSTR g_bstrSupportedAction(L"SupportedAction");
|
|
CComBSTR g_bstrProcedures(L"Procedures");
|
|
CComBSTR g_bstrDefaultProc(L"DefaultProc");
|
|
CComBSTR g_bstrCustomProc(L"CustomProc");
|
|
CComBSTR g_bstrTransformInfo(L"TransformInfo");
|
|
CComBSTR g_bstrScriptInfo(L"ScriptInfo");
|
|
|
|
//
|
|
// the following are attribute names
|
|
//
|
|
|
|
CComBSTR g_bstrAttrUniqueName(L"UniqueName");
|
|
CComBSTR g_bstrAttrMajorVersion(L"MajorVersion");
|
|
CComBSTR g_bstrAttrMinorVersion(L"MinorVersion");
|
|
CComBSTR g_bstrAttrProgID(L"ProgID");
|
|
CComBSTR g_bstrAttrActionName(L"ActionName");
|
|
CComBSTR g_bstrAttrActionType(L"ActionType");
|
|
CComBSTR g_bstrAttrTemplateFile(L"TemplateFile");
|
|
CComBSTR g_bstrAttrResultFile(L"ResultFile");
|
|
CComBSTR g_bstrAttrScriptFile(L"ScriptFile");
|
|
CComBSTR g_bstrAttrIsStatic(L"IsStatic");
|
|
CComBSTR g_bstrAttrIsExecutable(L"IsExecutable");
|
|
|
|
|
|
//
|
|
// these are the known action types
|
|
//
|
|
|
|
LPCWSTR g_pwszApply = L"Prepare";
|
|
LPCWSTR g_pwszPrepare = L"Prepare";
|
|
|
|
CComBSTR g_bstrReportFilesDir;
|
|
CComBSTR g_bstrConfigureFilesDir;
|
|
CComBSTR g_bstrRollbackFilesDir;
|
|
CComBSTR g_bstrTransformFilesDir;
|
|
CComBSTR g_bstrMemberFilesDir;
|
|
|
|
CComBSTR g_bstrTrue(L"True");
|
|
CComBSTR g_bstrFalse(L"False");
|
|
|
|
//
|
|
// A guid can be represented in string form such as
|
|
// {aabbccdd-1234-4321-abcd-1234567890ab}.
|
|
// The length of such string format guid returned from StringFromGUID2 etc.
|
|
// is 38
|
|
//
|
|
|
|
const long g_lGuidStringLen = 38;
|
|
|
|
//
|
|
// global helper function implementations
|
|
//
|
|
|
|
|
|
|
|
const BSTR
|
|
SsrPGetActionVerbString (
|
|
IN SsrActionVerb action
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
This will translate an SsrActionVerb value into
|
|
the corresponding BSTR
|
|
|
|
Virtual:
|
|
|
|
N/A.
|
|
|
|
Arguments:
|
|
|
|
action - The SsrActionVerb value
|
|
|
|
Return Value:
|
|
|
|
Success: const BSTR of that verb's string;
|
|
|
|
Failure: NULL.
|
|
|
|
Notes:
|
|
|
|
Callers must not release in any form of the returned
|
|
BSTR. It is a const BSTR, and you must honor that.
|
|
--*/
|
|
{
|
|
switch (action)
|
|
{
|
|
case ActionConfigure:
|
|
return g_bstrConfigure;
|
|
case ActionRollback:
|
|
return g_bstrRollback;
|
|
case ActionReport:
|
|
return g_bstrReport;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
SsrActionVerb
|
|
SsrPGetActionVerbFromString (
|
|
IN LPCWSTR pwszVerb
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
This will translate an string action verb value into
|
|
the corresponding SsrActionVerb value.
|
|
|
|
Virtual:
|
|
|
|
N/A.
|
|
|
|
Arguments:
|
|
|
|
pwszVerb - The action verb string
|
|
|
|
Return Value:
|
|
|
|
Success: the appropriate SsrActionVerb value if the verb is recognized
|
|
|
|
Failure: ActionInvalid.
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
SsrActionVerb ActVerb = ActionInvalid;
|
|
|
|
if (pwszVerb != NULL)
|
|
{
|
|
if (_wcsicmp(pwszVerb, g_bstrConfigure) == 0)
|
|
{
|
|
ActVerb = ActionConfigure;
|
|
}
|
|
else if (_wcsicmp(pwszVerb, g_bstrRollback) == 0)
|
|
{
|
|
ActVerb = ActionRollback;
|
|
}
|
|
else if (_wcsicmp(pwszVerb, g_bstrReport) == 0)
|
|
{
|
|
ActVerb = ActionReport;
|
|
}
|
|
}
|
|
|
|
return ActVerb;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SsrPDeleteEntireDirectory (
|
|
IN LPCWSTR pwszDirPath
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
This will do a recursive delete of all files and subdirectories of the given
|
|
directory. RemoveDirectory API only deletes empty directories.
|
|
|
|
|
|
Virtual:
|
|
|
|
N/A.
|
|
|
|
Arguments:
|
|
|
|
pwszDirPath - The path of the directory
|
|
|
|
Return Value:
|
|
|
|
Success: S_OK;
|
|
|
|
Failure: various error codes.
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WIN32_FIND_DATA FindFileData;
|
|
|
|
//
|
|
// prepare the find file filter
|
|
//
|
|
|
|
DWORD dwDirLen = wcslen(pwszDirPath);
|
|
|
|
if (dwDirLen > MAX_PATH)
|
|
{
|
|
return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
|
|
}
|
|
|
|
CComBSTR bstrPath(pwszDirPath);
|
|
bstrPath += CComBSTR(L"\\*");
|
|
|
|
if (bstrPath.m_str == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
HANDLE hFind = ::FindFirstFile(bstrPath, &FindFileData);
|
|
|
|
//
|
|
// IF we have find something, then we have to do a recursive delete,
|
|
// Copy the given directory path to our local memory so that we can
|
|
// create a full path for the found file/directory
|
|
//
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
WCHAR wszFullName[MAX_PATH + 2];
|
|
wszFullName[MAX_PATH + 1] = L'\0';
|
|
|
|
::memcpy(wszFullName, pwszDirPath, sizeof(WCHAR) * (dwDirLen + 1));
|
|
|
|
DWORD dwFileNameLength;
|
|
|
|
while (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
//
|
|
// don't do anything to the parent directories
|
|
//
|
|
|
|
bool bDots = wcscmp(FindFileData.cFileName, L".") == 0 ||
|
|
wcscmp(FindFileData.cFileName, L"..") == 0;
|
|
|
|
if (!bDots)
|
|
{
|
|
//
|
|
// create the full name of the file/directory
|
|
//
|
|
|
|
dwFileNameLength = wcslen(FindFileData.cFileName);
|
|
|
|
if (dwDirLen + 1 + dwFileNameLength > MAX_PATH)
|
|
{
|
|
//
|
|
// we don't want names longer than MAX_PATH
|
|
//
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// pwszFullName + dwDirLen is where the directory path ends
|
|
//
|
|
|
|
_snwprintf(wszFullName + dwDirLen,
|
|
1 + dwFileNameLength + 1, // backslah plus 0 term.
|
|
L"\\%s",
|
|
FindFileData.cFileName
|
|
);
|
|
|
|
if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
//
|
|
// a directory. recursively delete the entire directory
|
|
//
|
|
|
|
hr = ::SsrPDeleteEntireDirectory(wszFullName);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// a file
|
|
//
|
|
|
|
if (!::DeleteFile(wszFullName))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!::FindNextFile(hFind, &FindFileData))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
::FindClose(hFind);
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && !::RemoveDirectory(pwszDirPath))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
SsrPCreateSubDirectories (
|
|
IN OUT LPWSTR pwszPath,
|
|
IN LPCWSTR pwszSubRoot
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
This will create all subdirectory leading to the path.
|
|
The assumption is that the path contains a subdirectory
|
|
identified by pwszSubRoot, the creation will start from
|
|
there.
|
|
|
|
|
|
Virtual:
|
|
|
|
N/A.
|
|
|
|
Arguments:
|
|
|
|
pwszPath - The path of the directory
|
|
|
|
pwszSubRoot - The subdirectory where the creation sequence
|
|
will start.
|
|
|
|
Return Value:
|
|
|
|
Success: S_OK;
|
|
|
|
Failure: various error codes.
|
|
|
|
Notes:
|
|
|
|
We actually don't change pwszPath. But we will temporarily
|
|
modify the buffer during our operation, but upon returning,
|
|
the buffer is fully restored to the original value.
|
|
|
|
--*/
|
|
{
|
|
if (pwszPath == NULL || *pwszPath == L'\0')
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
LPCWSTR pwszCurrReadHead = pwszPath;
|
|
|
|
if (pwszSubRoot != NULL && *pwszSubRoot != L'\0')
|
|
{
|
|
pwszCurrReadHead = ::wcsstr(pwszPath, pwszSubRoot);
|
|
|
|
//
|
|
// if you specify a subroot, then it must exists in the path
|
|
//
|
|
|
|
if (pwszCurrReadHead == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
LPWSTR pwszNextReadHead = ::wcsstr(pwszCurrReadHead, L"\\");
|
|
|
|
//
|
|
// will try to create all subdirectories under SSR
|
|
//
|
|
|
|
while (true)
|
|
{
|
|
//
|
|
// Temporarily zero terminate it so that we can try
|
|
// to create the directory
|
|
//
|
|
|
|
if (pwszNextReadHead != NULL)
|
|
{
|
|
*pwszNextReadHead = L'\0';
|
|
}
|
|
|
|
if (!::CreateDirectory(pwszPath, NULL))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
|
|
if (dwError == ERROR_ALREADY_EXISTS)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwError);
|
|
|
|
//
|
|
// log the directory that failed to create
|
|
//
|
|
|
|
g_fblog.LogFeedback(SSR_FB_ERROR_GENERIC | FBLog_Log,
|
|
hr,
|
|
pwszPath,
|
|
IDS_FAIL_CREATE_DIRECTORY
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if we don't have any more backslash, then it's over
|
|
//
|
|
|
|
if (pwszNextReadHead == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Restore the backslash
|
|
//
|
|
|
|
*pwszNextReadHead = L'\\';
|
|
pwszNextReadHead = ::wcsstr(pwszNextReadHead + 1, L"\\");
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
SsrPLoadDOM (
|
|
BSTR bstrFile, // [in],
|
|
LONG lFlag, // [in],
|
|
IXMLDOMDocument2 * pDOM // [in]
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
Do the XML DOM loading
|
|
|
|
Virtual:
|
|
|
|
n/a.
|
|
|
|
Arguments:
|
|
|
|
bstrFile- the XML/XSL file path
|
|
|
|
uFlag - The flag that determines the transformation characteristics.
|
|
The one we use is SSR_LOADDOM_VALIDATE_ON_PARSE.
|
|
|
|
pDOM - The IXMLDOMDocument2 object interface.
|
|
|
|
Return Value:
|
|
|
|
Success:
|
|
|
|
various success codes returned from DOM or ourselves.
|
|
Use SUCCEEDED(hr) to test.
|
|
|
|
Failure:
|
|
|
|
various error codes returned from DOM or ourselves.
|
|
Use FAILED(hr) to test.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( NULL == pDOM) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// set the validateOnParse property
|
|
//
|
|
|
|
if (lFlag & SSR_LOADDOM_VALIDATE_ON_PARSE)
|
|
{
|
|
hr = pDOM->put_validateOnParse(VARIANT_TRUE);
|
|
}
|
|
else
|
|
{
|
|
hr = pDOM->put_validateOnParse(VARIANT_FALSE);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
g_fblog.LogFeedback(SSR_FB_ERROR_LOAD_MEMBER | FBLog_Log,
|
|
hr,
|
|
L"put_validateOnParse",
|
|
IDS_DOM_PROPERTY_PUT_FAILED
|
|
);
|
|
}
|
|
|
|
CComVariant varInput(bstrFile);
|
|
|
|
//
|
|
// we should try to see what happens if we set it to VARIANT_TRUE
|
|
//
|
|
|
|
VARIANT_BOOL fSuccess;
|
|
hr = pDOM->load(varInput, &fSuccess);
|
|
|
|
if (fSuccess == VARIANT_FALSE)
|
|
{
|
|
//
|
|
// somehow it fails, we want to figure out what is going on,
|
|
// potential parsing errors
|
|
//
|
|
|
|
CComPtr<IXMLDOMParseError> srpParseError;
|
|
|
|
//
|
|
// in case of any failure, we will use the bstrReason
|
|
// to log and feedback.
|
|
//
|
|
|
|
CComBSTR bstrReason;
|
|
|
|
long ulLine = 0, ulColumn = 0, ulCode = 0;
|
|
|
|
//
|
|
// if any of the following fails, there is nothing we can do
|
|
// other than logging the error.
|
|
//
|
|
|
|
hr = pDOM->get_parseError(&srpParseError);
|
|
if (FAILED(hr))
|
|
{
|
|
bstrReason = L"SsrPLoadDOM failed on pDOM->get_parseError.";
|
|
}
|
|
else
|
|
{
|
|
hr = srpParseError->get_reason(&bstrReason);
|
|
if (FAILED(hr))
|
|
{
|
|
bstrReason = L"SsrPLoadDOM failed on srpParseError->get_reason.";
|
|
}
|
|
else
|
|
{
|
|
hr = srpParseError->get_errorCode(&ulCode);
|
|
if (FAILED(hr))
|
|
{
|
|
bstrReason = L"SsrPLoadDOM failed on srpParseError->get_errorCode.";
|
|
}
|
|
|
|
hr = srpParseError->get_line(&ulLine);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
bstrReason = L"SsrPLoadDOM failed on srpParseError->get_line.";
|
|
}
|
|
}
|
|
}
|
|
|
|
const ULONG uHexMaxLen = 8;
|
|
const ULONG uDecMaxLen = 16;
|
|
|
|
LPWSTR pwszError = NULL;
|
|
|
|
//
|
|
// we can't continue creating more specific error info
|
|
// if we fail to get the reason - which may include out-of-memory
|
|
// system errors. We don't bother to modify our error to
|
|
// out-of-memory because we are guessing in that case and also
|
|
// others will catch that error fairly quickly.
|
|
//
|
|
|
|
if (SUCCEEDED(hr) && bstrReason != NULL && ulLine != 0)
|
|
{
|
|
//
|
|
// It's a parsing error
|
|
//
|
|
|
|
srpParseError->get_linepos(&ulColumn);
|
|
|
|
CComBSTR bstrFmt;
|
|
if (SUCCEEDED(bstrFmt.LoadString(IDS_XML_PARSING_ERROR)))
|
|
{
|
|
ULONG uTotLen = bstrFmt.Length() +
|
|
uHexMaxLen +
|
|
uDecMaxLen +
|
|
::wcslen(bstrReason) +
|
|
::wcslen(bstrFile) +
|
|
uDecMaxLen + 1;
|
|
|
|
pwszError = new WCHAR[uTotLen];
|
|
|
|
if (pwszError == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
_snwprintf( pwszError,
|
|
uTotLen,
|
|
bstrFmt,
|
|
ulCode,
|
|
ulLine,
|
|
bstrReason,
|
|
bstrFile,
|
|
ulColumn
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((HRESULT) ulCode == INET_E_OBJECT_NOT_FOUND)
|
|
{
|
|
g_fblog.LogString(IDS_OBJECT_NOT_FOUND, bstrFile);
|
|
}
|
|
}
|
|
|
|
//
|
|
// loading DOM failure is critical, do both logging and feedback
|
|
//
|
|
|
|
g_fblog.LogFeedback(SSR_FB_ERROR_MEMBER_XML | FBLog_Log,
|
|
bstrFile,
|
|
((pwszError != NULL) ? pwszError : bstrReason),
|
|
IDS_DOM_LOAD_FAILED
|
|
);
|
|
|
|
delete [] pwszError;
|
|
|
|
//
|
|
// I have seen the HRESULT code being a success code while
|
|
// it can't transform fSuccess == VARIANT_FALSE
|
|
//
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_SSR_INVALID_XML_FILE;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SsrPGetBSTRAttrValue (
|
|
IN IXMLDOMNamedNodeMap * pNodeMap,
|
|
IN BSTR bstrName,
|
|
OUT BSTR * pbstrValue
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
A helper function to get string attribute values
|
|
|
|
Virtual:
|
|
|
|
N/A.
|
|
|
|
Arguments:
|
|
|
|
pNodeMap - The map of attributes
|
|
|
|
bstrName - The name of the attribute
|
|
|
|
pbstrValue - Receives the string value.
|
|
|
|
Return Value:
|
|
|
|
S_OK if succeeded.
|
|
|
|
Various error codes. Watch out for E_SSR_MISSING_STRING_ATTRIBUTE
|
|
because if it is an optional attribute, then we should allow
|
|
this failure.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
if (pNodeMap == NULL || pbstrValue == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*pbstrValue = NULL;
|
|
|
|
CComPtr<IXMLDOMNode> srpAttr;
|
|
CComVariant varValue;
|
|
|
|
HRESULT hr = pNodeMap->getNamedItem(bstrName, &srpAttr);
|
|
if (SUCCEEDED(hr) && srpAttr != NULL)
|
|
{
|
|
hr = srpAttr->get_nodeValue(&varValue);
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && varValue.vt == VT_BSTR)
|
|
{
|
|
*pbstrValue = varValue.bstrVal;
|
|
|
|
//
|
|
// detach the bstr value so that we can reuse the variant
|
|
//
|
|
|
|
varValue.vt = VT_EMPTY;
|
|
varValue.bstrVal = NULL;
|
|
}
|
|
else if (varValue.vt != VT_BSTR)
|
|
{
|
|
hr = E_SSR_MISSING_STRING_ATTRIBUTE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SsrPCreateUniqueTempDirectory (
|
|
OUT LPWSTR pwszTempDirPath,
|
|
IN DWORD dwBufLen
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
Will create a unique (guid) temporary directory under ssr root
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pwszTempDirPath - The path of the temporary directory
|
|
|
|
dwBufLen - The buffer length in WCHAR counts
|
|
|
|
Return Value:
|
|
|
|
succeess: S_OK
|
|
failure: various error codes
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// we need the ssr root, the backslash and the guid (36 wchars) and 0 terminator
|
|
//
|
|
|
|
if (dwBufLen < g_dwSsrRootLen + 1 + g_lGuidStringLen + 1)
|
|
{
|
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
}
|
|
|
|
WCHAR wszGuid[g_lGuidStringLen + 1];
|
|
GUID guid;
|
|
memset(&guid, 0, sizeof(GUID));
|
|
memset(wszGuid, 0, sizeof(WCHAR) * (g_lGuidStringLen + 1) );
|
|
|
|
HRESULT hr = ::CoCreateGuid(&guid);
|
|
if (S_OK == hr)
|
|
{
|
|
::StringFromGUID2(guid, wszGuid, g_lGuidStringLen + 1);
|
|
|
|
memcpy(pwszTempDirPath, g_wszSsrRoot, g_dwSsrRootLen * sizeof(WCHAR));
|
|
pwszTempDirPath[g_dwSsrRootLen] = L'\\';
|
|
|
|
//
|
|
// skip the starting '{', and do not copy '}' either.
|
|
//
|
|
|
|
memcpy(pwszTempDirPath + g_dwSsrRootLen + 1,
|
|
wszGuid + 1,
|
|
(g_lGuidStringLen - 2) * sizeof(WCHAR)
|
|
);
|
|
|
|
//
|
|
// NULL terminate it
|
|
//
|
|
|
|
pwszTempDirPath[g_dwSsrRootLen + g_lGuidStringLen - 1] = L'\0';
|
|
|
|
if (!CreateDirectory(pwszTempDirPath, NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
SsrPMoveFiles (
|
|
IN LPCWSTR pwszSrcDirRoot,
|
|
IN LPCWSTR pwszDesDirRoot,
|
|
IN LPCWSTR pwszRelPath
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
Will move a file given by the relative path of the src directory
|
|
to the destination directory of the same relative path
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pwszSrcDirRoot - The src directory root path. Combined with the
|
|
pwszRelPath, it becomes the full path of the src file
|
|
|
|
pwszDesDirRoot - The dest directory root path. Combined with the pwszRelPath,
|
|
it becomes the full path of the destination file.
|
|
|
|
pwszRelPath - the file path relative to the src directory root.
|
|
|
|
Return Value:
|
|
|
|
Success: S_OK.
|
|
|
|
Failure: various error codes.
|
|
|
|
Notes:
|
|
|
|
If the destination directory doesn't exist, then we will create it
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// first, we must the source and destination files paths
|
|
//
|
|
|
|
DWORD dwSrcRootLen = wcslen(pwszSrcDirRoot);
|
|
DWORD dwDesRootLen = wcslen(pwszDesDirRoot);
|
|
|
|
DWORD dwRelPathLen = wcslen(pwszRelPath);
|
|
|
|
LPWSTR pwszSrcPath = new WCHAR[dwSrcRootLen + 1 + dwRelPathLen + 1];
|
|
LPWSTR pwszDesPath = new WCHAR[dwDesRootLen + 1 + dwRelPathLen + 1];
|
|
|
|
if (pwszSrcPath != NULL && pwszDesPath != NULL)
|
|
{
|
|
::memcpy(pwszSrcPath, pwszSrcDirRoot, sizeof(WCHAR) * dwSrcRootLen);
|
|
pwszSrcPath[dwSrcRootLen] = L'\\';
|
|
|
|
//
|
|
// copy one WCHAR more then length so that the 0 terminator is set
|
|
//
|
|
|
|
::memcpy(pwszSrcPath + dwSrcRootLen + 1,
|
|
pwszRelPath, sizeof(WCHAR) * (dwRelPathLen + 1));
|
|
|
|
|
|
::memcpy(pwszDesPath, pwszDesDirRoot, sizeof(WCHAR) * dwDesRootLen);
|
|
|
|
pwszDesPath[dwDesRootLen] = L'\\';
|
|
::memcpy(pwszDesPath + dwDesRootLen + 1,
|
|
pwszRelPath, sizeof(WCHAR) * (dwRelPathLen + 1));
|
|
|
|
if (!::MoveFile(pwszSrcPath, pwszDesPath))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
|
|
if (ERROR_FILE_NOT_FOUND != dwError)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwError);
|
|
}
|
|
|
|
//
|
|
// log the file name that fails to move
|
|
//
|
|
|
|
g_fblog.LogFeedback(SSR_FB_ERROR_GENERIC | FBLog_Log,
|
|
dwError,
|
|
pwszSrcPath,
|
|
IDS_FAIL_MOVE_FILE
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
delete [] pwszSrcPath;
|
|
delete [] pwszDesPath;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SsrPPressOn (
|
|
IN SsrActionVerb lActionVerb,
|
|
IN LONG lActionType,
|
|
IN HRESULT hr
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
Determines if we should continue based on the error
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
lActionVerb - The action
|
|
|
|
lActionType - The type of the action
|
|
|
|
hr - The HRESULT to test
|
|
|
|
Return Value:
|
|
|
|
true or false
|
|
|
|
Notes:
|
|
|
|
This function is just a placeholder for the need of the test. The implementation
|
|
is far from complete.
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(lActionVerb);
|
|
UNREFERENCED_PARAMETER(lActionType);
|
|
|
|
if (hr == E_OUTOFMEMORY ||
|
|
hr == E_SSR_MEMBER_XSD_INVALID)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const BSTR
|
|
SsrPGetDirectory (
|
|
IN SsrActionVerb lActionVerb,
|
|
IN BOOL bScriptFile
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
SSR controls the physical location for its members to place their files.
|
|
This function returns to the caller the physical directory path for a given
|
|
member. Since SSR is an action oriented architecture, such locations are also
|
|
relative to action. If bstrActionVerb is a non-empty string, then the function
|
|
retrieves the loction for that action. Otherwise, the function retrieves the
|
|
location for the member's root (actions are sub-directories of this root)
|
|
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
lActionVerb - The action verb in long format
|
|
|
|
bScriptFile - Whether or not it is asking for a script file. If false,
|
|
it is asking for transformation file
|
|
|
|
Return Value:
|
|
|
|
the file path if we recognize the call.
|
|
|
|
Notes:
|
|
|
|
!!!Warning!!!
|
|
|
|
Caller should never release the BSTR
|
|
--*/
|
|
{
|
|
if (!bScriptFile)
|
|
{
|
|
//
|
|
// asking for transformation files. All of them goes to
|
|
// the TransformFiles directory
|
|
//
|
|
|
|
return g_bstrTransformFilesDir;
|
|
}
|
|
|
|
if (lActionVerb == ActionConfigure)
|
|
{
|
|
return g_bstrConfigureFilesDir;
|
|
}
|
|
else if (lActionVerb == ActionRollback)
|
|
{
|
|
return g_bstrRollbackFilesDir;
|
|
}
|
|
else if (lActionVerb == ActionReport)
|
|
{
|
|
return g_bstrReportFilesDir;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SsrPDoDCOMSettings (
|
|
bool bReg
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Functionality:
|
|
|
|
This function will set the security related registry settings for our
|
|
SSR engine com objects
|
|
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
bReg - whether this is to register or to un-register
|
|
|
|
Return Value:
|
|
|
|
S_OK if succeeded.
|
|
Otherwise, various error codes
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
BOOL bDaclPresent = FALSE, bDaclDefault = FALSE;
|
|
|
|
ULONG ulSDSize = 0;
|
|
|
|
return 0;
|
|
/*
|
|
if (bReg)
|
|
{
|
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
|
|
g_pwszSsrDCOMSecDescripACL,
|
|
SDDL_REVISION_1,
|
|
&pSD,
|
|
&ulSDSize
|
|
) )
|
|
{
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// unregister, easy, just delete the AppID key
|
|
//
|
|
|
|
LONG lStatus = RegDeleteKey(HKEY_LOCAL_MACHINE,
|
|
g_pwszAppID);
|
|
|
|
if ( lStatus != NO_ERROR )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// now let's set the ACLs on these keys
|
|
//
|
|
|
|
HKEY hKey = NULL;
|
|
|
|
BYTE * lpData = (BYTE*)pSD;
|
|
DWORD dwDataSize = ulSDSize;
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
LONG lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
g_pwszAppID,
|
|
0,
|
|
KEY_WRITE,
|
|
&hKey );
|
|
|
|
if ( lStatus != NO_ERROR )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// set the access
|
|
//
|
|
|
|
lStatus = RegSetValueEx(
|
|
hKey,
|
|
g_pwszAccessPermission,
|
|
0,
|
|
REG_BINARY,
|
|
lpData,
|
|
dwDataSize
|
|
);
|
|
|
|
if ( lStatus == NO_ERROR )
|
|
{
|
|
//
|
|
// set the launch permission
|
|
//
|
|
|
|
lStatus = RegSetValueEx(
|
|
hKey,
|
|
g_pwszLaunchPermission,
|
|
0,
|
|
REG_BINARY,
|
|
lpData,
|
|
dwDataSize
|
|
);
|
|
}
|
|
|
|
if ( lStatus != NO_ERROR )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
if (pSD != NULL)
|
|
{
|
|
LocalFree(pSD);
|
|
}
|
|
|
|
return hr;
|
|
*/}
|