USB HID in a dll

Hi,
I try to make a dll able to drive an HID device , my protocol and my card works fine in a MFC exe file. But when Iput my code in my dll I can’t register to USB notification because I haven’t the form handle.
I’ve found a sample :
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363432(v=vs.85).aspx
but I don’t know how to launch this
HWND hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE | WS_EX_APPWINDOW,
WND_CLASS_NAME,
g_pszAppName,
WS_OVERLAPPEDWINDOW, // style
CW_USEDEFAULT, 0,
640, 480,
NULL, NULL,
hInstanceExe,
NULL);

in my dll to get my hWnd to get my handle.

Thanks you

I’ve tried to get the handle from the application who launch my dll with :
m_hWnd = FindWindowA(NULL, “Calculator” );
But the handle is not good , when I tried to register to notification it tell me acces denied.
Any ideas ?

xxxxx@gmail.com wrote:

I try to make a dll able to drive an HID device , my protocol and my card works fine in a MFC exe file. But when Iput my code in my dll I can’t register to USB notification because I haven’t the form handle.

What kind of notifications do you want? Some notification schemes can
use a callback as well as a window message.

If you know you are in a GUI application that has a message loop, and
you are being called from the application’s main thread, you can always
create a hidden window on your own:

HWND CreateHiddenWindow()
{
WNDCLASS _class;
static TCHAR gClassName = _T(SERVICENAME);

_class.style = 0;
_class.lpfnWndProc = MonitorWndProc;
_class.cbClsExtra = 0;
_class.cbWndExtra = sizeof(void*);
_class.hInstance = GetModuleHandle(NULL);
_class.hIcon = 0;
_class.hCursor = LoadCursor (0, IDC_ARROW);
_class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
_class.lpszMenuName = 0;
_class.lpszClassName = gClassName;

RegisterClass( &_class );

// Create a hidden window to catch the device notification messages.

HWND hWnd = CreateWindow(
gClassName,
gClassName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, GetModuleHandle(NULL), 0
);

return hWnd;
}


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

In the MSDN page for CreateWindowEx, you have the following statement (the second point may be of interest for you):


This function typically fails for one of the following reasons:

. an invalid parameter value
. the system class was registered by a different module
. The?WH_CBT?hook is installed and returns a failure code
. if one of the controls in the dialog template is not registered, or its window window procedure fails?WM_CREATE?orWM_NCCREATE

I think the second point states that WND_CLASS_NAME cannot be used both in the application’s main module and in your dll. You should also pass the GetLastError returned code to the FormatMessage API to obtain a string discribing the error.

Hi Tim,
I’ve replaced in your code _T by TEXT because my compiler doesn’t like it.
but wher can I find MonitorWndProc , in my dll I’ve not dll entry like a main where I can get the handle of the process that call my dll.
It is my biggest problem I must find a way to get a handle to use this function to register my interface for the USB interrupt.
DeviceNotificationHandle = RegisterDeviceNotification(m_hWnd, &DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
Actually my m_hWnd is always null .

On Oct 5, 2014, at 11:10 AM, xxxxx@gmail.com wrote:

Hi Tim,
I’ve replaced in your code _T by TEXT because my compiler doesn’t like it.
but wher can I find MonitorWndProc ,

Well, obviously, you have to provide it. That?s the function that will receive the window messages aimed at your window. You need a traditional window procedure here, with a case statement that matches the messages you expect. In this case, that?s probably WM_DEVICECHANGE. Everything else gets passed to DefWindowProc.

It?s a little concerning that you didn?t know this. This is the fundamental core of every Windows GUI application.

in my dll I’ve not dll entry like a main where I can get the handle of the process that call my dll.

You don?t need that. Your DLL is part of the same process.

It is my biggest problem I must find a way to get a handle to use this function to register my interface for the USB interrupt.
DeviceNotificationHandle = RegisterDeviceNotification(m_hWnd, &DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
Actually my m_hWnd is always null .

Have you done any Windows GUI programming? What you need to provide there is the handle of the window to which you want the device change messages sent. Thus, it?s the window handle that was returned from CreateWindow. If you are using a framework like MFC or WTL, then the handle is stored in a member variable like m_hWnd. If you are creating this from scratch, then you need to use whatever global you used to store the return from CreateWindow.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I’m not really aware about MFC programming , I’ve never done this.
My only c++ program is this dll. I work generally in c#.
This dll is not mine, it is a sample from the software I use.
It is to make an interface between this software and my electonic board.
In this dll , there is a start function called at startup of the software to initialize everything I need , but there is no parameter like handle .
In the dll sample code given I’ve no Handle declared that why I’ve to create one.
That why I tought I’ve to create a fake hidden windows only to get this handle.
In your tips I’ve to provide MonitorWndProc , but I don’t know how to get it ???

Thanks you

> It is my biggest problem I must find a way to get a handle to use this function to register my interface

for the USB interrupt.

In your DLL, create a special thread - exactly to handle the notifications - and a hidden window in it.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

Hi Maxim,
My code is based on a working mfc application I try to inject in my dll.
Actually I’ve debugged all the step except the RegisterDeviceNotification because I’ve the famous Handle.
In the MSDN they say
HDEVNOTIFY WINAPI RegisterDeviceNotification(
In HANDLE hRecipient,
In LPVOID NotificationFilter,
In DWORD Flags
);
hRecipient [in]
A handle to the window or service that will receive device events for the devices specified in the NotificationFilter parameter. The same window handle can be used in multiple calls to RegisterDeviceNotification.
Services can specify either a window handle or service status handle.

Flags [in]
This parameter can be one of the following values.
DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000 The hRecipient parameter is a window handle.
DEVICE_NOTIFY_SERVICE_HANDLE 0x00000001 The hRecipient parameter is a service status handle

What is the service status handle ?
Is it possible to not use a Windows ?

Thanks you

I’ve found a way to make a simple window like maxin say.
here :
http://sim0n.wordpress.com/2009/03/29/c-creating-a-window-from-a-dll/

in my startup function
CreateThread(0, NULL, ThreadProc, (LPVOID)L"Window Title", NULL, NULL);

and in the cpp
#define MYMENU_EXIT (WM_APP + 101)
#define MYMENU_MESSAGEBOX (WM_APP + 102)

HINSTANCE inj_hModule; //Injected Modules Handle
HWND prnt_hWnd; //Parent Window Handle

//WndProc for the new window
LRESULT CALLBACK DLLWindowProc (HWND, UINT, WPARAM, LPARAM);

//Register our windows Class
BOOL RegisterDLLWindowClass(wchar_t szClassName)
{
WNDCLASSEX wc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = “InjectedDLLWindowClass”;
wc.lpfnWndProc = DLLWindowProc;
wc.style = CS_DBLCLKS;
wc.cbSize = sizeof (WNDCLASSEX);
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wc))
return 0;
}
//Creating our windows Menu
HMENU CreateDLLWindowMenu()
{
HMENU hMenu;
hMenu = CreateMenu();
HMENU hMenuPopup;
if(hMenu==NULL)
return FALSE;
hMenuPopup = CreatePopupMenu();
AppendMenu (hMenuPopup, MF_STRING, MYMENU_EXIT, TEXT(“Exit”));
AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT(“File”));

hMenuPopup = CreatePopupMenu();
AppendMenu (hMenuPopup, MF_STRING,MYMENU_MESSAGEBOX, TEXT(“MessageBox”));
AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT(“Test”));
return hMenu;
}
//The new thread
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
MSG messages;
wchar_t *pString = reinterpret_cast<wchar_t> (lpParam);
HMENU hMenu = CreateDLLWindowMenu();
RegisterDLLWindowClass(L"InjectedDLLWindowClass");
prnt_hWnd = FindWindow(“Window Injected Into ClassName”, “Window Injected Into Caption”);

HWND hwnd = CreateWindowEx (0, “InjectedDLLWindowClass”, “Window Title”, WS_EX_PALETTEWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, prnt_hWnd, hMenu,inj_hModule, NULL );
ShowWindow (hwnd, SW_SHOWNORMAL);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return 1;
}
//Our new windows proc
LRESULT CALLBACK DLLWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
switch(wParam)
{
case MYMENU_EXIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
case MYMENU_MESSAGEBOX:
MessageBox(hwnd, “Test”, “MessageBox”,MB_OK);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}

but the handle from CreateWindowEx is still 0 ,maybe it is a print problem.
Do you think I’m wrong in my output handle printing ?

char buf[99] = “”;
sprintf(buf, “%p”, hwnd );
WriteToDebugFiles( “a”, buf );

void WriteToDebugFiles( const char * const openStr, const char * const msg )
{
FILE *fo;

fo = fopen( “Debug.txt”, openStr );
if( fo != NULL )
{
fprintf( fo, “%s\n”, msg );
fclose( fo );
}

}</wchar_t>

xxxxx@gmail.com wrote:

My code is based on a working mfc application I try to inject in my dll.
Actually I’ve debugged all the step except the RegisterDeviceNotification because I’ve the famous Handle.

Flags [in]
This parameter can be one of the following values.
DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000 The hRecipient parameter is a window handle.
DEVICE_NOTIFY_SERVICE_HANDLE 0x00000001 The hRecipient parameter is a service status handle

What is the service status handle ?

If you write a Windows service, then you have a main loop that receives
service messages (like start, stop, pause, shutdown, etc.), very similar
to a window proc. You do not have any windows, because that’s not
allowed for a service. The API allows you to specify either a service
handle (which doesn’t apply to you) or a window handle.

Is it possible to not use a Windows ?

Sure, as long as you don’t need notifications.

Look, it’s not rocket science. I gave you practically the whole code.
If you can’t even write a trivial window procedure, then you really have
no business injecting your DLL into an existing application.

I’ve found a way to make a simple window like maxin say.
here :

I already gave you the code to do this. The code you posted here
creates a VISIBLE window with a menu. I assume you do not want really
your DLL’s window to be see by the end user.

but the handle from CreateWindowEx is still 0 ,maybe it is a print problem.
Do you think I’m wrong in my output handle printing ?

No, it’s because you are copying code you do not understand. Your call
to CreateWindowEx specifies the window handle that will be the parent of
this new window. It gets that parent window handle by searching for a
specific name:

prnt_hWnd = FindWindow(“Window Injected Into ClassName”, “Window Injected Into Caption”);

The demo from which you copied this probably had an accompanying
application that had a window with that title. You don’t.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi,
Of course I’ve changed all the string

CreateThread(0, NULL, ThreadProc, (LPVOID)L"WindowDebug", NULL, NULL);

BOOL RegisterDLLWindowClass(wchar_t szClassName)
{
WNDCLASSEX wc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = “InjectedDLLWindowClass”;
wc.lpfnWndProc = DLLWindowProc;
wc.style = CS_DBLCLKS;
wc.cbSize = sizeof (WNDCLASSEX);
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wc))
return 0;
}

BOOL Register = RegisterDLLWindowClass(L"InjectedDLLWindowClass");prnt_hWnd = FindWindow(“InjectedDLLWindowClass”, “WindowDebug”);
hwnd = CreateWindowEx (0, “InjectedDLLWindowClass”, “WindowDebug”,…);

My code works perfectly when my application launch the WindowDebug appears …
but my Handle is still 0.
Sorry I put the web code instead of mine.

Thanks you for your help

I’ve found what you mean
in the DllMain sample code there is a input parameter :inj_hModule = hModule;
and this inj_hModule is used in the CreateWindowEx function .

Ok I’m 18 but this make me crazy each time I found a code something bug.
Now The windows appears but the Handle is impossible to get …

xxxxx@gmail.com wrote:


BOOL Register = RegisterDLLWindowClass(L"InjectedDLLWindowClass");
prnt_hWnd = FindWindow(“InjectedDLLWindowClass”, “WindowDebug”);
hwnd = CreateWindowEx (0, “InjectedDLLWindowClass”, “WindowDebug”,…);

OK, I want you to think about the ordering there. The FindWindow call
is trying to locate a window that already exists. Unless your
application has created a window exactly identical to the one you are
creating, it won’t exist yet. Thus, the FindWindow call is completely
useless.

My code works perfectly when my application launch the WindowDebug appears …
but my Handle is still 0.

Then you must be looking in the wrong place. If the window was created,
then CreateWindowEx would have returned the handle.

Instead of snippets and cuts and pastes, why don’t you post the entire
source code you are using?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> to a window proc. You do not have any windows, because that’s not

allowed for a service.

Hidden windows are perfectly allowed, this is how DCOM works in services.

The API allows you to specify either a service
handle (which doesn’t apply to you) or a window handle.

NOTE: the SC-handle-based API had bugs with non-Unicode strings, I think it can only provide Unicode strings to clients.

Also: windows (i.e. HWNDs) are not only UI objects, but also classic Windows way to make a kind of “message target” bound to a particular thread.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

Just read the docs on functions involved carefully and check the calls parameter by parameter.

Yes, the handle from DllMain must be used everywhere you need a hInstance.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> I’ve found what you mean
> in the DllMain sample code there is a input parameter :inj_hModule = hModule;
> and this inj_hModule is used in the CreateWindowEx function .
>
> Ok I’m 18 but this make me crazy each time I found a code something bug.
> Now The windows appears but the Handle is impossible to get …
>

You said that the FindWindow is useless but I need prnt_hWnd for the CreateWindowEx just after.
In the code
1: I register the Window class
2: Find the window
3: create the window with the handle given by the findWindows.
Ok it is stupid to find before create, I don’t understand why but all the sample and example I’ve found do like this !!!

Here is the code I use in the dll :

FILE *fo;
void WriteToDebugFile( const char * const openStr, const char * const msg )
{
if( fo != NULL )
{
fprintf( fo, “%s\n”, msg );
fflush(fo);
}
}

#pragma region Windows_Interface
#define MYMENU_EXIT (WM_APP + 101)
#define MYMENU_MESSAGEBOX (WM_APP + 102)

HINSTANCE inj_hModule; //Injected Modules Handle
HWND prnt_hWnd; //Parent Window Handle

//WndProc for the new window
LRESULT CALLBACK DLLWindowProc (HWND, UINT, WPARAM, LPARAM);

//Register our windows Class
BOOL RegisterDLLWindowClass(wchar_t szClassName)
{
WNDCLASSEX wc;
wc.cbSize = sizeof (WNDCLASSEX);
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = DLLWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
wc.lpszMenuName = NULL;
wc.lpszClassName = “InjectedDLLWindowClass”;
wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
if (!RegisterClassEx (&wc))
return 0;
}
//Creating our windows Menu
HMENU CreateDLLWindowMenu()
{
HMENU hMenu;
hMenu = CreateMenu();
HMENU hMenuPopup;
if(hMenu==NULL)
return FALSE;
hMenuPopup = CreatePopupMenu();
AppendMenu (hMenuPopup, MF_STRING, MYMENU_EXIT, TEXT(“Exit”));
AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT(“File”));

hMenuPopup = CreatePopupMenu();
AppendMenu (hMenuPopup, MF_STRING,MYMENU_MESSAGEBOX, TEXT(“MessageBox”));
AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT(“Test”));
return hMenu;
}
HWND hwnd;

//The new thread
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
char buf[99] = “”;
MSG messages;
wchar_t *pString = reinterpret_cast<wchar_t> (lpParam);
HMENU hMenu = CreateDLLWindowMenu();
BOOL Register = RegisterDLLWindowClass(L"InjectedDLLWindowClass");
sprintf(buf,“Windows Class is registered : %s”, Register?“true”:“false”);
WriteToDebugFile( “a”, buf );

HWND hWnd;
prnt_hWnd = FindWindow
(
“InjectedDLLWindowClass”, // lpClassName
“WindowDebug” // lpWindowName
);

sprintf(buf, “Handle windows : %d”, prnt_hWnd);
WriteToDebugFile( “a”, buf );

hwnd = CreateWindowEx
(
0, // dwExStyle
“InjectedDLLWindowClass”, // lpClassName
“WindowDebug”, // lpWindowName
WS_EX_PALETTEWINDOW, // dwStyle
CW_USEDEFAULT, // x
CW_USEDEFAULT, // y
400, // nWidth
300, // nHeight
prnt_hWnd, // hWndParent
hMenu, // hMenu
NULL,//inj_hModule, // hInstance
NULL // lpParam
);
ShowWindow (hwnd, SW_SHOWNORMAL);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return 1;
}
//Our new windows proc
LRESULT CALLBACK DLLWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
switch(wParam)
{
case MYMENU_EXIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
case MYMENU_MESSAGEBOX:
MessageBox(hwnd, “Test”, “MessageBox”,MB_OK);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}

#pragma endregion Windows_Interface

void Startup()
{
fo = fopen( “DEBUG_USB.txt”, “w” );
CreateThread(0, NULL, ThreadProc, (LPVOID)L"WindowDebug", NULL, NULL);
}

void ExampleInternalsPlugin::Shutdown()
{
fclose( fo );
}

This code works I pick it in my project I’ve tested and
prnt_hWnd = 0
hwnd =0
in my debug file but the windows appears
If it possible to send an MP I can send you the project.

Thanks you</wchar_t>

xxxxx@gmail.com wrote:

You said that the FindWindow is useless but I need prnt_hWnd for the CreateWindowEx just after.
In the code
1: I register the Window class
2: Find the window
3: create the window with the handle given by the findWindows.
Ok it is stupid to find before create, I don’t understand why but all the sample and example I’ve found do like this !!!

Well, you NEED to understand why! You can’t do programming at random!

In the example, the FindWindow call is trying to find the main window
for the main program. It does that so the DLL window can be made a
child of that window. That way, when the main window closes, so does
the child. The result of the FindWindow is passed to CreateWindowEx as
the “parent window” parameter.

In your case, you don’t KNOW what the main window is. Therefore, your
hidden window won’t HAVE a parent. So, you don’t need “prnt_hWnd”.
You can just eliminate the FindWindow call (which always fails), and
pass NULL for the parent, which is exactly what FindWindow is returning
to you.

//Register our windows Class
BOOL RegisterDLLWindowClass(wchar_t szClassName)
{
WNDCLASSEX wc;
wc.cbSize = sizeof (WNDCLASSEX);
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = DLLWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
wc.lpszMenuName = NULL;
wc.lpszClassName = “InjectedDLLWindowClass”;
wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
if (!RegisterClassEx (&wc))
return 0;
}

If RegisterClassEx fails, you return 0. That’s fine. But if
RegisterClassEx succeeds, what do you return? Answer: nothing. You
should just replace the last two lines with

return RegisterClassEx(&wc);

//The new thread
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
char buf[99] = “”;
MSG messages;
wchar_t *pString = reinterpret_cast<wchar_t> (lpParam);
> HMENU hMenu = CreateDLLWindowMenu();
> BOOL Register = RegisterDLLWindowClass(L"InjectedDLLWindowClass");
> sprintf(buf,“Windows Class is registered : %s”, Register?“true”:“false”);
> WriteToDebugFile( “a”, buf );
>
> HWND hWnd;
> prnt_hWnd = FindWindow
> (
> “InjectedDLLWindowClass”, // lpClassName
> “WindowDebug” // lpWindowName
> );
>
> sprintf(buf, “Handle windows : %d”, prnt_hWnd);
> WriteToDebugFile( “a”, buf );
>
> hwnd = CreateWindowEx
> (
> 0, // dwExStyle
> “InjectedDLLWindowClass”, // lpClassName
> “WindowDebug”, // lpWindowName
> WS_EX_PALETTEWINDOW, // dwStyle
> CW_USEDEFAULT, // x
> CW_USEDEFAULT, // y
> 400, // nWidth
> 300, // nHeight
> prnt_hWnd, // hWndParent
> hMenu, // hMenu
> NULL,//inj_hModule, // hInstance
> NULL // lpParam
> );

You need to pass something valid for the hInstance parameter. hwnParent
can be NULL, since you don’t have a parent, but you need to have an
instance handle. If you don’t have your DLL’s instance, you get use
GetModuleHandle(NULL).

> This code works I pick it in my project I’ve tested and
> prnt_hWnd = 0
> hwnd =0
> in my debug file but the windows appears
> If it possible to send an MP I can send you the project.

I don’t believe you, because nowhere in this source do you print that
second line. So, either this is not the right code, or you are not
looking at the right debug output file. You can send me stuff by
private email to timr at probo dot com.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.</wchar_t>

I’ve send you my project , I’ve clean it before send it to you.
Of course you’re rigth , I apologize it works perfectly with your modification

CreateWindowEx Handle: 721962

Thanks you

my next step is to use this Handle with the RegisterDeviceNotification for my USB card.

Now is it time to sleep , tomorrow it is school …

Thanks you once again

Back again with my problem.
Now I’ve my windows handle I try to register my USB with the RegisterDeviceNotification function.
Everything seems to work correctly until I try to write to the device , I have an error like this “Can’t write to device”
Here is my code to initialize my USB
In the startup function I call : FindTheHID();

#pragma region USB_Interface

void DisplayLastError(const char * const openStr,const char * const Operation)
{
LPVOID lpMsgBuf=“”;

FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);

DWORD dw = GetLastError();

LPVOID StrError = (LPVOID)LocalAlloc(LMEM_ZEROINIT,(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)Operation) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)StrError,LocalSize(StrError) / sizeof(TCHAR),TEXT(“%4d %s %s”),dw,Operation, lpMsgBuf);

if( fo != NULL )
{
fprintf( fo, “%s”, StrError);
fflush(fo);
}

LocalFree(lpMsgBuf);
LocalFree(StrError);
}

//HWND m_hWnd;
ULONG Length;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData;
HANDLE DeviceHandle;
GUID HidGuid;
HANDLE hDevInfo;
ULONG Required;
bool MyDeviceDetected = FALSE;
std::string MyDevicePathName;
int VendorID = 0xFFFE;
int ProductID = 0x0001;
HIDP_CAPS Capabilities;
HANDLE WriteHandle;
HANDLE ReadHandle;
HANDLE hEventObject;
OVERLAPPED HIDOverlapped;
unsigned char OutputReport[255];

SERVICE_STATUS_HANDLE m_hServiceStatus;

void DoEvents()
{
MSG msg;
BOOL result;

while ( ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE ) )
{
result = ::GetMessage(&msg, NULL, 0, 0);
if (result == 0) // WM_QUIT
{
::PostQuitMessage(msg.wParam);
break;
}
else if (result == -1)
{
// Handle errors/exit application, etc.
}
else
{
::TranslateMessage(&msg);
:: DispatchMessage(&msg);
}
}
}

void RegisterForDeviceNotifications()
{
char Str[50];
// Request to receive messages when a device is attached or removed.
// Also see WM_DEVICECHANGE in BEGIN_MESSAGE_MAP(CUsbhidiocDlg, CDialog).

// m_hServiceStatus = RegisterServiceCtrlHandlerEx(“Service”, (LPHANDLER_FUNCTION_EX)_Handler,0);

DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface;
HDEVNOTIFY DeviceNotificationHandle;

ZeroMemory(&DevBroadcastDeviceInterface, sizeof(DevBroadcastDeviceInterface));

DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface);
sprintf(Str,“\tInterface Size: %d”,DevBroadcastDeviceInterface.dbcc_size);
WriteToDebugFile(“a+”,Str);

DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
sprintf(Str,“\tInterface type: %d”,DevBroadcastDeviceInterface.dbcc_devicetype);
WriteToDebugFile(“a+”,Str);

DevBroadcastDeviceInterface.dbcc_reserved = 0;

DevBroadcastDeviceInterface.dbcc_classguid = HidGuid;//GUID_DEVINTERFACE_USB_DEVICE;
sprintf(Str,“\tInterface HIDGUI: %8X-%4X-%4X-%4X”,DevBroadcastDeviceInterface.dbcc_classguid.Data1,DevBroadcastDeviceInterface.dbcc_classguid.Data2,DevBroadcastDeviceInterface.dbcc_classguid.Data3,DevBroadcastDeviceInterface.dbcc_classguid.Data4);
WriteToDebugFile(“a+”,Str);

// Wait until the fake windows is created
while (WindowsHandle == NULL)
{
sprintf(Str,“\tWait: %d”,WindowsHandle);
WriteToDebugFile(“a+”,Str);
DoEvents();
}

sprintf(Str,“\tGot it: %d”,WindowsHandle);
WriteToDebugFile(“a+”,Str);

DeviceNotificationHandle = RegisterDeviceNotification(WindowsHandle, &DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);//DEVICE_NOTIFY_SERVICE_HANDLE);
sprintf(Str,“\thandle: %d”,DeviceNotificationHandle);
WriteToDebugFile(“a+”,Str);
DisplayLastError( “a”,"RegisterDeviceNotification: ");

//HDEVNOTIFY hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);

}

void GetDeviceCapabilities()
{
//Get the Capabilities structure for the device.

PHIDP_PREPARSED_DATA PreparsedData;

/*
API function: HidD_GetPreparsedData
Returns: a pointer to a buffer containing the information about the device’s capabilities.
Requires: A handle returned by CreateFile.
There’s no need to access the buffer directly,
but HidP_GetCaps and other API functions require a pointer to the buffer.
*/

HidD_GetPreparsedData(DeviceHandle,&PreparsedData);

DisplayLastError( “a”,"HidD_GetPreparsedData: ");
char Str[50];

/*
API function: HidP_GetCaps
Learn the device’s capabilities.
For standard devices such as joysticks, you can find out the specific
capabilities of the device.
For a custom device, the software will probably know what the device is capable of,
and the call only verifies the information.
Requires: the pointer to the buffer returned by HidD_GetPreparsedData.
Returns: a Capabilities structure containing the information.
*/

HidP_GetCaps(PreparsedData,&Capabilities);

DisplayLastError( “a”,"HidP_GetCaps: ");

//Display the capabilities

sprintf(Str,“\tUsage Page: %X”,Capabilities.UsagePage);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tInput Report Byte Length: %d”, Capabilities.InputReportByteLength);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tOutput Report Byte Length: %d”, Capabilities.OutputReportByteLength);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tFeature Report Byte Length: %d”, Capabilities.FeatureReportByteLength);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Link Collection Nodes: %d”, Capabilities.NumberLinkCollectionNodes);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Input Button Caps: %d”, Capabilities.NumberInputButtonCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of InputValue Caps: %d”, Capabilities.NumberInputValueCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of InputData Indices: %d”, Capabilities.NumberInputDataIndices);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Output Button Caps: %d”, Capabilities.NumberOutputButtonCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Output Value Caps: %d”, Capabilities.NumberOutputValueCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Output Data Indices: %d”, Capabilities.NumberOutputDataIndices);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Feature Button Caps: %d”, Capabilities.NumberFeatureButtonCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Feature Value Caps: %d”, Capabilities.NumberFeatureValueCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Feature Data Indices: %d”, Capabilities.NumberFeatureDataIndices);
WriteToDebugFile(“a+”,Str);

//No need for PreparsedData any more, so free the memory it’s using.

HidD_FreePreparsedData(PreparsedData);
DisplayLastError( “a”,"HidD_FreePreparsedData: ") ;
}

void PrepareForOverlappedTransfer()
{
//Get a handle to the device for the overlapped ReadFiles.

ReadHandle=CreateFile
(detailData->DevicePath,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);

DisplayLastError( “a”,"CreateFile (ReadHandle): ");

//Get an event object for the overlapped structure.

/*API function: CreateEvent
Requires:
Security attributes or Null
Manual reset (true). Use ResetEvent to set the event object’s state to non-signaled.
Initial state (true = signaled)
Event object name (optional)
Returns: a handle to the event object
*/

if (hEventObject == 0)
{
hEventObject = CreateEvent
(NULL,
TRUE,
TRUE,
“”);
DisplayLastError( “a”,"CreateEvent: ") ;

//Set the members of the overlapped structure.

HIDOverlapped.hEvent = hEventObject;
HIDOverlapped.Offset = 0;
HIDOverlapped.OffsetHigh = 0;
}
}

bool FindTheHID()
{

//Use a series of API calls to find a HID with a specified Vendor IF and Product ID.

HIDD_ATTRIBUTES Attributes;
//DWORD DeviceUsage;
SP_DEVICE_INTERFACE_DATA devInfoData;
bool LastDevice = FALSE;
int MemberIndex = 0;
LONG Result;
std::string UsageDescription;

Length = 0;
detailData = NULL;
DeviceHandle=NULL;

/*
API function: HidD_GetHidGuid
Get the GUID for all system HIDs.
Returns: the GUID in HidGuid.
*/

HidD_GetHidGuid(&HidGuid);

/*
API function: SetupDiGetClassDevs
Returns: a handle to a device information set for all installed devices.
Requires: the GUID returned by GetHidGuid.
*/

hDevInfo=SetupDiGetClassDevs
(&HidGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);

devInfoData.cbSize = sizeof(devInfoData);

//Step through the available devices looking for the one we want.
//Quit on detecting the desired device or checking all available devices without success.

MemberIndex = 0;
LastDevice = FALSE;

do
{
/*
API function: SetupDiEnumDeviceInterfaces
On return, MyDeviceInterfaceData contains the handle to a
SP_DEVICE_INTERFACE_DATA structure for a detected device.
Requires:
The DeviceInfoSet returned in SetupDiGetClassDevs.
The HidGuid returned in GetHidGuid.
An index to specify a device.
*/

Result=SetupDiEnumDeviceInterfaces
(hDevInfo,
0,
&HidGuid,
MemberIndex,
&devInfoData);

if (Result != 0)
{
//A device has been detected, so get more information about it.

/*
API function: SetupDiGetDeviceInterfaceDetail
Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure
containing information about a device.
To retrieve the information, call this function twice.
The first time returns the size of the structure in Length.
The second time returns a pointer to the data in DeviceInfoSet.
Requires:
A DeviceInfoSet returned by SetupDiGetClassDevs
The SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces.

The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure.
This application doesn’t retrieve or use the structure.
If retrieving the structure, set
MyDeviceInfoData.cbSize = length of MyDeviceInfoData.
and pass the structure’s address.
*/

//Get the Length value.
//The call will return with a “buffer too small” error which can be ignored.

Result = SetupDiGetDeviceInterfaceDetail
(hDevInfo,
&devInfoData,
NULL,
0,
&Length,
NULL);

//Allocate memory for the hDevInfo structure, using the returned Length.

detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);

//Set cbSize in the detailData structure.

detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

//Call the function again, this time passing it the returned buffer size.

Result = SetupDiGetDeviceInterfaceDetail
(hDevInfo,
&devInfoData,
detailData,
Length,
&Required,
NULL);

// Open a handle to the device.
// To enable retrieving information about a system mouse or keyboard,
// don’t request Read or Write access for this handle.

/*
API function: CreateFile
Returns: a handle that enables reading and writing to the device.
Requires:
The DevicePath in the detailData structure
returned by SetupDiGetDeviceInterfaceDetail.
*/

DeviceHandle=CreateFile
(detailData->DevicePath,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);

DisplayLastError( “w”, “CreateFile: " );
char Str[50];
sprintf(Str,”\t Handle %d", DeviceHandle);
WriteToDebugFile(“a+”,Str);
//WriteToDebugFile(“a”,detailData->DevicePath);

/*
API function: HidD_GetAttributes
Requests information from the device.
Requires: the handle returned by CreateFile.
Returns: a HIDD_ATTRIBUTES structure containing
the Vendor ID, Product ID, and Product Version Number.
Use this information to decide if the detected device is
the one we’re looking for.
*/

//Set the Size to the number of bytes in the structure.

Attributes.Size = sizeof(Attributes);

Result = HidD_GetAttributes
(DeviceHandle,
&Attributes);

DisplayLastError( “a+”, “HidD_GetAttributes: “);
sprintf(Str,”\t Size %lu PID %4X VID %4X Version %4X”, Attributes.Size,Attributes.ProductID,Attributes.VendorID,Attributes.VersionNumber);
WriteToDebugFile(“a+”,Str);

//Is it the desired device?

MyDeviceDetected = FALSE;

if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
//Both the Vendor ID and Product ID match.

MyDeviceDetected = TRUE;
MyDevicePathName = detailData->DevicePath;
DisplayLastError( “a”, “Device detected”);

//Register to receive device notifications.

RegisterForDeviceNotifications();
DisplayLastError( “a”, “Register for notification”);

//Get the device’s capablities.

GetDeviceCapabilities();

// Get a handle for writing Output reports.
WriteHandle=CreateFile
(detailData->DevicePath,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);

DisplayLastError( “a”,"CreateFile: ");

// Prepare to read reports using Overlapped I/O.

PrepareForOverlappedTransfer();

} //if (Attributes.ProductID == ProductID)

else
//The Product ID doesn’t match.

CloseHandle(DeviceHandle);

} //if (Attributes.VendorID == VendorID)

else
//The Vendor ID doesn’t match.

CloseHandle(DeviceHandle);

//Free the memory used by the detailData structure (no longer needed).

free(detailData);

} //if (Result != 0)

else
//SetupDiEnumDeviceInterfaces returned 0, so there are no more devices to check.

LastDevice=TRUE;

//If we haven’t found the device yet, and haven’t tried every available device,
//try the next one.

MemberIndex = MemberIndex + 1;

} //do

while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE));

if (MyDeviceDetected == FALSE)
DisplayLastError( “a”,“Device not detected”);
else
DisplayLastError( “a”,“Device detected”);

//Free the memory reserved for hDevInfo by SetupDiClassDevs.

SetupDiDestroyDeviceInfoList(hDevInfo);
DisplayLastError( "a ",“SetupDiDestroyDeviceInfoList”);

return MyDeviceDetected;

}

void WriteToDevice()
{

DisplayLastError( “a”,“***HID Test Report***”);

//If the device hasn’t been detected already, look for it.
// Do nothing if the device isn’t detected.

if (MyDeviceDetected==TRUE)
{
WriteOutputReport();
//ReadInputReport();
}
}

void WriteOutputReport()
{
//Send a report to the device.

DWORD BytesWritten = 0;
INT Index =0;
ULONG Result;
std::string strBytesWritten = “”;

/*
HidD_SetOutputReport
Sends a report to the device.
Returns: success or failure.
Requires:
The device handle returned by CreateFile.
A buffer that holds the report.
The Output Report length returned by HidP_GetCaps,
*/

if (WriteHandle != INVALID_HANDLE_VALUE)
{
Result = HidD_SetOutputReport
(WriteHandle,
OutputReport,
Capabilities.OutputReportByteLength);

DisplayLastError( “a”,"HidD_SetOutputReport: ");
}

if (Result)
{
DisplayLastError( “a”,“An Output report was written to the device.”);
}
else
{
//The write attempt failed, so close the handles, display a message,
//and set MyDeviceDetected to FALSE so the next attempt will look for the device.

CloseHandles();
DisplayLastError( “a”,“Can’t write to device”);
MyDeviceDetected = FALSE;
}
}

void CloseHandles()
{
//Close open handles.

if (DeviceHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(DeviceHandle);
DisplayLastError( “a”,“Close Device Handle”);
}

if (ReadHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(ReadHandle);
DisplayLastError( “a”,“Close Read Handle”);
}

if (WriteHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(WriteHandle);
DisplayLastError( “a”,“Close Write Handle”);
}
}

#pragma endregion USB_Interface

and I try to send data with this
void Update()
{
OutputReport[0] = 0x00;
OutputReport[1] = 0x0c;
OutputReport[3] = 0x12;
OutputReport[2] = 0x34;
OutputReport[4] = 0x56;
OutputReport[5] = 0x78;

WriteOutputReport();
}
And In the WriteOutputReport I’ve this error .
I took this code from
http://janaxelson.com/files/usbhidio_vc6.zip
I try to reproduce the function to send once frame.
Thanks you