| |
| |
| |
| |
| |
| |
| #include <psxtypes/psxtypes.h> |
| #include <pemagine/pemagine.h> |
| #include "pe_os.h" |
| |
| int32_t pe_find_framework_loader( |
| struct pe_framework_runtime_data * rtdata, |
| const wchar16_t * basename, |
| const wchar16_t * rrelname, |
| void * refaddr, |
| uintptr_t * buffer, |
| uint32_t bufsize, |
| uint32_t flags) |
| { |
| int32_t status; |
| struct pe_unicode_str path; |
| struct os_oa oa; |
| struct os_iosb iosb; |
| void * himage; |
| void * himgdir; |
| void * hdsodir; |
| void * hloader; |
| void * hparent; |
| void * hprevious; |
| const wchar16_t * wch; |
| const wchar16_t * wch_cap; |
| void * hntdll; |
| os_zw_close * zw_close; |
| os_zw_open_file * zw_open_file; |
| |
| |
| if (!(hntdll = pe_get_ntdll_module_handle())) |
| return OS_STATUS_INTERNAL_ERROR; |
| |
| if (!(zw_close = (os_zw_close *)pe_get_procedure_address( |
| hntdll,"ZwClose"))) |
| return OS_STATUS_INTERNAL_ERROR; |
| |
| if (!(zw_open_file = (os_zw_open_file *)pe_get_procedure_address( |
| hntdll,"ZwOpenFile"))) |
| return OS_STATUS_INTERNAL_ERROR; |
| |
| |
| if (flags == PE_LDSO_INTEGRAL_ONLY) |
| (void)0; |
| else if (flags == PE_LDSO_DEFAULT_EXECUTABLE) |
| (void)0; |
| else if (flags == PE_LDSO_STANDALONE_EXECUTABLE) |
| (void)0; |
| else |
| return OS_STATUS_INVALID_PARAMETER; |
| |
| |
| oa.len = sizeof(struct os_oa); |
| oa.root_dir = 0; |
| oa.obj_name = &path; |
| oa.obj_attr = OS_OBJ_CASE_INSENSITIVE; |
| oa.sec_desc = 0; |
| oa.sec_qos = 0; |
| |
| |
| if (flags == PE_LDSO_STANDALONE_EXECUTABLE) { |
| wch = basename; |
| wch_cap = basename + 512; |
| |
| for (; *wch && wch<wch_cap; wch++) |
| if ((*wch == '\\') || (*wch == '/')) |
| return OS_STATUS_INVALID_PARAMETER; |
| |
| if (*wch) |
| return OS_STATUS_NAME_TOO_LONG; |
| |
| path.buffer = (wchar16_t *)basename; |
| path.strlen = sizeof(wchar16_t) * (wch - basename); |
| path.maxlen = 0; |
| |
| if ((status = pe_open_image_from_addr( |
| &himage,refaddr, |
| buffer,bufsize, |
| 0, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| 0))) |
| return status; |
| |
| if ((status = pe_open_physical_parent_directory( |
| &hdsodir,himage, |
| buffer,bufsize, |
| 0, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| 0))) |
| return status; |
| |
| oa.root_dir = hdsodir; |
| |
| if ((status = zw_open_file( |
| &hloader, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| &oa,&iosb, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| OS_FILE_NON_DIRECTORY_FILE))) |
| return status; |
| |
| if (rtdata->hloader) |
| zw_close(hloader); |
| else |
| rtdata->hloader = hloader; |
| |
| rtdata->hdsodir = hdsodir; |
| rtdata->himage = himage; |
| |
| return OS_STATUS_SUCCESS; |
| } |
| |
| |
| wch = rrelname; |
| wch_cap = rrelname + 512; |
| |
| for (; *wch && wch<wch_cap; ) |
| wch++; |
| |
| if (*wch) |
| return OS_STATUS_NAME_TOO_LONG; |
| |
| path.buffer = (wchar16_t *)rrelname; |
| path.strlen = sizeof(wchar16_t) * (wch - rrelname); |
| path.maxlen = 0; |
| |
| |
| if (rtdata->hroot) { |
| oa.root_dir = rtdata->hroot; |
| |
| if ((status = zw_open_file( |
| &hloader, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| &oa,&iosb, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| OS_FILE_NON_DIRECTORY_FILE))) |
| return status; |
| |
| if (rtdata->hloader) |
| zw_close(hloader); |
| else |
| rtdata->hloader = hloader; |
| |
| rtdata->hdsodir = 0; |
| |
| return OS_STATUS_SUCCESS; |
| } |
| |
| |
| if (flags == PE_LDSO_INTEGRAL_ONLY) |
| return OS_STATUS_COULD_NOT_INTERPRET; |
| |
| |
| if ((status = pe_open_image_from_addr( |
| &himage,refaddr, |
| buffer,bufsize, |
| 0, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| 0))) |
| return status; |
| |
| if ((status = pe_open_physical_parent_directory( |
| &himgdir,himage, |
| buffer,bufsize, |
| 0, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| 0))) |
| return status; |
| |
| if ((status = pe_open_physical_parent_directory( |
| &hparent,himgdir, |
| buffer,bufsize, |
| OS_OBJ_INHERIT, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| 0))) |
| return status; |
| |
| zw_close(himgdir); |
| |
| hloader = 0; |
| oa.root_dir = hparent; |
| |
| status = zw_open_file( |
| &hloader, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| &oa,&iosb, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| OS_FILE_NON_DIRECTORY_FILE); |
| |
| while (!hloader) { |
| if (status == OS_STATUS_OBJECT_NAME_NOT_FOUND) |
| (void)0; |
| else if (status == OS_STATUS_OBJECT_PATH_NOT_FOUND) |
| (void)0; |
| else |
| return status; |
| |
| hprevious = hparent; |
| |
| if ((status = pe_open_physical_parent_directory( |
| &hparent,hprevious, |
| buffer,bufsize, |
| OS_OBJ_INHERIT, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| 0))) |
| return status; |
| |
| oa.root_dir = hparent; |
| |
| status = zw_open_file( |
| &hloader, |
| OS_SEC_SYNCHRONIZE |
| | OS_FILE_READ_ACCESS |
| | OS_FILE_READ_ATTRIBUTES, |
| &oa,&iosb, |
| OS_FILE_SHARE_READ |
| | OS_FILE_SHARE_WRITE |
| | OS_FILE_SHARE_DELETE, |
| OS_FILE_NON_DIRECTORY_FILE); |
| |
| zw_close(hprevious); |
| } |
| |
| if (rtdata->hloader) |
| zw_close(hloader); |
| else |
| rtdata->hloader = hloader; |
| |
| rtdata->hdsodir = 0; |
| rtdata->himage = himage; |
| rtdata->hroot = hparent; |
| |
| return OS_STATUS_SUCCESS; |
| } |