dxcapi.use.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. namespace dxc {
  16. static void TrimEOL(_Inout_z_ char *pMsg) {
  17. char *pEnd = pMsg + strlen(pMsg);
  18. --pEnd;
  19. while (pEnd > pMsg && *pEnd == '\r' || *pEnd == '\n') {
  20. --pEnd;
  21. }
  22. pEnd[1] = '\0';
  23. }
  24. static std::string GetWin32ErrorMessage(DWORD err) {
  25. char formattedMsg[200];
  26. DWORD formattedMsgLen =
  27. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  28. nullptr, err, 0, formattedMsg, _countof(formattedMsg), 0);
  29. if (formattedMsg > 0 && formattedMsgLen < _countof(formattedMsg)) {
  30. TrimEOL(formattedMsg);
  31. return std::string(formattedMsg);
  32. }
  33. return std::string();
  34. }
  35. void IFT_Data(HRESULT hr, LPCWSTR data) {
  36. if (SUCCEEDED(hr)) return;
  37. CW2A pData(data, CP_UTF8);
  38. std::string errMsg;
  39. if (HRESULT_IS_WIN32ERR(hr)) {
  40. DWORD err = HRESULT_AS_WIN32ERR(hr);
  41. errMsg.append(GetWin32ErrorMessage(err));
  42. if (data != nullptr) {
  43. errMsg.append(" ", 1);
  44. }
  45. }
  46. if (data != nullptr) {
  47. errMsg.append(pData);
  48. }
  49. throw ::hlsl::Exception(hr, errMsg);
  50. }
  51. void EnsureEnabled(DxcDllSupport &dxcSupport) {
  52. if (!dxcSupport.IsEnabled()) {
  53. IFT(dxcSupport.Initialize());
  54. }
  55. }
  56. void ReadFileIntoBlob(DxcDllSupport &dxcSupport, _In_ LPCWSTR pFileName,
  57. _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) {
  58. CComPtr<IDxcLibrary> library;
  59. IFT(dxcSupport.CreateInstance(CLSID_DxcLibrary, &library));
  60. IFT_Data(library->CreateBlobFromFile(pFileName, nullptr, ppBlobEncoding),
  61. pFileName);
  62. }
  63. void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult,
  64. bool outputWarnings) {
  65. HRESULT status;
  66. IFT(pResult->GetStatus(&status));
  67. if (FAILED(status) || outputWarnings) {
  68. CComPtr<IDxcBlobEncoding> pErrors;
  69. IFT(pResult->GetErrorBuffer(&pErrors));
  70. if (pErrors.p != nullptr) {
  71. WriteBlobToConsole(pErrors, STD_ERROR_HANDLE);
  72. }
  73. }
  74. }
  75. void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult,
  76. bool outputWarnings) {
  77. WriteOperationErrorsToConsole(pRewriteResult, outputWarnings);
  78. CComPtr<IDxcBlob> pBlob;
  79. IFT(pRewriteResult->GetResult(&pBlob));
  80. WriteBlobToConsole(pBlob, STD_OUTPUT_HANDLE);
  81. }
  82. void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob, DWORD streamType) {
  83. if (pBlob == nullptr) {
  84. return;
  85. }
  86. // Assume UTF-8 for now, which is typically the case for dxcompiler ouput.
  87. WriteUtf8ToConsoleSizeT((char *)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), streamType);
  88. }
  89. void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName) {
  90. if (pBlob == nullptr) {
  91. return;
  92. }
  93. CHandle file(CreateFile2(pFileName, GENERIC_WRITE, FILE_SHARE_READ,
  94. CREATE_ALWAYS, nullptr));
  95. if (file == INVALID_HANDLE_VALUE) {
  96. IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
  97. }
  98. WriteBlobToHandle(pBlob, file, pFileName);
  99. }
  100. void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, _In_ HANDLE hFile, _In_opt_ LPCWSTR pFileName) {
  101. if (pBlob == nullptr) {
  102. return;
  103. }
  104. DWORD written;
  105. if (FALSE == WriteFile(hFile, pBlob->GetBufferPointer(),
  106. pBlob->GetBufferSize(), &written, nullptr)) {
  107. IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
  108. }
  109. }
  110. void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
  111. int charCount, DWORD streamType) {
  112. if (charCount == 0 || pText == nullptr) {
  113. return;
  114. }
  115. std::string resultToPrint;
  116. wchar_t *utf16Message = nullptr;
  117. size_t utf16MessageLen;
  118. bool lossy; // Note: even if there was loss, print anyway
  119. Unicode::UTF8BufferToUTF16Buffer(pText, charCount, &utf16Message,
  120. &utf16MessageLen);
  121. std::string consoleMessage;
  122. Unicode::UTF16ToConsoleString(utf16Message, &consoleMessage, &lossy);
  123. if (streamType == STD_OUTPUT_HANDLE) {
  124. fprintf(stdout, "%s\n", consoleMessage.c_str());
  125. }
  126. else if (streamType == STD_ERROR_HANDLE) {
  127. fprintf(stderr, "%s\n", consoleMessage.c_str());
  128. }
  129. else {
  130. throw hlsl::Exception(E_INVALIDARG);
  131. }
  132. delete[] utf16Message;
  133. }
  134. void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
  135. size_t charCount, DWORD streamType) {
  136. if (charCount == 0) {
  137. return;
  138. }
  139. int charCountInt;
  140. IFT(SizeTToInt(charCount, &charCountInt));
  141. WriteUtf8ToConsole(pText, charCountInt, streamType);
  142. }
  143. } // namespace dxc