/* ObjectWindows base object destruction protocol. */ #include "tdkpin_object_lifecycle.h" enum { OBJECT_PARENT_OFFSET = 6, OBJECT_BOUND_THUNK_OFFSET = 0x12, OBJECT_TEARDOWN_SLOT = 0x24, DISPOSE_CHILD_CALLBACK_OFFSET = 0x03e9, }; static void write_far( Win16FarPtr object, uint16_t offset, Win16FarPtr value) { win16_write_u16(object, offset, win16_far_offset(value)); win16_write_u16( object, (uint16_t)(offset + 2), win16_far_selector(value)); } /* * 1018:0341 — construct the ObjectWindows base object and its bound thunk. * The object joins its parent's circular child ring before publishing its own * empty child tail and callback thunk. */ Win16FarPtr object_windows_object_construct( Win16FarPtr object, uint16_t vmt, Win16FarPtr parent) { BorlandObjectCallFrame frame = {object, vmt}; if (!borland_enter_object_constructor(&frame, 0)) { return frame.object; } frame.object = borland_default_object_constructor(frame.object, 0); win16_write_u16(frame.object, 2, 0); win16_write_u16(frame.object, 4, 0); win16_write_u16(frame.object, 0x17, 0); write_far(frame.object, OBJECT_PARENT_OFFSET, parent); if (parent == 0) { write_far(frame.object, 0x19, 0); } else { object_windows_append_child(parent, frame.object); } write_far(frame.object, 0x0a, 0); write_far(frame.object, 0x0e, 0); write_far( frame.object, OBJECT_BOUND_THUNK_OFFSET, object_windows_allocate_bound_thunk(frame.object)); win16_write_u8(win16_far_add_offset(frame.object, 0x16), 0); object_windows_set_flag_4(frame.object); return frame.object; } /* * 1018:03ff — destroy one ObjectWindows object. * Ordering is binary-significant: virtual teardown, child disposal, parent * unlink, bound-thunk release, root destruction, then owned-allocation free. */ void object_windows_object_destruct( Win16FarPtr object, uint16_t vmt) { uint16_t installed_vmt = win16_read_u16(object); Win16FarPtr teardown = win16_read_far_pointer( win16_dgroup_pointer(installed_vmt), OBJECT_TEARDOWN_SLOT); win16_call_object_method(teardown, object); object_windows_for_each_child( object, win16_relocated_code_pointer(4, DISPOSE_CHILD_CALLBACK_OFFSET)); Win16FarPtr parent = win16_read_far_pointer(object, OBJECT_PARENT_OFFSET); if (parent != 0) { object_windows_remove_child(parent, object); } object_windows_release_bound_thunk( win16_read_far_pointer(object, OBJECT_BOUND_THUNK_OFFSET)); borland_default_object_destructor(object, 0); BorlandObjectCallFrame frame = {object, vmt}; borland_finish_object_destructor(&frame, 0); }