dxcapi.use.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // dxcapi.use.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Provides support for DXC API users. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/Support/WinIncludes.h"
  12. #include "dxc/Support/dxcapi.use.h"
  13. #include "dxc/Support/Global.h"
  14. #include "dxc/Support/Unicode.h"
  15. #include "dxc/Support/WinFunctions.h"
  16. namespace dxc {
  17. #ifdef _WIN32
  18. static void TrimEOL(_Inout_z_ char *pMsg) {
  19. char *pEnd = pMsg + strlen(pMsg);
  20. --pEnd;
  21. while (pEnd > pMsg && (*pEnd == '\r' || *pEnd == '\n')) {
  22. --pEnd;
  23. }
  24. pEnd[1] = '\0';
  25. }
  26. static std::string GetWin32ErrorMessage(DWORD err) {
  27. char formattedMsg[200];
  28. DWORD formattedMsgLen =
  29. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  30. nullptr, err, 0, formattedMsg, _countof(formattedMsg), 0);
  31. if (formattedMsg > 0 && formattedMsgLen < _countof(formattedMsg)) {
  32. TrimEOL(formattedMsg);
  33. return std::string(formattedMsg);
  34. }
  35. return std::string();
  36. }
  37. #else
  38. static std::string GetWin32ErrorMessage(DWORD err) {
  39. // Since we use errno for handling messages, we use strerror to get the error
  40. // message.
  41. return std::string(std::strerror(err));
  42. }
  43. #endif // _WIN32
  44. void IFT_Data(HRESULT hr, LPCWSTR data) {
  45. if (SUCCEEDED(hr)) return;
  46. CW2A pData(data, CP_UTF8);
  47. std::string errMsg;
  48. if (HRESULT_IS_WIN32ERR(hr)) {
  49. DWORD err = HRESULT_AS_WIN32ERR(hr);
  50. errMsg.append(GetWin32ErrorMessage(err));
  51. if (data != nullptr) {
  52. errMsg.append(" ", 1);
  53. }
  54. }
  55. if (data != nullptr) {
  56. errMsg.append(pData);
  57. }
  58. throw ::hlsl::Exception(hr, errMsg);
  59. }
  60. void EnsureEnabled(DxcDllSupport &dxcSupport) {
  61. if (!dxcSupport.IsEnabled()) {
  62. IFT(dxcSupport.Initialize());
  63. }
  64. }
  65. void ReadFileIntoBlob(DxcDllSupport &dxcSupport, _In_ LPCWSTR pFileName,
  66. _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) {
  67. CComPtr<IDxcLibrary> library;
  68. IFT(dxcSupport.CreateInstance(CLSID_DxcLibrary, &library));
  69. IFT_Data(library->CreateBlobFromFile(pFileName, nullptr, ppBlobEncoding),
  70. pFileName);
  71. }
  72. void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult,
  73. bool outputWarnings) {
  74. HRESULT status;
  75. IFT(pResult->GetStatus(&status));
  76. if (FAILED(status) || outputWarnings) {
  77. CComPtr<IDxcBlobEncoding> pErrors;
  78. IFT(pResult->GetErrorBuffer(&pErrors));
  79. if (pErrors.p != nullptr) {
  80. WriteBlobToConsole(pErrors, STD_ERROR_HANDLE);
  81. }
  82. }
  83. }
  84. void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult,
  85. bool outputWarnings) {
  86. WriteOperationErrorsToConsole(pRewriteResult, outputWarnings);
  87. CComPtr<IDxcBlob> pBlob;
  88. IFT(pRewriteResult->GetResult(&pBlob));
  89. WriteBlobToConsole(pBlob, STD_OUTPUT_HANDLE);
  90. }
  91. void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob, DWORD streamType) {
  92. if (pBlob == nullptr) {
  93. return;
  94. }
  95. // Assume UTF-8 for now, which is typically the case for dxcompiler ouput.
  96. WriteUtf8ToConsoleSizeT((char *)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), streamType);
  97. }
  98. void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName) {
  99. if (pBlob == nullptr) {
  100. return;
  101. }
  102. CHandle file(CreateFileW(pFileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr,
  103. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
  104. if (file == INVALID_HANDLE_VALUE) {
  105. IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
  106. }
  107. WriteBlobToHandle(pBlob, file, pFileName);
  108. }
  109. void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, _In_ HANDLE hFile, _In_opt_ LPCWSTR pFileName) {
  110. if (pBlob == nullptr) {
  111. return;
  112. }
  113. DWORD written;
  114. if (FALSE == WriteFile(hFile, pBlob->GetBufferPointer(),
  115. pBlob->GetBufferSize(), &written, nullptr)) {
  116. IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
  117. }
  118. }
  119. void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
  120. int charCount, DWORD streamType) {
  121. if (charCount == 0 || pText == nullptr) {
  122. return;
  123. }
  124. std::string resultToPrint;
  125. wchar_t *utf16Message = nullptr;
  126. size_t utf16MessageLen;
  127. bool lossy; // Note: even if there was loss, print anyway
  128. Unicode::UTF8BufferToUTF16Buffer(pText, charCount, &utf16Message,
  129. &utf16MessageLen);
  130. std::string consoleMessage;
  131. Unicode::UTF16ToConsoleString(utf16Message, &consoleMessage, &lossy);
  132. if (streamType == STD_OUTPUT_HANDLE) {
  133. fprintf(stdout, "%s\n", consoleMessage.c_str());
  134. }
  135. else if (streamType == STD_ERROR_HANDLE) {
  136. fprintf(stderr, "%s\n", consoleMessage.c_str());
  137. }
  138. else {
  139. throw hlsl::Exception(E_INVALIDARG);
  140. }
  141. delete[] utf16Message;
  142. }
  143. void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
  144. size_t charCount, DWORD streamType) {
  145. if (charCount == 0) {
  146. return;
  147. }
  148. int charCountInt = 0;
  149. IFT(SizeTToInt(charCount, &charCountInt));
  150. WriteUtf8ToConsole(pText, charCountInt, streamType);
  151. }
  152. } // namespace dxc