2014-11-05 16 views
10

Ich habe ein einfaches Unicode-Fenster erstellt, und ich habe eine Taste auf der Tastatur gedrückt, um zu sehen, was der Wert von wParam für die WM_CHAR-Nachricht wäre, und es gab mir wie erwartet den Unicode-Code-Punkt für das Zeichen, drückte ich die ' S 'Taste und mein Tastaturlayout wurde auf Arabisch eingestellt (arabisches Zeichen ist' Ó ').Spion ++ zeigt falsche Ergebnisse an?

Jetzt habe ich auch die Fensternachrichten in Spy ++ erfasst, aber ich habe festgestellt, dass es mir einen falschen Wert für wParam gab, es gab mir tatsächlich den Wert für den Zeichencode in der Windows: Arabischen Codepage!

dies ist ein Screenshot der Ergebnisse:

enter image description here

und dies ist der Quellcode:

#define UNICODE 

#include <Windows.h> 
#include <stdio.h> 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch(message) 
    { 
    case WM_CLOSE: 
     DestroyWindow(hWnd); 
     break; 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    case WM_CHAR: 
     char str[256]; 
     sprintf(str, "0x%.4x", wParam); 
     MessageBoxA(NULL, str, "", 0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow) 
{ 
    WNDCLASSEX wc; 
    wc.cbSize = sizeof(WNDCLASSEX); 
    wc.style = 0; 
    wc.lpfnWndProc = WndProc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance = hInstance; 
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 
    wc.lpszMenuName = NULL; 
    wc.lpszClassName = L"WinClass"; 
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 
    RegisterClassEx(&wc); 

    HWND hWnd = CreateWindowEx(0, L"WinClass", L"My Title", WS_OVERLAPPEDWINDOW, 261, 172, 594, 384, NULL, NULL, hInstance, NULL); 
    ShowWindow(hWnd, nCmdShow); 
    UpdateWindow(hWnd); 

    MSG msg; 
    while(GetMessage(&msg, NULL, 0, 0) > 0) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return msg.wParam; 
} 
+0

Ich frage mich, ob der folgende in den Dokumenten für 'TranslateMessage 'gefundene Hinweis hier relevant ist:' "TranslateMessage erzeugt WM_CHAR-Nachrichten ** nur für Schlüssel, die vom Tastaturtreiber auf ASCII-Zeichen abgebildet werden **.") - auf win7 mit 'English (Australia) - US' lang und einem amerikanischen Tastaturlayout, bekomme ich den gleichen Wert, der sowohl vom Programm als auch von spy ++ angezeigt wird (0x7A - 122) – enhzflep

+0

Das Problem ist mit Zeichen außerhalb von ASCII (für Beispiel Arabisch/Hebräisch/Türkisch/etc.), weil die ASCII - Zeichen die gleichen Werte wie in Unicode haben, also ist 0x7A ('z') in ASCII die gleiche wie in Unicode (U + 007A), deshalb zeigen sie das gleicher Wert im Programm und in Spy ++ (aber wenn Sie ein arabisches Zeichen testen, sehen Sie den Unterschied!). –

+1

Das Problem, über das gefragt wird, ist, warum Johnnys App 0x633 empfängt, aber Spy ++ stattdessen 0xD3 empfängt. –

Antwort

8

Wie Spy ++ funktioniert ist ein bisschen ein öffentliches Geheimnis, können Sie leicht feststellen, wenn Sie Dumpbin.exe /imports auf die EXE-Datei ausführen. Für spyxx_amd64.exe (die 64-Bit-Version), die wichtigsten Einträge sind:

SPYXXHK_AMD64.DLL 
    ... 
         3 SpyxxCallWndRetProc 
         2 SpyxxCallWndProc 
         4 SpyxxGetMsgProc 
USER32.dll 
    ... 
        320 SetWindowsHookExW 
        31F SetWindowsHookExA 

Mit anderen Worten, es verwendet SetWindowsHookEx() 3 Haken zu setzen, WH_CALLWNDPROC, WH_CALLWNDPROCRET und WH_GETMESSAGE. Spyxxhk_amd64.dll ist die DLL, die in jeden Prozess injiziert wird, sie enthält die Hook-Callbacks.

Beachten Sie, dass es die die Unicode- und die Ansi-Version von SetWindowsHookEx() verwendet. Eine Möglichkeit, Ihr Ergebnis einfach zu erklären, ist, wenn es die Ansi-Version (SetWindowsHookExA) in Ihrem Unicode-Fenster verwendet. Ein solcher Hook kann nur die Ansi-Version der WM_CHAR-Nachricht beobachten. Denken Sie daran, dass Spy ++ ein unmögliches Problem zu lösen hat, wenn Sie Prozesse auf Ihrem Desktop ausführen, die sowohl Unicode- als auch Ansi-Fenster enthalten. Dies ist nicht ungewöhnlich, es kann nicht alle glücklich machen. Die einfachste Annahme ist, dass es für SetWindowsHookExA nur den kleinsten gemeinsamen Nenner darstellt.

Eigentlich Prüfung, dass Spy ++ das falsch macht ist viel schwieriger zu tun und ich putzte es für eine ganze Weile. Jeder Versuch, Spy ++ zu finden, indem man die Hooks installiert, während man sie benutzt, ist ein Fehler, die Hooks werden sehr früh beim Programmstart installiert. Die Debugging-Technik, die ich schließlich entdeckt:

  • ich zum ersten Mal die native api Einstiegspunkt befindet NtUserSetWindowHookEx durch den Code für SetWindowsHookExW zerlegen. Auf meinem Rechner (Win8.1) befindet es sich unter 0x00007FFECC3BA970.
  • Gestartet VS erhöht, erforderlich, um Spy ++ zu starten.
  • Datei + Öffnen + Projekt/Lösung und wählen Sie Spyxx_amd64.exe.
  • Debug + Schritt In. Dies startet das Programm und lokalisiert den Ausführungspunkt bei AfxWinMain (Spy ++ wurde mit der MFC-Bibliothek geschrieben).
  • Debug + Windows + Disassembly, fügen Sie 0x00007FFECC3BA970 in das Adressfeld ein
  • Legen Sie den Haltepunkt an dieser Adresse fest.Drücken Sie F5

Es gibt zwei falsche Treffer, MFC verwendet SetWindowsHookExW() intern. Aber dann leuchtet sie, drei Treffer, die alle ähnlich aussehen:

user32.dll!NtUserSetWindowsHookEx()  
user32.dll!_SetWindowsHookEx() + 0x5b bytes  
user32.dll!SetWindowsHookExAW() + 0x5b bytes 
user32.dll!SetWindowsHookExA() + 0x11 bytes  
spyxx_amd64.exe!SetMsgHook() + 0x6a bytes 
spyxx_amd64.exe!HookMain() + 0x470 bytes 
msvcr120.dll!_callthreadstart() Line 257 C 
msvcr120.dll!_threadstart(void * ptd) Line 237 + 0x5 bytes C 
kernel32.dll!BaseThreadInitThunk() + 0xd bytes 
ntdll.dll!RtlUserThreadStart() + 0x34 bytes  

Welche Beweis ist, können Sie SetWindowsHookExA sehen() aufgerufen wird. Die Ansi-Version, Spy ++ kann immer nur die Ansi-Version der WM_CHAR-Nachricht anzeigen.

0

Vielleicht haben Sie arabische Codepage als Standard in den Ländereinstellungen festgelegt haben, und Spy ++ zeigt die gleichen Werte wie in einem Programm ohne Unicode-Unterstützung? Nur eine wilde Vermutung.