ntdll: Correct implementation for atom query functions.
This commit is contained in:
parent
30086feb44
commit
b7607aebdc
|
@ -97,6 +97,25 @@ NTSTATUS WINAPI RtlDeleteAtomFromAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* integral_atom_name (internal)
|
||||||
|
*
|
||||||
|
* Helper for fetching integral (local/global) atoms names.
|
||||||
|
*/
|
||||||
|
static ULONG integral_atom_name(WCHAR* buffer, ULONG len, RTL_ATOM atom)
|
||||||
|
{
|
||||||
|
static WCHAR fmt[] = {'#','%','u',0};
|
||||||
|
WCHAR tmp[16];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = sprintfW( tmp, fmt, atom );
|
||||||
|
if (!len) return ret * sizeof(WCHAR);
|
||||||
|
if (len <= ret) ret = len - 1;
|
||||||
|
memcpy( buffer, tmp, ret * sizeof(WCHAR) );
|
||||||
|
buffer[ret] = 0;
|
||||||
|
return ret * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* RtlQueryAtomInAtomTable (NTDLL.@)
|
* RtlQueryAtomInAtomTable (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
|
@ -104,18 +123,13 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, UL
|
||||||
ULONG* pin, WCHAR* name, ULONG* len )
|
ULONG* pin, WCHAR* name, ULONG* len )
|
||||||
{
|
{
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
WCHAR full_name[MAX_ATOM_LEN];
|
|
||||||
DWORD wlen = 0;
|
DWORD wlen = 0;
|
||||||
|
|
||||||
if (!table) status = STATUS_INVALID_PARAMETER;
|
if (!table) status = STATUS_INVALID_PARAMETER;
|
||||||
else if (atom < MAXINTATOM)
|
else if (atom < MAXINTATOM)
|
||||||
{
|
{
|
||||||
if (!atom) return STATUS_INVALID_PARAMETER;
|
if (!atom) return STATUS_INVALID_PARAMETER;
|
||||||
if (len)
|
if (len) wlen = integral_atom_name( name, *len, atom);
|
||||||
{
|
|
||||||
static WCHAR fmt[] = {'#','%','d',0};
|
|
||||||
wlen = sprintfW( full_name, fmt, atom ) * sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
if (ref) *ref = 1;
|
if (ref) *ref = 1;
|
||||||
if (pin) *pin = 1;
|
if (pin) *pin = 1;
|
||||||
}
|
}
|
||||||
|
@ -125,11 +139,12 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, UL
|
||||||
{
|
{
|
||||||
req->atom = atom;
|
req->atom = atom;
|
||||||
req->table = table;
|
req->table = table;
|
||||||
if (len) wine_server_set_reply( req, full_name, sizeof(full_name) );
|
if (len && *len && name)
|
||||||
|
wine_server_set_reply( req, name, *len );
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
wlen = wine_server_reply_size( reply );
|
wlen = reply->total;
|
||||||
if (ref) *ref = reply->count;
|
if (ref) *ref = reply->count;
|
||||||
if (pin) *pin = reply->pinned;
|
if (pin) *pin = reply->pinned;
|
||||||
}
|
}
|
||||||
|
@ -138,17 +153,17 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, UL
|
||||||
}
|
}
|
||||||
if (status == STATUS_SUCCESS && len)
|
if (status == STATUS_SUCCESS && len)
|
||||||
{
|
{
|
||||||
if (*len > wlen)
|
if (*len)
|
||||||
{
|
{
|
||||||
memcpy( name, full_name, wlen );
|
wlen = min( *len - sizeof(WCHAR), wlen );
|
||||||
name[wlen / sizeof(WCHAR)] = 0;
|
if (name) name[wlen / sizeof(WCHAR)] = 0;
|
||||||
}
|
}
|
||||||
else status = STATUS_BUFFER_TOO_SMALL;
|
else status = STATUS_BUFFER_TOO_SMALL;
|
||||||
*len = wlen;
|
*len = wlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE( "%p %x -> %s (%lu)\n",
|
TRACE( "%p %x -> %s (%lx)\n",
|
||||||
table, atom, len ? debugstr_w(name) : NULL, status );
|
table, atom, len ? debugstr_wn(name, wlen / sizeof(WCHAR)) : NULL, status );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,20 +387,20 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
|
||||||
ULONG name_len;
|
ULONG name_len;
|
||||||
ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
|
ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
|
||||||
|
|
||||||
name_len = size - (sizeof(ATOM_BASIC_INFORMATION) - sizeof(WCHAR));
|
if (size < sizeof(ATOM_BASIC_INFORMATION))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
name_len = size - sizeof(ATOM_BASIC_INFORMATION);
|
||||||
|
|
||||||
if (atom < MAXINTATOM)
|
if (atom < MAXINTATOM)
|
||||||
{
|
{
|
||||||
if (!atom) status = STATUS_INVALID_PARAMETER;
|
if (atom)
|
||||||
else if (name_len >= 7 * sizeof(WCHAR))
|
|
||||||
{
|
{
|
||||||
static WCHAR fmt[] = {'#','%','d',0};
|
abi->NameLength = integral_atom_name( abi->Name, name_len, atom );
|
||||||
abi->NameLength = snprintfW( abi->Name, name_len / sizeof(WCHAR), fmt, atom ) * sizeof(WCHAR);
|
status = (name_len) ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL;
|
||||||
abi->ReferenceCount = 1;
|
abi->ReferenceCount = 1;
|
||||||
abi->Pinned = 1;
|
abi->Pinned = 1;
|
||||||
status = STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
else status = STATUS_BUFFER_TOO_SMALL;
|
else status = STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -395,19 +410,32 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
|
||||||
req->table = NULL;
|
req->table = NULL;
|
||||||
if (name_len) wine_server_set_reply( req, abi->Name, name_len );
|
if (name_len) wine_server_set_reply( req, abi->Name, name_len );
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
name_len = wine_server_reply_size( reply );
|
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
abi->NameLength = name_len;
|
name_len = wine_server_reply_size( reply );
|
||||||
|
if (name_len)
|
||||||
|
{
|
||||||
|
abi->NameLength = name_len;
|
||||||
|
abi->Name[name_len / sizeof(WCHAR)] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name_len = reply->total;
|
||||||
|
abi->NameLength = name_len;
|
||||||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
abi->ReferenceCount = reply->count;
|
abi->ReferenceCount = reply->count;
|
||||||
abi->Pinned = reply->pinned;
|
abi->Pinned = reply->pinned;
|
||||||
}
|
}
|
||||||
|
else name_len = 0;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
}
|
}
|
||||||
TRACE( "%x -> %s (%lu)\n", atom, debugstr_wn(abi->Name, name_len/sizeof(WCHAR)), status );
|
TRACE( "%x -> %s (%lu)\n",
|
||||||
|
atom, debugstr_wn(abi->Name, abi->NameLength / sizeof(WCHAR)),
|
||||||
|
status );
|
||||||
if (psize)
|
if (psize)
|
||||||
*psize = sizeof(ATOM_BASIC_INFORMATION) - sizeof(WCHAR) + name_len;
|
*psize = sizeof(ATOM_BASIC_INFORMATION) + name_len;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -54,6 +54,9 @@ static NTSTATUS (WINAPI *pRtlLookupAtomInAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_A
|
||||||
static NTSTATUS (WINAPI *pRtlPinAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM);
|
static NTSTATUS (WINAPI *pRtlPinAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM);
|
||||||
static NTSTATUS (WINAPI *pRtlQueryAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM,PULONG,PULONG,PWSTR,PULONG);
|
static NTSTATUS (WINAPI *pRtlQueryAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM,PULONG,PULONG,PWSTR,PULONG);
|
||||||
|
|
||||||
|
static NTSTATUS (WINAPI* pNtAddAtom)(LPCWSTR,ULONG,RTL_ATOM*);
|
||||||
|
static NTSTATUS (WINAPI* pNtQueryInformationAtom)(RTL_ATOM,DWORD,void*,ULONG,PULONG);
|
||||||
|
|
||||||
static const WCHAR EmptyAtom[] = {0};
|
static const WCHAR EmptyAtom[] = {0};
|
||||||
static const WCHAR testAtom1[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
|
static const WCHAR testAtom1[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
|
||||||
static const WCHAR testAtom2[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0};
|
static const WCHAR testAtom2[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0};
|
||||||
|
@ -81,6 +84,9 @@ static void InitFunctionPtr(void)
|
||||||
pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable");
|
pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable");
|
||||||
pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable");
|
pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable");
|
||||||
pRtlQueryAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlQueryAtomInAtomTable");
|
pRtlQueryAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlQueryAtomInAtomTable");
|
||||||
|
|
||||||
|
pNtAddAtom = (void *)GetProcAddress(hntdll, "NtAddAtom");
|
||||||
|
pNtQueryInformationAtom = (void *)GetProcAddress(hntdll, "NtQueryInformationAtom");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +198,15 @@ static void test_NtAtom(void)
|
||||||
ok(!strcmpW(Name, testAtom2), "We found wrong atom\n");
|
ok(!strcmpW(Name, testAtom2), "We found wrong atom\n");
|
||||||
ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
|
ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
|
||||||
|
|
||||||
|
Len = 8;
|
||||||
|
Name[0] = Name[1] = Name[2] = Name[3] = Name[4] = 0x55AA;
|
||||||
|
res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, NULL, NULL, Name, &Len);
|
||||||
|
ok(!res, "query atom %lx\n", res);
|
||||||
|
ok(Len == 6, "wrong length %lu\n", Len);
|
||||||
|
ok(!memcmp(Name, testAtom2, Len), "wrong atom string\n");
|
||||||
|
ok(!Name[3], "wrong string termination\n");
|
||||||
|
ok(Name[4] == 0x55AA, "buffer overwrite\n");
|
||||||
|
|
||||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
|
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
|
||||||
ok(!res, "We can't find our pinned atom!! retval: %lx\n", res);
|
ok(!res, "We can't find our pinned atom!! retval: %lx\n", res);
|
||||||
ok(testAtom == Atom2, "We found wrong atom!!!\n");
|
ok(testAtom == Atom2, "We found wrong atom!!!\n");
|
||||||
|
@ -402,6 +417,47 @@ static void test_NtRefPinAtom(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_Global(void)
|
||||||
|
{
|
||||||
|
NTSTATUS res;
|
||||||
|
RTL_ATOM atom;
|
||||||
|
char ptr[sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR)];
|
||||||
|
ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
|
||||||
|
ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR);
|
||||||
|
|
||||||
|
res = pNtAddAtom(testAtom1, lstrlenW(testAtom1) * sizeof(WCHAR), &atom);
|
||||||
|
ok(!res, "Added atom (%lx)\n", res);
|
||||||
|
|
||||||
|
memset(abi->Name, 0x55, 255 * sizeof(WCHAR));
|
||||||
|
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||||
|
ok(!res, "atom lookup\n");
|
||||||
|
ok(!lstrcmpW(abi->Name, testAtom1), "ok strings\n");
|
||||||
|
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
|
||||||
|
ok(abi->Name[lstrlenW(testAtom1)] == 0, "wrong string termination %x\n", abi->Name[lstrlenW(testAtom1)]);
|
||||||
|
ok(abi->Name[lstrlenW(testAtom1) + 1] == 0x5555, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
|
||||||
|
|
||||||
|
ptr_size = sizeof(ATOM_BASIC_INFORMATION);
|
||||||
|
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||||
|
ok(res == STATUS_BUFFER_TOO_SMALL, "wrong return status (%lx)\n", res);
|
||||||
|
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "ok string length\n");
|
||||||
|
|
||||||
|
memset(abi->Name, 0x55, lstrlenW(testAtom1) * sizeof(WCHAR));
|
||||||
|
ptr_size = sizeof(ATOM_BASIC_INFORMATION) + lstrlenW(testAtom1) * sizeof(WCHAR);
|
||||||
|
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||||
|
ok(!res, "atom lookup %lx\n", res);
|
||||||
|
ok(!lstrcmpW(abi->Name, testAtom1), "strings don't match\n");
|
||||||
|
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
|
||||||
|
ok(abi->Name[lstrlenW(testAtom1)] == 0, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1)]);
|
||||||
|
ok(abi->Name[lstrlenW(testAtom1) + 1] == 0x5555, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
|
||||||
|
|
||||||
|
ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 4 * sizeof(WCHAR);
|
||||||
|
abi->Name[0] = abi->Name[1] = abi->Name[2] = abi->Name[3] = '\0';
|
||||||
|
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||||
|
ok(!res, "couldn't find atom\n");
|
||||||
|
ok(abi->NameLength == 8, "wrong string length %u\n", abi->NameLength);
|
||||||
|
ok(!memcmp(abi->Name, testAtom1, 8), "strings don't match\n");
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(atom)
|
START_TEST(atom)
|
||||||
{
|
{
|
||||||
InitFunctionPtr();
|
InitFunctionPtr();
|
||||||
|
@ -410,5 +466,6 @@ START_TEST(atom)
|
||||||
test_NtAtom();
|
test_NtAtom();
|
||||||
test_NtIntAtom();
|
test_NtIntAtom();
|
||||||
test_NtRefPinAtom();
|
test_NtRefPinAtom();
|
||||||
|
test_Global();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2078,6 +2078,7 @@ struct get_atom_information_reply
|
||||||
struct reply_header __header;
|
struct reply_header __header;
|
||||||
int count;
|
int count;
|
||||||
int pinned;
|
int pinned;
|
||||||
|
size_t total;
|
||||||
/* VARARG(name,unicode_str); */
|
/* VARARG(name,unicode_str); */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4346,6 +4347,6 @@ union generic_reply
|
||||||
struct query_symlink_reply query_symlink_reply;
|
struct query_symlink_reply query_symlink_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 217
|
#define SERVER_PROTOCOL_VERSION 218
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -413,10 +413,11 @@ DECL_HANDLER(get_atom_information)
|
||||||
if ((entry = get_atom_entry( table, req->atom )))
|
if ((entry = get_atom_entry( table, req->atom )))
|
||||||
{
|
{
|
||||||
size_t len = entry->len * sizeof(WCHAR);
|
size_t len = entry->len * sizeof(WCHAR);
|
||||||
if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
|
if (get_reply_max_size())
|
||||||
else if (get_reply_max_size()) set_error( STATUS_BUFFER_OVERFLOW );
|
set_reply_data( entry->str, min( len, get_reply_max_size()));
|
||||||
reply->count = entry->count;
|
reply->count = entry->count;
|
||||||
reply->pinned = entry->pinned;
|
reply->pinned = entry->pinned;
|
||||||
|
reply->total = len;
|
||||||
}
|
}
|
||||||
else reply->count = -1;
|
else reply->count = -1;
|
||||||
release_object( table );
|
release_object( table );
|
||||||
|
|
|
@ -1488,6 +1488,7 @@ enum char_info_mode
|
||||||
@REPLY
|
@REPLY
|
||||||
int count; /* atom lock count */
|
int count; /* atom lock count */
|
||||||
int pinned; /* whether the atom has been pinned */
|
int pinned; /* whether the atom has been pinned */
|
||||||
|
size_t total; /* actual length of atom name */
|
||||||
VARARG(name,unicode_str); /* atom name */
|
VARARG(name,unicode_str); /* atom name */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
|
@ -1961,6 +1961,7 @@ static void dump_get_atom_information_reply( const struct get_atom_information_r
|
||||||
{
|
{
|
||||||
fprintf( stderr, " count=%d,", req->count );
|
fprintf( stderr, " count=%d,", req->count );
|
||||||
fprintf( stderr, " pinned=%d,", req->pinned );
|
fprintf( stderr, " pinned=%d,", req->pinned );
|
||||||
|
fprintf( stderr, " total=%d,", req->total );
|
||||||
fprintf( stderr, " name=" );
|
fprintf( stderr, " name=" );
|
||||||
dump_varargs_unicode_str( cur_size );
|
dump_varargs_unicode_str( cur_size );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue