windows-nt/Source/XPSP1/NT/base/win32/fusion/utils/helpers.cpp
2020-09-26 16:20:57 +08:00

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;
}