Accessing dbch_devicetype fails - c++

I have a piece of MS C++ (unmanaged) code that runs whenever a USB device is inserted or removed into my computer. On Windows 7, this code runs fine. On Windows 10, it throws an error. What happens is that when a USB drive, or any other USB device for that matter, is inserted into my computer, the OnMyDeviceChange routine gets called 3 times; it is only called two (correct) times on Windows 7. Anyways, on Windows 10, the first two times, the routine runs fine. The third time it fails on this line: type.Format("%d",pHdr->dbch_devicetype);. Does anyone know why?
Note: we now know that for the code that fails, pHdr is null.
Here is my code:
ON_MESSAGE(WM_DEVICECHANGE, OnMyDeviceChange)//in BEGIN_MESSAGE_MAP(CMainFrame, CBCGPMDIFrameWnd)
LRESULT CMainFrame::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
//return 0;//essentially comment out everything else
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
AddLogLine("1");
// AfxMessageBox(pHdr->dbch_devicetype);
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
AddLogLine("2");
CString type;
type.Format("%d",pHdr->dbch_devicetype);
AddLogLine("type = " + type);
if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
UpdateDevice(pDevInf, wParam);
}
return 0;
}
//More relevant code:
struct _DEV_BROADCAST_HDR { /* */
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
};
typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR;
typedef DEV_BROADCAST_HDR DBTFAR* PDEV_BROADCAST_HDR;

Related

Thread is terminated for no apparent reason

So I am currently making a system to list all visible windows and then choose a random one. The code exists and is working.. in 32-bit. The problem is that it won't work when compiling for 64-bit. It does not even hit my breaking point before terminating the thread. I have also tried using a try block with the same result. The thread exit code is 0. NOTE: The code is messy due to it being filled with debugging and testing stuff.
Here is my code:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
wchar_t wnd_title[2048]; // Will be replaced
SendMessage(hwnd, WM_GETTEXT, sizeof(wnd_title), (LPARAM)wnd_title);
if (!hwnd || !IsWindowVisible(hwnd) || !SendMessage(hwnd, WM_GETTEXT, sizeof(wnd_title), (LPARAM)wnd_title)) {
return TRUE;
}
std::vector<HWND>& Windows = *reinterpret_cast<std::vector<HWND>*>(lParam);
Windows.push_back(hwnd);
OutputDebugString(wnd_title);
OutputDebugString(L"\n");
return TRUE;
}
std::vector<HWND> GetOpenWindows() {
std::vector<HWND> Windows;
EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&Windows));
return Windows;
}
void GetRandomWindow() {
stringstream ss; // For Debug
std::ostringstream stream; //For Debug
std::vector<HWND> Windows = GetOpenWindows();
int ChosenWindow = Utils::RandIntRange(0, Windows.size());
if (ChosenWindow < Windows.size()) { // Breaking point here (HIT)
TCHAR wnd_title[MAX_PATH];
SendMessage(Windows[ChosenWindow], WM_GETTEXT, MAX_PATH, (LPARAM)wnd_title); //Breaking point here (NOT HIT)
OutputDebugString(L"\n");
OutputDebugString(wnd_title);
MessageBox(NULL, L"Hi", L"Test", MB_OK);
}
}
The thread was terminated because the wrong size was passed to the message. The thread hang issue was fixed by using SendMessageTimeout(...); instead of SendMessage(..);. This works because a window was not responding to any messages.
(Answer is for people who have the same issue)
Thanks to Igor Tandetnik and Peter for the help!

DirectSound crashes due to a read access violation when calling IDirectSoundBuffer8::Play (inside LFQueuePut, a dsound.dll internal function)

I am working on a game, and am sporadically observing crashes inside of dsound.dll.
This happens right after creating a IDirectSoundBuffer8 audio buffer, when calling the Play method on it. At this point I haven't written to the buffer or done anything to the sound system besides creating the audio device, setting the cooperative level, creating the audio buffer and starting to play.
All values returned by DirectSound indicate success, and even when I explicitely query the buffer for things like DSERR_BUFFERLOST, no sign of error is indicated.
This is the callstack:
After hunting this bug down by process of elimination, it seems to be a Windows/Driver issue. In short: DirectSound may crash your application if you reserve 10 TiB of address space. I'm using this address space for a debug allocator that helps hunting down use-after frees, and for some reason DirectSound seems to interact with this allocation.
I was able to produce the following repro, that crashes about every other execution (although I have also seen crash rates as low as 5% in my application). I was able to reproduced this on 2 PCs, and one other person who tried it was also able to reproduce. You have to execute this code in a debugger though, because otherwise you won't be able to distinguish a crash due to access violation from the execution finishing normally:
#include "dsound.h"
#include "assert.h"
//link against user32.lib, dsound.lib and dxguid.lib
LRESULT CALLBACK WindowProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam){
return DefWindowProcW(handle, message, wParam, lParam);
}
void main(){
VirtualAlloc(nullptr, 10llu * 1024 * 1024 * 1024 * 1024, MEM_RESERVE, PAGE_NOACCESS); //if you comment this out, it won't crash
auto application_instance = GetModuleHandle(NULL);
WNDCLASSEXW window_class;
ZeroMemory(&window_class, sizeof(window_class));
window_class.cbSize = sizeof(window_class);
window_class.style = CS_HREDRAW|CS_VREDRAW;
window_class.lpfnWndProc = WindowProc;
window_class.hInstance = application_instance;
window_class.lpszClassName = L"TEST_WINDOW_CLASS";
if(RegisterClassExW(&window_class) == 0)
assert(false);
auto window_handle = CreateWindowExW(0, window_class.lpszClassName, L"smashing", WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, 0, 0, application_instance, 0);
IDirectSound8* active_device = nullptr;
IDirectSoundBuffer8* active_buffer = nullptr;
if(DirectSoundCreate8(NULL, &active_device, NULL) != DS_OK)
assert(false);
if(active_device->SetCooperativeLevel(window_handle, DSSCL_PRIORITY) != DS_OK)
assert(false);
WAVEFORMATEX format_description;
format_description.wFormatTag = WAVE_FORMAT_PCM;
format_description.nChannels = 2;
format_description.nSamplesPerSec = 44100;
format_description.nAvgBytesPerSec = 44100 * 4;
format_description.nBlockAlign = 4;
format_description.wBitsPerSample = 16;
format_description.cbSize = 0;
DSBUFFERDESC buffer_description;
buffer_description.dwSize = sizeof(buffer_description);
buffer_description.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
buffer_description.dwBufferBytes = 44100 * 4;
buffer_description.dwReserved = 0;
buffer_description.lpwfxFormat = &format_description;
buffer_description.guid3DAlgorithm = DS3DALG_DEFAULT;
LPDIRECTSOUNDBUFFER buffer_before_cast = nullptr;
if(active_device->CreateSoundBuffer(&buffer_description, &buffer_before_cast, NULL) != DS_OK)
assert(false);
if(buffer_before_cast->QueryInterface(IID_IDirectSoundBuffer8, (void **)&active_buffer) != S_OK)
assert(false);
if(active_buffer->Play(0, 0, DSBPLAY_LOOPING) != DS_OK) //this is the place where it crashes more often than not
assert(false);
}
I have not found a solution to this issue, and since there is no real way to report such a bug to microsoft with any hopes of it actually getting fixed, I decided to put this on Stackoverflow so that other people hopefully don't waste as much time on it as I have. I will probably try using WASAPI instead next.

RDP connection hook called twice for every connection

I want my application to hook remote connect and disconnect events for all sessions on the specified computer.
According to the documentation, I should call WTSRegisterSessionNotification function first:
WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_ALL_SESSIONS);
Then in the messages processor callback I should do the required stuff on WM_WTSSESSION_CHANGE message type:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WTSSESSION_CHANGE:
{
// do stuff
break;
}
}
}
It works very strange however. Every time I connect or disconnect to/from the computer where my application running, WTS_REMOTE_CONNECT or WTS_REMOTE_DISCONNECT called twice -- in one of these calls I can get user name and in another I can't (it's just an empty string).
case WM_WTSSESSION_CHANGE:
{
const int reason = (int)wParam;
const DWORD sessionId = (DWORD)lParam;
switch (reason)
{
case WTS_REMOTE_CONNECT:
{
DWORD bytesReturned = 0;
LPSTR pData = NULL;
if (WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pData, &bytesReturned) == 0)
{
// Handle error
break;
}
const std::string username = pData;
WTSFreeMemory(pData);
// do other stuff
I found this question but it has very strange accepted answer:
Hmm, the answer appears to be that it's fairly normal for these fields
to be empty on a terminal services/RDP session
I don't understand why it actually works this way.

Disable task switching keys with c++

I've done a lot of searching around with no real solution (to my own problem) so I thought I'd ask here.
I'm designing a kiosk-like program that prevents the user from using task keys (alt+tab, alt+esc, ctrl+esc, etc) while the program is running. Note I'm a novice programmer thus I'd want to stay away from separate dll handling if I can. Particularly, I have went to this site http://support.microsoft.com/kb/226359/en-us for the code. A simplified part of my code looks like this at the top:
HHOOK mule;
HHOOK g_hKeyboardHook;
BOOL g_bFullscreen;
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{
// By returning a non-zero value from the hook procedure, the
// message does not get passed to the target window
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
BOOL bControlKeyDown = 0;
switch (nCode)
{
case HC_ACTION:
{
// Check to see if the CTRL key is pressed
bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
// Disable CTRL+ESC
if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
return 1;
// Disable ALT+TAB
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
// Disable ALT+ESC
if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
break;
}
default:
break;
}
return CallNextHookEx (mule, nCode, wParam, lParam);
}
The my main is
int main(int argc, char **argv)
{
_getch();
g_hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
cout << "Testing task keys disabling (alt tab, ctrl esc, alt esc) and taskbar..." << endl;
_getch();
UnhookWindowsHookEx( g_hKeyboardHook );
cout << "Re enabled" << endl;
_getch();
return 0;
}
I realize this code is for really old windows OS, but I've looked around and the other solutions resemble this code so I thought it should work.
But for some reason it doesn't seem to be working. Whenever my program gets to that line of code, the program stalls for like 5 seconds and continues to run, but the task keys are still working.
I've heard that I should be implementing that function as a dll instead of putting everything in one file, but I'm not sure if they're absolutely right (also I know nothing of dlls)
In addition, I've also tried code (to disable windows key) here: http://msdn.microsoft.com/en-us/library/windows/desktop/ee416808(v=vs.85).aspx and it does the same thing my own program (stalls and does nothing)
Can anyone spot where I did something wrong? I'm using VC++ 2010 on windows 7 64bit.
Your code is fine, hooks just doesn't work with console application because windows can't callback into a console application, it requires a message loop.
Read this answer by Hans Passant which applies here too.

C++ Console app, SetWindowsHookEx, Callback is never called

I have a little console application that has an embedded v8 engine, and I would like to add a hook to register key events. This all worked before when I was using Qt and QtScript, but I am porting it all over to straight C++ in VC++ 2008. The application compiles and runs, but the hook is never called, here is the relevant code:
In main()
HWND hwndC = GetConsoleWindow() ;
HINSTANCE hInst = (HINSTANCE)GetWindowLong( hwndC, GWL_HINSTANCE );
if (SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, hInst, NULL) == 0) {
printf("Failed to set hook\n");
} else {
printf("Hook established\n");
}
g->RunScript(argc,argv);
And the proc:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("HookProc called\n");
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) (lParam);
if (wParam == WM_KEYDOWN) {
keyDown(p,g);
} else if (wParam == WM_KEYUP) {
keyUp(p,g);
}
fflush(stdout);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
This is essentially an expansion on shell.cc from the v8 sample code. I wonder if it is somehow blocking? I admit to not really knowing what I am doing here, just playing around and learning but this one has me stumped.
Inside of keyDown say, I have something like this:
v8::Handle<v8::String> callback_name = v8::String::New("onKeyDown");
v8::Handle<v8::Value> callback_val = g->_context->Global()->Get(callback_name);
if (!callback_val->IsFunction()) {
printf("No onKeyDown handler found\n");
return;
}
v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(callback_val);
const int argc = 1;
v8::Handle<v8::Value> argv[argc] = { v8::Int32::New(char(p->vkCode)) };
printf("Calling onKeyDown\n");
v8::Handle<v8::Value> result = callback->Call(g->_context->Global(), argc, argv);
Some of this may actually not work in the end, but it just never gets called, when I run the program, and define: onKeyDown = function(key) {...}; I can see that onKeyDown is working just fine, I can use all of my bound c++ method etc from JS, so this thing is just driving me batty.
Any help, maybe pointers to some educational materials would be much appreciated.
Just to be clear, this function in c: LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) is never getting called, or never seeing a printf, and the output at the start says: Hook established, so windows is reporting the hook is established.
/Jason
A low-level hook, like WH_KEYBOARD_LL requires that your application pumps a message loop. That's the only way that Windows can break into your thread and make the call to the HookProc callback you registered.
A console mode app doesn't pump a message loop like regular Windows GUI apps do. Judging from your snippet, it isn't going to be easy to add one either. You'll need to create a thread.
Maybe this function will be of help to you?
GetAsyncKeyState