2014-11-05 21 views
10

Ho creato una semplice finestra Unicode, e ho premuto un tasto sulla tastiera per vedere quale sarebbe il valore di wParam per il messaggio WM_CHAR, e mi ha dato come previsto il codice Unicode per il carattere, ho premuto il tasto ' La chiave di S 'e il layout della mia tastiera erano impostati sull'arabo (quindi il carattere arabo è' س ').Spia ++ che mostra risultati errati?

Ora, ho anche catturato i messaggi della finestra in Spy ++, ma ho notato che mi ha dato un valore errato per wParam, in realtà mi ha dato il valore per il codice di carattere nella pagina di codice di Windows: arabo!

questo è uno screenshot dei risultati:

enter image description here

e questo è il codice sorgente:

#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

Mi chiedo se la seguente nota trovata nei documenti per 'TranslateMessage' sia rilevante qui:' "TranslateMessage produce messaggi WM_CHAR ** solo per le chiavi che sono mappate su caratteri ASCII dal driver della tastiera **." '(La mia enfasi) - su win7 con 'English (Australia) - US' lang e layout di tastiera USA, ottengo lo stesso valore visualizzato sia dal programma che dallo spy ++ (0x7A - 122) – enhzflep

+0

Il problema è con caratteri che non sono ASCII (per esempio arabo/ebraico/turco/ecc.), perché i caratteri ASCII hanno gli stessi valori di Unicode, quindi 0x7A ('z') in ASCII è lo stesso di Unicode (U + 007A), questo è il motivo per cui mostrano il lo stesso valore nel programma e in Spy ++ (ma se provi un personaggio arabo vedrai la differenza!). –

+1

Il problema che viene posto è perché l'app di Johnny sta ricevendo 0x633, ma Spy ++ sta invece ricevendo 0xD3. –

risposta

8

Come funziona Spy ++ è un po 'un segreto pubblico, si può facilmente dire quando si esegue sul file .exe. Per spyxx_amd64.exe (la versione a 64 bit), le voci più rilevanti sono:

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

In altre parole, esso utilizza SetWindowsHookEx() per impostare 3 ganci, WH_CALLWNDPROC, WH_CALLWNDPROCRET e WH_GETMESSAGE. Spyxxhk_amd64.dll è la DLL che viene iniettata in ogni processo, contiene i callback di hook.

Si noti che utilizza sia l'Unicode e la versione Ansi di SetWindowsHookEx(). Un modo in cui il risultato può essere facilmente spiegato è quando utilizza la versione Ansi (SetWindowsHookExA) sulla tua finestra Unicode. Un tale hook può solo osservare la versione Ansi del messaggio WM_CHAR.

Ricordare che Spy ++ ha un problema impossibile da risolvere quando si eseguono processi sul desktop che contengono sia finestre Unicode che Ansi, il che non è raro, non può renderli tutti felici. L'ipotesi più semplice è che punterà semplicemente SetWindowsHookExA come minimo comune denominatore.

In realtà dimostrando che Spy ++ ottiene questo errore è molto più difficile da fare e io ci ho messo un po 'di tempo. Qualsiasi tentativo di catturare Spy ++ durante l'installazione dei ganci durante il suo utilizzo si è rivelato un fallimento, i ganci sono stati installati molto presto all'avvio del programma. La tecnica di debug alla fine ho scoperto:

  • ho localizzato l'API entrypoint nativo NtUserSetWindowHookEx smontando il codice per SetWindowsHookExW. Sulla mia macchina (Win8.1) si trova a 0x00007FFECC3BA970.
  • Avviato VS elevato, necessario per avviare Spy ++.
  • File + Apri + Progetto/Soluzione e selezionare Spyxx_amd64.exe.
  • Debug + Step into. Ciò avvia il programma e individua il punto di esecuzione in AfxWinMain (Spy ++ è stato scritto con la libreria MFC).
  • Debug + Windows + Smontaggio, incollare 0x00007FFECC3BA970 nella casella dell'indirizzo
  • Impostare il punto di interruzione a questo indirizzo.Premere F5

Sono presenti due false hit, MFC utilizza SetWindowsHookExW() internamente. Ma poi si accende, tre colpi che sembrano tutti simili a questo:

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  

Quale è la prova, si può vedere SetWindowsHookExA() viene chiamato. La versione Ansi, Spy ++ può solo mostrare la versione Ansi del messaggio WM_CHAR.

0

Forse tabella codici araba impostato in modo predefinito in Impostazioni internazionali, e visualizza Spy ++ gli stessi valori che otterresti in un programma senza supporto Unicode? Solo una supposizione selvaggia però.

Problemi correlati