server: Implement the \??\GLOBALROOT symbolic link.
\??\GLOBALROOT is a well-known NT symbolic link that allows applications to access the NT object manager's root namespace via Win32 APIs. Signed-off-by: Jinoh Kang <jinoh.kang.kr@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9f0df41a6c
commit
3b37584316
|
@ -2388,6 +2388,64 @@ static void test_get_next_thread(void)
|
|||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
static void test_globalroot(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING str;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
HANDLE h;
|
||||
WCHAR buffer[256];
|
||||
ULONG len, full_len, i;
|
||||
static const struct { const WCHAR *name, *target; } symlinks[] = {
|
||||
{ L"\\??\\GLOBALROOT", L"" },
|
||||
{ L"\\??\\GLOBALROOT\\??\\GLOBALROOT", L"" },
|
||||
{ L"\\??\\GLOBALROOT\\??\\GLOBALROOT\\??\\GLOBALROOT", L"" },
|
||||
{ L"\\??\\GLOBALROOT\\DosDevices", L"\\??" },
|
||||
{ L"\\??\\GLOBALROOT\\BaseNamedObjects\\Global", NULL },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(symlinks); i++)
|
||||
{
|
||||
pRtlInitUnicodeString(&str, symlinks[i].name);
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtOpenSymbolicLinkObject( &h, SYMBOLIC_LINK_QUERY, &attr );
|
||||
ok(status == STATUS_SUCCESS, "NtOpenSymbolicLinkObject failed %08x\n", status);
|
||||
|
||||
str.Buffer = buffer;
|
||||
str.MaximumLength = sizeof(buffer);
|
||||
len = 0xdeadbeef;
|
||||
memset( buffer, 0xaa, sizeof(buffer) );
|
||||
status = pNtQuerySymbolicLinkObject( h, &str, &len);
|
||||
ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
|
||||
full_len = str.Length + sizeof(WCHAR);
|
||||
ok( len == full_len, "bad length %u (expected %u)\n", len, full_len );
|
||||
ok( buffer[len / sizeof(WCHAR) - 1] == 0, "no terminating null\n" );
|
||||
|
||||
if (symlinks[i].target)
|
||||
{
|
||||
ok( compare_unicode_string( &str, symlinks[i].target ),
|
||||
"symlink %s: target expected %s, got %s\n",
|
||||
debugstr_w( symlinks[i].name ),
|
||||
debugstr_w( symlinks[i].target ),
|
||||
debugstr_w( str.Buffer ) );
|
||||
}
|
||||
|
||||
pNtClose(h);
|
||||
}
|
||||
|
||||
pRtlInitUnicodeString(&str, L"\\??\\GLOBALROOT\\Device\\Null");
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
status = pNtOpenFile(&h, GENERIC_READ | GENERIC_WRITE, &attr, &iosb,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
|
||||
ok(status == STATUS_SUCCESS,
|
||||
"expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
test_object_type(h, L"File");
|
||||
|
||||
pNtClose(h);
|
||||
}
|
||||
|
||||
START_TEST(om)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
|
@ -2446,4 +2504,5 @@ START_TEST(om)
|
|||
test_duplicate_object();
|
||||
test_object_types();
|
||||
test_get_next_thread();
|
||||
test_globalroot();
|
||||
}
|
||||
|
|
|
@ -378,6 +378,7 @@ void init_directories( struct fd *intl_fd )
|
|||
|
||||
/* symlinks */
|
||||
static const WCHAR link_dosdevW[] = {'D','o','s','D','e','v','i','c','e','s'};
|
||||
static const WCHAR link_globalrootW[] = {'G','L','O','B','A','L','R','O','O','T'};
|
||||
static const WCHAR link_globalW[] = {'G','l','o','b','a','l'};
|
||||
static const WCHAR link_nulW[] = {'N','U','L'};
|
||||
static const WCHAR link_pipeW[] = {'P','I','P','E'};
|
||||
|
@ -392,6 +393,7 @@ void init_directories( struct fd *intl_fd )
|
|||
static const WCHAR link_consoleW[] = {'\\','D','e','v','i','c','e','\\','C','o','n','D','r','v',
|
||||
'\\','C','o','n','s','o','l','e'};
|
||||
static const struct unicode_str link_dosdev_str = {link_dosdevW, sizeof(link_dosdevW)};
|
||||
static const struct unicode_str link_globalroot_str = {link_globalrootW, sizeof(link_globalrootW)};
|
||||
static const struct unicode_str link_global_str = {link_globalW, sizeof(link_globalW)};
|
||||
static const struct unicode_str link_nul_str = {link_nulW, sizeof(link_nulW)};
|
||||
static const struct unicode_str link_pipe_str = {link_pipeW, sizeof(link_pipeW)};
|
||||
|
@ -470,6 +472,7 @@ void init_directories( struct fd *intl_fd )
|
|||
|
||||
/* symlinks */
|
||||
release_object( create_obj_symlink( &root_directory->obj, &link_dosdev_str, OBJ_PERMANENT, &dir_global->obj, NULL ));
|
||||
release_object( create_root_symlink( &dir_global->obj, &link_globalroot_str, OBJ_PERMANENT, NULL ));
|
||||
release_object( create_obj_symlink( &dir_global->obj, &link_global_str, OBJ_PERMANENT, &dir_global->obj, NULL ));
|
||||
release_object( create_obj_symlink( &dir_global->obj, &link_nul_str, OBJ_PERMANENT, null_device, NULL ));
|
||||
release_object( create_obj_symlink( &dir_global->obj, &link_pipe_str, OBJ_PERMANENT, named_pipe_device, NULL ));
|
||||
|
|
|
@ -279,6 +279,8 @@ extern void init_directories( struct fd *intl_fd );
|
|||
|
||||
/* symbolic link functions */
|
||||
|
||||
extern struct object *create_root_symlink( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd );
|
||||
extern struct object *create_obj_symlink( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, struct object *target,
|
||||
const struct security_descriptor *sd );
|
||||
|
|
|
@ -110,6 +110,8 @@ static struct object *symlink_lookup_name( struct object *obj, struct unicode_st
|
|||
if (!name->len && (attr & OBJ_OPENLINK)) return NULL;
|
||||
if (obj == root) return NULL;
|
||||
|
||||
if (!symlink->len) return get_root_directory();
|
||||
|
||||
target_str.str = symlink->target;
|
||||
target_str.len = symlink->len;
|
||||
if ((target = lookup_named_object( NULL, &target_str, attr, &name_left )))
|
||||
|
@ -131,6 +133,17 @@ static void symlink_destroy( struct object *obj )
|
|||
free( symlink->target );
|
||||
}
|
||||
|
||||
struct object *create_root_symlink( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd )
|
||||
{
|
||||
struct symlink *symlink;
|
||||
|
||||
if (!(symlink = create_named_object( root, &symlink_ops, name, attr, sd ))) return NULL;
|
||||
symlink->target = NULL;
|
||||
symlink->len = 0;
|
||||
return &symlink->obj;
|
||||
}
|
||||
|
||||
struct object *create_symlink( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct unicode_str *target,
|
||||
const struct security_descriptor *sd )
|
||||
|
|
Loading…
Reference in New Issue