#include "../tdkpin_object_windows.h" #include Win16FarPtr g_object_windows_creating_object; uint16_t g_object_windows_thunk_code_selector; Win16FarPtr g_object_windows_free_thunk; Win16FarPtr g_object_windows_dispatch_proc; Win16FarPtr g_object_windows_message_hook; static Win16FarPtr g_expected_handler; static Win16FarPtr g_expected_object; static unsigned g_handler_calls; static unsigned g_hook_calls; static ObjectWindowsMessage g_hook_message; static Win16FarPtr g_event_pointer; void win16_call_object_message_handler( Win16FarPtr procedure, Win16FarPtr object, ObjectWindowsMessage *message) { assert(procedure == g_expected_handler); assert(object == g_expected_object); assert(message->window == 0x77); assert(message->wparam == 0x3344); assert(message->lparam == (LPARAM16)0x89abcdefu); message->result = (LRESULT16)0x12345678u; g_handler_calls++; } void win16_call_object_message_hook( Win16FarPtr procedure, Win16FarPtr object, Win16FarPtr handler, HWND16 window, UINT16 message, WPARAM16 wparam, LPARAM16 lparam) { assert(procedure == g_object_windows_message_hook); assert(object == g_expected_object && handler == g_expected_handler); g_hook_message = (ObjectWindowsMessage){ window, message, wparam, lparam, 0}; g_hook_calls++; } void win16_call_object_event_handler( Win16FarPtr procedure, Win16FarPtr object, Win16FarPtr event) { assert(procedure == g_expected_handler); assert(object == g_expected_object); g_event_pointer = event; } static void write_far(uint16_t offset, Win16FarPtr pointer) { win16_write_u16( win16_dgroup_pointer(offset), 0, win16_far_offset(pointer)); win16_write_u16( win16_dgroup_pointer((uint16_t)(offset + 2)), 0, win16_far_selector(pointer)); } int main(void) { static uint8_t dgroup[0x1000]; static uint8_t object_bytes[64]; static uint8_t event_bytes[32]; win16_reset_segment_bindings(); win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true); win16_set_dgroup_selector(0x5000); win16_bind_segment( 0x7000, object_bytes, sizeof(object_bytes), true); win16_bind_segment( 0x7100, event_bytes, sizeof(event_bytes), true); const uint16_t vmt = 0x0100; const uint16_t derived_table = 0x0200; const uint16_t parent_table = 0x0300; Win16FarPtr fallback = win16_make_far_pointer(0x6100, 0x1111); Win16FarPtr derived = win16_make_far_pointer(0x6200, 0x2222); Win16FarPtr parent = win16_make_far_pointer(0x6300, 0x3333); write_far((uint16_t)(vmt + 0x0c), fallback); win16_write_u16( win16_dgroup_pointer((uint16_t)(vmt + 4)), 0, derived_table); win16_write_u16(win16_dgroup_pointer(derived_table), 0, parent_table); win16_write_u16(win16_dgroup_pointer(derived_table + 2), 0, 0xffff); win16_write_u16(win16_dgroup_pointer(derived_table + 4), 0, 0xffff); win16_write_u16(win16_dgroup_pointer(derived_table + 6), 0, 1); win16_write_u16(win16_dgroup_pointer(derived_table + 8), 0, 0x0100); write_far((uint16_t)(derived_table + 10), derived); win16_write_u16(win16_dgroup_pointer(parent_table), 0, 0); win16_write_u16(win16_dgroup_pointer(parent_table + 2), 0, 0xffff); win16_write_u16(win16_dgroup_pointer(parent_table + 4), 0, 0xffff); win16_write_u16(win16_dgroup_pointer(parent_table + 6), 0, 1); win16_write_u16(win16_dgroup_pointer(parent_table + 8), 0, 0x0200); write_far((uint16_t)(parent_table + 10), parent); assert(object_windows_resolve_message_handler(vmt, 0x0100, 0x0c) == win16_dgroup_pointer(derived_table + 10)); assert(object_windows_resolve_message_handler(vmt, 0x0200, 0x0c) == win16_dgroup_pointer(parent_table + 10)); assert(win16_read_u16(win16_dgroup_pointer(derived_table + 2)) == 0x0200); assert(win16_read_u16(win16_dgroup_pointer(derived_table + 4)) == parent_table + 10); /* Cache lookup still works after the table contents become unusable. */ win16_write_u16(win16_dgroup_pointer(derived_table + 6), 0, 0xffff); assert(object_windows_resolve_message_handler(vmt, 0x0200, 0x0c) == win16_dgroup_pointer(parent_table + 10)); win16_write_u16(win16_dgroup_pointer(derived_table + 6), 0, 1); assert(object_windows_resolve_message_handler(vmt, 0x0999, 0x0c) == win16_dgroup_pointer(vmt + 0x0c)); Win16FarPtr object = win16_make_far_pointer(0x7000, 4); win16_write_u16(object, 0, vmt); g_expected_object = object; g_object_windows_message_hook = win16_make_far_pointer(0x6400, 0x4444); g_expected_handler = parent; g_handler_calls = 0; g_hook_calls = 0; LRESULT16 result = object_dispatch_window_or_dialog_proc( object, 0x77, 0x0200, 0x3344, (LPARAM16)0x89abcdefu); assert(result == (LRESULT16)0x12345678u); assert(win16_read_u16(win16_far_add_offset(object, 4)) == 0x77); assert(g_handler_calls == 1 && g_hook_calls == 1); assert(g_hook_message.message == 0x0200); assert(g_hook_message.lparam == (LPARAM16)0x89abcdefu); g_object_windows_message_hook = win16_make_far_pointer(0, 0x9999); g_expected_handler = fallback; g_hook_calls = 0; (void)object_dispatch_window_or_dialog_proc( object, 0x77, 0xffff, 0x3344, (LPARAM16)0x89abcdefu); assert(g_hook_calls == 0); Win16FarPtr event = win16_make_far_pointer(0x7100, 2); win16_write_u16(event, 0, 0x77); win16_write_u16(event, 2, 0x0100); win16_write_u16(event, 4, 0x3344); win16_write_u16(event, 6, 0xcdef); win16_write_u16(event, 8, 0x89ab); g_object_windows_message_hook = win16_make_far_pointer(0x6400, 0x4444); g_expected_handler = derived; g_hook_calls = 0; g_event_pointer = 0; object_windows_dispatch_event(0x0c, 0x0100, event, object); assert(g_event_pointer == event); assert(g_hook_calls == 1); assert(g_hook_message.window == 0x77); assert(g_hook_message.message == 0x0100); assert(g_hook_message.wparam == 0x3344); assert(g_hook_message.lparam == (LPARAM16)0x89abcdefu); return 0; }