DirectSound captures gigabytes of frames instead of megabytes - c++

I am using DirectSound to capture the sound of my desktop, using the tutorial from MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/ee416968(v=vs.85).aspx
The problem is that when I start to capture, my WAV file gets to hundreds of MB and even GB, in a few seconds.When I play the WAV file, 5 seconds of audio capture become 30 minutes, and the same frame of sound is duplicated like 1000 times.I have noticed that WAIT_OBJECT_0 + 1 and 2 are never fired.Thanks in advance.
bool captureSound = false;
wav_header wavFile; // the wav file
UINT totalData = 0;
LPDIRECTSOUNDCAPTURE8 capturer = NULL;
GUID guid = DSDEVID_DefaultCapture;
HRESULT err;
DSCBUFFERDESC dscbd;
LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB8;
DWORD g_dwNextCaptureOffset = 0;
DWORD g_dwCaptureBufferSize = 0;
DWORD g_dwNotifySize = 0;
#define cEvents 3
WAVEFORMATEX wfx;
HANDLE rghEvent[cEvents] = {0,0,0};
DSBPOSITIONNOTIFY rgdsbpn[cEvents];
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
BOOL bDone;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WIN32PROJECT2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT2));
bDone = FALSE;
// Main message loop:
while( !bDone ) {
dwResult = MsgWaitForMultipleObjects( 3, rghEvent,
FALSE, INFINITE, QS_ALLEVENTS );
switch( dwResult ) {
case WAIT_OBJECT_0 + 0:
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("Error!"), TEXT("Error"), MB_OK);
break;
case WAIT_OBJECT_0 + 1:
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("Error!"), TEXT("Error"), MB_OK);
break;
case WAIT_OBJECT_0 + 2:
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("Error!"), TEXT("Error"), MB_OK);
break;
case WAIT_OBJECT_0 + 3:
//MessageBox(NULL,TEXT("wait3"), TEXT("Error"), MB_OK);
// Windows messages are available
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if( msg.message == WM_QUIT )
bDone = TRUE;
}
break;
}
}
//CloseHandle(rghEvent);
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_CAPTURESOUND:
captureSound = true;
if (FAILED(createWav(&wavFile)))
{
closeWav(wavFile.pFile);
MessageBox(NULL,TEXT("Error creating the sound file!"), TEXT("Error"), MB_OK);
}
// add the WAV header
for(int i = 0; i < 4; i++) {
fputc(wavFile.riff_header[i], wavFile.pFile);
}
fwrite((char*)&wavFile.wav_size,sizeof(int),1,wavFile.pFile);
for(int i = 0; i < 4; i++) {
fputc(wavFile.wave_header[i], wavFile.pFile);
}
for(int i = 0; i < 4; i++) {
fputc(wavFile.fmt_header[i], wavFile.pFile);
}
fwrite((const char*)&wavFile.fmt_chunk_size,4,1,wavFile.pFile);
fwrite((const char*)&wavFile.audio_format,2,1,wavFile.pFile);
fwrite((const char*)&wavFile.num_channels,2,1,wavFile.pFile);
fwrite((const char*)&wavFile.sample_rate,4,1,wavFile.pFile);
fwrite((const char*)&wavFile.byte_rate,4,1,wavFile.pFile);
fwrite((const char*)&wavFile.sample_alignment,2,1,wavFile.pFile);
fwrite((const char*)&wavFile.bit_depth,2,1,wavFile.pFile);
for(int i = 0; i < 4; i++) {
fputc(wavFile.data_header[i], wavFile.pFile);
}
fwrite((const char*)&wavFile.data_bytes,4,1,wavFile.pFile);
/* Use DirectSoundCaptureCreate8() to create and initialize an object and get the pointer (pDSC8) to IDirectSoundCapture8 */
if(FAILED(DirectSoundCaptureCreate8(&guid, &capturer, NULL))) {
ErrorExit(TEXT("DirectSoundCaptureCreate8"));
}
/* Use the method CreateCaptureBuffer() of IDirectSoundCapture8(pDSC8->CreateSoundBuffer()) to create
and initialize an object and get the pointer (pDSCB) to IDirectSoundCaptureBuffer. */
if(FAILED(CreateCaptureBuffer(capturer,&pDSCB8))) {
ErrorExit(TEXT("CreateCaptureBuffer"));
}
/* Use the method QueryInterface of IDirectSoundCaptureBuffer8(pDSCB8->QueryInterface()) to get a pointer(lpDsNotify) to the interface IDirectSoundNotify8. */
if(FAILED(SetCaptureNotifications(pDSCB8))) {
ErrorExit(TEXT("SetCaptureNotifications"));
}
/* Start capturing */
if(FAILED(pDSCB8->Start( DSCBSTART_LOOPING ) ) )
ErrorExit(TEXT("Start"));
else MessageBox(NULL,TEXT("Started capturing!"), TEXT("Good"), MB_OK);
break;
case IDM_OPRESTE:
captureSound = false;
// Stop the buffer, and read any data that was not
// caught by a notification
if( FAILED(pDSCB8->Stop() ) )
ErrorExit(TEXT("Stop"));
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("ERROR "), TEXT("Error"), MB_OK);
/* Update the fields in the WAV header and close the file */
fseek (wavFile.pFile, 4 , SEEK_SET );
wavFile.wav_size += totalData;
fwrite((char*)&wavFile.wav_size,sizeof(int),1,wavFile.pFile);
wavFile.data_bytes += totalData;
fseek (wavFile.pFile, 40 , SEEK_SET );
fwrite((char*)&wavFile.data_bytes,sizeof(int),1,wavFile.pFile);
closeWav(wavFile.pFile);
break;
case IDM_EXIT:
DestroyWindow(hWnd); // POSTS THE MESSAGE WM_DESTROY TO DESTROY THE CREATED WINDOW.
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
HRESULT CreateCaptureBuffer(LPDIRECTSOUNDCAPTURE8 pDSC,
LPDIRECTSOUNDCAPTUREBUFFER8* ppDSCB8)
{
HRESULT hr;
DSCBUFFERDESC dscbd;
LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
// Set up WAVEFORMATEX for 44.1 kHz 16-bit stereo.
WAVEFORMATEX wfx =
{WAVE_FORMAT_PCM, wavFile.num_channels, wavFile.sample_rate, wavFile.byte_rate, wavFile.sample_alignment, wavFile.bit_depth, 0};
// wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec,
// nBlockAlign, wBitsPerSample, cbSize
if ((NULL == pDSC) || (NULL == ppDSCB8)) return E_INVALIDARG;
dscbd.dwSize = sizeof(DSCBUFFERDESC);
dscbd.dwFlags = 0;
dscbd.dwBufferBytes = wfx.nAvgBytesPerSec;
dscbd.dwReserved = 0;
dscbd.lpwfxFormat = &wfx;
dscbd.dwFXCount = 0;
dscbd.lpDSCFXDesc = NULL;
g_dwNotifySize = MAX( 1024, wavFile.byte_rate / 8 );
g_dwNotifySize -= g_dwNotifySize % wavFile.sample_alignment;
g_dwCaptureBufferSize = g_dwNotifySize * 3;
if (SUCCEEDED(hr = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL)))
{
/* Use the method QueryInterface of IDirectSoundCaptureBuffer(pDSCB->QueryInterface()) to get a
pointer(pDSCB8) to the interface IDirectSoundCaptureBuffer8 */
hr = pDSCB->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)ppDSCB8);
pDSCB->Release();
}
return hr;
}
HRESULT SetCaptureNotifications(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB)
{
LPDIRECTSOUNDNOTIFY8 pDSNotify;
HRESULT hr;
if (NULL == pDSCB) return E_INVALIDARG;
if (FAILED(hr = pDSCB->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNotify)))
{
return hr;
}
if (FAILED(hr = pDSCB->GetFormat(&wfx, sizeof(WAVEFORMATEX), NULL)))
{
return hr;
}
// Create events.
for (int i = 0; i < cEvents; ++i)
{
rghEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == rghEvent[i])
{
hr = GetLastError();
return hr;
}
}
// Describe notifications.
rgdsbpn[0].dwOffset = (wfx.nAvgBytesPerSec/2) -1;
rgdsbpn[0].hEventNotify = rghEvent[0];
rgdsbpn[1].dwOffset = wfx.nAvgBytesPerSec - 1;
rgdsbpn[1].hEventNotify = rghEvent[1];
rgdsbpn[2].dwOffset = DSBPN_OFFSETSTOP;
rgdsbpn[2].hEventNotify = rghEvent[2];
/* Use the SetNotificationPositions() of IDirectSoundNotify8(lpDsNotify->SetNotificationPositions())
to set the notification buffer positions */
hr = pDSNotify->SetNotificationPositions(cEvents, rgdsbpn);
pDSNotify->Release();
return hr;
}
HRESULT RecordCapturedData()
{
HRESULT hr;
VOID* pbCaptureData = NULL;
DWORD dwCaptureLength;
VOID* pbCaptureData2 = NULL;
DWORD dwCaptureLength2;
VOID* pbPlayData = NULL;
UINT dwDataWrote;
DWORD dwReadPos;
LONG lLockSize;
if (NULL == pDSCB8)
MessageBox(NULL,TEXT("Empty buffer!"), TEXT("Error"), MB_OK);
if (NULL == wavFile.pFile)
MessageBox(NULL,TEXT("Empty .wav file!"), TEXT("Error"), MB_OK);
if (FAILED (hr = pDSCB8->GetCurrentPosition(
NULL, &dwReadPos)))
MessageBox(NULL,TEXT("Failed to get current position!"), TEXT("Error"), MB_OK);
// Lock everything between the private cursor
// and the read cursor, allowing for wraparound.
lLockSize = dwReadPos - g_dwNextCaptureOffset;
if( lLockSize < 0 ) lLockSize += g_dwCaptureBufferSize;
// Block align lock size so that we are always write on a boundary
//lLockSize -= (lLockSize % g_dwNotifySize);
if( lLockSize == 0 ) return S_FALSE;
if (FAILED(hr = pDSCB8->Lock(
g_dwNextCaptureOffset, lLockSize,
&pbCaptureData, &dwCaptureLength,
&pbCaptureData2, &dwCaptureLength2, 0L)))
MessageBox(NULL,TEXT("Lock failed!"), TEXT("Error"), MB_OK);
// Write the data. This is done in two steps
// to account for wraparound.
if (FAILED( addData(&wavFile, (BYTE*)pbCaptureData, dwCaptureLength, &dwDataWrote)))
MessageBox(NULL,TEXT("Error writting to the file!"), TEXT("Error"), MB_OK);
if (pbCaptureData2 != NULL)
{
if (FAILED( addData(&wavFile, (BYTE*)pbCaptureData2, dwCaptureLength2, &dwDataWrote)))
MessageBox(NULL,TEXT("Error writting to the file 2!"), TEXT("Error"), MB_OK);
}
// Unlock the capture buffer.
pDSCB8->Unlock( pbCaptureData, dwCaptureLength,
pbCaptureData2, dwCaptureLength2 );
// Move the capture offset forward.
g_dwNextCaptureOffset += dwCaptureLength;
g_dwNextCaptureOffset %= g_dwCaptureBufferSize;
g_dwNextCaptureOffset += dwCaptureLength2;
g_dwNextCaptureOffset %= g_dwCaptureBufferSize;
totalData += (dwCaptureLength + dwCaptureLength2);
return S_OK;
}
Wav writer utility
#include "stdafx.h"
#include "Wav.h"
HRESULT createWav(wav_header* pWav) {
pWav->pFile = fopen("sound.wav","w");
if(pWav->pFile == NULL) {
return 0;
}
strcpy(pWav->riff_header, "RIFF");
strcpy(pWav->wave_header, "WAVE");
strcpy(pWav->fmt_header, "fmt ");
pWav->fmt_chunk_size = 16;
pWav->audio_format = 1;
pWav->num_channels = 2;
pWav->sample_rate = 44100; // 44.1 KHz - CD-quality audio
pWav->bit_depth = 16; // Bits per Sample – The number of bits available for one sample.
pWav->sample_alignment = pWav->num_channels * (pWav->bit_depth)/8; // This is the number of bytes in a frame
pWav->byte_rate = pWav->sample_rate * pWav->sample_alignment; // number of bytes per second captured
strcpy(pWav->data_header, "data");
pWav->data_bytes = 0; // n * frames , n = 0 empty data default, to be updated each time new data is added
pWav->wav_size = 36 + pWav->data_bytes; // to be updated each time new data is added
return S_OK;
}
HRESULT closeWav(FILE * pFile) {
fclose(pFile);
return S_OK;
}
HRESULT addData(wav_header* pWav, VOID* data,UINT dataLength, UINT* dataWrote) {
// set the positon back at the end of the file
fseek (pWav->pFile, 0 , SEEK_END );
*dataWrote = fwrite((const char*)data,sizeof(byte),(size_t)dataLength, pWav->pFile);
return S_OK;
}

Related

Get dos_name of usb on inserting or removal

I have designed a program to detect whenever a usb device is connected or removed. I want to know the either the dos path of the connected device or a Guid like this \\?\Volume{17ee3574-7082-4881-aeae-07893db4e957}\
But instead dbcc_name gives me \\?\STORAGE#Volume#_??_USBSTOR#Disk&Ven_JetFlash&Prod_Transcend_8GB&Rev_1100#546IYBDAPBE1075Q&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
Is there anyway to obtain the guid of the connected logical drive or its dos name. My code is:
#define CLS_NAME L"USB_LISTENER_CLASS"
#define HID_CLASSGUID {0x4d1e55b2, 0xf16f, 0x11cf,{ 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}}
LRESULT message_handler(HWND__* hwnd, UINT uint, WPARAM wparam, LPARAM lparam)
{
switch (uint)
{
case WM_NCCREATE: // before window creation
return true;
break;
case WM_CREATE: // the actual creation of the window
{
// you can get your creation params here..like GUID..
LPCREATESTRUCT params = (LPCREATESTRUCT)lparam;
GUID InterfaceClassGuid = *((GUID*)params->lpCreateParams);
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_VOLUME;
HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if (dev_notify == NULL)
{
throw std::runtime_error("Could not register for device Notifications!");
}
}
break;
case WM_DEVICECHANGE:
{
PDEV_BROADCAST_HDR(lpdb) = (PDEV_BROADCAST_HDR)lparam;
PDEV_BROADCAST_DEVICEINTERFACE_W lpdbv = (PDEV_BROADCAST_DEVICEINTERFACE_W)lpdb;
switch (wparam)
{
case DBT_DEVICEARRIVAL: //A device or piece of media has been inserted and is now available.
std::cout << "Device Arrived" << std::endl;
std::cout << "GUID od inserted device: " << lpdbv->dbcc_name;
break;
case DBT_DEVICEREMOVECOMPLETE:
std::cout << "Device Removed" << std::endl;
break;
}
}
}
return 0L;
}
void UsbListener::RegisterListener()
{
HWND hWnd = NULL;
WNDCLASSEXW wx;
ZeroMemory(&wx, sizeof(wx));
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = reinterpret_cast<WNDPROC>(message_handler);
wx.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
wx.style = CS_HREDRAW | CS_VREDRAW;
wx.hInstance = GetModuleHandle(0);
wx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wx.lpszClassName = CLS_NAME;
GUID guid = HID_CLASSGUID;
if (RegisterClassExW(&wx))
{
hWnd = CreateWindowW(
CLS_NAME, L"DeviceNotificationWindow", WS_ICONIC, 0, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), (void*)&guid
);
}
if (hWnd == NULL)
{
throw std::runtime_error("Could not create message window!");
}
std::cout <<std::endl<< "Listening..." << std::endl;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
I want to know the Dos name of the exact drive that is inserted or removed so that UI can display. I am new to winapi so please bear with the code,
at the begin you need open Mount Manager and save it handle in class associated with your window, for not open/close it multiple time, bit only once
#include <mountmgr.h>
HANDLE hMountMgr = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, 0, 0, 0, OPEN_EXISTING, 0, 0);
for query dos like name (if it exist !) you need first get device name via IOCTL_MOUNTDEV_QUERY_DEVICE_NAME which need send to device, which interface name you have. so you need first open it.
then you can send IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH to Mount Manager and got what you want
volatile UCHAR guz;
ULONG GetDosVolumePath(HANDLE hMountMgr, PCWSTR InterfaceLink, PWSTR* ppszDosPath)
{
*ppszDosPath = 0;
HANDLE hFile = CreateFileW(InterfaceLink, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE) return GetLastError();
union {
PVOID buf;
PMOUNTDEV_NAME pmdn;
};
ULONG dwError;
PVOID stack = alloca(guz);
ULONG cb = 0, rcb, InputBufferLength = sizeof(MOUNTDEV_NAME) + 0x40;
do
{
if (cb < InputBufferLength)
{
cb = RtlPointerToOffset(buf = alloca(InputBufferLength - cb), stack);
}
dwError = BOOL_TO_ERROR(DeviceIoControl(hFile, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, 0, 0, pmdn, cb, &rcb, 0));
InputBufferLength = FIELD_OFFSET(MOUNTDEV_NAME, Name) + pmdn->NameLength;
} while ( dwError == ERROR_MORE_DATA);
CloseHandle(hFile);
if (dwError == NOERROR)
{
union {
PVOID pv;
PMOUNTMGR_VOLUME_PATHS pmvp;
};
cb = 0, rcb = sizeof(MOUNTMGR_VOLUME_PATHS) + 8;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(pv = alloca(rcb - cb), pmdn);
}
dwError = BOOL_TO_ERROR(DeviceIoControl(hMountMgr,
IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
pmdn, InputBufferLength, pmvp, cb, &rcb, 0));
if (dwError == NOERROR)
{
*ppszDosPath = _wcsdup(pmvp->MultiSz);
}
rcb = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + pmvp->MultiSzLength;
} while (dwError == ERROR_MORE_DATA);
}
return dwError;
}

EnumDesktopWindows Error: (183) Cannot create a file when that file already exists

Anyone know why returns 183 in call EnumDesktopWindows
This process is an service running in System LocalService
I'm trying to put the window in the top, because the process starts minimized.
Thank for Help
My Code:
BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
{
DWORD dwPID;
GetWindowThreadProcessId( hwnd, &dwPID );
if( dwPID == lParam ) {
SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE );
SwitchToThisWindow(hwnd, true);
SetFocus( hwnd );
return FALSE;
}
return TRUE;
}
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam) {
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if(hDesk != NULL) {
if(!EnumDesktopWindows(hDesk,&EnumWindowsProc, lParam)) {
//This call returns (183) Cannot create a file when that file already exists
}
CloseDesktop(hDesk);
}
return TRUE;
}
BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation,FALSE,WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if(hWinStat) {
SetProcessWindowStation(hWinStat);
EnumDesktops(hWinStat,&EnumDesktopProc,lParam);
CloseWindowStation(hWinStat);
}
return TRUE;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bResult = FALSE;
DWORD dwSessionId,winlogonPid;
HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
DWORD dwCreationFlags;
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId();
//////////////////////////////////////////
// Find the winlogon process
////////////////////////////////////////
PROCESSENTRY32 procEntry;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
return false;
procEntry.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &procEntry))
return false;
do {
if (_wcsicmp(procEntry.szExeFile, L"winlogon.exe") == 0) {
// We found a winlogon process...make sure it's running in the console session
DWORD winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId) {
winlogonPid = procEntry.th32ProcessID;
break;
}
}
} while (Process32Next(hSnap, &procEntry));
WTSQueryUserToken(dwSessionId,&hUserToken);
dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL|SW_RESTORE;
ZeroMemory(&pi, sizeof(pi));
TOKEN_PRIVILEGES tp;
LUID luid;
hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);
if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
|TOKEN_READ|TOKEN_WRITE,&hPToken))
{
return false;
}
if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
return false;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));
if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
return false;
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
return false;
LPVOID pEnv = NULL;
if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
else
pEnv = NULL;
// Launch the process in the client's logon session.
std::wstring params = aParams;
std::wstring path = aPath;
if(aMode == L"select") {
TCHAR infoBuffer[MAX_PATH];
GetSystemWindowsDirectory(infoBuffer, MAX_PATH);
std::wstring windowsDir(infoBuffer);
path = windowsDir+L"\\explorer.exe";
params = L" /n, /select,"+replaceString(aPath, L"\\\\", L"\\");
}
bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
path.c_str(), // file to execute
params.length() > 0 ? stringToLPWSTR(wideToUtf8(params)) : NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
EnumWindowStations(&EnumWindowStationProc, (LPARAM)(pi.dwProcessId));
// End impersonation of client.
//GetLastError Shud be 0
int rv = GetLastError();
//Perform All the Close Handles task
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
return !rv;
}
Error 183 is ERROR_ALREADY_EXISTS. EnumDesktopWindows() does not set that error, so it must be a carry-over from an earlier API call. If you read the documentation says this:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682615.aspx
You must ensure that the callback function sets SetLastError if it fails.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682614.aspx
If the callback function fails, the return value is zero. The callback function can call SetLastError to set an error code for the caller to retrieve by calling GetLastError.
So try something more like this:
struct WndInfo
{
DWORD dwProcessID;
HWND hWnd;
};
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
WndInfo *pInfo = (WndInfo*) lParam;
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if (dwPID == pInfo->dwProcessID)
{
pInfo->hWnd = hwnd;
SetLastError(0);
return FALSE;
}
return TRUE;
}
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam)
{
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if (hDesk != NULL)
{
if (!EnumDesktopWindows(hDesk, &EnumWindowsProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
CloseDesktop(hDesk);
WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}
return TRUE;
}
BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if (hWinStat != NULL)
{
SetProcessWindowStation(hWinStat);
if (!EnumDesktops(hWinStat, &EnumDesktopProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
CloseWindowStation(hWinStat);
WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}
return TRUE;
}
HWND findWindowForProcess(DWORD PID)
{
WndInfo info;
info.dwProcessID = PID;
info.hWnd = NULL;
if (!EnumWindowStations(&EnumWindowStationProc, (LPARAM)&info))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
return info.hWnd;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
...
bResult = CreateProcessAsUser(...);
if (bResult)
{
HWND hWnd = findWindowForProcess(pi.dwProcessId);
if (hWnd != NULL)
{
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
SwitchToThisWindow(hWnd, TRUE);
SetFocus(hWnd);
}
}
...
}
With that said, since all you are really trying to do is execute a new process in a specific user session, you don't need to bother with all that enumeration logic. You don't need to find the WinLogon process at all, you already have the user's token from WTSQueryUserToken() so just duplicate+adjust that token as needed. And you are not doing anything useful in your window enumeration that the new process would not already do by default when it is started, so just get rid of that logic, too.
And then finally fix your error handling (or lack of) so you can close any handles that are open and not leak them.

Serial Port Communication using Bluetooth not Receiving Response, VC++, MFC

I am developing a ELM327 Simulator device(http://en.wikipedia.org/wiki/ELM327) using VC++ in MFC..It implements Serial port communication with my PC and tab..My Pc contains BLuetooth plugged into it and the device (tab) is being paired with my PC..My program should send the required result for the received response..
Eg:
For Speed, Command : 010D should respond with output 41 0D 12
My problrm is that it is not receiving response from PC after sending command..What could probably the reason be..
Thanks to All
My code For ReceiveData is Like This.
LRESULT CELM327SimDlg::OnReceiveData(WPARAM wParam, LPARAM lParam)
{
int iLen = (int)wParam; // iLen has value 5
LPBYTE lpDataBuffer = (LPBYTE)lParam;
//lpDataBuffer has value AT Z
// Parse and handle the received here.
WORD wCmd = m_ELM327Cmd.ParseAndGetCmd(lpDataBuffer, iLen); //Goes to ParseAndGetCmd function
if( ELM327_CMD_SUP_CMD == wCmd ) //If condition fails program control goes to else part
{
for( int i = 0; i < 3; i++ )
{
m_objSerialPort.SendData(m_ELM327Cmd.GetSupBuf(i), m_ELM327Cmd.GetSupBufLen());
}
}
else
{
DWORD dwData = 0;
switch(wCmd) // Not getting to switch block
{
case ELM327_CMD_RPM:
dwData = m_ctrlRPMSlider.GetPos();
break;
case ELM327_CMD_SPEED:
dwData = m_ctrlSpeedSlider.GetPos();
break;
case ELM327_CMD_MAF:
dwData = m_ctrlMAFSlider.GetPos();
break;
case ELM327_CMD_FUELLVL:
dwData = m_ctrlFuelSlider.GetPos();break;
default:break;
}
if(m_ELM327Cmd.SetResponse(wCmd, dwData)) //Program calling SetResponse function.
{
m_objSerialPort.SendData(m_ELM327Cmd.GetResponseBuf(), m_ELM327Cmd.GetResponseLen());
}
}
if( NULL != lpDataBuffer )
{
delete [] lpDataBuffer;
lpDataBuffer = NULL;
}
return 0;
}
SendData Function is as follows
// Send data to comport
void CSerialPort::SendData(LPBYTE lpBuffer, DWORD dwBytes)
{
if(m_bConnected)
{
if( NULL == lpBuffer || dwBytes == 0 )
{
return;
}
LPBYTE lpDataBuffer = new BYTE[dwBytes];
if( NULL == lpDataBuffer )
{
return;
}
CopyMemory(lpDataBuffer, lpBuffer, dwBytes );
::PostMessage( m_hWnd, UWM_SEND_DATA, (WPARAM)dwBytes, (LPARAM)lpDataBuffer );
}
return;
}

Call a function when "event.GetFrom(m_cpVoice)==S_OK" (ergo when event happens) [SAPI 5.1 and C++]

I'm doing a project with a 3D model, that speaks.
So, I'm using SAPI 5.1, and I want to call a function asynchronously when there's a Viseme event (in order to play the animation related to).
How could I do it?
Thank you very much.
Note: I use : hRes = m_cpVoice->Speak(L"All I want is to solve this problem", SPF_ASYNC , NULL);
And I know the CspEvent, event.eEventId . All I want is how to call a function when Sapi event happens
First, you need to call m_cpVoice->SetInterest(SPFEI(SPEI_VISEME), SPFEI(SPEI_VISEME)); that will tell SAPI to send an event when a VISEME event fires.
Second, you need to set up an event handler by calling m_cpVoice->SetNotifyCallbackInterface, with your callback. (It must implement ISpNotifyCallback, which is a virtual C++ interface that your object would implement.)
You can look at the SAPI events documentation for more details.
A sample implementation of ISpNotifyCallback would look like this:
TTSHandler.h:
class CTTSHandler : ISpNotifyCallback
{
public:
CTTSHandler(void);
~CTTSHandler(void);
HRESULT Initialize();
HRESULT DoSpeak();
HRESULT Uninitialize();
private:
HRESULT STDMETHODCALLTYPE NotifyCallback(WPARAM wParam, LPARAM lParam);
void TTSAppStatusMessage(LPCTSTR str);
CComPtr<ISpAudio> m_cpOutAudio;
CComPtr<ISpVoice> m_cpVoice;
HANDLE m_hSpeakDone;
};
TTSHandler.cpp:
#include "TTSHandler.h"
#include <sphelper.h>
CTTSHandler::CTTSHandler(void) : m_hSpeakDone(INVALID_HANDLE_VALUE)
{
}
CTTSHandler::~CTTSHandler(void)
{
}
HRESULT CTTSHandler::Initialize()
{
HRESULT hr = m_cpVoice.CoCreateInstance( CLSID_SpVoice );
if ( SUCCEEDED( hr ) )
{
SpCreateDefaultObjectFromCategoryId( SPCAT_AUDIOOUT, &m_cpOutAudio );
}
if( SUCCEEDED( hr ) )
{
hr = m_cpVoice->SetOutput( m_cpOutAudio, FALSE );
}
if ( SUCCEEDED( hr ) )
{
hr = m_cpVoice->SetNotifyCallbackInterface(this, 0, 0);
}
// We're interested in all TTS events
if( SUCCEEDED( hr ) )
{
hr = m_cpVoice->SetInterest( SPFEI_ALL_TTS_EVENTS, SPFEI_ALL_TTS_EVENTS );
}
if (SUCCEEDED(hr))
{
m_hSpeakDone = ::CreateEvent(NULL, TRUE, FALSE, NULL); // anonymous event used to wait for speech done
}
return hr;
}
HRESULT CTTSHandler::DoSpeak()
{
HRESULT hr = m_cpVoice->Speak( L"This is a reasonably long string that should take a while to speak. This is some more text.", SPF_ASYNC |SPF_IS_NOT_XML, 0 );
if (FAILED(hr))
{
TTSAppStatusMessage( _T("speak failed\r\n") );
}
else
{
BOOL fContinue = TRUE;
while (fContinue)
{
DWORD dwWaitId = ::MsgWaitForMultipleObjectsEx(1, &m_hSpeakDone, INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
switch (dwWaitId)
{
case WAIT_OBJECT_0:
{
fContinue = FALSE;
}
break;
case WAIT_OBJECT_0 + 1:
{
MSG Msg;
while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&Msg);
::DispatchMessage(&Msg);
}
}
break;
case WAIT_TIMEOUT:
{
hr = S_FALSE;
fContinue = FALSE;
}
break;
default:// Unexpected error
{
TTSAppStatusMessage(L"Unexpected error returned from MsgWaitForMultipleObj");
hr = HRESULT_FROM_WIN32(::GetLastError());
fContinue = FALSE;
}
break;
}
}
}
return hr;
}
HRESULT CTTSHandler::Uninitialize()
{
m_cpVoice = NULL;
return S_OK;
}
void CTTSHandler::TTSAppStatusMessage(LPCTSTR szMessage )
{
wprintf_s(L"%s", szMessage);
}
/////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE CTTSHandler::NotifyCallback(WPARAM, LPARAM)
/////////////////////////////////////////////////////////////////
//
// Handles the WM_TTSAPPCUSTOMEVENT application defined message and all
// of it's appropriate SAPI5 events.
//
{
CSpEvent event; // helper class in sphelper.h for events that releases any
// allocated memory in it's destructor - SAFER than SPEVENT
int i = 0;
HRESULT hr = S_OK;
while( event.GetFrom(m_cpVoice) == S_OK )
{
switch( event.eEventId )
{
case SPEI_START_INPUT_STREAM:
TTSAppStatusMessage( _T("StartStream event\r\n") );
break;
case SPEI_END_INPUT_STREAM:
TTSAppStatusMessage( _T("EndStream event\r\n") );
SetEvent(m_hSpeakDone);
break;
case SPEI_VOICE_CHANGE:
TTSAppStatusMessage( _T("Voicechange event\r\n") );
break;
case SPEI_TTS_BOOKMARK:
{
// Get the string associated with the bookmark
// and add the null terminator.
TCHAR szBuff2[MAX_PATH] = _T("Bookmark event: ");
size_t cEventString = wcslen( event.String() ) + 1;
WCHAR *pwszEventString = new WCHAR[ cEventString ];
if ( pwszEventString )
{
wcscpy_s( pwszEventString, cEventString, event.String() );
_tcscat_s( szBuff2, _countof(szBuff2), CW2T(pwszEventString) );
delete[] pwszEventString;
}
_tcscat_s( szBuff2, _countof(szBuff2), _T("\r\n") );
TTSAppStatusMessage( szBuff2 );
}
break;
case SPEI_WORD_BOUNDARY:
TTSAppStatusMessage( _T("Wordboundary event\r\n") );
break;
case SPEI_PHONEME:
TTSAppStatusMessage( _T("Phoneme event\r\n") );
break;
case SPEI_VISEME:
TTSAppStatusMessage( _T("Viseme event\r\n") );
break;
case SPEI_SENTENCE_BOUNDARY:
TTSAppStatusMessage( _T("Sentence event\r\n") );
break;
case SPEI_TTS_AUDIO_LEVEL:
WCHAR wszBuff[MAX_PATH];
swprintf_s(wszBuff, _countof(wszBuff), L"Audio level: %d\r\n", (ULONG)event.wParam);
TTSAppStatusMessage( CW2T(wszBuff) );
break;
case SPEI_TTS_PRIVATE:
TTSAppStatusMessage( _T("Private engine event\r\n") );
break;
default:
TTSAppStatusMessage( _T("Unknown message\r\n") );
break;
}
}
return hr;
}

Not able to Print the folder path in EditBox- MFC

I am using the following function ..instead of CFolderDialog.. to get the folder path...check my code below....am getting a run time error when i try toprint the folder path name in a edit box..
void
CSelfExtractorUIDlg::OnBnClickedButton1()
{
CDialog dlg;
HWND hwnd = NULL; LPCTSTR szCurrent =
(LPCTSTR)malloc(25*sizeof(TCHAR));
szCurrent = NULL; LPTSTR szPath =
(LPTSTR)malloc(25*sizeof(TCHAR)); BOOL
check =
BrowseForFolder(hwnd,szCurrent,szPath);
if( check == TRUE) {
dlg.SetDlgItemTextW(IDC_EDIT1,szPath);
}
}
BOOL BrowseForFolder(HWND hwnd,
LPCTSTR szCurrent, LPTSTR szPath) {
BROWSEINFO bi = { 0 }; LPITEMIDLIST
pidl; TCHAR szDisplay[256]; BOOL
retval;
//CoInitialize();
bi.hwndOwner = hwnd;
bi.pszDisplayName = szDisplay;
bi.lpszTitle = TEXT("Please
choose a folder."); bi.ulFlags
= BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; bi.lpfn
= BrowseCallbackProc; bi.lParam = (LPARAM) szCurrent;
pidl = SHBrowseForFolder(&bi);
if (NULL != pidl) {
retval = SHGetPathFromIDList(pidl, szPath);
CoTaskMemFree(pidl); } else {
retval = FALSE; }
if (!retval) {
szPath[0] = TEXT('\0'); }
CoUninitialize(); return retval;
} static int CALLBACK
BrowseCallbackProc(HWND hwnd,UINT
uMsg, LPARAM lParam, LPARAM lpData)
{
// If the BFFM_INITIALIZED message is
received // set the path to the start
path.
switch (uMsg) { case
BFFM_INITIALIZED: { if (NULL !=
lpData) { SendMessage(hwnd,
BFFM_SETSELECTION, TRUE, lpData); }
} }
return 0; // The function
25 characters seems a little short for a full path length, I'd use MAX_PATH.