Source code of Windows XP (NT5)
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.

144 lines
5.1 KiB

  1. // Copyright (c) 2000 Microsoft Corporation. All rights reserved.
  2. //
  3. // Implementation of PackExceptionFileAndLine and UnpackExceptionFileAndLine.
  4. //
  5. #include "stdinc.h"
  6. #include "packexception.h"
  7. #include "oleaut.h"
  8. const WCHAR g_wszDescriptionFileSeparator[] = L""; // magic character for separating the filename, line, and description
  9. const WCHAR g_wchDescriptionFileSeparator = g_wszDescriptionFileSeparator[0];
  10. void SeparateDescriptionFileAndLine(BSTR bstrDescription, const WCHAR **ppwszFilename, const WCHAR **ppwszLine, const WCHAR **ppwszDescription)
  11. {
  12. assert(bstrDescription && ppwszFilename && ppwszLine && ppwszDescription);
  13. // if there aren't any packed fields, the whole thing is the description
  14. *ppwszDescription = bstrDescription;
  15. WCHAR *pwszLine = wcsstr(bstrDescription, g_wszDescriptionFileSeparator);
  16. if (!pwszLine)
  17. return;
  18. WCHAR *pwszDescription = wcsstr(pwszLine + 1, g_wszDescriptionFileSeparator);
  19. if (!pwszDescription)
  20. return;
  21. // String looks like this:
  22. // MyScript.spt�23�Description of the error
  23. // pExcepInfo->bstrDescription-^ pwszLine-^ ^-pwszDescription
  24. *ppwszFilename = bstrDescription;
  25. assert(*pwszLine == g_wchDescriptionFileSeparator);
  26. *ppwszLine = pwszLine + 1;
  27. assert(*pwszDescription == g_wchDescriptionFileSeparator);
  28. *ppwszDescription = pwszDescription + 1;
  29. }
  30. bool wcsIsBlankTillSeparator(const WCHAR *pwsz)
  31. {
  32. return !pwsz[0] || pwsz[0] == g_wchDescriptionFileSeparator;
  33. }
  34. void wcscpyTillSeparator(WCHAR *pwszDestination, const WCHAR *pwszSource)
  35. {
  36. assert(pwszDestination && pwszSource);
  37. while (!wcsIsBlankTillSeparator(pwszSource))
  38. {
  39. *pwszDestination++ = *pwszSource++;
  40. }
  41. *pwszDestination = L'\0';
  42. }
  43. void wcscatTillSeparator(WCHAR *pwszDestination, const WCHAR *pwszSource)
  44. {
  45. assert(pwszDestination && pwszSource);
  46. while (*pwszDestination != L'\0')
  47. ++pwszDestination;
  48. wcscpyTillSeparator(pwszDestination, pwszSource);
  49. }
  50. void PackExceptionFileAndLine(bool fUseOleAut, EXCEPINFO *pExcepInfo, const WCHAR *pwszFilename, const ULONG *pulLine)
  51. {
  52. if (!pExcepInfo || !pExcepInfo->bstrDescription)
  53. return;
  54. const WCHAR *pwszDescrFilename = L"";
  55. const WCHAR *pwszDescrLine = L"";
  56. const WCHAR *pwszDescrDescription = L"";
  57. SeparateDescriptionFileAndLine(pExcepInfo->bstrDescription, &pwszDescrFilename, &pwszDescrLine, &pwszDescrDescription);
  58. if (wcsIsBlankTillSeparator(pwszDescrFilename) && pwszFilename)
  59. {
  60. // Filename is blank. Use the specified filename.
  61. pwszDescrFilename = pwszFilename;
  62. }
  63. // MSDN documentation for _ultow says max is 33 characters, but PREFIX complains if the length
  64. // is less than 40.
  65. WCHAR wszLineBuffer[40] = L"";
  66. if (wcsIsBlankTillSeparator(pwszDescrLine) && pulLine)
  67. {
  68. // Line is blank. Use the specified line.
  69. _ultow(*pulLine, wszLineBuffer, 10);
  70. pwszDescrLine = wszLineBuffer;
  71. }
  72. WCHAR *pwszNewDescription = new WCHAR[wcslen(pwszDescrFilename) + wcslen(pwszDescrLine) + wcslen(pwszDescrDescription) + (wcslen(g_wszDescriptionFileSeparator) * 2 + 1)];
  73. if (pwszNewDescription)
  74. {
  75. wcscpyTillSeparator(pwszNewDescription, pwszDescrFilename);
  76. wcscat(pwszNewDescription, g_wszDescriptionFileSeparator);
  77. wcscatTillSeparator(pwszNewDescription, pwszDescrLine);
  78. wcscat(pwszNewDescription, g_wszDescriptionFileSeparator);
  79. wcscat(pwszNewDescription, pwszDescrDescription);
  80. DMS_SysFreeString(fUseOleAut, pExcepInfo->bstrDescription);
  81. pExcepInfo->bstrDescription = DMS_SysAllocString(fUseOleAut, pwszNewDescription);
  82. delete[] pwszNewDescription;
  83. }
  84. }
  85. void UnpackExceptionFileAndLine(BSTR bstrDescription, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
  86. {
  87. assert(pErrorInfo && bstrDescription);
  88. if (pErrorInfo && bstrDescription)
  89. {
  90. const WCHAR *pwszDescrFilename = L"";
  91. const WCHAR *pwszDescrLine = L"";
  92. const WCHAR *pwszDescrDescription = L"";
  93. SeparateDescriptionFileAndLine(bstrDescription, &pwszDescrFilename, &pwszDescrLine, &pwszDescrDescription);
  94. // String looks like this:
  95. // CoolScriptFile.spt�23�Description of the error
  96. // pwszDescrFilename-^ pwszDescrLine-^ ^-pwszDescrDescription
  97. // Except that if these weren't found then they point to a separate empty string.
  98. if (!wcsIsBlankTillSeparator(pwszDescrFilename))
  99. {
  100. // Filename is present. Copy to pErrorInfo.
  101. assert(*(pwszDescrLine - 1) == g_wchDescriptionFileSeparator);
  102. wcsTruncatedCopy(pErrorInfo->wszSourceFile,
  103. pwszDescrFilename,
  104. std::_MIN<UINT>(DMUS_MAX_FILENAME, pwszDescrLine - pwszDescrFilename));
  105. }
  106. if (!wcsIsBlankTillSeparator(pwszDescrLine))
  107. {
  108. // Line is present. Copy to pErrorInfo.
  109. WCHAR *pwszLineSeparator = const_cast<WCHAR *>(pwszDescrDescription - 1);
  110. assert(*pwszLineSeparator == g_wchDescriptionFileSeparator);
  111. *pwszLineSeparator = L'\0'; // terminate the line for wcstoul
  112. pErrorInfo->ulLineNumber = wcstoul(pwszDescrLine, NULL, 10);
  113. *pwszLineSeparator = g_wchDescriptionFileSeparator; // restore the separator
  114. }
  115. // Always copy the description
  116. wcsTruncatedCopy(pErrorInfo->wszDescription, pwszDescrDescription, DMUS_MAX_FILENAME);
  117. }
  118. }