// 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(DMUS_MAX_FILENAME, pwszDescrLine - pwszDescrFilename)); } if (!wcsIsBlankTillSeparator(pwszDescrLine)) { // Line is present. Copy to pErrorInfo. WCHAR *pwszLineSeparator = const_cast(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); } }