// Redirects stdout/stderr back to the original stdout/stderr. // Note, this will not restore the original handle values returned by GetStdHandle, // rather a duplicated number. This is because the original handle value is invalid // due to dup2 closing the file originally in stdout/stderr HRESULT StdWrapper::StopRedirection() const { // After setting the std handle, we need to set stdout/stderr to the current // output/error handle. FILE * file = _fdopen(m_previousFileDescriptor, "w"); if (file == nullptr) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, reinterpret_cast<HANDLE>(_get_osfhandle(m_previousFileDescriptor)))); if (!m_enableNativeRedirection) { return S_OK; } // Set stdout/stderr to the newly created file output. const auto dup2Result = _dup2(_fileno(file), _fileno(m_stdStream)); if (dup2Result != 0) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } if (setvbuf(m_stdStream, nullptr, _IONBF, 0) != 0) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } if (fclose(m_redirectedFile) != 0) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } return S_OK; }
HRESULT ClientReader::Initialize(bool IsLoopback, FLOAT SampleRate, HANDLE WaitEvent, CComPtr<IMMDevice> InputDevice, CComPtr<IDXAudioCallback> Callback) { HRESULT hr = S_OK; BYTE* Buffer = nullptr; int error = 0; m_Callback = Callback; //Create the SRC_STATE object m_ResampleState = src_new ( SRC_SINC_FASTEST, //More than adequate for a real time stream 2, //Two channels (stereo) &error ); if (error != 0) { m_Callback->OnObjectFailure ( FILENAME, __LINE__, E_FAIL ); return E_FAIL; } //"Activate" the device (create the IAudioClient interface) hr = InputDevice->Activate ( __uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)(&m_Client) ); RETURN_HR(__LINE__); //Retrieves the device period - this is how often new information is provided //to the stream, in 100-nanosecond units. hr = m_Client->GetDevicePeriod ( &m_Period, nullptr ); RETURN_HR(__LINE__); //Retrieves the mix format - this is the format in which the audio endpoint gives //us the data. This data will need to be resampled, so we need to know what form //it's in. hr = m_Client->GetMixFormat ( (WAVEFORMATEX**)(&m_WaveFormat) ); RETURN_HR(__LINE__); //Initialize the client, marking how we're going to be using it hr = m_Client->Initialize ( AUDCLNT_SHAREMODE_SHARED, //Always use shared - exclusive is meant for drivers and is unpredictable otherwise WaitEvent ? AUDCLNT_STREAMFLAGS_EVENTCALLBACK : NULL | //Use an event callback if specified IsLoopback ? AUDCLNT_STREAMFLAGS_LOOPBACK : NULL, //Make this a loopback stream if specified m_Period, //Creates a buffer large enough to store one packet m_Period, //Use the endpoint's periodicity (this can't ve any other value) (WAVEFORMATEX*)(m_WaveFormat), //Pass in the wave format we just retrieved NULL //No audio session stuff ); RETURN_HR(__LINE__); //Create the IAudioCaptureClient interface hr = m_Client->GetService ( IID_PPV_ARGS(&m_CaptureClient) ); RETURN_HR(__LINE__); //If using an event callback mechanism, provide the event handle (this is from CDXAudioStream) if (WaitEvent != NULL) { hr = m_Client->SetEventHandle ( WaitEvent ); RETURN_HR(__LINE__); } //Calculate the number of frames the endpoint is going to give us each period. m_PeriodFrames = (UINT32)(ceil(DOUBLE(m_Period * m_WaveFormat->Format.nSamplesPerSec) / 10000000)); //Calculate the resample ratio - this is the ratio of the output sample rate to the input sample rate, IE //the sample rate specified by the application developer divided by the sample rate used by the endpoint. //This value is used by libsamplerate. m_ResampleRatio = DOUBLE(SampleRate) / DOUBLE(m_WaveFormat->Format.nSamplesPerSec); //Output sample rate / input sample rate return S_OK; }
// Redirects stdout/stderr to the provided handle. // Example: // If the handleToRedirecTo = 0x24 // Before: // _fileno(stdout) = 1 // GetStdHandle(STD_OUTPUT_HANDLE) = 0x20 // After: // _fileno(stdout) = 3 // GetStdHandle(STD_OUTPUT_HANDLE) = 0x28 <- Duplicated from 0x24 HRESULT StdWrapper::StartRedirection() { HANDLE stdHandle; // In IIS, stdout and stderr are set to null as w3wp is created with DETACHED_PROCESS, // so fileno(m_stdStream) returns -2. // Open a null file such that undoing the redirection succeeds and _dup2 works. // m_previousFileDescriptor will be used for restoring stdout/stderr if (_fileno(m_stdStream) == -2) { freopen_s((FILE**)&m_stdStream, "nul", "w", m_stdStream); m_previousFileDescriptor = _dup(_fileno(m_stdStream)); } else { m_previousFileDescriptor = _dup(_fileno(m_stdStream)); } if (!m_enableNativeRedirection) { RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, m_handleToRedirectTo)); return S_OK; } // After setting the std handle, we need to set stdout/stderr to the current // output/error handle. // Duplicate the handle before opening the handle and associating a file pointer. // If we don't by calling close on the file, the same handle value will be closed // multiple times. // Note, by calling duplicate handle, the new handle returned will have a different value // than the original, but point to the same underlying file object. RETURN_LAST_ERROR_IF(!DuplicateHandle( /* hSourceProcessHandle*/ GetCurrentProcess(), /* hSourceHandle */ m_handleToRedirectTo, /* hTargetProcessHandle */ GetCurrentProcess(), /* lpTargetHandle */&stdHandle, /* dwDesiredAccess */ 0, // dwDesired is ignored if DUPLICATE_SAME_ACCESS is specified /* bInheritHandle */ TRUE, /* dwOptions */ DUPLICATE_SAME_ACCESS)); RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, stdHandle)); // _open_osfhandle will associate a filedescriptor with the handle. const auto fileDescriptor = _open_osfhandle(reinterpret_cast<intptr_t>(stdHandle), _O_WTEXT | _O_TEXT); if (fileDescriptor == -1) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } m_redirectedFile = _fdopen(fileDescriptor, "w"); if (m_redirectedFile == nullptr) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } // Set stdout/stderr to the newly created file. const auto dup2Result = _dup2(_fileno(m_redirectedFile), _fileno(m_stdStream)); if (dup2Result != 0) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } // Removes buffering from the output if (setvbuf(m_stdStream, nullptr, _IONBF, 0) != 0) { RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID)); } return S_OK; }
HRESULT SwapChainController12::CreateSwapChain(CComPtr<IUnknown> DeviceUnk, UINT NumBuffers) { HRESULT hr = S_OK; BOOL bresult = TRUE; if (NumBuffers < 2) { hr = E_INVALIDARG; RETURN_HR(__LINE__); } DXGI_SWAP_CHAIN_DESC desc; Zero(desc); CComPtr<IDXGIFactory4> factory; CComPtr<IDXGISwapChain> BaseSwapChain; RECT WindowRect; //Retrieves the client area of the window, which tells us its renderable width and height bresult = GetClientRect ( m_Handle, &WindowRect ); RETURN_BRESULT(__LINE__); //Fill the swap chain description desc.BufferCount = NumBuffers; //For D3D12, this is the total number of buffers, not the number of back buffers. desc.BufferDesc.Format = GLOBAL_DXGI_FORMAT; desc.BufferDesc.Width = WindowRect.right - WindowRect.left; desc.BufferDesc.Height = WindowRect.bottom - WindowRect.top; desc.BufferDesc.RefreshRate.Numerator = 0; desc.BufferDesc.RefreshRate.Denominator = 0; desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; desc.OutputWindow = m_Handle; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; desc.Windowed = TRUE; //This is the factory that made the application's device hr = m_OutputEnum.GetAdapter()->GetParent ( IID_PPV_ARGS(&factory) ); RETURN_HR(__LINE__); //Use that factory to create the swap chain hr = factory->CreateSwapChain ( DeviceUnk, &desc, &BaseSwapChain ); RETURN_HR(__LINE__); hr = BaseSwapChain->QueryInterface ( IID_PPV_ARGS(&m_SwapChain) ); RETURN_HR(__LINE__); //Turn off alt-enter, since we're using F11 instead hr = factory->MakeWindowAssociation ( m_Handle, DXGI_MWA_NO_WINDOW_CHANGES ); RETURN_HR(__LINE__); return S_OK; }