[Programming] Ứng dụng chế Hook - Phần Ứng dụng chế Hook để xây dựng chương trình hỗ trợ gõ Tiếng Việt Hệ Điều Hành Windows 32 Bit - Phần I.Sự kiện thông điệp HĐH Windows I.1.Giới thiệu Ngày nay, Windows có lẽ khơng xa lạ với người sử dụng PC Nhắc đến Windows, người ta thường nghĩ Hệ Điều Hành (HĐH) dễ sử dụng, đó, tương tác người dùng với ứng dụng với thành phần tiện ích Windows thơng qua giao diện đồ họa (GUI), thao tác keyboard, mouse vô đơn giản Một câu hỏi đặt : “Các ứng dụng làm để phân loại, lưu giữ đáp lại tương tác cho người dùng ?” Đối với Windows vấn đề giải cách trọn vẹn : HĐH đưa chế thông điệp (message) với tập hợp cấu trúc liệu hàm API hỗ trợ ứng dụng việc giao tiếp với người dùng I.2.Hai loại hàng đợi thông điệp Windows Trước hết, ta cần phải biết làm HĐH Windows lưu trữ thông điệp Hai loại hàng đợi Windows phục vụ cho mục đích : + Hàng đợi hệ thống (The System Queue) + Hàng đợi thông điệp ứng dụng (Application Queue) Hàng đợi hệ thống (The System Queue) Windows có trình điều khiển thiết bị (Drivers) chịu trách nhiệm cho dịch vụ ngắt từ thiết bị phần cứng mouse keyboard Tại thời điểm ngắt phát sinh, Driver gọi điểm vào (hàm) đặc biệt USER.EXE để kiện vừa xảy Tất kiện mouse, keyboard lưu hàng đợi gọi hàng đợi hệ thống (The System Queue) Đây hàng đợi dùng chung cho toàn hệ thống , tiến trình chạy chia xẻ hàng đợi Nhiệm vụ độc ghi nhận lại kiện phần cứng (mouse actions, keystrokes) chúng xảy Hàng đợi thông điệp ứng dụng (Application Queue) Khi tiến trình khởi tạo, hàng đợi đại diện cho tạo ra, hàng đợi (đôi gọi hàng đợi tác vụ) dùng để chứa thông điệp gởi cho cửa sổ ứng dụng Những thông điệp thông điệp gởi cách tường minh hai hàm sau : + PostMessage + PostAppMessage (Lưu ý : Hàm PostQuitMessage không gởi thông điệp vào hàng đợi ứng dụng Ứng dụng dùng hai Primitive GetMessage PeekMessage doWindows cung cấp để khảo sát hàng đợi Hai hàm cho phép ứng dụng “Lấy message khỏi hàng đợi” để từ phân loại có “Trả lời” thích hợp với người dùng I.3.Bàn thêm GetMessage PeekMessage Bên HĐH Windows, GetMessage PeekMessage thi hành mã lệnh Điểm khác biệt hàm trường hợp khơng có message trả cho ứng dụng Trong trường hợp này, GetMessage đặt ứng dụng vào trạng thái “Sleep” PeekMessage trả ứng dụng giá trị NULL Ngay trước GetMessage PeekMessage trả message cho ứng dụng, hệ thống kiểm tra xem có tồn hook WH_GETMESSAGE hay khơng Nếu có “Filter Function” (thực chất hàm) ứng với hook cài đặt, hàm gọi “Filter Function” khơng gọi PeekMessage khơng tìm thấy message trả NULL PeekMessage với tùy chọn PM_NOREMOVE Theo mặc định, PeekMessage GetMessage lấy message khỏi hàng đợi message trả cho ứng dụng Tuy nhiên, có đơi lúc, ứng dụng muốn vào hàng đợi để kiểm tra tồn messsage mà không muốn gỡ bỏ Để làm điều này, chương trình ta gọi PeekMessage với tùy chọn PM_NOREMOVE, lúc PeekMessage trả message thường lệ không lấy khỏi hàng đợi.(Chi tiết GetMessage PeekMessage tham khảo Article “GetMessage and PeekMessage Internals” thư viện MSDN) II.Sự kiện bàn phím II.1.Mơ hình chung Mỗi phím bàn phím hệ thống gắn với giá trị gọi mã quét (Scan Code), giá trị phụ thuộc thiết bị, tức giá trị lệ thuộc vào loại bàn phím cụ thể Khi người dùng gõ phím, có mã qt sinh : phím nhấn phím thả Trình điều khiển bàn phím (Keyboard Device Driver) thơng dịch mã qt chuyển thành mã phím ảo (vitual-key code), giá trị độc lập thiết bị, định nghĩa hệ thống Sau đó, trình điều khiển tạo thơng điệp bao gồm scancode, virtual-key code số thông tin khác (sự lặp phím, trạng thái phím Alt, Ctrl ) , đặt vào hàng đợi hệ thống Hệ thống lấy thông điệp khỏi hàng đợi hệ thống gởi đến hàng đợi thơng điệp ứng dụng Cuối cùng, vịng lặp thông điệp (Message Loop) lấy thông điệp khỏi hàng đợi ứng dụng chuyển đến hàm xử lý message thích hợp để xử lý Q trình minh hoạ qua hình vẽ sau : Rõ ràng ta có cách để có message trước đến hàm xử lý thơng điệp cửa sổ, ta thực vài thao tác thú vị Và HĐH Windows, điều hồn tồn thực nhờ chế hook ta thấy phần sau II.2.Các thơng điệp liên quan bàn phím Khi ta nhấn phím, thơng điệp WM_KEYDOWN đặt vào hàng đợi tiểu trình ứng với cửa sổ focus Và ta nhả phím, hàng đợi có thơng điệp WM_KEYUP Hai thơng điệp thường xuất thành cặp Tuy nhiên, ta nhấn phím giữ phím đủ lâu làm đặc tính “Automatic Repeat” bàn phím hoạt động, hệ thống sinh nhiều thông điệp WM_KEYDOWN liên tiếp Và lưu ý điều nhả phím, có thơng điệp WM_KEYUP phát sinh mà thơi wParam thông điệp cho ta mã phím ảo (virtual-key code) phím nhấn lParam dùng 32 bit để mơ tả thơng tin thêm kiện gõ phím tạo message Thơng tin bao gồm : lặp phím, mã quét (scan code), trạn thái phím ALT, trạng thái phím trước, Sơ đồ 32 bit sau : Repeat Count : Hệ thống tăng đếm lên bàn phím phát sinh thơng điệp WM_KEYDOWN nhanh khả xử lý message ứng dụng Điều thường xảy người dùng giữ phím đủ lâu làm cho đặc tính “Automatic Repeat” bàn phím hoạt động Lúc này, thay đặt vào hàng đợi hệ thống nhiều thông điệp WM_KEYDOWN liên tiếp, hệ thống kết hợp message thành message tăng giá trị Repeat Count Tác vụ nhả phím khơng làm cho đặc tính “Automatic Repeat” kích hoạt, giá trị Repeat Count thơng điệp WM_KEYUP luôn Scan Code : Giá trị phụ thuộc thiết bị bàn phím phát sinh phím bị nhấn hay nhả Đây khơng phải mã ký tự đại diện cho phím nhấn Ứng dụng thường không quan tâm đến giá trị này, thay vậy, sử dụng giá trị độc lập thiết bị mã phím ảo (virtual-key code) để xử lý message Extended-Key Flag Bit cờ hiệu cho biết phím có phải phím mở rộng hay khơng Bit bật phím bị nhấn phím mở rộng : INS, DEL, HOME, END, Context Code Bit cờ hiệu cho biết thời điểm thông điệp phát sinh, phím ALT có bị nhấn hay khơng Bit bật phím ALT bị nhấn, tắt phím ALT nhả Previous Key-State Flag Bit cờ hiệu cho biết trạng thái phím trước gởi message “up” hay “down” Bit phím “down”, phím “up” Transition-State Flag Bit WM_KEYDOWN, WM_KEYUP.Thông điệp WM_KEYDOWN, WM_KEYUP cung cấp cho ta nhiều thông tin kiện gõ phím, nhiên, khơng cho ta mã ký tự phím nhấn Để có thông tin này, ứng dụng phải thêm hàm TranslateMessage vào vịng lặp thơng điệp mình.Hàm chuyển thơng điệp WM_KEYDOWN thành thông điệp WM_CHAR chứa mã ký tự ứng với phím gõ, sau kiểm tra trạng thái phím SHIFT CAPS LOCK II.3.Giả lập gõ phím Đơi muốn có kiện gõ phím mà khơng có tác động mặt vật lý bàn phím Hàm keybd_event giúp ta có khả này, chức giả lập thao tác bàn phím (nhấn hay nhả) Khai báo hàm sau : VOID keybd_event( BYTE bVk, // virtual-key code BYTE bScan, // hardware scan code DWORD dwFlags, // function options ULONG_PTR dwExtraInfo // additional keystroke data ); Ý nghĩa tham số : bVk : mã phím ảo phím cần giả lập bScan : tham số không dùng dwFlags : xác định loại thao tác cần giả lập, tham số giá trị sau : Giá trị Ý nghĩa KEYEVENTF_EXTENDEDKEYScan Code trước giá trị 224 KEYEVENTF_KEYUP Giả lập thao tác nhả phím dwExtraInfo : thơng tin thêm kiện ta giả lập III.Cơ chế Hook HĐH Windows III.1.Giới thiệu Trên HĐH Windows, hook chế mà nhờ hàm chặn kiện (message, mouse actions, keystrokes) trước chúng đến ứng dụng Hàm thực số thao tác kiện, vài trường hợp định nghĩa lại hủy bỏ kiện mà bắt Một đặc điểm quan trọng cần lưu ý hàm gọi thân HĐH Windows ứng dụng Các hàm thuộc loại vừa nêu thường gọi Filter Function, chúng phân loại theo loại kiện mà chúng can thiệp.Ví dụ, Filter Function hứng tất kiện mouse khác với Filter Function can thiệp kiện keyboard … Một Filter Funtion muốn Windows gọi trước tiên phải gắn với Windows Hook, công việc thường gọi “Cài đặt hook” Windows Hook thật loại hook khác HĐH định nghĩa, giúp người sử dụng cài đặt Filter Function với mục đích mà họ mong muốn Khi cài đặt hook, ta xác định loại hook thông qua số có dạng WH_XXX, ví dụ WH_KEYBOARD xác định loại hook dùng để can thiệp kiện thuộc bàn phím Một Windows Hook có nhiều Filter Function gắn với nó, tình này, Windows trì chuỗi Filter Function Hàm cài đặt gần đầu chuỗi, hàm cài đặt lâu cuối chuỗi Lúc này, có kiện xảy kiện tương ứng với loại hook ta cài đặt, Windows gọi hàm chuỗi Filter Function ứng với hook III.2.Khả ứng dụng chế Hook Hook cung cấp khả mạnh cho ứng dụng chạy Windows, ứng dụng dùng hook để : · Xử lý định nghĩa tất thông điệp cho dialog box, message box, scroll bar, menu ứng dụng (Sử dụng hook WH_MSGFILTER) · Xử lý định nghĩa tất thông điệp cho dialog box, message box, scroll bar, menu hệ thống (Sử dụng hook WH_SYSMSGFILTER) · Xử lý định nghĩa tất thông điệp (bất chấp thông điệp gì) hệ thống GetMessage PeekMessage gọi (Sử dụng hook WH_GETMESSAGE) · Xử lý định nghĩa tất thông điệp (bất chấp thơng điệp gì) hệ thống SendMessage gọi (Sử dụng hook WH_CALLWNDPROC) · Thu (Record) phát lại (Playback) kiện keyboard mouse (Sử dụng hook WH_JOURNALRECORD, WH_JOURNALPLAYBACK) · Xử lý , định nghĩa hủy bỏ tất kiện bàn phím.(Sử dụng hook WH_KEYBOARD) · Xử lý , định nghĩa hủy bỏ tất kiện chuột (Sử dụng hook WH_MOUSE) Tận dụng khả trên, ứng dụng sử dụng hook để : · Cung cấp phím trợ giúp F1 hỗ trợ menu, dialog box message box (Sử dụng hook WH_MSGFILTER) · Cung cấp tính thu phát kiện mouse keyboard, thường gọi macro (Sử dụng hook WH_JOURNALRECORD, WH_JOURNALPLAYBACK) · Theo dõi thông điệp để biết thông điệp gởi đến cửa sổ hành động làm phát sinh thông điệp tương ứng (Sử dụng hook WH_GETMESSAGE & WH_CALLWNDPROC) Chương trình Spy Win32™ SDK Windows NT thành công việc sử dụng hook để thực tác vụ · Giả lặp tác vụ input keyboard mouse (Sử dụng hook WH_JOURNALPLAYBACK) Chỉ có hook cho ta phương pháp chắn tin cậy để thực điều Nếu ta tiếp cận theo cách khác, gởi message chẳng hạn, Windows không cập nhật trạng thái mouse keyboard, điều dẫn đến hành động khơng mong muốn Cịn hook sử dụng, kiện xử lý y hệt kiện vật lý III.3.Quản lý chuỗi Filter Function Giao diện lập trình ứng dụng (API) Windows cung cấp hàm để thao tác với hook : · SetWindowsHookEx · UnhookWindowsHookEx · CallNextHookEx Cài đặt Filter Function vào chuỗi Filter Function hook Tác vụ thực thông qua hàm SetWindowsHookEx, khai báo hàm sau : HHOOK SetWindowsHookEx( int idHook, // hook type HOOKPROC lpfn, // hook procedure HINSTANCE hMod, // handle to application instance DWORD dwThreadId // thread identifier ); Ý nghĩa tham số : idHook : Xác định loại hook mà ta muốn cài đặt, tham số giá trị sau : · WH_CALLWNDPROC · WH_CALLWNDPROCRET · WH_CBT · WH_DEBUG · WH_FOREGROUNDIDLE · WH_GETMESSAGE · WH_JOURNALPLAYBACK · WH_JOURNALRECORD · WH_KEYBOARD · WH_MOUSE · WH_MSGFILTER · WH_SYSMSGFILTER Mỗi giá trị xác định loại hook mà ta muốn cài đặt, loại hook có ý nghĩa tình sử dụng khác nhau, chi tiết loại hook đề cập sau lpfn : Địa Filter Function mà ta muốn gắn với hook, hàm phải “export” macro thích hợp ta cài đặt hMod : Handle module chứa Filter Function Nếu ta cài đặt hook cục (nghĩa thực thi Filter Function ảnh hưởng tiến trình cài đặt hook), tham số phải NULL Cịn ta muốn có hook với phạm vi toàn hệ thống (tức tiến trình hữu chịu ảnh hưởng Filter Function ta), tham số Handle DLL chứa Filter Function dwThreadID : Định danh thread ứng với hook cài đặt Nếu tham số số khác 0, Filter Function gắn với hook gọi ngữ cảnh thread xác định Còn dwThreadID = 0, Filter Function có phạm vi tồn hệ thống, dĩ nhiên, gọi ngữ cảnh thread tồn HĐH Có thể sử dụng hàm GetCurrentThreadId để lấy handle thread muốn cài đặt hook Một hook sử dụng mức hệ thống, mức cục bộ, hai mức vừa nêu Bảng sau mơ tả loại hook tầm ảnh hưởng : WH_CALLWNDPROC Thread , global WH_CALLWNDPROCRET Thread , global WH_CBT Thread , global WH_DEBUG Thread , global WH_FOREGROUNDIDLE Thread , global WH_GETMESSAGE Thread , global WH_JOURNALPLAYBACKGlobal WH_JOURNALRECORD Global WH_KEYBOARD Thread , global WH_MOUSE Thread , global WH_MSGFILTER Thread , global WH_SYSMSGFILTER Global Với loại hook xác định, hook cục gọi trước, sau hook tồn cục SetWindowsHookEx trả handle hook cài đặt (là giá trị có kiểu HHOOK) Giá trị cần lưu lại để dùng hàm UnhookWindowsHookEx ta muốn gỡ bỏ hook Nó trả NULL gắn Filter Function vào hook, trường hợp này, gọi hàm GetLastError để biết lý cài đặt hook thất bại, giá trị mã lỗi giá trị sau : ERROR_INVALID_HOOK_FILTER : số xác định loại hook sai ERROR_INVALID_FILTER_PROC : địa Filter Function khơng xác ERROR_HOOK_NEEDS_HMOD : tham số hMod hàm SetWindowsHookEx NULL ứng dụng muốn cài đặt hook toàn cục ERROR_GLOBAL_ONLY_HOOK : Ứng dụng cố cài đặt hook cục chất loại hook hook toàn cục ERROR_INVALID_PARAMETER : giá trị tham số dwThreadID khơng xác ERROR_JOURNAL_HOOK_SET : Đã có hook loại “Journal” (WH_JOURNALPLAYBACK WH_JOURNALRECORD) hữu hệ thống Vì lý an toàn, Windows cho phép ta cài đặt hook loại “Journal” thời điểm ERROR_MOD_NOT_FOUND : Ứng dụng định vị handle DLL muốn cài đặt hook toàn cục Các giá trị khác : Vấn đề an toàn HĐH không cho phép hook cài đặt, hệ thống hết nhớ Tải FULL (18 trang): bit.ly/36dR03q Dự phòng: fb.com/TaiHo123doc.net Gỡ bỏ Filter Function khỏi chuỗi Filter Function hook Windows cung cấp hàm UnhookWindowsHookEx giúp ta thực việc này.Khai báo sau : BOOL UnhookWindowsHookEx( HHOOK hhk // handle to hook procedure ); Tham số hàm handle hook cần gỡ bỏ Giá trị giá trị trả từ hàm SetWindowsHookEx ta cài đặt hook Chi tiết Filter Function Đây thời điểm thích hợp để bàn Filter Function Nhắc lại Filter Function hàm gắn với loại hook mà ta muốn cài đặt Hàm gọi HĐH Windows không gọi ứng dụng, lý mà đơi người ta thường gọi “Callback Function” Tuy nhiên , để thống mặt thuật ngữ, từ sau ta gọi Filter Function Tất Filter Function có dạng sau : LRESULT CALLBACK FilterFunc(int nCode, WPARAM wParam, LPARAM lParam); Lưu ý : “FilterFunc” tên hàm tượng trưng, cài đặt, Filter Function có tên theo ý lập trình viên · Ý nghĩa tham số truyền cho hàm nCode : tham số thường gọi “hook code”, Filter Function sử dụng giá trị để định cách thức xử lý kiện (Lưu ý điều hồn tồn tuỳ thuộc vào lập trình viên Có thể hình dung hook code đem lại thơng tin đó, từ thơng tin này, lập trình viên định xử lý kiện bắt theo hướng riêng anh ta) Giá trị hook code tùy thuộc vào loại hook cụ thể, loại hook có tập hợp giá trị hook code đặc trưng riêng Có quy luật mà dường Filter Function loại hook cần tuân thủ : Khi Windows truyền cho hàm giá trị hook code âm, Filter Function không xử lý kiện mà phải gọi hàm CallNextHookEx với tham số mà HĐH truyền cho Sau đó, phải trả giá trị trả hàm CallNextHookEx wParam, lParam : Đây thông tin cần thiết cho Filter Function trình xử lý kiện Các giá trị có ý nghĩa khác tuỳ thuộc vào loại hook Ví dụ, Filter Function gắn với hook WH_KEYBOARD nhận mã phím ảo (Virtual-Key Code) từ wParam, đồng thời có từ lParam thơng tin mơ tả trạng thái bàn phím kiện gõ phím xảy 3136976 ... với hook III.2.Khả ứng dụng chế Hook Hook cung cấp khả mạnh cho ứng dụng chạy Windows, ứng dụng dùng hook để : · Xử lý định nghĩa tất thông điệp cho dialog box, message box, scroll bar, menu ứng. .. diện lập trình ứng dụng (API) Windows cung cấp hàm để thao tác với hook : · SetWindowsHookEx · UnhookWindowsHookEx · CallNextHookEx Cài đặt Filter Function vào chuỗi Filter Function hook Tác... kiện chuột (Sử dụng hook WH_MOUSE) Tận dụng khả trên, ứng dụng sử dụng hook để : · Cung cấp phím trợ giúp F1 hỗ trợ menu, dialog box message box (Sử dụng hook WH_MSGFILTER) · Cung cấp tính thu