/* Complete NE program entry sequence for TDKPIN.EXE. */ #include "tdkpin_program_entry.h" #include "tdkpin_application.h" #include "tdkpin_borland_runtime.h" #include "tdkpin_initialization.h" #include "tdkpin_multimedia.h" #include "tdkpin_stack.h" #include "tdkpin_tpwincrt_lifecycle.h" enum { DGROUP_APPLICATION_VMT = 0x0024, DGROUP_VERSION_ERROR_TEXT = 0x0396, DGROUP_APPLICATION_TITLE = 0x03c8, DGROUP_APPLICATION_NAME = 0x03e1, DGROUP_APPLICATION_OBJECT = 0x0748, APPLICATION_RUN_SLOT = 0x1c, APPLICATION_DESTRUCTOR_SLOT = 0x08, WIN16_MB_ICONHAND = 0x0010, }; static bool windows_version_is_supported(uint32_t version) { uint8_t major = (uint8_t)version; uint8_t minor = (uint8_t)(version >> 8); return major > 3 || (major == 3 && minor >= 10); } /* * 1000:fd85 -- process entry named by the NE header. InitTask supplies the * register contract consumed by 1020:0002. Unit initializers run in the exact * image order before the independent Windows 3.10 gate. The application Run * and destructor calls remain indirect through VMT +1c and +08 respectively. * Both the unsupported-version path and normal application return Halt(0). */ _Noreturn void tdkpin_ne_program_entry(void) { BorlandWin16StartupRegisters registers = InitTask16(); borland_initialize_win16_runtime(®isters); tdkpin_initialize_stack_guard(); tpwincrt_initialize_runtime_unit(); multimedia_initialize_runtime_unit(); tdkpin_initialize_unit_ordinal_91(); tdkpin_initialize_unit_ordinal_86(); tdkpin_initialize_unit_ordinal_72(); g_tdkpin_windows_version = GetVersion16(); if (!windows_version_is_supported(g_tdkpin_windows_version)) { (void)win16_call_message_box_far( g_win16_message_box, 0, win16_dgroup_pointer(DGROUP_VERSION_ERROR_TEXT), win16_dgroup_pointer(DGROUP_APPLICATION_TITLE), WIN16_MB_ICONHAND); } else { Win16FarPtr application = win16_dgroup_pointer(DGROUP_APPLICATION_OBJECT); (void)object_windows_application_construct( application, DGROUP_APPLICATION_VMT, win16_dgroup_pointer(DGROUP_APPLICATION_NAME)); uint16_t vmt_offset = win16_read_u16(application); Win16FarPtr vmt = win16_dgroup_pointer(vmt_offset); win16_call_object_method( win16_read_far_pointer(vmt, APPLICATION_RUN_SLOT), application); win16_call_object_destructor( win16_read_far_pointer(vmt, APPLICATION_DESTRUCTOR_SLOT), application, 0); } borland_runtime_exit(0); }