summaryrefslogtreecommitdiffhomepage
path: root/src/ldso
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2017-01-28 05:15:30 +0000
committermidipix <writeonce@midipix.org>2017-01-28 00:26:01 -0500
commit77cbd46254c491fb56d863494b9102217f297252 (patch)
tree532a057079f66403057d49c6ed29519f4baf10b7 /src/ldso
parent7cd4117bbe6a97ca13ff81c2ff2a165268bdeb55 (diff)
downloadpemagine-77cbd46254c491fb56d863494b9102217f297252.tar.bz2
pemagine-77cbd46254c491fb56d863494b9102217f297252.tar.xz
ldso: added pe_find_framework_loader().
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/pe_find_framework_loader.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/ldso/pe_find_framework_loader.c b/src/ldso/pe_find_framework_loader.c
new file mode 100644
index 0000000..df18655
--- /dev/null
+++ b/src/ldso/pe_find_framework_loader.c
@@ -0,0 +1,271 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013--2017 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#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;
+
+ /* init */
+ 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;
+
+ /* flags */
+ 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 */
+ 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;
+
+ /* standalone executable? */
+ 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;
+
+ rtdata->hdsodir = hdsodir;
+ rtdata->hloader = hloader;
+ rtdata->himage = himage;
+
+ return OS_STATUS_SUCCESS;
+ }
+
+ /* root-relative loader path */
+ 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;
+
+ /* inherited root directory? */
+ 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;
+
+ rtdata->hdsodir = 0;
+ rtdata->hloader = hloader;
+ rtdata->himage = himage;
+
+ return OS_STATUS_SUCCESS;
+ }
+
+ /* integral only and no inherited root directory? */
+ if (flags == PE_LDSO_INTEGRAL_ONLY)
+ return OS_STATUS_COULD_NOT_INTERPRET;
+
+ /* finde Pluto / find Waldo */
+ 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 == (int32_t)OS_STATUS_OBJECT_NAME_NOT_FOUND)
+ (void)0;
+ else if (status == (int32_t)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);
+ }
+
+ rtdata->hdsodir = 0;
+ rtdata->hloader = hloader;
+ rtdata->himage = himage;
+ rtdata->hroot = hparent;
+
+ return OS_STATUS_SUCCESS;
+}