123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // dxcapi.use.cpp //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // Provides support for DXC API users. //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #include "dxc/Support/WinIncludes.h"
- #include "dxc/Support/dxcapi.use.h"
- #include "dxc/Support/Global.h"
- #include "dxc/Support/Unicode.h"
- #include "dxc/Support/FileIOHelper.h"
- #include "dxc/Support/WinFunctions.h"
- namespace dxc {
- #ifdef _WIN32
- static void TrimEOL(_Inout_z_ char *pMsg) {
- char *pEnd = pMsg + strlen(pMsg);
- --pEnd;
- while (pEnd > pMsg && (*pEnd == '\r' || *pEnd == '\n')) {
- --pEnd;
- }
- pEnd[1] = '\0';
- }
- static std::string GetWin32ErrorMessage(DWORD err) {
- char formattedMsg[200];
- DWORD formattedMsgLen =
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, err, 0, formattedMsg, _countof(formattedMsg), 0);
- if (formattedMsg > 0 && formattedMsgLen < _countof(formattedMsg)) {
- TrimEOL(formattedMsg);
- return std::string(formattedMsg);
- }
- return std::string();
- }
- #else
- static std::string GetWin32ErrorMessage(DWORD err) {
- // Since we use errno for handling messages, we use strerror to get the error
- // message.
- return std::string(std::strerror(err));
- }
- #endif // _WIN32
- void IFT_Data(HRESULT hr, LPCWSTR data) {
- if (SUCCEEDED(hr)) return;
- CW2A pData(data, CP_UTF8);
- std::string errMsg;
- if (HRESULT_IS_WIN32ERR(hr)) {
- DWORD err = HRESULT_AS_WIN32ERR(hr);
- errMsg.append(GetWin32ErrorMessage(err));
- if (data != nullptr) {
- errMsg.append(" ", 1);
- }
- }
- if (data != nullptr) {
- errMsg.append(pData);
- }
- throw ::hlsl::Exception(hr, errMsg);
- }
- void EnsureEnabled(DxcDllSupport &dxcSupport) {
- if (!dxcSupport.IsEnabled()) {
- IFT(dxcSupport.Initialize());
- }
- }
- void ReadFileIntoBlob(DxcDllSupport &dxcSupport, _In_ LPCWSTR pFileName,
- _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) {
- CComPtr<IDxcLibrary> library;
- IFT(dxcSupport.CreateInstance(CLSID_DxcLibrary, &library));
- IFT_Data(library->CreateBlobFromFile(pFileName, nullptr, ppBlobEncoding),
- pFileName);
- }
- void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult,
- bool outputWarnings) {
- HRESULT status;
- IFT(pResult->GetStatus(&status));
- if (FAILED(status) || outputWarnings) {
- CComPtr<IDxcBlobEncoding> pErrors;
- IFT(pResult->GetErrorBuffer(&pErrors));
- if (pErrors.p != nullptr) {
- WriteBlobToConsole(pErrors, STD_ERROR_HANDLE);
- }
- }
- }
- void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult,
- bool outputWarnings) {
- WriteOperationErrorsToConsole(pRewriteResult, outputWarnings);
- CComPtr<IDxcBlob> pBlob;
- IFT(pRewriteResult->GetResult(&pBlob));
- WriteBlobToConsole(pBlob, STD_OUTPUT_HANDLE);
- }
- static void WriteUtf16NullTermToConsole(_In_opt_count_(charCount) const wchar_t *pText,
- DWORD streamType) {
- if (pText == nullptr) {
- return;
- }
- bool lossy; // Note: even if there was loss, print anyway
- std::string consoleMessage;
- Unicode::UTF16ToConsoleString(pText, &consoleMessage, &lossy);
- if (streamType == STD_OUTPUT_HANDLE) {
- fprintf(stdout, "%s\n", consoleMessage.c_str());
- }
- else if (streamType == STD_ERROR_HANDLE) {
- fprintf(stderr, "%s\n", consoleMessage.c_str());
- }
- else {
- throw hlsl::Exception(E_INVALIDARG);
- }
- }
- static HRESULT BlobToUtf8IfText(_In_opt_ IDxcBlob *pBlob, IDxcBlobUtf8 **ppBlobUtf8) {
- CComPtr<IDxcBlobEncoding> pBlobEncoding;
- if (SUCCEEDED(pBlob->QueryInterface(&pBlobEncoding))) {
- BOOL known;
- UINT32 cp = 0;
- IFT(pBlobEncoding->GetEncoding(&known, &cp));
- if (known) {
- return hlsl::DxcGetBlobAsUtf8(pBlob, nullptr, ppBlobUtf8);
- }
- }
- return S_OK;
- }
- static HRESULT BlobToUtf16IfText(_In_opt_ IDxcBlob *pBlob, IDxcBlobUtf16 **ppBlobUtf16) {
- CComPtr<IDxcBlobEncoding> pBlobEncoding;
- if (SUCCEEDED(pBlob->QueryInterface(&pBlobEncoding))) {
- BOOL known;
- UINT32 cp = 0;
- IFT(pBlobEncoding->GetEncoding(&known, &cp));
- if (known) {
- return hlsl::DxcGetBlobAsUtf16(pBlob, nullptr, ppBlobUtf16);
- }
- }
- return S_OK;
- }
- void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob, DWORD streamType) {
- if (pBlob == nullptr) {
- return;
- }
- // Try to get as UTF-16 or UTF-8
- BOOL known;
- UINT32 cp = 0;
- CComPtr<IDxcBlobEncoding> pBlobEncoding;
- IFT(pBlob->QueryInterface(&pBlobEncoding));
- IFT(pBlobEncoding->GetEncoding(&known, &cp));
- if (cp == DXC_CP_UTF16) {
- CComPtr<IDxcBlobUtf16> pUtf16;
- IFT(hlsl::DxcGetBlobAsUtf16(pBlob, nullptr, &pUtf16));
- WriteUtf16NullTermToConsole(pUtf16->GetStringPointer(), streamType);
- } else if (cp == CP_UTF8) {
- CComPtr<IDxcBlobUtf8> pUtf8;
- IFT(hlsl::DxcGetBlobAsUtf8(pBlob, nullptr, &pUtf8));
- WriteUtf8ToConsoleSizeT(pUtf8->GetStringPointer(), pUtf8->GetStringLength(), streamType);
- }
- }
- void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName, _In_ UINT32 textCodePage) {
- if (pBlob == nullptr) {
- return;
- }
- CHandle file(CreateFileW(pFileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
- if (file == INVALID_HANDLE_VALUE) {
- IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
- }
- WriteBlobToHandle(pBlob, file, pFileName, textCodePage);
- }
- void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, _In_ HANDLE hFile, _In_opt_ LPCWSTR pFileName, _In_ UINT32 textCodePage) {
- if (pBlob == nullptr) {
- return;
- }
- LPCVOID pPtr = pBlob->GetBufferPointer();
- SIZE_T size = pBlob->GetBufferSize();
- std::string BOM;
- CComPtr<IDxcBlobUtf8> pBlobUtf8;
- CComPtr<IDxcBlobUtf16> pBlobUtf16;
- if (textCodePage == DXC_CP_UTF8) {
- IFT_Data(BlobToUtf8IfText(pBlob, &pBlobUtf8), pFileName);
- if (pBlobUtf8) {
- pPtr = pBlobUtf8->GetStringPointer();
- size = pBlobUtf8->GetStringLength();
- // TBD: Should we write UTF-8 BOM?
- //BOM = "\xef\xbb\xbf"; // UTF-8
- }
- } else if (textCodePage == DXC_CP_UTF16) {
- IFT_Data(BlobToUtf16IfText(pBlob, &pBlobUtf16), pFileName);
- if (pBlobUtf16) {
- pPtr = pBlobUtf16->GetStringPointer();
- size = pBlobUtf16->GetStringLength() * sizeof(wchar_t);
- BOM = "\xff\xfe"; // UTF-16 LE
- }
- }
- IFT_Data(size > (SIZE_T)UINT32_MAX ? E_OUTOFMEMORY : S_OK , pFileName);
- DWORD written;
- if (!BOM.empty()) {
- if (FALSE == WriteFile(hFile, BOM.data(), BOM.length(), &written, nullptr)) {
- IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
- }
- }
- if (FALSE == WriteFile(hFile, pPtr, (DWORD)size, &written, nullptr)) {
- IFT_Data(HRESULT_FROM_WIN32(GetLastError()), pFileName);
- }
- }
- void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText,
- int charCount, DWORD streamType) {
- if (charCount == 0 || pText == nullptr) {
- return;
- }
- std::string resultToPrint;
- wchar_t *utf16Message = nullptr;
- size_t utf16MessageLen;
- Unicode::UTF8BufferToUTF16Buffer(pText, charCount, &utf16Message,
- &utf16MessageLen);
- WriteUtf16NullTermToConsole(utf16Message, streamType);
- delete[] utf16Message;
- }
- void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
- size_t charCount, DWORD streamType) {
- if (charCount == 0) {
- return;
- }
- int charCountInt = 0;
- IFT(SizeTToInt(charCount, &charCountInt));
- WriteUtf8ToConsole(pText, charCountInt, streamType);
- }
- } // namespace dxc
|