|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
dd89bb |
/* Copyright (C) 2013,2014,2015 Z. Gilboa */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <pemagine/pemagine.h>
|
|
|
dd89bb |
#include <ntapi/nt_sysinfo.h>
|
|
|
dd89bb |
#include <ntapi/nt_memory.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include <ntapi/nt_atomic.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_system_directory_native_path(
|
|
|
dd89bb |
__out nt_mem_sec_name * buffer,
|
|
|
dd89bb |
__in uint32_t buffer_size,
|
|
|
dd89bb |
__in wchar16_t * base_name,
|
|
|
dd89bb |
__in uint32_t base_name_size,
|
|
|
dd89bb |
__out nt_unicode_string * nt_path __optional)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
wchar16_t * wch_src;
|
|
|
dd89bb |
wchar16_t * wch_dst;
|
|
|
dd89bb |
wchar16_t * wch_cap;
|
|
|
dd89bb |
size_t maxlen_saved;
|
|
|
dd89bb |
size_t info_size;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validation */
|
|
|
dd89bb |
if (!buffer || !buffer_size)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
else if (base_name && !base_name_size)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* init buffer */
|
|
|
dd89bb |
buffer->section_name.strlen = 0;
|
|
|
dd89bb |
buffer->section_name.maxlen = (uint16_t)(buffer_size - sizeof(nt_unicode_string));
|
|
|
dd89bb |
buffer->section_name.buffer = buffer->section_name_buffer;
|
|
|
dd89bb |
|
|
|
dd89bb |
maxlen_saved = buffer->section_name.maxlen;
|
|
|
dd89bb |
info_size = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_query_virtual_memory(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
pe_get_ntdll_module_handle(),
|
|
|
dd89bb |
NT_MEMORY_SECTION_NAME,
|
|
|
dd89bb |
buffer,
|
|
|
dd89bb |
buffer_size,
|
|
|
dd89bb |
&info_size);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* find directory portion */
|
|
|
dd89bb |
wch_dst = buffer->section_name.buffer + (buffer->section_name.strlen / sizeof(wchar16_t));
|
|
|
dd89bb |
wch_dst--;
|
|
|
dd89bb |
|
|
|
dd89bb |
while ((*wch_dst != '\\') && (wch_dst > buffer->section_name.buffer))
|
|
|
dd89bb |
wch_dst--;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (wch_dst == buffer->section_name.buffer)
|
|
|
dd89bb |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* base_name */
|
|
|
dd89bb |
if (base_name) {
|
|
|
dd89bb |
wch_dst++;
|
|
|
dd89bb |
wch_src = base_name;
|
|
|
dd89bb |
wch_cap = (wchar16_t *)((uintptr_t)wch_dst + base_name_size);
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((uintptr_t)wch_cap - (uintptr_t)(buffer->section_name.buffer) > maxlen_saved)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
while (wch_dst < wch_cap) {
|
|
|
dd89bb |
*wch_dst = *wch_src;
|
|
|
dd89bb |
wch_dst++;
|
|
|
dd89bb |
wch_src++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* null termination */
|
|
|
dd89bb |
*wch_dst = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* nt_path */
|
|
|
dd89bb |
if (nt_path)
|
|
|
dd89bb |
__ntapi->rtl_init_unicode_string(
|
|
|
dd89bb |
nt_path,
|
|
|
dd89bb |
buffer->section_name.buffer);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_system_directory_handle(
|
|
|
dd89bb |
__out void ** hsysdir,
|
|
|
dd89bb |
__out nt_mem_sec_name * buffer __optional,
|
|
|
dd89bb |
__in uint32_t buffer_size __optional)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_oa oa;
|
|
|
dd89bb |
nt_iosb iosb;
|
|
|
dd89bb |
nt_unicode_string path;
|
|
|
dd89bb |
char _buffer[256];
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validation */
|
|
|
dd89bb |
if (!hsysdir)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_1;
|
|
|
dd89bb |
else if (buffer_size && buffer_size < 0x20)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* buffer */
|
|
|
dd89bb |
if (!buffer) {
|
|
|
dd89bb |
buffer = (nt_mem_sec_name *)_buffer;
|
|
|
dd89bb |
buffer_size = sizeof(_buffer);
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(buffer,0,sizeof(buffer));
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* sysdir path */
|
|
|
dd89bb |
status = __ntapi_tt_get_system_directory_native_path(
|
|
|
dd89bb |
buffer,
|
|
|
dd89bb |
buffer_size,
|
|
|
dd89bb |
(wchar16_t *)0,
|
|
|
dd89bb |
0,
|
|
|
dd89bb |
&path);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* oa */
|
|
|
dd89bb |
oa.len = sizeof(nt_oa);
|
|
|
dd89bb |
oa.root_dir = (void *)0;
|
|
|
dd89bb |
oa.obj_name = &pat;;
|
|
|
dd89bb |
oa.obj_attr = 0;
|
|
|
dd89bb |
oa.sec_desc = 0;
|
|
|
dd89bb |
oa.sec_qos = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* open file/folder */
|
|
|
dd89bb |
status = __ntapi->zw_open_file(
|
|
|
dd89bb |
hsysdir,
|
|
|
dd89bb |
NT_SEC_SYNCHRONIZE | NT_FILE_READ_ATTRIBUTES | NT_FILE_READ_ACCESS,
|
|
|
dd89bb |
&oa,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE,
|
|
|
dd89bb |
NT_FILE_DIRECTORY_FILE | NT_FILE_SYNCHRONOUS_IO_ALERT);
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_system_directory_dos_path(
|
|
|
dd89bb |
__in void * hsysdir __optional,
|
|
|
dd89bb |
__out wchar16_t * buffer,
|
|
|
dd89bb |
__in uint32_t buffer_size,
|
|
|
dd89bb |
__in wchar16_t * base_name,
|
|
|
dd89bb |
__in uint32_t base_name_size,
|
|
|
dd89bb |
__out nt_unicode_string * nt_path __optional)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_statfs statfs;
|
|
|
dd89bb |
wchar16_t * wch;
|
|
|
dd89bb |
wchar16_t * wch_src;
|
|
|
dd89bb |
wchar16_t * wch_cap;
|
|
|
dd89bb |
nt_iosb iosb;
|
|
|
dd89bb |
nt_fni * fni;
|
|
|
dd89bb |
uint32_t fni_length;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validation */
|
|
|
dd89bb |
if (!buffer)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_2;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* hsysdir */
|
|
|
dd89bb |
if (!hsysdir) {
|
|
|
dd89bb |
status = __ntapi_tt_get_system_directory_handle(
|
|
|
dd89bb |
&hsysdir,
|
|
|
dd89bb |
(nt_mem_sec_name *)buffer,
|
|
|
dd89bb |
buffer_size);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* statfs */
|
|
|
dd89bb |
status = __ntapi->tt_statfs(
|
|
|
dd89bb |
hsysdir,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
(nt_unicode_string *)0,
|
|
|
dd89bb |
&statfs,
|
|
|
dd89bb |
(uintptr_t *)buffer,
|
|
|
dd89bb |
buffer_size,
|
|
|
dd89bb |
NT_STATFS_DOS_DRIVE_LETTER);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* dos path name (always shorter than the native path, so buffer_size must be ok) */
|
|
|
dd89bb |
wch = buffer;
|
|
|
dd89bb |
*wch = '\\'; wch++;
|
|
|
dd89bb |
*wch = '?'; wch++;
|
|
|
dd89bb |
*wch = '?'; wch++;
|
|
|
dd89bb |
*wch = '\\'; wch++;
|
|
|
dd89bb |
*wch = statfs.nt_drive_letter; wch++;
|
|
|
dd89bb |
*wch = ':'; wch++;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* alignment */
|
|
|
dd89bb |
fni = (nt_fni *)((uintptr_t)buffer + 0x10);
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_query_information_file(
|
|
|
dd89bb |
hsysdir,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
fni,
|
|
|
dd89bb |
buffer_size - 8 * sizeof(wchar16_t),
|
|
|
dd89bb |
NT_FILE_NAME_INFORMATION);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* fni->file_name_length: save */
|
|
|
dd89bb |
fni_length = fni->file_name_length;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* overwrite */
|
|
|
dd89bb |
wch_src = fni->file_name;
|
|
|
dd89bb |
wch_cap = (wchar16_t *)((uintptr_t)wch_src + fni_length);
|
|
|
dd89bb |
|
|
|
dd89bb |
while (wch_src < wch_cap) {
|
|
|
dd89bb |
*wch = *wch_src;
|
|
|
dd89bb |
wch++;
|
|
|
dd89bb |
wch_src++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* ultimate path separator */
|
|
|
dd89bb |
*wch = '\\'; wch++;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* base_name */
|
|
|
dd89bb |
if (base_name) {
|
|
|
dd89bb |
wch_src = base_name;
|
|
|
dd89bb |
wch_cap = (wchar16_t *)((uintptr_t)wch + base_name_size);
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((uintptr_t)wch_cap - (uintptr_t)buffer - sizeof(wchar16_t) > buffer_size)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
while (wch < wch_cap) {
|
|
|
dd89bb |
*wch = *wch_src;
|
|
|
dd89bb |
wch++;
|
|
|
dd89bb |
wch_src++;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* null termination */
|
|
|
dd89bb |
*wch = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* nt_path */
|
|
|
dd89bb |
if (nt_path)
|
|
|
dd89bb |
__ntapi->rtl_init_unicode_string(
|
|
|
dd89bb |
nt_path,
|
|
|
dd89bb |
buffer);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|