446 lines
13 KiB
C++
446 lines
13 KiB
C++
|
#include "stdinc.h"
|
||
|
#include "util.h"
|
||
|
#include "fusionbuffer.h"
|
||
|
#include "xmlparser.h"
|
||
|
#include "fusionhandle.h"
|
||
|
|
||
|
// deliberately no surrounding parens or trailing comma
|
||
|
#define STRING_AND_LENGTH(x) (x), (NUMBER_OF(x) - 1)
|
||
|
|
||
|
#define MAXIMUM_PROCESSOR_ARCHITECTURE_NAME_LENGTH (sizeof("Alpha64") - 1)
|
||
|
|
||
|
const static struct
|
||
|
{
|
||
|
USHORT ProcessorArchitecture;
|
||
|
WCHAR String[MAXIMUM_PROCESSOR_ARCHITECTURE_NAME_LENGTH+1];
|
||
|
SIZE_T Cch;
|
||
|
} gs_rgPAMap[] =
|
||
|
{
|
||
|
{ PROCESSOR_ARCHITECTURE_INTEL, STRING_AND_LENGTH(L"x86") },
|
||
|
{ PROCESSOR_ARCHITECTURE_AMD64, STRING_AND_LENGTH(L"AMD64") },
|
||
|
{ PROCESSOR_ARCHITECTURE_IA64, STRING_AND_LENGTH(L"IA64") },
|
||
|
{ PROCESSOR_ARCHITECTURE_ALPHA, STRING_AND_LENGTH(L"Alpha") },
|
||
|
{ PROCESSOR_ARCHITECTURE_MIPS, STRING_AND_LENGTH(L"Mips") },
|
||
|
{ PROCESSOR_ARCHITECTURE_PPC, STRING_AND_LENGTH(L"PPC") },
|
||
|
{ PROCESSOR_ARCHITECTURE_ALPHA64, STRING_AND_LENGTH(L"Alpha64") },
|
||
|
{ PROCESSOR_ARCHITECTURE_SHX, STRING_AND_LENGTH(L"SHX") },
|
||
|
{ PROCESSOR_ARCHITECTURE_ARM, STRING_AND_LENGTH(L"ARM") },
|
||
|
{ PROCESSOR_ARCHITECTURE_MSIL, STRING_AND_LENGTH(L"MSIL") },
|
||
|
{ PROCESSOR_ARCHITECTURE_IA32_ON_WIN64, STRING_AND_LENGTH(L"WOW64") },
|
||
|
{ PROCESSOR_ARCHITECTURE_UNKNOWN, STRING_AND_LENGTH(L"Data") },
|
||
|
};
|
||
|
|
||
|
static BOOL
|
||
|
FusionpGetLocaleInfo(
|
||
|
LANGID LangID,
|
||
|
CBaseStringBuffer *Buffer,
|
||
|
LCTYPE lcType,
|
||
|
SIZE_T *CchWritten = NULL
|
||
|
)
|
||
|
{
|
||
|
LCID locale = MAKELCID(LangID, SORT_DEFAULT);
|
||
|
|
||
|
CStringBufferAccessor BufferAccessor;
|
||
|
|
||
|
BufferAccessor.Attach(Buffer);
|
||
|
|
||
|
INT i = GetLocaleInfoW(locale, lcType, BufferAccessor.GetBufferPtr(), static_cast<INT>(BufferAccessor.GetBufferCch()));
|
||
|
if (i != 0)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
if (::FusionpGetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
i = GetLocaleInfoW(locale, lcType, NULL, 0);
|
||
|
if (i == 0)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
if (!Buffer->Win32ResizeBuffer(i, eDoNotPreserveBufferContents))
|
||
|
{
|
||
|
i = 0;
|
||
|
goto Exit;
|
||
|
}
|
||
|
i = GetLocaleInfoW(locale, lcType, BufferAccessor.GetBufferPtr(), static_cast<INT>(BufferAccessor.GetBufferCch()));
|
||
|
Exit:
|
||
|
if (i != 0 && CchWritten != NULL)
|
||
|
{
|
||
|
*CchWritten = i;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
FusionpFormatEnglishLanguageName(
|
||
|
LANGID LangID,
|
||
|
CBaseStringBuffer *Buffer,
|
||
|
SIZE_T *CchWritten
|
||
|
)
|
||
|
{
|
||
|
return ::FusionpGetLocaleInfo(LangID, Buffer, LOCALE_SENGLANGUAGE, CchWritten);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
FusionpParseProcessorArchitecture(
|
||
|
PCWSTR String,
|
||
|
SIZE_T Cch,
|
||
|
USHORT *ProcessorArchitecture,
|
||
|
bool &rfValid
|
||
|
)
|
||
|
{
|
||
|
ULONG i;
|
||
|
BOOL fSuccess = FALSE;
|
||
|
|
||
|
rfValid = false;
|
||
|
|
||
|
// We'll let ProcessorArchitecture be NULL if the caller just wants to
|
||
|
// test whether there is a match.
|
||
|
|
||
|
for (i=0; i<NUMBER_OF(gs_rgPAMap); i++)
|
||
|
{
|
||
|
if (::FusionpCompareStrings(
|
||
|
gs_rgPAMap[i].String,
|
||
|
gs_rgPAMap[i].Cch,
|
||
|
String,
|
||
|
Cch,
|
||
|
true) == 0)
|
||
|
{
|
||
|
if (ProcessorArchitecture != NULL)
|
||
|
*ProcessorArchitecture = gs_rgPAMap[i].ProcessorArchitecture;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i != NUMBER_OF(gs_rgPAMap))
|
||
|
rfValid = true;
|
||
|
|
||
|
fSuccess = TRUE;
|
||
|
|
||
|
// Exit:
|
||
|
return fSuccess;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
BOOL
|
||
|
FusionpFormatLocalizedLanguageName(
|
||
|
LANGID LangID,
|
||
|
CBaseStringBuffer *Buffer,
|
||
|
SIZE_T *CchWritten
|
||
|
)
|
||
|
{
|
||
|
LOCALE_SNATIVELANGNAME -- I think this is the one want, the language's name in its own language
|
||
|
LOCALE_SLANGUAGE -- I think this is the language's name in the language of the installed OS
|
||
|
return SxspFormatLanguageName(LangID, Buffer, ?);
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
BOOL
|
||
|
FusionpFormatProcessorArchitecture(
|
||
|
USHORT ProcessorArchitecture,
|
||
|
CBaseStringBuffer &rBuffer
|
||
|
)
|
||
|
{
|
||
|
BOOL fSuccess = FALSE;
|
||
|
FN_TRACE_WIN32(fSuccess);
|
||
|
ULONG i;
|
||
|
|
||
|
for (i=0; i<NUMBER_OF(gs_rgPAMap); i++)
|
||
|
{
|
||
|
if (gs_rgPAMap[i].ProcessorArchitecture == ProcessorArchitecture)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
PARAMETER_CHECK(i != NUMBER_OF(gs_rgPAMap));
|
||
|
|
||
|
IFW32FALSE_EXIT(rBuffer.Win32Assign(gs_rgPAMap[i].String, gs_rgPAMap[i].Cch));
|
||
|
|
||
|
fSuccess = TRUE;
|
||
|
Exit:
|
||
|
return fSuccess;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
FusionpHRESULTToWin32(
|
||
|
HRESULT hr
|
||
|
)
|
||
|
{
|
||
|
DWORD dwWin32ErrorCode = ERROR_INTERNAL_ERROR;
|
||
|
|
||
|
if ((HRESULT_FACILITY(hr) != FACILITY_WIN32) &&
|
||
|
(FAILED(hr)))
|
||
|
{
|
||
|
switch (hr)
|
||
|
{
|
||
|
default:
|
||
|
break;
|
||
|
#define X(x,y) case x: hr = HRESULT_FROM_WIN32(y); break;
|
||
|
|
||
|
X(E_UNEXPECTED, ERROR_INTERNAL_ERROR)
|
||
|
X(E_FAIL, ERROR_FUNCTION_FAILED)
|
||
|
|
||
|
X(STG_E_PATHNOTFOUND, ERROR_PATH_NOT_FOUND)
|
||
|
X(STG_E_FILENOTFOUND, ERROR_FILE_NOT_FOUND)
|
||
|
X(STG_E_ACCESSDENIED, ERROR_ACCESS_DENIED)
|
||
|
X(STG_E_INVALIDHANDLE, ERROR_INVALID_HANDLE)
|
||
|
X(STG_E_INSUFFICIENTMEMORY, ERROR_NOT_ENOUGH_MEMORY) // or ERROR_OUTOFMEMORY
|
||
|
X(STG_E_TOOMANYOPENFILES, ERROR_TOO_MANY_OPEN_FILES)
|
||
|
X(STG_E_NOMOREFILES, ERROR_NO_MORE_FILES)
|
||
|
X(STG_E_WRITEFAULT, ERROR_WRITE_FAULT)
|
||
|
X(STG_E_READFAULT, ERROR_READ_FAULT)
|
||
|
X(STG_E_SHAREVIOLATION, ERROR_SHARING_VIOLATION)
|
||
|
X(STG_E_LOCKVIOLATION, ERROR_LOCK_VIOLATION)
|
||
|
X(STG_E_INVALIDPARAMETER, ERROR_INVALID_PARAMETER)
|
||
|
X(STG_E_MEDIUMFULL, ERROR_DISK_FULL) // or ERROR_HANDLE_DISK_FULL
|
||
|
// There's more, but I doubt we really need most of this.
|
||
|
#undef X
|
||
|
}
|
||
|
}
|
||
|
if ((HRESULT_FACILITY(hr) == FACILITY_WIN32) &&
|
||
|
(FAILED(hr)))
|
||
|
{
|
||
|
dwWin32ErrorCode = HRESULT_CODE(hr);
|
||
|
|
||
|
if (FAILED(hr) && (dwWin32ErrorCode == ERROR_SUCCESS))
|
||
|
{
|
||
|
dwWin32ErrorCode = ERROR_INTERNAL_ERROR;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::FusionpDbgPrintEx(
|
||
|
FUSION_DBG_LEVEL_INFO,
|
||
|
"SXS.DLL: " __FUNCTION__ " HRESULT 0x%08x - facility is not Win32; setting to ERROR_SXS_UNTRANSLATABLE_HRESULT\n",
|
||
|
hr);
|
||
|
dwWin32ErrorCode = ERROR_SXS_UNTRANSLATABLE_HRESULT;
|
||
|
}
|
||
|
|
||
|
return dwWin32ErrorCode;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FusionpSetLastErrorFromHRESULT(
|
||
|
HRESULT hr
|
||
|
)
|
||
|
{
|
||
|
::SetLastError(::FusionpHRESULTToWin32(hr));
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FusionpConvertCOMFailure(HRESULT & __hr)
|
||
|
{
|
||
|
/*
|
||
|
XML_E_PARSEERRORBASE = 0xC00CE500L,
|
||
|
|
||
|
// character level error codes.
|
||
|
XML_E_ENDOFINPUT = XML_E_PARSEERRORBASE,
|
||
|
XML_E_MISSINGEQUALS, // 1
|
||
|
XML_E_MISSINGQUOTE, // 2
|
||
|
XML_E_COMMENTSYNTAX, // 3
|
||
|
XML_E_BADSTARTNAMECHAR, // 4
|
||
|
XML_E_BADNAMECHAR, // 5
|
||
|
XML_E_BADCHARINSTRING, // 6
|
||
|
// under 256
|
||
|
*/
|
||
|
if ((__hr & XML_E_PARSEERRORBASE) == XML_E_PARSEERRORBASE)
|
||
|
{
|
||
|
//
|
||
|
// for normal XML ERROR,we convert hresult to a better-understanding hresult
|
||
|
// xiaoyuw@01/08/2001
|
||
|
//
|
||
|
#define MAP_XML_HRESULT(x) case(x) : dwWin32Error = ERROR_SXS_## x; break
|
||
|
DWORD dwWin32Error;
|
||
|
|
||
|
switch (__hr)
|
||
|
{
|
||
|
MAP_XML_HRESULT(XML_E_MISSINGEQUALS);
|
||
|
MAP_XML_HRESULT(XML_E_MISSINGQUOTE);
|
||
|
MAP_XML_HRESULT(XML_E_COMMENTSYNTAX);
|
||
|
MAP_XML_HRESULT(XML_E_BADSTARTNAMECHAR);
|
||
|
MAP_XML_HRESULT(XML_E_BADNAMECHAR);
|
||
|
MAP_XML_HRESULT(XML_E_BADCHARINSTRING);
|
||
|
MAP_XML_HRESULT(XML_E_XMLDECLSYNTAX);
|
||
|
MAP_XML_HRESULT(XML_E_BADCHARDATA);
|
||
|
MAP_XML_HRESULT(XML_E_MISSINGWHITESPACE);
|
||
|
MAP_XML_HRESULT(XML_E_EXPECTINGTAGEND);
|
||
|
MAP_XML_HRESULT(XML_E_MISSINGSEMICOLON);
|
||
|
MAP_XML_HRESULT(XML_E_UNBALANCEDPAREN);
|
||
|
MAP_XML_HRESULT(XML_E_INTERNALERROR);
|
||
|
MAP_XML_HRESULT(XML_E_UNEXPECTED_WHITESPACE);
|
||
|
MAP_XML_HRESULT(XML_E_INCOMPLETE_ENCODING);
|
||
|
MAP_XML_HRESULT(XML_E_MISSING_PAREN);
|
||
|
MAP_XML_HRESULT(XML_E_EXPECTINGCLOSEQUOTE);
|
||
|
MAP_XML_HRESULT(XML_E_MULTIPLE_COLONS);
|
||
|
MAP_XML_HRESULT(XML_E_INVALID_DECIMAL);
|
||
|
MAP_XML_HRESULT(XML_E_INVALID_HEXIDECIMAL);
|
||
|
MAP_XML_HRESULT(XML_E_INVALID_UNICODE);
|
||
|
MAP_XML_HRESULT(XML_E_WHITESPACEORQUESTIONMARK);
|
||
|
MAP_XML_HRESULT(XML_E_UNEXPECTEDENDTAG);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDTAG);
|
||
|
MAP_XML_HRESULT(XML_E_DUPLICATEATTRIBUTE);
|
||
|
MAP_XML_HRESULT(XML_E_MULTIPLEROOTS);
|
||
|
MAP_XML_HRESULT(XML_E_INVALIDATROOTLEVEL);
|
||
|
MAP_XML_HRESULT(XML_E_BADXMLDECL);
|
||
|
MAP_XML_HRESULT(XML_E_MISSINGROOT);
|
||
|
MAP_XML_HRESULT(XML_E_UNEXPECTEDEOF);
|
||
|
MAP_XML_HRESULT(XML_E_BADPEREFINSUBSET);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDSTARTTAG);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDENDTAG);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDSTRING);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDCOMMENT);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDDECL);
|
||
|
MAP_XML_HRESULT(XML_E_UNCLOSEDCDATA);
|
||
|
MAP_XML_HRESULT(XML_E_RESERVEDNAMESPACE);
|
||
|
MAP_XML_HRESULT(XML_E_INVALIDENCODING);
|
||
|
MAP_XML_HRESULT(XML_E_INVALIDSWITCH);
|
||
|
MAP_XML_HRESULT(XML_E_BADXMLCASE);
|
||
|
MAP_XML_HRESULT(XML_E_INVALID_STANDALONE);
|
||
|
MAP_XML_HRESULT(XML_E_UNEXPECTED_STANDALONE);
|
||
|
MAP_XML_HRESULT(XML_E_INVALID_VERSION);
|
||
|
default:
|
||
|
dwWin32Error=(ERROR_SXS_MANIFEST_PARSE_ERROR);
|
||
|
break;
|
||
|
} // end of switch
|
||
|
__hr = HRESULT_FROM_WIN32(dwWin32Error);
|
||
|
} //end of if
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
FusionpGetActivationContextFromFindResult(
|
||
|
PCACTCTX_SECTION_KEYED_DATA askd,
|
||
|
HANDLE * phActCtx
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
HANDLE hActCtx = NULL;
|
||
|
|
||
|
if (phActCtx != NULL)
|
||
|
*phActCtx = NULL;
|
||
|
PARAMETER_CHECK(askd != NULL);
|
||
|
PARAMETER_CHECK(phActCtx != NULL);
|
||
|
PARAMETER_CHECK(RTL_CONTAINS_FIELD(askd, askd->cbSize, hActCtx));
|
||
|
PARAMETER_CHECK(RTL_CONTAINS_FIELD(askd, askd->cbSize, ulFlags));
|
||
|
|
||
|
hActCtx = askd->hActCtx;
|
||
|
if (hActCtx == ACTCTX_PROCESS_DEFAULT)
|
||
|
{
|
||
|
switch (askd->ulFlags
|
||
|
& (
|
||
|
ACTIVATION_CONTEXT_SECTION_KEYED_DATA_FLAG_FOUND_IN_PROCESS_DEFAULT
|
||
|
| ACTIVATION_CONTEXT_SECTION_KEYED_DATA_FLAG_FOUND_IN_SYSTEM_DEFAULT
|
||
|
))
|
||
|
{
|
||
|
case ACTIVATION_CONTEXT_SECTION_KEYED_DATA_FLAG_FOUND_IN_PROCESS_DEFAULT:
|
||
|
break;
|
||
|
case ACTIVATION_CONTEXT_SECTION_KEYED_DATA_FLAG_FOUND_IN_SYSTEM_DEFAULT:
|
||
|
hActCtx = ACTCTX_SYSTEM_DEFAULT;
|
||
|
break;
|
||
|
default:
|
||
|
TRACE_PARAMETER_CHECK(askd->ulFlags);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
*phActCtx = hActCtx;
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
FusionpSearchPath(
|
||
|
ULONG ulFusionFlags,
|
||
|
LPCWSTR lpPath,
|
||
|
LPCWSTR lpFileName, // file name
|
||
|
LPCWSTR lpExtension, // file extension
|
||
|
CBaseStringBuffer & StringBuffer,
|
||
|
SIZE_T * lpFilePartOffset, // file component
|
||
|
HANDLE hActCtx
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
ULONG_PTR ulActCookie = 0;
|
||
|
PWSTR lpFilePart = NULL;
|
||
|
CFusionActCtxScope ActCtxScope;
|
||
|
|
||
|
if (lpFilePartOffset != NULL)
|
||
|
*lpFilePartOffset = 0;
|
||
|
|
||
|
PARAMETER_CHECK((ulFusionFlags & ~(FUSIONP_SEARCH_PATH_ACTCTX)) == 0);
|
||
|
|
||
|
if ((ulFusionFlags & FUSIONP_SEARCH_PATH_ACTCTX) != 0)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(ActCtxScope.Win32Activate(hActCtx));
|
||
|
}
|
||
|
if (StringBuffer.GetBufferCch() == 0)
|
||
|
IFW32FALSE_EXIT(StringBuffer.Win32ResizeBuffer(MAX_PATH, eDoNotPreserveBufferContents));
|
||
|
for (;;)
|
||
|
{
|
||
|
DWORD dw = 0;
|
||
|
{
|
||
|
CStringBufferAccessor StringBufferAccessor(&StringBuffer);
|
||
|
|
||
|
IFW32FALSE_EXIT((dw = ::SearchPathW(
|
||
|
lpPath,
|
||
|
lpFileName,
|
||
|
lpExtension,
|
||
|
StringBufferAccessor.GetBufferCchAsDWORD(),
|
||
|
StringBufferAccessor,
|
||
|
&lpFilePart
|
||
|
)) != 0);
|
||
|
if (dw < StringBuffer.GetBufferCch())
|
||
|
{
|
||
|
// lpFilePart equals NULL if filename ends in a slash, or somesuch..
|
||
|
if (lpFilePartOffset != NULL && lpFilePart != NULL)
|
||
|
{
|
||
|
*lpFilePartOffset = (lpFilePart - static_cast<PWSTR>(StringBufferAccessor));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
IFW32FALSE_EXIT(StringBuffer.Win32ResizeBuffer(dw + 1, eDoNotPreserveBufferContents));
|
||
|
}
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
FusionpGetModuleFileName(
|
||
|
ULONG ulFusionFlags,
|
||
|
HMODULE hmodDll,
|
||
|
CBaseStringBuffer & StringBuffer
|
||
|
)
|
||
|
/* note that GetModuleFileName is an unusual truncating API,
|
||
|
that's why we fudge the buffer size
|
||
|
if GetModuleFileName returns buffersize - 1, it may be a truncated result
|
||
|
*/
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
|
||
|
PARAMETER_CHECK(ulFusionFlags == 0);
|
||
|
|
||
|
if (StringBuffer.GetBufferCch() < 2)
|
||
|
IFW32FALSE_EXIT(StringBuffer.Win32ResizeBuffer(MAX_PATH, eDoNotPreserveBufferContents));
|
||
|
for (;;)
|
||
|
{
|
||
|
DWORD dw = 0;
|
||
|
{
|
||
|
CStringBufferAccessor StringBufferAccessor(&StringBuffer);
|
||
|
|
||
|
IFW32FALSE_EXIT((dw = ::GetModuleFileNameW(
|
||
|
hmodDll,
|
||
|
StringBufferAccessor,
|
||
|
StringBufferAccessor.GetBufferCchAsDWORD()
|
||
|
)) != 0);
|
||
|
if (dw < (StringBuffer.GetBufferCch() - 1))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/* we don't know what to grow to, so grow by a slightly big chunk */
|
||
|
IFW32FALSE_EXIT(StringBuffer.Win32ResizeBuffer(dw + 64, eDoNotPreserveBufferContents));
|
||
|
}
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|