Device Notification - präziser darstellen anhand lParam und wParam



  • Hallo nochmal
    @Mox habe dein Vorschlag eingebaut und Fehler beseitigt. Also bekomme schonmal verschiedene Ausgaben. Danke für den Tipp!

    Habe nun folgende bibliothek "#include "hidsdi.h"" eingebunden.

    Nun bekomme ich auch keine Linker Fehler und ich bekomme interessante Ausgaben:
    Message 1: DBT_DEVNODES_CHANGED //Beim abstecken eines bereits angeschlossenen HID-Device
    Message 2: DBT_DEVICEREMOVECOMPLETE
    Message 3: DBT_DEVICEREMOVECOMPLETE

    Message 4: DBT_DEVNODES_CHANGED //Beim wieder anstecken
    Message 5: DBT_DEVNODES_CHANGED
    Message 6: DBT_DEVNODES_CHANGED
    Message 7: DBT_DEVNODES_CHANGED
    Message 8: DBT_DEVNODES_CHANGED
    Message 9: DBT_DEVNODES_CHANGED
    Message 10: DBT_DEVNODES_CHANGED
    Message 11: DBT_DEVICEARRIVAL
    Message 12: DBT_DEVNODES_CHANGED
    Message 13: DBT_DEVICEARRIVAL
    Message 14: DBT_DEVNODES_CHANGED

    Das ist schonmal gut!
    Aber mein Problem ist, will ich nun das geöffnete Fenster mit dem x rechts oben schließen, bekomm ich einen Windows(??)-fehler:

    UnregisterDeviceNotification  failed with error 1784: Der angegebene Benutzerpuffer ist für den angeforderten Vorgang nicht zulässig.
    

    Wo schau ich denn jetzt am besten nach dem Fehler für den Puffer?



  • pargus schrieb:

    Das ist schonmal gut!

    Na siehste. 😉

    pargus schrieb:

    Aber mein Problem ist, will ich nun das geöffnete Fenster mit dem x rechts oben schließen, bekomm ich einen Windows(??)-fehler:

    UnregisterDeviceNotification  failed with error 1784: Der angegebene Benutzerpuffer ist für den angeforderten Vorgang nicht zulässig.
    

    Wo schau ich denn jetzt am besten nach dem Fehler für den Puffer?

    Wie ich vorhin schon sagte, Du musst Dir den Rückgabewert von RegisterDeviceNotification merken. Also:

    h = RegisterDeviceNotification(..);
    .
    .
    .
    UnregisterDeviceNotification(h);
    


  • case WM_CLOSE:
    		if (!UnregisterDeviceNotification(RegisterDeviceNotification))
    		{
    			ErrorHandler(TEXT("UnregisterDeviceNotification"));
    		}
    		DestroyWindow(hWnd);
    		break;
    

    Hab ich ja gemacht kommt aber immer noch der Fehler beim Schließen des Fensters

    (Aber siehste so dumm bin ich auch net 😃 ;))

    Haste irgendwelche Ideen?
    oder auch zu oben?



  • Habe weiter geforscht und denke dass ich zumindest weiß wo der Fehler entsteht:

    void ErrorHandler(
    	LPTSTR lpszFunction
    	)
    	// Routine Description:
    	//     Support routine.
    	//     Retrieve the system error message for the last-error code
    	//     and pop a modal alert box with usable info.
    
    	// Parameters:
    	//     lpszFunction - String containing the function name where 
    	//     the error occurred plus any other relevant data you'd 
    	//     like to appear in the output. 
    
    	// Return Value:
    	//     None
    
    	// Note:
    	//     This routine is independent of the other windowing routines
    	//     in this application and can be used in a regular console
    	//     application without modification.
    {
    
    	LPVOID lpMsgBuf;
    	LPVOID lpDisplayBuf;
    	DWORD dw = GetLastError();
    
    	FormatMessage(
    		FORMAT_MESSAGE_ALLOCATE_BUFFER |
    		FORMAT_MESSAGE_FROM_SYSTEM |
    		FORMAT_MESSAGE_IGNORE_INSERTS,
    		NULL,
    		dw,
    		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    		(LPTSTR)&lpMsgBuf,
    		0, NULL);
    
    	// Display the error message and exit the process.
    
    	lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
    		(lstrlen((LPCTSTR)lpMsgBuf)
    		+ lstrlen((LPCTSTR)lpszFunction) + 40)
    		* sizeof(TCHAR));
    	StringCchPrintf((LPTSTR)lpDisplayBuf,
    		LocalSize(lpDisplayBuf) / sizeof(TCHAR),
    		TEXT("%s failed with error %d: %s"),
    		lpszFunction, dw, lpMsgBuf);
    	MessageBox(NULL, (LPCTSTR)lpDisplayBuf, g_pszAppName, MB_OK);
    
    	LocalFree(lpMsgBuf);
    	LocalFree(lpDisplayBuf);
    }
    

    irgendwie gibt er diesen Fehler aus. Ich denke (vllt stimmts auch nciht) dass in einen der drei folgenden Funktionen etwas nicht stimmt:
    -lpszFunction,
    -dw = GetLastError() und
    -lpMsgBuf

    Ich update ich sobald ich was neues hab. Bitte zu jedem Post wenn ihr Anmerkungen habt einfach reinschreiben 🙂



  • pargus schrieb:

    if (!UnregisterDeviceNotification(RegisterDeviceNotification))
    

    Hilfe! Du sollst hier keinen Funktionszeiger übergeben, sondern den Rückgabewert des vorherigen Aufrufs von RegisterDeviceNotification. Das, was Du da geschrieben hast, ist genau so ein Nonsens wie dieses hier:

    free(malloc));
    

    Ich hoffe, es brennt Dir jetzt ebenso in den Augen wie mir.



  • Mox schrieb:

    free(malloc));
    

    Ich hoffe, es brennt Dir jetzt ebenso in den Augen wie mir.

    ok leuchtet mir jetzt auch ein.

    Hab das jetzt mit nem HANDLE h; und h = RegisterDeviceNotification(..); und UnregisterDeviceNotification(h) wieder wegbekommen.

    Wie gesagt kenn mich mit den Bedeutungen von den Windows Funktionen auch nicht gut aus. (Wusste also nicht das RegisterDeviceNotification ein Funktionszeiger ist.)

    Darum bitte ich euch ja um Hilfe.

    Hast du auch noch vorschläge wie ich eventuell genauere Details über folgende Nachrichten bekommen kann (oder ist das nciht möglich?):

    Registered for USB device notification...
    Message 1: DBT_DEVNODES_CHANGED
    Message 2: DBT_DEVICEREMOVECOMPLETE
    Message 3: DBT_DEVICEREMOVECOMPLETE
    Message 4: DBT_DEVNODES_CHANGED
    Message 5: DBT_DEVNODES_CHANGED
    Message 6: DBT_DEVNODES_CHANGED
    Message 7: DBT_DEVNODES_CHANGED
    Message 8: DBT_DEVNODES_CHANGED
    Message 9: DBT_DEVNODES_CHANGED
    Message 10: DBT_DEVNODES_CHANGED
    Message 11: DBT_DEVICEARRIVAL
    Message 12: DBT_DEVNODES_CHANGED
    Message 13: DBT_DEVICEARRIVAL
    Message 14: DBT_DEVNODES_CHANGED
    


  • pargus schrieb:

    Hast du auch noch vorschläge wie ich eventuell genauere Details über folgende Nachrichten bekommen kann (oder ist das nciht möglich?):

    Die Details findest Du unter Device Management Events. Konzentriere Dich aber auf DBT_DEVICEARRIVAL und DBT_DEVICEREMOVECOMPLETE, das sind für Deine Anwendung die einzig interessanten Notifications. Den Rest darfst Du zunächst ruhigen Gewissens ignorieren.



  • pargus schrieb:

    Wie gesagt kenn mich mit den Bedeutungen von den Windows Funktionen auch nicht gut aus. (Wusste also nicht das RegisterDeviceNotification ein Funktionszeiger ist.)

    Was hast Du denn gedacht was das sonst ist? Ein Funktions-Aufruf kann es ja schließlich nicht sein, denn dafür hätte sich ja wohl mindestens noch eine Klammer öffnen müssen. Das passiert aber nicht, der Name der Funktion steht einfach nur da.

    Und das hat mit Windows nichts zu tun, Das sind C-Grundlagen.



  • Hallo nochmal

    ich bin noch bei dem selben Thema mit dem USB Port und den Notficiations aber schon bissal weiter.

    da ich ja folgende Ausgabe kriege:

    Nachrichten beim Abstecken

    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVICEREMOVECOMPLETE
    Message: DBT_DEVICEREMOVECOMPLETE
    Message: DBT_DEVNODES_CHANGED
    

    Nachrichten beim ANstecken

    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVICEARRIVAL
    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVICEARRIVAL
    Message: DBT_DEVNODES_CHANGED
    

    Dies kommt wenn ich meine Platine an oder abstecke, darum habe ich mit meinem Prof ausgemacht , wir kümmern uns nur um das erste "arrival" und das erste "removal" notification.

    Mein Problem ist nur wie kann ich das in dem unten stehenden code anbauen, dass er mir die erste Nachricht von Removal ausspuckt und die nächste drei ignoriert, aber trotzdem bei einem erneuten abstecken eines anderen GErätes wieder eine removal nachricht ausgibt und wieder die restlichen ignoriert.

    Code:

    //
    // WinProcCallback
    //
    INT_PTR WINAPI WinProcCallback(
                                  HWND hWnd,
                                  UINT message,
                                  WPARAM wParam,
                                  LPARAM lParam
                                  )
    // Routine Description:
    //     Simple Windows callback for handling messages.
    //     This is where all the work is done because the example
    //     is using a window to process messages. This logic would be handled 
    //     differently if registering a service instead of a window.
    
    // Parameters:
    //     hWnd - the window handle being registered for events.
    
    //     message - the message being interpreted.
    
    //     wParam and lParam - extended information provided to this
    //          callback by the message sender.
    
    //     For more information regarding these parameters and return value,
    //     see the documentation for WNDCLASSEX and CreateWindowEx.
    {
        LRESULT lRet = 1;
        static HDEVNOTIFY hDeviceNotify;
        static HWND hEditWnd;
        static ULONGLONG msgCount = 0;
    
        switch (message)
        {
        case WM_CREATE:
            //
            // This is the actual registration., In this example, registration 
            // should happen only once, at application startup when the window
            // is created.
            //
            // If you were using a service, you would put this in your main code 
            // path as part of your service initialization.
            //
            if ( ! DoRegisterDeviceInterfaceToHwnd(
                            WceusbshGUID, 
                            hWnd,
                            &hDeviceNotify) )
            {
                // Terminate on failure.
                ErrorHandler(TEXT("DoRegisterDeviceInterfaceToHwnd"));
                ExitProcess(1);
            }
    
            //
            // Make the child window for output.
            //
            hEditWnd = CreateWindow(TEXT("EDIT"),// predefined class 
                                    NULL,        // no window title 
                                    WS_CHILD | WS_VISIBLE | WS_VSCROLL | 
                                    ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL, 
                                    0, 0, 0, 0,  // set size in WM_SIZE message 
                                    hWnd,        // parent window 
                                    (HMENU)1,    // edit control ID 
                                    (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE), 
                                    NULL);       // pointer not needed 
    
            if ( hEditWnd == NULL )
            {
                // Terminate on failure.
                ErrorHandler(TEXT("CreateWindow: Edit Control"));
                ExitProcess(1);
            }
            // Add text to the window. 
            SendMessage(hEditWnd, WM_SETTEXT, 0, 
                (LPARAM)TEXT("Registered for USB device notification...\n")); 
    
            break;
    
        case WM_SETFOCUS: 
            SetFocus(hEditWnd); 
    
            break;
    
        case WM_SIZE: 
            // Make the edit control the size of the window's client area. 
            MoveWindow(hEditWnd, 
                       0, 0,                  // starting x- and y-coordinates 
                       LOWORD(lParam),        // width of client area 
                       HIWORD(lParam),        // height of client area 
                       TRUE);                 // repaint window 
    
            break;
    
        case WM_DEVICECHANGE:
        {
            //
            // This is the actual message from the interface via Windows messaging.
            // This code includes some additional decoding for this particular device type
            // and some common validation checks.
            //
            // Note that not all devices utilize these optional parameters in the same
            // way. Refer to the extended information for your particular device type 
            // specified by your GUID.
            //
            PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam;
            TCHAR strBuff[256];
    
            // Output some messages to the window.
            switch (wParam)
            {
            case DBT_DEVICEARRIVAL:
                msgCount++;
                StringCchPrintf(
                    strBuff, 256, 
                    TEXT("Message %d: DBT_DEVICEARRIVAL\n"), msgCount);
                break;
            case DBT_DEVICEREMOVECOMPLETE:
                msgCount++;
                StringCchPrintf(
                    strBuff, 256, 
                    TEXT("Message %d: DBT_DEVICEREMOVECOMPLETE\n"), msgCount);
                break;
            case DBT_DEVNODES_CHANGED:
                msgCount++;
                StringCchPrintf(
                    strBuff, 256, 
                    TEXT("Message %d: DBT_DEVNODES_CHANGED\n"), msgCount);
                break;
            default:
                msgCount++;
                StringCchPrintf(
                    strBuff, 256, 
                    TEXT("Message %d: WM_DEVICECHANGE message received, value %d unhandled.\n"), 
                    msgCount, wParam);
                break;
            }
            OutputMessage(hEditWnd, wParam, (LPARAM)strBuff);
        }
                break;
        case WM_CLOSE:
            if ( ! UnregisterDeviceNotification(hDeviceNotify) )
            {
               ErrorHandler(TEXT("UnregisterDeviceNotification")); 
            }
            DestroyWindow(hWnd);
            break;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
        default:
            // Send all other messages on to the default windows handler.
            lRet = DefWindowProc(hWnd, message, wParam, lParam);
            break;
        }
    
        return lRet;
    }
    

    Mittlerweile schauen meine Cases wie folgt aus

    case WM_DEVICECHANGE:
    	{
    		// declaration of the structures for later usage
    
    		// new structur for the output of every table item, to allocate memory for the structure and fill it with the function "hid_devchange"
    		HID_INFO_INTERN *hid_info3 = (HID_INFO_INTERN*)malloc(sizeof(HID_INFO_INTERN));
    		int i = 0;
    		//HID_INFO_INTERN *hid_info2;		// for test below
    		//HID_INFO_PUBLIC hid_public2;
    
    					//
    					// This is the actual message from the interface via Windows messaging.
    					// This code includes some additional decoding for this particular device type
    					// and some common validation checks.
    					//
    					// Note that not all devices utilize these optional parameters in the same
    					// way. Refer to the extended information for your particular device type 
    					// specified by your GUID.
    					//
    					PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
    					TCHAR strBuff[256];
    
    					// Output some messages to the window.
    					switch (wParam)
    					{	
    						// wParam = 0x8004
    						// lParam = A pointer to a structure identifying the device inserted. 
    						//		   The structure consists of an event-independent header, followed by 
    						//		   event-dependent members that describe the device. To use this structure, 
    						//		   treat the structure as a DEV_BROADCAST_HDR structure, then check its dbch_devicetype
    						//		   member to determine the device type.
    						case DBT_DEVICEARRIVAL:
    						{
    							msgCount++;
    							// Output message of Arrival-Notification
    							logprintf(L"Message: DBT_DEVICEARRIVAL\n");
    
    							// deallocate the allocated memory
    							free(hid_info3);
    						}
    						break;
    
    						// wParam = 0x8004
    						// lParam = A pointer to a structure identifying the device removed. 
    						//			The structure consists of an event-independent header, 
    						//			followed by event-dependent members that describe the device. 
    						//			To use this structure, treat the structure as a DEV_BROADCAST_HDR structure, 
    						//			then check its dbch_devicetype member to determine the device type. 
    						case DBT_DEVICEREMOVECOMPLETE:
    							msgCount++;
    								logprintf(L"Message: DBT_DEVICEREMOVECOMPLETE\r\n");
    
    								// deallocate the allocated memory
    								free(hid_info3);
    						break;
    
    						// wParam = 0x0007 
    						// lParam = Set to zero.
    						case DBT_DEVNODES_CHANGED:		//F12
    							msgCount++;
    							//hid_devchange(hid_info3, i);
    							logprintf(L"Message: DBT_DEVNODES_CHANGED\n");
    
    							// deallocate the allocated memory
    							free(hid_info3);
    						break;
    
    						default:
    							msgCount++;
    							loggprintf(L"WM_DEVICECHANGE message received, value %d unhandled.\n", wParam);
    						break;
    					}
    	}
    		break;
    

    Falls einer ne Idee hat wie ich nur in einmal in den Case reingehe und danach für dieses eine Abstecken nicht mehr (also die drei anderen "Removals" ignoriere) wäre ich sehr dankbar weil ich grad aufm Schlauch stehe.

    Danke Markus



  • pargus schrieb:

    Falls einer ne Idee hat wie ich nur in einmal in den Case reingehe und danach für dieses eine Abstecken nicht mehr (also die drei anderen "Removals" ignoriere) wäre ich sehr dankbar weil ich grad aufm Schlauch stehe.

    Welche drei anderen Removals? Du bekommst doch insgesamt nur zwei gesendet, ich zitiere:

    pargus schrieb:

    Message: DBT_DEVNODES_CHANGED
    Message: DBT_DEVICEREMOVECOMPLETE
    Message: DBT_DEVICEREMOVECOMPLETE
    Message: DBT_DEVNODES_CHANGED

    Ansonsten sollst Du gefälligst beide Removals bearbeiten. Oder woher weißt Du, welche der beiden Nachrichten für Dich interessant ist? Bislang schaust Du nicht nach, ob es überhaupt ein Removal für Dein Gerät ist. Du schaust Dir die Informationen gleich gar nicht an.

    Du wartest doch auf Ereignisse, die Device-Interfaces betreffen. Schau nach, ob Du per LPARAM Strukturen des Typs DBT_DEVTYP_DEVICEINTERFACE übermittelt bekommst. Dann schaust Du, ob es Dein Gerät betrifft. Und wenn Du dieses Gerät nicht oder nicht mehr geöffnet hast, machst Du eben auch nichts.

    Nur auf das erste Removal zu reagieren, geht definitiv in die Büx. Aber schön, dass Du zumindest mit Deinem Prof einig bist. Man, man...


Anmelden zum Antworten