Leaked source code of windows server 2003
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.

167 lines
3.6 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // core utility functions
  4. //
  5. // 30 Nov 1999 sburns
  6. #include "headers.hxx"
  7. HINSTANCE
  8. Burnslib::GetResourceModuleHandle()
  9. {
  10. ASSERT(hResourceModuleHandle);
  11. return hResourceModuleHandle;
  12. }
  13. // Attempt to locate a message in a given module. Return the message string
  14. // if found, the empty string if not.
  15. //
  16. // flags - FormatMessage flags to use
  17. //
  18. // module - module handle of message dll to look in, or 0 to use the system
  19. // message table.
  20. //
  21. // code - message code to look for. This could be an HRESULT, or a win32
  22. // error code.
  23. String
  24. GetMessageHelper(DWORD flags, HMODULE module, DWORD code)
  25. {
  26. // REVIEWED-2002/03/29-sburns no unbounded allocation error here.
  27. // If I pass nSize = 0 and FORMAT_MESSAGE_ALLOCATE_BUFFER in dwFlags,
  28. // the max result size is 32K - 1 characters. Looking at the code in
  29. // message.c, it looks like the reserve space is whatever the user asked
  30. // as a maximum rounded up to the nearest 64K. That makes sense given my
  31. // test, since 32K chars = 64K bytes. Experimentally, even if I ask for
  32. // a max buffer size > 0x87FFF chars, it looks like the most I can get
  33. // is 0x87FFE chars.
  34. flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
  35. String message;
  36. TCHAR* sysMessage = 0;
  37. DWORD result =
  38. ::FormatMessage(
  39. flags,
  40. module,
  41. code,
  42. 0,
  43. reinterpret_cast<PTSTR>(&sysMessage),
  44. 0,
  45. 0);
  46. if (result)
  47. {
  48. ASSERT(sysMessage);
  49. if (sysMessage)
  50. {
  51. message = sysMessage;
  52. ASSERT(result == message.length());
  53. ::LocalFree(sysMessage);
  54. message.replace(L"\r\n", L" ");
  55. }
  56. }
  57. return message;
  58. }
  59. // Attempts to locate message strings for various facility codes in the
  60. // HRESULT
  61. String
  62. Burnslib::GetErrorMessage(HRESULT hr)
  63. {
  64. LOG_FUNCTION2(GetErrorMessage, String::format(L"%1!08X!", hr));
  65. if (!FAILED(hr) && hr != S_OK)
  66. {
  67. // no messages for success codes other than S_OK
  68. ASSERT(false);
  69. return String();
  70. }
  71. String message;
  72. // default is the system error message table
  73. HMODULE module = 0;
  74. do
  75. {
  76. WORD code = static_cast<WORD>(HRESULT_CODE(hr));
  77. if (code == -1)
  78. {
  79. // return "unknown" message
  80. break;
  81. }
  82. DWORD flags =
  83. FORMAT_MESSAGE_ALLOCATE_BUFFER
  84. | FORMAT_MESSAGE_IGNORE_INSERTS
  85. | FORMAT_MESSAGE_FROM_SYSTEM;
  86. if (!HRESULT_FACILITY(hr) && (code >= 0x5000 && code <= 0x50FF))
  87. {
  88. // It's an ADSI error
  89. flags |= FORMAT_MESSAGE_FROM_HMODULE;
  90. module =
  91. ::LoadLibraryEx(
  92. L"activeds.dll",
  93. 0,
  94. LOAD_LIBRARY_AS_DATAFILE | DONT_RESOLVE_DLL_REFERENCES);
  95. if (!module)
  96. {
  97. // return "unknown" message
  98. LOG_HRESULT(Win32ToHresult(::GetLastError()));
  99. break;
  100. }
  101. }
  102. // try FormatMessage with the full HRESULT first
  103. message = GetMessageHelper(flags, module, hr);
  104. if (message.empty())
  105. {
  106. // try again with just the error code
  107. message = GetMessageHelper(flags, module, code);
  108. }
  109. }
  110. while (0);
  111. if (message.empty())
  112. {
  113. message = String::load(IDS_UNKNOWN_ERROR_CODE);
  114. }
  115. if (module)
  116. {
  117. BOOL unused = ::FreeLibrary(module);
  118. ASSERT(unused);
  119. }
  120. return message.strip(String::BOTH);
  121. }