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;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* 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.@)
|
||||
*/
|
||||
|
@ -104,18 +123,13 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, UL
|
|||
ULONG* pin, WCHAR* name, ULONG* len )
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
WCHAR full_name[MAX_ATOM_LEN];
|
||||
DWORD wlen = 0;
|
||||
|
||||
if (!table) status = STATUS_INVALID_PARAMETER;
|
||||
else if (atom < MAXINTATOM)
|
||||
{
|
||||
if (!atom) return STATUS_INVALID_PARAMETER;
|
||||
if (len)
|
||||
{
|
||||
static WCHAR fmt[] = {'#','%','d',0};
|
||||
wlen = sprintfW( full_name, fmt, atom ) * sizeof(WCHAR);
|
||||
}
|
||||
if (len) wlen = integral_atom_name( name, *len, atom);
|
||||
if (ref) *ref = 1;
|
||||
if (pin) *pin = 1;
|
||||
}
|
||||
|
@ -125,11 +139,12 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, UL
|
|||
{
|
||||
req->atom = atom;
|
||||
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 );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
wlen = wine_server_reply_size( reply );
|
||||
wlen = reply->total;
|
||||
if (ref) *ref = reply->count;
|
||||
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 (*len > wlen)
|
||||
if (*len)
|
||||
{
|
||||
memcpy( name, full_name, wlen );
|
||||
name[wlen / sizeof(WCHAR)] = 0;
|
||||
wlen = min( *len - sizeof(WCHAR), wlen );
|
||||
if (name) name[wlen / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
else status = STATUS_BUFFER_TOO_SMALL;
|
||||
*len = wlen;
|
||||
}
|
||||
|
||||
TRACE( "%p %x -> %s (%lu)\n",
|
||||
table, atom, len ? debugstr_w(name) : NULL, status );
|
||||
TRACE( "%p %x -> %s (%lx)\n",
|
||||
table, atom, len ? debugstr_wn(name, wlen / sizeof(WCHAR)) : NULL, status );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -372,20 +387,20 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
|
|||
ULONG name_len;
|
||||
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) status = STATUS_INVALID_PARAMETER;
|
||||
else if (name_len >= 7 * sizeof(WCHAR))
|
||||
if (atom)
|
||||
{
|
||||
static WCHAR fmt[] = {'#','%','d',0};
|
||||
abi->NameLength = snprintfW( abi->Name, name_len / sizeof(WCHAR), fmt, atom ) * sizeof(WCHAR);
|
||||
abi->NameLength = integral_atom_name( abi->Name, name_len, atom );
|
||||
status = (name_len) ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL;
|
||||
abi->ReferenceCount = 1;
|
||||
abi->Pinned = 1;
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else status = STATUS_BUFFER_TOO_SMALL;
|
||||
else status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -395,19 +410,32 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
|
|||
req->table = NULL;
|
||||
if (name_len) wine_server_set_reply( req, abi->Name, name_len );
|
||||
status = wine_server_call( req );
|
||||
name_len = wine_server_reply_size( reply );
|
||||
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->Pinned = reply->pinned;
|
||||
}
|
||||
else name_len = 0;
|
||||
}
|
||||
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)
|
||||
*psize = sizeof(ATOM_BASIC_INFORMATION) - sizeof(WCHAR) + name_len;
|
||||
*psize = sizeof(ATOM_BASIC_INFORMATION) + name_len;
|
||||
}
|
||||
break;
|
||||
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 *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 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};
|
||||
|
@ -81,6 +84,9 @@ static void InitFunctionPtr(void)
|
|||
pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable");
|
||||
pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable");
|
||||
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((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);
|
||||
ok(!res, "We can't find our pinned atom!! retval: %lx\n", res);
|
||||
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)
|
||||
{
|
||||
InitFunctionPtr();
|
||||
|
@ -410,5 +466,6 @@ START_TEST(atom)
|
|||
test_NtAtom();
|
||||
test_NtIntAtom();
|
||||
test_NtRefPinAtom();
|
||||
test_Global();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2078,6 +2078,7 @@ struct get_atom_information_reply
|
|||
struct reply_header __header;
|
||||
int count;
|
||||
int pinned;
|
||||
size_t total;
|
||||
/* VARARG(name,unicode_str); */
|
||||
};
|
||||
|
||||
|
@ -4346,6 +4347,6 @@ union generic_reply
|
|||
struct query_symlink_reply query_symlink_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 217
|
||||
#define SERVER_PROTOCOL_VERSION 218
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -413,10 +413,11 @@ DECL_HANDLER(get_atom_information)
|
|||
if ((entry = get_atom_entry( table, req->atom )))
|
||||
{
|
||||
size_t len = entry->len * sizeof(WCHAR);
|
||||
if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
|
||||
else if (get_reply_max_size()) set_error( STATUS_BUFFER_OVERFLOW );
|
||||
if (get_reply_max_size())
|
||||
set_reply_data( entry->str, min( len, get_reply_max_size()));
|
||||
reply->count = entry->count;
|
||||
reply->pinned = entry->pinned;
|
||||
reply->total = len;
|
||||
}
|
||||
else reply->count = -1;
|
||||
release_object( table );
|
||||
|
|
|
@ -1488,6 +1488,7 @@ enum char_info_mode
|
|||
@REPLY
|
||||
int count; /* atom lock count */
|
||||
int pinned; /* whether the atom has been pinned */
|
||||
size_t total; /* actual length of atom name */
|
||||
VARARG(name,unicode_str); /* atom name */
|
||||
@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, " pinned=%d,", req->pinned );
|
||||
fprintf( stderr, " total=%d,", req->total );
|
||||
fprintf( stderr, " name=" );
|
||||
dump_varargs_unicode_str( cur_size );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue