windows-nt/Source/XPSP1/NT/multimedia/directx/dmusic/dmscript/packexception.cpp
2020-09-26 16:20:57 +08:00

145 lines
5.1 KiB
C++

// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// Implementation of PackExceptionFileAndLine and UnpackExceptionFileAndLine.
//
#include "stdinc.h"
#include "packexception.h"
#include "oleaut.h"
const WCHAR g_wszDescriptionFileSeparator[] = L"»"; // magic character for separating the filename, line, and description
const WCHAR g_wchDescriptionFileSeparator = g_wszDescriptionFileSeparator[0];
void SeparateDescriptionFileAndLine(BSTR bstrDescription, const WCHAR **ppwszFilename, const WCHAR **ppwszLine, const WCHAR **ppwszDescription)
{
assert(bstrDescription && ppwszFilename && ppwszLine && ppwszDescription);
// if there aren't any packed fields, the whole thing is the description
*ppwszDescription = bstrDescription;
WCHAR *pwszLine = wcsstr(bstrDescription, g_wszDescriptionFileSeparator);
if (!pwszLine)
return;
WCHAR *pwszDescription = wcsstr(pwszLine + 1, g_wszDescriptionFileSeparator);
if (!pwszDescription)
return;
// String looks like this:
// MyScript.spt»23»Description of the error
// pExcepInfo->bstrDescription-^ pwszLine-^ ^-pwszDescription
*ppwszFilename = bstrDescription;
assert(*pwszLine == g_wchDescriptionFileSeparator);
*ppwszLine = pwszLine + 1;
assert(*pwszDescription == g_wchDescriptionFileSeparator);
*ppwszDescription = pwszDescription + 1;
}
bool wcsIsBlankTillSeparator(const WCHAR *pwsz)
{
return !pwsz[0] || pwsz[0] == g_wchDescriptionFileSeparator;
}
void wcscpyTillSeparator(WCHAR *pwszDestination, const WCHAR *pwszSource)
{
assert(pwszDestination && pwszSource);
while (!wcsIsBlankTillSeparator(pwszSource))
{
*pwszDestination++ = *pwszSource++;
}
*pwszDestination = L'\0';
}
void wcscatTillSeparator(WCHAR *pwszDestination, const WCHAR *pwszSource)
{
assert(pwszDestination && pwszSource);
while (*pwszDestination != L'\0')
++pwszDestination;
wcscpyTillSeparator(pwszDestination, pwszSource);
}
void PackExceptionFileAndLine(bool fUseOleAut, EXCEPINFO *pExcepInfo, const WCHAR *pwszFilename, const ULONG *pulLine)
{
if (!pExcepInfo || !pExcepInfo->bstrDescription)
return;
const WCHAR *pwszDescrFilename = L"";
const WCHAR *pwszDescrLine = L"";
const WCHAR *pwszDescrDescription = L"";
SeparateDescriptionFileAndLine(pExcepInfo->bstrDescription, &pwszDescrFilename, &pwszDescrLine, &pwszDescrDescription);
if (wcsIsBlankTillSeparator(pwszDescrFilename) && pwszFilename)
{
// Filename is blank. Use the specified filename.
pwszDescrFilename = pwszFilename;
}
// MSDN documentation for _ultow says max is 33 characters, but PREFIX complains if the length
// is less than 40.
WCHAR wszLineBuffer[40] = L"";
if (wcsIsBlankTillSeparator(pwszDescrLine) && pulLine)
{
// Line is blank. Use the specified line.
_ultow(*pulLine, wszLineBuffer, 10);
pwszDescrLine = wszLineBuffer;
}
WCHAR *pwszNewDescription = new WCHAR[wcslen(pwszDescrFilename) + wcslen(pwszDescrLine) + wcslen(pwszDescrDescription) + (wcslen(g_wszDescriptionFileSeparator) * 2 + 1)];
if (pwszNewDescription)
{
wcscpyTillSeparator(pwszNewDescription, pwszDescrFilename);
wcscat(pwszNewDescription, g_wszDescriptionFileSeparator);
wcscatTillSeparator(pwszNewDescription, pwszDescrLine);
wcscat(pwszNewDescription, g_wszDescriptionFileSeparator);
wcscat(pwszNewDescription, pwszDescrDescription);
DMS_SysFreeString(fUseOleAut, pExcepInfo->bstrDescription);
pExcepInfo->bstrDescription = DMS_SysAllocString(fUseOleAut, pwszNewDescription);
delete[] pwszNewDescription;
}
}
void UnpackExceptionFileAndLine(BSTR bstrDescription, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
{
assert(pErrorInfo && bstrDescription);
if (pErrorInfo && bstrDescription)
{
const WCHAR *pwszDescrFilename = L"";
const WCHAR *pwszDescrLine = L"";
const WCHAR *pwszDescrDescription = L"";
SeparateDescriptionFileAndLine(bstrDescription, &pwszDescrFilename, &pwszDescrLine, &pwszDescrDescription);
// String looks like this:
// CoolScriptFile.spt»23»Description of the error
// pwszDescrFilename-^ pwszDescrLine-^ ^-pwszDescrDescription
// Except that if these weren't found then they point to a separate empty string.
if (!wcsIsBlankTillSeparator(pwszDescrFilename))
{
// Filename is present. Copy to pErrorInfo.
assert(*(pwszDescrLine - 1) == g_wchDescriptionFileSeparator);
wcsTruncatedCopy(pErrorInfo->wszSourceFile,
pwszDescrFilename,
std::_MIN<UINT>(DMUS_MAX_FILENAME, pwszDescrLine - pwszDescrFilename));
}
if (!wcsIsBlankTillSeparator(pwszDescrLine))
{
// Line is present. Copy to pErrorInfo.
WCHAR *pwszLineSeparator = const_cast<WCHAR *>(pwszDescrDescription - 1);
assert(*pwszLineSeparator == g_wchDescriptionFileSeparator);
*pwszLineSeparator = L'\0'; // terminate the line for wcstoul
pErrorInfo->ulLineNumber = wcstoul(pwszDescrLine, NULL, 10);
*pwszLineSeparator = g_wchDescriptionFileSeparator; // restore the separator
}
// Always copy the description
wcsTruncatedCopy(pErrorInfo->wszDescription, pwszDescrDescription, DMUS_MAX_FILENAME);
}
}