|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
dde53a |
/* Copyright (C) 2013--2017 Z. Gilboa */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <ntapi/nt_object.h>
|
|
|
dd89bb |
#include <ntapi/nt_guid.h>
|
|
|
dd89bb |
#include <ntapi/nt_string.h>
|
|
|
b8eeed |
#include <ntapi/nt_acl.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
typedef ntapi_zw_open_directory_object objdir_open_fn;
|
|
|
dd89bb |
|
|
|
d5e229 |
static void __tt_guid_to_hex_utf16(
|
|
|
d5e229 |
__in const nt_guid * guid,
|
|
|
d5e229 |
__out wchar16_t * hex_str)
|
|
|
d5e229 |
{
|
|
|
d5e229 |
uint16_t key;
|
|
|
d5e229 |
|
|
|
d5e229 |
__ntapi_tt_uint32_to_hex_utf16(
|
|
|
d5e229 |
guid->data1,&hex_str[0]);
|
|
|
d5e229 |
|
|
|
d5e229 |
__ntapi_tt_uint16_to_hex_utf16(
|
|
|
d5e229 |
guid->data2,&hex_str[9]);
|
|
|
d5e229 |
|
|
|
d5e229 |
__ntapi_tt_uint16_to_hex_utf16(
|
|
|
d5e229 |
guid->data3,&hex_str[14]);
|
|
|
d5e229 |
|
|
|
d5e229 |
key = guid->data4[0] * 0x100 + guid->data4[1];
|
|
|
d5e229 |
|
|
|
d5e229 |
__ntapi_tt_uint16_to_hex_utf16(
|
|
|
d5e229 |
key,&hex_str[19]);
|
|
|
d5e229 |
|
|
|
d5e229 |
key = guid->data4[2] * 0x100 + guid->data4[3];
|
|
|
d5e229 |
|
|
|
d5e229 |
__ntapi_tt_uint16_to_hex_utf16(
|
|
|
d5e229 |
key,&hex_str[24]);
|
|
|
d5e229 |
|
|
|
d5e229 |
key = guid->data4[4] * 0x100 + guid->data4[5];
|
|
|
af6bd7 |
|
|
|
d5e229 |
__ntapi_tt_uint16_to_hex_utf16(
|
|
|
d5e229 |
key,&hex_str[28]);
|
|
|
d5e229 |
|
|
|
d5e229 |
key = guid->data4[6] * 0x100 + guid->data4[7];
|
|
|
d5e229 |
|
|
|
d5e229 |
__ntapi_tt_uint16_to_hex_utf16(
|
|
|
d5e229 |
key,&hex_str[32]);
|
|
|
d5e229 |
|
|
|
d5e229 |
hex_str[8] = '-';
|
|
|
d5e229 |
hex_str[13] = '-';
|
|
|
d5e229 |
hex_str[18] = '-';
|
|
|
d5e229 |
hex_str[23] = '-';
|
|
|
d5e229 |
}
|
|
|
661c27 |
|
|
|
b8eeed |
static nt_access_allowed_ace * __ipc_ace_init(
|
|
|
b8eeed |
nt_access_allowed_ace * ace,
|
|
|
b8eeed |
uint32_t mask,
|
|
|
b8eeed |
const nt_sid * sid)
|
|
|
b8eeed |
{
|
|
|
b8eeed |
ace->mask = mask;
|
|
|
b8eeed |
ace->header.ace_type = NT_ACE_TYPE_ACCESS_ALLOWED;
|
|
|
b8eeed |
ace->header.ace_flags = 0;
|
|
|
b8eeed |
ace->header.ace_size = sizeof(uint32_t) * sid->sub_authority_count
|
|
|
b8eeed |
+ __offsetof(nt_access_allowed_ace,sid_start)
|
|
|
b8eeed |
+ __offsetof(nt_sid,sub_authority);
|
|
|
b8eeed |
|
|
|
b8eeed |
__ntapi->tt_sid_copy(
|
|
|
b8eeed |
(nt_sid *)&ace->sid_start,
|
|
|
b8eeed |
sid);
|
|
|
b8eeed |
|
|
|
b8eeed |
return (nt_access_allowed_ace *)((size_t)ace + ace->header.ace_size);
|
|
|
b8eeed |
}
|
|
|
b8eeed |
|
|
|
b8eeed |
static void __ipc_sd_init(nt_sd_common_buffer * sd, int fdir)
|
|
|
b8eeed |
{
|
|
|
b8eeed |
nt_access_allowed_ace * ace;
|
|
|
b8eeed |
uint32_t mask_system;
|
|
|
b8eeed |
uint32_t mask_owner;
|
|
|
b8eeed |
uint32_t mask_other;
|
|
|
b8eeed |
|
|
|
b8eeed |
/* access mask */
|
|
|
b8eeed |
if (fdir) {
|
|
|
b8eeed |
mask_system = NT_SEC_READ_CONTROL
|
|
|
b8eeed |
| NT_DIRECTORY_QUERY
|
|
|
b8eeed |
| NT_DIRECTORY_TRAVERSE
|
|
|
b8eeed |
| NT_DIRECTORY_CREATE_OBJECT
|
|
|
b8eeed |
| NT_DIRECTORY_CREATE_SUBDIRECTORY;
|
|
|
b8eeed |
|
|
|
b8eeed |
mask_owner = NT_DIRECTORY_ALL_ACCESS;
|
|
|
b8eeed |
mask_other = mask_system;
|
|
|
b8eeed |
} else {
|
|
|
b8eeed |
mask_system = NT_SYMBOLIC_LINK_ALL_ACCESS;
|
|
|
b8eeed |
mask_owner = NT_SYMBOLIC_LINK_ALL_ACCESS;
|
|
|
b8eeed |
mask_other = NT_SYMBOLIC_LINK_QUERY;
|
|
|
b8eeed |
}
|
|
|
b8eeed |
|
|
|
b8eeed |
/* sd header */
|
|
|
b8eeed |
sd->sd.revision = 1;
|
|
|
b8eeed |
sd->sd.sbz_1st = 0;
|
|
|
b8eeed |
sd->sd.control = NT_SE_SELF_RELATIVE | NT_SE_DACL_PRESENT;
|
|
|
b8eeed |
sd->sd.offset_owner = __offsetof(nt_sd_common_buffer,owner);
|
|
|
b8eeed |
sd->sd.offset_group = 0;
|
|
|
b8eeed |
sd->sd.offset_dacl = __offsetof(nt_sd_common_buffer,dacl);
|
|
|
b8eeed |
sd->sd.offset_sacl = 0;
|
|
|
b8eeed |
|
|
|
b8eeed |
/* owner sid */
|
|
|
b8eeed |
__ntapi->tt_sid_copy(
|
|
|
b8eeed |
(nt_sid *)&sd->owner,
|
|
|
0a8487 |
__ntapi_internals()->user);
|
|
|
b8eeed |
|
|
|
b8eeed |
|
|
|
b8eeed |
/* ace's for LOCAL_SYSTEM, AUTHENTICATED_USERS, and process token user */
|
|
|
b8eeed |
ace = (nt_access_allowed_ace *)&sd->buffer;
|
|
|
b8eeed |
ace = __ipc_ace_init(ace,mask_system,&(nt_sid){1,1,{{0,0,0,0,0,5}},{18}});
|
|
|
b8eeed |
ace = __ipc_ace_init(ace,mask_other,&(nt_sid){1,1,{{0,0,0,0,0,5}},{11}});
|
|
|
b8eeed |
ace = __ipc_ace_init(ace,mask_owner,(nt_sid *)&sd->owner);
|
|
|
b8eeed |
|
|
|
b8eeed |
sd->dacl.acl_revision = 0x02;
|
|
|
b8eeed |
sd->dacl.sbz_1st = 0;
|
|
|
b8eeed |
sd->dacl.acl_size = (uint16_t)((char *)ace - (char *)&sd->dacl);
|
|
|
b8eeed |
sd->dacl.ace_count = 3;
|
|
|
b8eeed |
sd->dacl.sbz_2nd = 0;
|
|
|
b8eeed |
|
|
|
b8eeed |
}
|
|
|
b8eeed |
|
|
|
661c27 |
static int32_t __stdcall __tt_create_ipc_object_directory(
|
|
|
661c27 |
__out void ** hdir,
|
|
|
661c27 |
__in uint32_t desired_access,
|
|
|
661c27 |
__in const wchar16_t prefix[6],
|
|
|
ae515f |
__in const nt_guid * guid)
|
|
|
661c27 |
{
|
|
|
661c27 |
int32_t status;
|
|
|
661c27 |
nt_ipc_objdir_name objdir_name;
|
|
|
661c27 |
nt_unicode_string name;
|
|
|
b8eeed |
nt_sd_common_buffer sd;
|
|
|
661c27 |
nt_oa oa;
|
|
|
661c27 |
nt_sqos sqos = {
|
|
|
661c27 |
sizeof(sqos),
|
|
|
661c27 |
NT_SECURITY_IMPERSONATION,
|
|
|
661c27 |
NT_SECURITY_TRACKING_DYNAMIC,
|
|
|
661c27 |
1};
|
|
|
661c27 |
|
|
|
b8eeed |
__ipc_sd_init(&sd,1);
|
|
|
b8eeed |
|
|
|
661c27 |
__ntapi->tt_generic_memcpy(
|
|
|
d5e229 |
objdir_name.base_named_objects,
|
|
|
d5e229 |
(wchar16_t[])__NT_BASED_NAMED_OBJECTS,
|
|
|
d5e229 |
sizeof(objdir_name.base_named_objects));
|
|
|
661c27 |
|
|
|
661c27 |
__ntapi->tt_memcpy_utf16(
|
|
|
661c27 |
objdir_name.prefix,
|
|
|
661c27 |
prefix,
|
|
|
661c27 |
sizeof(objdir_name.prefix));
|
|
|
661c27 |
|
|
|
d5e229 |
__tt_guid_to_hex_utf16(
|
|
|
d5e229 |
guid,objdir_name.guid);
|
|
|
661c27 |
|
|
|
661c27 |
objdir_name.backslash = '\\';
|
|
|
d5e229 |
objdir_name.uscore = '_';
|
|
|
661c27 |
|
|
|
661c27 |
name.strlen = sizeof(objdir_name);
|
|
|
661c27 |
name.maxlen = 0;
|
|
|
d5e229 |
name.buffer = objdir_name.base_named_objects;
|
|
|
661c27 |
|
|
|
661c27 |
oa.len = sizeof(oa);
|
|
|
661c27 |
oa.root_dir = 0;
|
|
|
661c27 |
oa.obj_name = &nam;;
|
|
|
661c27 |
oa.obj_attr = NT_OBJ_INHERIT
|
|
|
661c27 |
| NT_OBJ_OPENIF
|
|
|
661c27 |
| NT_OBJ_CASE_INSENSITIVE;
|
|
|
b8eeed |
oa.sec_desc = &sd.sd;
|
|
|
661c27 |
oa.sec_qos = &sqo;;
|
|
|
661c27 |
|
|
|
661c27 |
status = __ntapi->zw_create_directory_object(
|
|
|
661c27 |
hdir,desired_access,&oa);
|
|
|
661c27 |
|
|
|
661c27 |
return (status == NT_STATUS_OBJECT_NAME_EXISTS)
|
|
|
661c27 |
? NT_STATUS_SUCCESS
|
|
|
661c27 |
: status;
|
|
|
661c27 |
}
|
|
|
661c27 |
|
|
|
661c27 |
|
|
|
dd89bb |
static int32_t __stdcall __tt_create_keyed_object_directory(
|
|
|
dd89bb |
__out void ** hdir,
|
|
|
dd89bb |
__in uint32_t desired_access,
|
|
|
d5e229 |
__in void * hparent,
|
|
|
dd89bb |
__in uint32_t key,
|
|
|
dd89bb |
__in objdir_open_fn * openfn)
|
|
|
dd89bb |
{
|
|
|
d5e229 |
wchar16_t keystr[8];
|
|
|
dd89bb |
nt_unicode_string name;
|
|
|
b8eeed |
nt_sd_common_buffer sd;
|
|
|
dd89bb |
nt_oa oa;
|
|
|
dd89bb |
nt_sqos sqos = {
|
|
|
dd89bb |
sizeof(sqos),
|
|
|
dd89bb |
NT_SECURITY_IMPERSONATION,
|
|
|
dd89bb |
NT_SECURITY_TRACKING_DYNAMIC,
|
|
|
dd89bb |
1};
|
|
|
dd89bb |
|
|
|
b8eeed |
__ipc_sd_init(&sd,1);
|
|
|
b8eeed |
|
|
|
dd89bb |
__ntapi->tt_uint32_to_hex_utf16(
|
|
|
d5e229 |
key,keystr);
|
|
|
dd89bb |
|
|
|
d5e229 |
name.strlen = sizeof(keystr);
|
|
|
d5e229 |
name.maxlen = 0;
|
|
|
d5e229 |
name.buffer = keystr;
|
|
|
dd89bb |
|
|
|
dd89bb |
oa.len = sizeof(oa);
|
|
|
d5e229 |
oa.root_dir = hparent;
|
|
|
dd89bb |
oa.obj_name = &nam;;
|
|
|
dd89bb |
oa.obj_attr = NT_OBJ_INHERIT;
|
|
|
b8eeed |
oa.sec_desc = &sd.sd;
|
|
|
dd89bb |
oa.sec_qos = &sqo;;
|
|
|
dd89bb |
|
|
|
dd89bb |
return openfn(hdir,desired_access,&oa);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
661c27 |
static int32_t __stdcall __tt_create_object_directory_entry(
|
|
|
dd89bb |
__out void ** hentry,
|
|
|
dd89bb |
__in uint32_t desired_access,
|
|
|
dd89bb |
__in void * hdir,
|
|
|
dd89bb |
__in void * htarget,
|
|
|
dd89bb |
__in nt_unicode_string * target_name,
|
|
|
dd89bb |
__in uint32_t key)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_oa oa;
|
|
|
dd89bb |
nt_unicode_string name;
|
|
|
b8eeed |
nt_sd_common_buffer sd;
|
|
|
dd89bb |
wchar16_t keystr[8];
|
|
|
dd89bb |
uintptr_t buffer[2048/sizeof(uintptr_t)];
|
|
|
dd89bb |
nt_sqos sqos = {
|
|
|
dd89bb |
sizeof(sqos),
|
|
|
dd89bb |
NT_SECURITY_IMPERSONATION,
|
|
|
dd89bb |
NT_SECURITY_TRACKING_DYNAMIC,
|
|
|
dd89bb |
1};
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!target_name) {
|
|
|
dd89bb |
if ((status = __ntapi->zw_query_object(
|
|
|
dd89bb |
htarget,
|
|
|
dd89bb |
NT_OBJECT_NAME_INFORMATION,
|
|
|
dd89bb |
buffer,sizeof(buffer),0)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
target_name = (nt_unicode_string *)buffer;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
b8eeed |
__ipc_sd_init(&sd,0);
|
|
|
dd89bb |
__ntapi->tt_uint32_to_hex_utf16(key,keystr);
|
|
|
dd89bb |
|
|
|
dd89bb |
name.strlen = sizeof(keystr);
|
|
|
dd89bb |
name.maxlen = 0;
|
|
|
dd89bb |
name.buffer = keystr;
|
|
|
dd89bb |
|
|
|
dd89bb |
oa.len = sizeof(oa);
|
|
|
dd89bb |
oa.root_dir = hdir;
|
|
|
dd89bb |
oa.obj_name = &nam;;
|
|
|
dd89bb |
oa.obj_attr = 0;
|
|
|
b8eeed |
oa.sec_desc = &sd.sd;
|
|
|
dd89bb |
oa.sec_qos = &sqo;;
|
|
|
dd89bb |
|
|
|
dd89bb |
return __ntapi->zw_create_symbolic_link_object(
|
|
|
dd89bb |
hentry,
|
|
|
dd89bb |
desired_access,
|
|
|
dd89bb |
&oa,target_name);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
661c27 |
int32_t __stdcall __ntapi_tt_open_ipc_object_directory(
|
|
|
661c27 |
__out void ** hdir,
|
|
|
661c27 |
__in uint32_t desired_access,
|
|
|
661c27 |
__in const wchar16_t prefix[6],
|
|
|
ae515f |
__in const nt_guid * guid)
|
|
|
661c27 |
{
|
|
|
661c27 |
return __tt_create_ipc_object_directory(
|
|
|
661c27 |
hdir,desired_access,
|
|
|
661c27 |
prefix,guid);
|
|
|
661c27 |
}
|
|
|
661c27 |
|
|
|
661c27 |
int32_t __stdcall __ntapi_tt_create_ipc_object_directory_entry(
|
|
|
661c27 |
__out void ** hentry,
|
|
|
661c27 |
__in uint32_t desired_access,
|
|
|
661c27 |
__in void * hdir,
|
|
|
661c27 |
__in void * htarget,
|
|
|
661c27 |
__in nt_unicode_string * target_name,
|
|
|
661c27 |
__in uint32_t key)
|
|
|
661c27 |
{
|
|
|
661c27 |
return __tt_create_object_directory_entry(
|
|
|
661c27 |
hentry,desired_access,
|
|
|
661c27 |
hdir,htarget,target_name,key);
|
|
|
661c27 |
}
|
|
|
661c27 |
|
|
|
6729c8 |
int32_t __stdcall __ntapi_tt_open_dev_object_directory(
|
|
|
6729c8 |
__out void ** hdir,
|
|
|
6729c8 |
__in uint32_t desired_access,
|
|
|
6729c8 |
__in const wchar16_t prefix[6],
|
|
|
6729c8 |
__in const nt_guid * ipc_guid)
|
|
|
6729c8 |
{
|
|
|
6729c8 |
return __tt_create_ipc_object_directory(
|
|
|
6729c8 |
hdir,desired_access,
|
|
|
6729c8 |
prefix,ipc_guid);
|
|
|
6729c8 |
}
|
|
|
6729c8 |
|
|
|
6729c8 |
int32_t __stdcall __ntapi_tt_create_dev_object_directory_entry(
|
|
|
6729c8 |
__out void ** hentry,
|
|
|
6729c8 |
__in uint32_t desired_access,
|
|
|
6729c8 |
__in void * hdir,
|
|
|
6729c8 |
__in void * htarget,
|
|
|
6729c8 |
__in nt_unicode_string * target_name,
|
|
|
6729c8 |
__in const nt_guid * dev_guid)
|
|
|
6729c8 |
{
|
|
|
6729c8 |
int32_t status;
|
|
|
6729c8 |
nt_oa oa;
|
|
|
6729c8 |
nt_unicode_string name;
|
|
|
6729c8 |
nt_sd_common_buffer sd;
|
|
|
6729c8 |
nt_guid_str_utf16 guidstr;
|
|
|
6729c8 |
uintptr_t buffer[2048/sizeof(uintptr_t)];
|
|
|
6729c8 |
nt_sqos sqos = {
|
|
|
6729c8 |
sizeof(sqos),
|
|
|
6729c8 |
NT_SECURITY_IMPERSONATION,
|
|
|
6729c8 |
NT_SECURITY_TRACKING_DYNAMIC,
|
|
|
6729c8 |
1};
|
|
|
6729c8 |
|
|
|
6729c8 |
if (!target_name) {
|
|
|
6729c8 |
if ((status = __ntapi->zw_query_object(
|
|
|
6729c8 |
htarget,
|
|
|
6729c8 |
NT_OBJECT_NAME_INFORMATION,
|
|
|
6729c8 |
buffer,sizeof(buffer),0)))
|
|
|
6729c8 |
return status;
|
|
|
6729c8 |
target_name = (nt_unicode_string *)buffer;
|
|
|
6729c8 |
}
|
|
|
6729c8 |
|
|
|
6729c8 |
__ipc_sd_init(&sd,0);
|
|
|
6729c8 |
__ntapi->tt_guid_to_string_utf16(dev_guid,&guidstr);
|
|
|
6729c8 |
|
|
|
6729c8 |
name.strlen = sizeof(guidstr);
|
|
|
6729c8 |
name.maxlen = 0;
|
|
|
6729c8 |
name.buffer = &guidstr.lbrace;
|
|
|
6729c8 |
|
|
|
6729c8 |
oa.len = sizeof(oa);
|
|
|
6729c8 |
oa.root_dir = hdir;
|
|
|
6729c8 |
oa.obj_name = &nam;;
|
|
|
6729c8 |
oa.obj_attr = 0;
|
|
|
6729c8 |
oa.sec_desc = &sd.sd;
|
|
|
6729c8 |
oa.sec_qos = &sqo;;
|
|
|
6729c8 |
|
|
|
6729c8 |
return __ntapi->zw_create_symbolic_link_object(
|
|
|
6729c8 |
hentry,
|
|
|
6729c8 |
desired_access,
|
|
|
6729c8 |
&oa,target_name);
|
|
|
6729c8 |
}
|
|
|
6729c8 |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_create_keyed_object_directory(
|
|
|
dd89bb |
__out void ** hdir,
|
|
|
dd89bb |
__in uint32_t desired_access,
|
|
|
d5e229 |
__in void * hparent,
|
|
|
dd89bb |
__in uint32_t key)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return __tt_create_keyed_object_directory(
|
|
|
dd89bb |
hdir,desired_access,
|
|
|
d5e229 |
hparent,key,
|
|
|
dd89bb |
__ntapi->zw_create_directory_object);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_open_keyed_object_directory(
|
|
|
dd89bb |
__out void ** hdir,
|
|
|
dd89bb |
__in uint32_t desired_access,
|
|
|
d5e229 |
__in void * hparent,
|
|
|
dd89bb |
__in uint32_t key)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return __tt_create_keyed_object_directory(
|
|
|
dd89bb |
hdir,desired_access,
|
|
|
d5e229 |
hparent,key,
|
|
|
dd89bb |
__ntapi->zw_open_directory_object);
|
|
|
dd89bb |
}
|
|
|
661c27 |
|
|
|
661c27 |
int32_t __stdcall __ntapi_tt_create_keyed_object_directory_entry(
|
|
|
661c27 |
__out void ** hentry,
|
|
|
661c27 |
__in uint32_t desired_access,
|
|
|
661c27 |
__in void * hdir,
|
|
|
661c27 |
__in void * htarget,
|
|
|
661c27 |
__in nt_unicode_string * target_name,
|
|
|
661c27 |
__in uint32_t key)
|
|
|
661c27 |
{
|
|
|
661c27 |
return __tt_create_object_directory_entry(
|
|
|
661c27 |
hentry,desired_access,
|
|
|
661c27 |
hdir,htarget,target_name,key);
|
|
|
661c27 |
}
|
|
|
8ca63f |
|
|
|
8ca63f |
int32_t __stdcall __ntapi_tt_keyed_object_to_key(
|
|
|
8ca63f |
__in void * hentry,
|
|
|
8ca63f |
__out uint32_t * key,
|
|
|
8ca63f |
__out void * buffer,
|
|
|
8ca63f |
__in size_t buflen)
|
|
|
8ca63f |
{
|
|
|
8ca63f |
int32_t status;
|
|
|
8ca63f |
wchar16_t * pidname;
|
|
|
8ca63f |
nt_unicode_string * dirname;
|
|
|
8ca63f |
|
|
|
8ca63f |
if ((status = __ntapi->zw_query_object(
|
|
|
8ca63f |
hentry,
|
|
|
8ca63f |
NT_OBJECT_NAME_INFORMATION,
|
|
|
8ca63f |
buffer,buflen,
|
|
|
8ca63f |
&(uint32_t){0})))
|
|
|
8ca63f |
return status;
|
|
|
8ca63f |
|
|
|
8ca63f |
dirname = (nt_unicode_string *)buffer;
|
|
|
8ca63f |
pidname = dirname->buffer;
|
|
|
8ca63f |
|
|
|
8ca63f |
if (dirname->strlen <= 8 * sizeof(wchar16_t))
|
|
|
8ca63f |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
8ca63f |
|
|
|
8ca63f |
pidname += dirname->strlen / sizeof(wchar16_t);
|
|
|
8ca63f |
pidname -= 8;
|
|
|
8ca63f |
|
|
|
8ca63f |
if (pidname[-1] != '\\')
|
|
|
8ca63f |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
8ca63f |
|
|
|
8ca63f |
return __ntapi->tt_hex_utf16_to_uint32(
|
|
|
8ca63f |
pidname,key);
|
|
|
8ca63f |
}
|