|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
4256e2 |
/* Copyright (C) 2013--2016 Z. Gilboa */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <ntapi/nt_object.h>
|
|
|
dd89bb |
#include <ntapi/nt_file.h>
|
|
|
dd89bb |
#include <ntapi/nt_mount.h>
|
|
|
dd89bb |
#include <ntapi/nt_atomic.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
typedef enum __dos_drive_handle_type {
|
|
|
dd89bb |
__DOS_DRIVE_DEVICE_HANDLE,
|
|
|
dd89bb |
__DOS_DRIVE_ROOT_HANDLE
|
|
|
dd89bb |
} _dos_drive_handle_type;
|
|
|
dd89bb |
|
|
|
dd89bb |
typedef struct __dos_name_buffer {
|
|
|
dd89bb |
wchar16_t global_prefix[4];
|
|
|
dd89bb |
wchar16_t dos_letter;
|
|
|
dd89bb |
wchar16_t colon;
|
|
|
dd89bb |
wchar16_t root;
|
|
|
dd89bb |
wchar16_t null_termination;
|
|
|
dd89bb |
} _dos_name_buffer;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __stdcall __tt_connect_to_mount_point_manager(void)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
|
|
|
dd89bb |
void * hdev;
|
|
|
dd89bb |
void * hdev_prev;
|
|
|
dd89bb |
nt_oa oa;
|
|
|
dd89bb |
nt_iosb iosb;
|
|
|
dd89bb |
nt_unicode_string dev_name;
|
|
|
dd89bb |
uint16_t dev_name_buffer[] = {
|
|
|
dd89bb |
'\\','?','?','\\',
|
|
|
dd89bb |
'M','o','u','n','t',
|
|
|
dd89bb |
'P','o','i','n','t',
|
|
|
dd89bb |
'M','a','n','a','g','e','r',0};
|
|
|
dd89bb |
|
|
|
dd89bb |
dev_name.strlen = sizeof(wchar16_t) * (4+5+5+7);
|
|
|
dd89bb |
dev_name.maxlen = 0;
|
|
|
dd89bb |
dev_name.buffer = dev_name_buffer;
|
|
|
dd89bb |
|
|
|
dd89bb |
oa.len = sizeof(nt_oa);
|
|
|
dd89bb |
oa.root_dir = (void *)0;
|
|
|
dd89bb |
oa.obj_name = &dev_name;
|
|
|
dd89bb |
oa.obj_attr = NT_OBJ_CASE_INSENSITIVE;
|
|
|
dd89bb |
oa.sec_desc = (nt_sd *)0;
|
|
|
dd89bb |
oa.sec_qos = (nt_sqos *)0;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_create_file(
|
|
|
dd89bb |
&hdev,
|
|
|
dd89bb |
NT_SEC_SYNCHRONIZE | NT_FILE_READ_ATTRIBUTES,
|
|
|
dd89bb |
&oa,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
0,
|
|
|
dd89bb |
NT_FILE_ATTRIBUTE_NORMAL,
|
|
|
dd89bb |
NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE,
|
|
|
dd89bb |
NT_FILE_OPEN,
|
|
|
dd89bb |
NT_FILE_NON_DIRECTORY_FILE | NT_FILE_SYNCHRONOUS_IO_NONALERT,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
0);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
hdev_prev = (void *)at_locked_cas(
|
|
|
dd89bb |
(intptr_t *)&__ntapi_internals()->hdev_mount_point_mgr,
|
|
|
dd89bb |
0,(intptr_t)hdev);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (hdev_prev)
|
|
|
dd89bb |
__ntapi->zw_close(hdev);
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __stdcall __tt_get_dos_drive_device_or_root_handle(
|
|
|
dd89bb |
__out void ** hdrive,
|
|
|
9dabeb |
__in wchar16_t drive_letter,
|
|
|
dd89bb |
__in _dos_drive_handle_type handle_type)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
#define __common_mode (NT_FILE_SYNCHRONOUS_IO_ALERT)
|
|
|
dd89bb |
#define __common_access (NT_SEC_SYNCHRONIZE \
|
|
|
dd89bb |
| NT_FILE_READ_ATTRIBUTES)
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_oa oa;
|
|
|
dd89bb |
nt_iosb iosb;
|
|
|
dd89bb |
uint32_t open_flags;
|
|
|
dd89bb |
uint32_t access_flags;
|
|
|
dd89bb |
nt_unicode_string dos_name;
|
|
|
dd89bb |
_dos_name_buffer dos_name_buffer = {
|
|
|
dd89bb |
{'\\','?','?','\\'},
|
|
|
dd89bb |
'_',':',0,0};
|
|
|
dd89bb |
|
|
|
9dabeb |
if ((drive_letter>='A') && (drive_letter<='Z'))
|
|
|
9dabeb |
dos_name_buffer.dos_letter = drive_letter;
|
|
|
9dabeb |
else if ((drive_letter>='a') && (drive_letter<='z'))
|
|
|
9dabeb |
dos_name_buffer.dos_letter = drive_letter + 'A' - 'a';
|
|
|
dd89bb |
else
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_2;
|
|
|
dd89bb |
|
|
|
dd89bb |
dos_name.strlen = ((size_t)(&((_dos_name_buffer *)0)->root));
|
|
|
dd89bb |
dos_name.maxlen = 0;
|
|
|
dd89bb |
dos_name.buffer = &(dos_name_buffer.global_prefix[0]);
|
|
|
dd89bb |
|
|
|
dd89bb |
switch (handle_type) {
|
|
|
dd89bb |
case __DOS_DRIVE_DEVICE_HANDLE:
|
|
|
dd89bb |
open_flags = __common_mode;
|
|
|
dd89bb |
access_flags = __common_access;
|
|
|
dd89bb |
break;
|
|
|
dd89bb |
|
|
|
dd89bb |
case __DOS_DRIVE_ROOT_HANDLE:
|
|
|
dd89bb |
open_flags = __common_mode | NT_FILE_DIRECTORY_FILE;
|
|
|
dd89bb |
access_flags = __common_access | NT_FILE_READ_ACCESS;
|
|
|
dd89bb |
dos_name_buffer.root = '\\';
|
|
|
dd89bb |
dos_name.strlen += sizeof(wchar16_t);
|
|
|
dd89bb |
break;
|
|
|
dd89bb |
default:
|
|
|
dd89bb |
open_flags = 0;
|
|
|
dd89bb |
access_flags = 0;
|
|
|
dd89bb |
break;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
oa.len = sizeof(nt_oa);
|
|
|
dd89bb |
oa.root_dir = (void *)0;
|
|
|
dd89bb |
oa.obj_name = &dos_name;
|
|
|
dd89bb |
oa.obj_attr = NT_OBJ_INHERIT;
|
|
|
dd89bb |
oa.sec_desc = (nt_sd *)0;
|
|
|
dd89bb |
oa.sec_qos = (nt_sqos *)0;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_open_file(
|
|
|
dd89bb |
hdrive,
|
|
|
dd89bb |
access_flags,
|
|
|
dd89bb |
&oa,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE,
|
|
|
dd89bb |
open_flags);
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_dos_drive_device_handle(
|
|
|
dd89bb |
__out void ** hdevice,
|
|
|
9dabeb |
__in wchar16_t drive_letter)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return __tt_get_dos_drive_device_or_root_handle(
|
|
|
dd89bb |
hdevice,
|
|
|
dd89bb |
drive_letter,
|
|
|
dd89bb |
__DOS_DRIVE_DEVICE_HANDLE);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_dos_drive_root_handle(
|
|
|
dd89bb |
__out void ** hroot,
|
|
|
9dabeb |
__in wchar16_t drive_letter)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return __tt_get_dos_drive_device_or_root_handle(
|
|
|
dd89bb |
hroot,
|
|
|
dd89bb |
drive_letter,
|
|
|
dd89bb |
__DOS_DRIVE_ROOT_HANDLE);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_dos_drive_device_name(
|
|
|
dd89bb |
__in void * hdevice __optional,
|
|
|
9dabeb |
__in wchar16_t drive_letter __optional,
|
|
|
dd89bb |
__out nt_mount_dev_name * buffer,
|
|
|
dd89bb |
__in uint32_t buffer_size)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_iosb iosb;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!hdevice && (status = __tt_get_dos_drive_device_or_root_handle(
|
|
|
dd89bb |
&hdevice,
|
|
|
dd89bb |
drive_letter,
|
|
|
dd89bb |
__DOS_DRIVE_DEVICE_HANDLE)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
return __ntapi->zw_device_io_control_file(
|
|
|
dd89bb |
hdevice,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
(nt_io_apc_routine *)0,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
NT_IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
0,
|
|
|
dd89bb |
buffer,
|
|
|
dd89bb |
buffer_size);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_dos_drive_mount_points(
|
|
|
dd89bb |
__in void * hdevice __optional,
|
|
|
9dabeb |
__in wchar16_t drive_letter __optional,
|
|
|
dd89bb |
__in nt_mount_dev_name * dev_name __optional,
|
|
|
dd89bb |
__out void * buffer,
|
|
|
dd89bb |
__in uint32_t buffer_size)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_iosb iosb;
|
|
|
dd89bb |
wchar16_t dev_name_buffer[64];
|
|
|
dd89bb |
nt_mount_point_param * dev_mount_point;
|
|
|
dd89bb |
nt_mount_points * dev_mount_points;
|
|
|
dd89bb |
uintptr_t addr;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!dev_name) {
|
|
|
dd89bb |
dev_name = (nt_mount_dev_name *)&dev_name_buffer;
|
|
|
dd89bb |
if ((status = __ntapi_tt_get_dos_drive_device_name(
|
|
|
dd89bb |
hdevice,
|
|
|
dd89bb |
drive_letter,
|
|
|
dd89bb |
dev_name,
|
|
|
dd89bb |
sizeof(dev_name_buffer))))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (buffer_size < sizeof(nt_mount_mgr_mount_point) \
|
|
|
dd89bb |
+ sizeof(nt_mount_dev_name) \
|
|
|
dd89bb |
+ sizeof(dev_name->name_length))
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
dev_mount_point = (nt_mount_point_param *)buffer;
|
|
|
dd89bb |
dev_mount_point->symlink_name_offset = 0;
|
|
|
dd89bb |
dev_mount_point->symlink_name_length = 0;
|
|
|
dd89bb |
dev_mount_point->unique_id_offset = 0;
|
|
|
dd89bb |
dev_mount_point->unique_id_length = 0;
|
|
|
dd89bb |
dev_mount_point->device_name_offset = ((size_t)(&((nt_mount_point_param *)0)->device_name));
|
|
|
dd89bb |
dev_mount_point->device_name_length = dev_name->name_length;
|
|
|
dd89bb |
dev_mount_point->mount_points_offset = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->tt_memcpy_utf16(
|
|
|
dd89bb |
dev_mount_point->device_name,
|
|
|
dd89bb |
dev_name->name,
|
|
|
dd89bb |
dev_name->name_length);
|
|
|
dd89bb |
|
|
|
dd89bb |
addr = (uintptr_t)(dev_mount_point->device_name) + dev_name->name_length;
|
|
|
dd89bb |
addr += sizeof(uintptr_t) - 1;
|
|
|
dd89bb |
addr /= sizeof(uintptr_t);
|
|
|
dd89bb |
addr *= sizeof(uintptr_t);
|
|
|
dd89bb |
dev_mount_points = (nt_mount_points *)addr;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!__ntapi_internals()->hdev_mount_point_mgr)
|
|
|
edfe66 |
if ((status = __tt_connect_to_mount_point_manager()))
|
|
|
edfe66 |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_device_io_control_file(
|
|
|
dd89bb |
__ntapi_internals()->hdev_mount_point_mgr,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
(nt_io_apc_routine *)0,
|
|
|
dd89bb |
(void *)0,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
NT_IOCTL_MOUNTMGR_QUERY_POINTS,
|
|
|
dd89bb |
dev_mount_point,
|
|
|
dd89bb |
(uint32_t)(uintptr_t)&(((nt_mount_point_param *)0)->device_name) + dev_name->name_length,
|
|
|
dd89bb |
dev_mount_points,
|
|
|
dd89bb |
(uint32_t)((uintptr_t)buffer + buffer_size - addr));
|
|
|
dd89bb |
|
|
|
dd89bb |
dev_mount_point->mount_points_offset = (uint16_t)((uintptr_t)addr - (uintptr_t)buffer);
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_dev_mount_points_to_statfs(
|
|
|
dd89bb |
__in nt_mount_points * mount_points,
|
|
|
dd89bb |
__in_out nt_statfs * statfs)
|
|
|
dd89bb |
{
|
|
|
fc8f1d |
int32_t status;
|
|
|
fc8f1d |
uint32_t i;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_mount_mgr_mount_point * mount_point;
|
|
|
fc8f1d |
wchar16_t * symlink;
|
|
|
dd89bb |
|
|
|
dd89bb |
mount_point = mount_points->mount_points;
|
|
|
dd89bb |
statfs->nt_drive_letter = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
for (i = 0; i < mount_points->number; i++, mount_point++) {
|
|
|
fc8f1d |
symlink = (wchar16_t *)mount_points;
|
|
|
fc8f1d |
symlink += mount_point->symlink_name_offset / sizeof(wchar16_t);
|
|
|
fc8f1d |
|
|
|
fc8f1d |
if (symlink[0] != '\\')
|
|
|
fc8f1d |
return NT_STATUS_UNEXPECTED_IO_ERROR;
|
|
|
fc8f1d |
|
|
|
fc8f1d |
if ((symlink[1] == 'D')
|
|
|
fc8f1d |
&& (symlink[2] == 'o')
|
|
|
fc8f1d |
&& (symlink[3] == 's')
|
|
|
fc8f1d |
&& (symlink[4] == 'D')
|
|
|
fc8f1d |
&& (symlink[5] == 'e')
|
|
|
fc8f1d |
&& (symlink[6] == 'v')
|
|
|
fc8f1d |
&& (symlink[7] == 'i')
|
|
|
fc8f1d |
&& (symlink[8] == 'c')
|
|
|
fc8f1d |
&& (symlink[9] == 'e')
|
|
|
fc8f1d |
&& (symlink[10] == 's'))
|
|
|
dd89bb |
statfs->nt_drive_letter = ((nt_dos_devices_name *)(symlink))->letter;
|
|
|
fc8f1d |
|
|
|
fc8f1d |
else if ((symlink[1] == '?')
|
|
|
fc8f1d |
&& (symlink[2] == '?')
|
|
|
fc8f1d |
&& (symlink[3] == '\\')
|
|
|
fc8f1d |
&& (symlink[4] == 'V')
|
|
|
fc8f1d |
&& (symlink[5] == 'o')
|
|
|
fc8f1d |
&& (symlink[6] == 'l')
|
|
|
fc8f1d |
&& (symlink[7] == 'u')
|
|
|
fc8f1d |
&& (symlink[8] == 'm')
|
|
|
fc8f1d |
&& (symlink[9] == 'e')
|
|
|
fc8f1d |
&& (symlink[10] == '{')) {
|
|
|
fc8f1d |
if ((status = __ntapi_tt_utf16_string_to_guid(
|
|
|
fc8f1d |
(nt_guid_str_utf16 *)&symlink[10],
|
|
|
fc8f1d |
&statfs->nt_volume_guid)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
fc8f1d |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_get_dos_drive_letter_from_device(
|
|
|
dd89bb |
__in void * hdevice __optional,
|
|
|
dd89bb |
__out wchar16_t * drive_letter,
|
|
|
dd89bb |
__in nt_mount_dev_name * dev_name __optional,
|
|
|
dd89bb |
__out void * buffer,
|
|
|
dd89bb |
__in uint32_t buffer_size)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
wchar16_t dev_name_buffer[128];
|
|
|
dd89bb |
nt_statfs statfs;
|
|
|
dd89bb |
uint32_t offset;
|
|
|
dd89bb |
nt_mount_points * mnt_points;
|
|
|
dd89bb |
|
|
|
c713d8 |
(void)buffer_size;
|
|
|
c713d8 |
|
|
|
dd89bb |
if (!dev_name) {
|
|
|
dd89bb |
dev_name = (nt_mount_dev_name *)&dev_name_buffer;
|
|
|
dd89bb |
|
|
|
9dabeb |
if ((status = __ntapi_tt_get_dos_drive_device_name(
|
|
|
9dabeb |
hdevice,0,dev_name,
|
|
|
9dabeb |
sizeof(dev_name_buffer))))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
offset = ((nt_mount_point_param *)buffer)->mount_points_offset;
|
|
|
dd89bb |
mnt_points = (nt_mount_points *)((uintptr_t)buffer + offset);
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi_tt_dev_mount_points_to_statfs(
|
|
|
dd89bb |
mnt_points,
|
|
|
dd89bb |
&statfs);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS)
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
*drive_letter = statfs.nt_drive_letter;
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|