|
|
77cbd4 |
/*****************************************************************************/
|
|
|
77cbd4 |
/* pemagination: a (virtual) tour into portable bits and executable bytes */
|
|
|
6dda52 |
/* Copyright (C) 2013--2020 SysDeer Technologies, LLC */
|
|
|
77cbd4 |
/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
|
|
|
77cbd4 |
/*****************************************************************************/
|
|
|
77cbd4 |
|
|
|
77cbd4 |
#include <psxtypes/psxtypes.h>
|
|
|
77cbd4 |
#include <pemagine/pemagine.h>
|
|
|
77cbd4 |
#include "pe_os.h"
|
|
|
77cbd4 |
|
|
|
77cbd4 |
int32_t pe_find_framework_loader(
|
|
|
77cbd4 |
struct pe_framework_runtime_data * rtdata,
|
|
|
77cbd4 |
const wchar16_t * basename,
|
|
|
77cbd4 |
const wchar16_t * rrelname,
|
|
|
77cbd4 |
void * refaddr,
|
|
|
77cbd4 |
uintptr_t * buffer,
|
|
|
77cbd4 |
uint32_t bufsize,
|
|
|
77cbd4 |
uint32_t flags)
|
|
|
77cbd4 |
{
|
|
|
77cbd4 |
int32_t status;
|
|
|
77cbd4 |
struct pe_unicode_str path;
|
|
|
77cbd4 |
struct os_oa oa;
|
|
|
77cbd4 |
struct os_iosb iosb;
|
|
|
77cbd4 |
void * himage;
|
|
|
77cbd4 |
void * himgdir;
|
|
|
77cbd4 |
void * hdsodir;
|
|
|
77cbd4 |
void * hloader;
|
|
|
77cbd4 |
void * hparent;
|
|
|
77cbd4 |
void * hprevious;
|
|
|
77cbd4 |
const wchar16_t * wch;
|
|
|
77cbd4 |
const wchar16_t * wch_cap;
|
|
|
77cbd4 |
void * hntdll;
|
|
|
77cbd4 |
os_zw_close * zw_close;
|
|
|
77cbd4 |
os_zw_open_file * zw_open_file;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* init */
|
|
|
77cbd4 |
if (!(hntdll = pe_get_ntdll_module_handle()))
|
|
|
77cbd4 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if (!(zw_close = (os_zw_close *)pe_get_procedure_address(
|
|
|
77cbd4 |
hntdll,"ZwClose")))
|
|
|
77cbd4 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if (!(zw_open_file = (os_zw_open_file *)pe_get_procedure_address(
|
|
|
77cbd4 |
hntdll,"ZwOpenFile")))
|
|
|
77cbd4 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* flags */
|
|
|
77cbd4 |
if (flags == PE_LDSO_INTEGRAL_ONLY)
|
|
|
77cbd4 |
(void)0;
|
|
|
77cbd4 |
else if (flags == PE_LDSO_DEFAULT_EXECUTABLE)
|
|
|
77cbd4 |
(void)0;
|
|
|
77cbd4 |
else if (flags == PE_LDSO_STANDALONE_EXECUTABLE)
|
|
|
77cbd4 |
(void)0;
|
|
|
77cbd4 |
else
|
|
|
77cbd4 |
return OS_STATUS_INVALID_PARAMETER;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* oa */
|
|
|
77cbd4 |
oa.len = sizeof(struct os_oa);
|
|
|
77cbd4 |
oa.root_dir = 0;
|
|
|
77cbd4 |
oa.obj_name = &pat;;
|
|
|
77cbd4 |
oa.obj_attr = OS_OBJ_CASE_INSENSITIVE;
|
|
|
77cbd4 |
oa.sec_desc = 0;
|
|
|
77cbd4 |
oa.sec_qos = 0;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* standalone executable? */
|
|
|
77cbd4 |
if (flags == PE_LDSO_STANDALONE_EXECUTABLE) {
|
|
|
77cbd4 |
wch = basename;
|
|
|
77cbd4 |
wch_cap = basename + 512;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
for (; *wch && wch
|
|
|
49f412 |
if ((*wch == '\\') || (*wch == '/'))
|
|
|
77cbd4 |
return OS_STATUS_INVALID_PARAMETER;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if (*wch)
|
|
|
77cbd4 |
return OS_STATUS_NAME_TOO_LONG;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
path.buffer = (wchar16_t *)basename;
|
|
|
77cbd4 |
path.strlen = sizeof(wchar16_t) * (wch - basename);
|
|
|
77cbd4 |
path.maxlen = 0;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = pe_open_image_from_addr(
|
|
|
77cbd4 |
&himage,refaddr,
|
|
|
77cbd4 |
buffer,bufsize,
|
|
|
77cbd4 |
0,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
0)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = pe_open_physical_parent_directory(
|
|
|
77cbd4 |
&hdsodir,himage,
|
|
|
77cbd4 |
buffer,bufsize,
|
|
|
77cbd4 |
0,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
0)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
oa.root_dir = hdsodir;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = zw_open_file(
|
|
|
77cbd4 |
&hloader,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
&oa,&iosb,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
OS_FILE_NON_DIRECTORY_FILE)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
80fd71 |
if (rtdata->hloader)
|
|
|
80fd71 |
zw_close(hloader);
|
|
|
80fd71 |
else
|
|
|
80fd71 |
rtdata->hloader = hloader;
|
|
|
80fd71 |
|
|
|
77cbd4 |
rtdata->hdsodir = hdsodir;
|
|
|
77cbd4 |
rtdata->himage = himage;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
return OS_STATUS_SUCCESS;
|
|
|
77cbd4 |
}
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* root-relative loader path */
|
|
|
77cbd4 |
wch = rrelname;
|
|
|
77cbd4 |
wch_cap = rrelname + 512;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
for (; *wch && wch
|
|
|
77cbd4 |
wch++;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if (*wch)
|
|
|
77cbd4 |
return OS_STATUS_NAME_TOO_LONG;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
path.buffer = (wchar16_t *)rrelname;
|
|
|
77cbd4 |
path.strlen = sizeof(wchar16_t) * (wch - rrelname);
|
|
|
77cbd4 |
path.maxlen = 0;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* inherited root directory? */
|
|
|
77cbd4 |
if (rtdata->hroot) {
|
|
|
77cbd4 |
oa.root_dir = rtdata->hroot;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = zw_open_file(
|
|
|
77cbd4 |
&hloader,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
&oa,&iosb,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
OS_FILE_NON_DIRECTORY_FILE)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
80fd71 |
if (rtdata->hloader)
|
|
|
80fd71 |
zw_close(hloader);
|
|
|
80fd71 |
else
|
|
|
80fd71 |
rtdata->hloader = hloader;
|
|
|
80fd71 |
|
|
|
77cbd4 |
rtdata->hdsodir = 0;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
return OS_STATUS_SUCCESS;
|
|
|
77cbd4 |
}
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* integral only and no inherited root directory? */
|
|
|
77cbd4 |
if (flags == PE_LDSO_INTEGRAL_ONLY)
|
|
|
77cbd4 |
return OS_STATUS_COULD_NOT_INTERPRET;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
/* finde Pluto / find Waldo */
|
|
|
77cbd4 |
if ((status = pe_open_image_from_addr(
|
|
|
77cbd4 |
&himage,refaddr,
|
|
|
77cbd4 |
buffer,bufsize,
|
|
|
77cbd4 |
0,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
0)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = pe_open_physical_parent_directory(
|
|
|
77cbd4 |
&himgdir,himage,
|
|
|
77cbd4 |
buffer,bufsize,
|
|
|
77cbd4 |
0,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
0)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = pe_open_physical_parent_directory(
|
|
|
77cbd4 |
&hparent,himgdir,
|
|
|
77cbd4 |
buffer,bufsize,
|
|
|
77cbd4 |
OS_OBJ_INHERIT,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
0)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
zw_close(himgdir);
|
|
|
77cbd4 |
|
|
|
77cbd4 |
hloader = 0;
|
|
|
77cbd4 |
oa.root_dir = hparent;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
status = zw_open_file(
|
|
|
77cbd4 |
&hloader,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
&oa,&iosb,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
OS_FILE_NON_DIRECTORY_FILE);
|
|
|
77cbd4 |
|
|
|
77cbd4 |
while (!hloader) {
|
|
|
a29a7a |
if (status == OS_STATUS_OBJECT_NAME_NOT_FOUND)
|
|
|
77cbd4 |
(void)0;
|
|
|
a29a7a |
else if (status == OS_STATUS_OBJECT_PATH_NOT_FOUND)
|
|
|
77cbd4 |
(void)0;
|
|
|
77cbd4 |
else
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
hprevious = hparent;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
if ((status = pe_open_physical_parent_directory(
|
|
|
77cbd4 |
&hparent,hprevious,
|
|
|
77cbd4 |
buffer,bufsize,
|
|
|
77cbd4 |
OS_OBJ_INHERIT,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
0)))
|
|
|
77cbd4 |
return status;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
oa.root_dir = hparent;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
status = zw_open_file(
|
|
|
77cbd4 |
&hloader,
|
|
|
77cbd4 |
OS_SEC_SYNCHRONIZE
|
|
|
77cbd4 |
| OS_FILE_READ_ACCESS
|
|
|
77cbd4 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
77cbd4 |
&oa,&iosb,
|
|
|
77cbd4 |
OS_FILE_SHARE_READ
|
|
|
77cbd4 |
| OS_FILE_SHARE_WRITE
|
|
|
77cbd4 |
| OS_FILE_SHARE_DELETE,
|
|
|
77cbd4 |
OS_FILE_NON_DIRECTORY_FILE);
|
|
|
77cbd4 |
|
|
|
77cbd4 |
zw_close(hprevious);
|
|
|
77cbd4 |
}
|
|
|
77cbd4 |
|
|
|
80fd71 |
if (rtdata->hloader)
|
|
|
80fd71 |
zw_close(hloader);
|
|
|
80fd71 |
else
|
|
|
80fd71 |
rtdata->hloader = hloader;
|
|
|
80fd71 |
|
|
|
77cbd4 |
rtdata->hdsodir = 0;
|
|
|
77cbd4 |
rtdata->himage = himage;
|
|
|
77cbd4 |
rtdata->hroot = hparent;
|
|
|
77cbd4 |
|
|
|
77cbd4 |
return OS_STATUS_SUCCESS;
|
|
|
77cbd4 |
}
|