ntdll / kernel32: #52-e3
Eric Pouech
eric.pouech at wanadoo.fr
Sun Dec 11 02:56:52 CST 2005
Finish moving atom handling from kernel32 to ntdll.
Fixed a couple of failing test at the same time.
A+
--
Eric Pouech
-------------- next part --------------
Subject: [PATCH]
- fixed ntdll's function about atom query (local / global)
- implemented kernel32 atom query functions on top of ntdll's ones
---
dlls/kernel/atom.c | 177 ++++++++++++++++++----------------------
dlls/kernel/tests/atom.c | 23 ++---
dlls/ntdll/atom.c | 81 +++++++++++++-----
server/atom.c | 5 +
server/protocol.def | 3 -
5 files changed, 153 insertions(+), 142 deletions(-)
applies-to: 410aa2e7eec4336305e9407ae20067321e790da6
bc0753b7a64146dc9bb5821b9d24fde0f72216c1
diff --git a/dlls/kernel/atom.c b/dlls/kernel/atom.c
index 5db47e8..4ea0f5f 100644
--- a/dlls/kernel/atom.c
+++ b/dlls/kernel/atom.c
@@ -398,59 +398,6 @@ ATOM WINAPI FindAtomW( LPCWSTR str )
}
-static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, struct atom_table* table )
-{
- INT len;
-
- if (count <= 0)
- {
- SetLastError( ERROR_MORE_DATA );
- return 0;
- }
- if (atom < MAXINTATOM)
- {
- char name[8];
- if (!atom)
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return 0;
- }
- len = sprintf( name, "#%d", atom );
- lstrcpynA( buffer, name, count );
- }
- else
- {
- WCHAR full_name[MAX_ATOM_LEN];
-
- len = 0;
- SERVER_START_REQ( get_atom_information )
- {
- req->atom = atom;
- req->table = table;
- wine_server_set_reply( req, full_name, sizeof(full_name) );
- if (!wine_server_call_err( req ))
- {
- len = WideCharToMultiByte( CP_ACP, 0, full_name,
- wine_server_reply_size(reply) / sizeof(WCHAR),
- buffer, count - 1, NULL, NULL );
- if (!len) len = count; /* overflow */
- else buffer[len] = 0;
- }
- }
- SERVER_END_REQ;
- }
-
- if (len && count <= len)
- {
- SetLastError( ERROR_MORE_DATA );
- buffer[count-1] = 0;
- return 0;
- }
- TRACE( "(%s) %x -> %s\n", table ? "local" : "global", atom, debugstr_a(buffer) );
- return len;
-}
-
-
/***********************************************************************
* GlobalGetAtomNameA (KERNEL32.@)
*
@@ -465,7 +412,25 @@ UINT WINAPI GlobalGetAtomNameA(
LPSTR buffer, /* [out] Pointer to buffer for atom string */
INT count ) /* [in] Size of buffer */
{
- return ATOM_GetAtomNameA( atom, buffer, count, NULL );
+ WCHAR tmpW[MAX_ATOM_LEN + 1];
+ UINT wlen, len = 0, c;
+
+ if (count <= 0) SetLastError( ERROR_MORE_DATA );
+ else if ((wlen = GlobalGetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
+ {
+ char tmp[MAX_ATOM_LEN + 1];
+
+ len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
+ c = min(len, count - 1);
+ memcpy(buffer, tmp, c);
+ buffer[c] = '\0';
+ if (len >= count)
+ {
+ len = 0;
+ SetLastError( ERROR_MORE_DATA );
+ }
+ }
+ return len;
}
@@ -483,53 +448,24 @@ UINT WINAPI GetAtomNameA(
LPSTR buffer, /* [out] Pointer to string for atom string */
INT count) /* [in] Size of buffer */
{
- return ATOM_GetAtomNameA( atom, buffer, count, get_local_table(0) );
-}
+ WCHAR tmpW[MAX_ATOM_LEN + 1];
+ UINT wlen, len = 0, c;
-
-static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, struct atom_table* table )
-{
- INT len;
-
- if (count <= 0)
+ if (count <= 0) SetLastError( ERROR_MORE_DATA );
+ else if ((wlen = GetAtomNameW( atom, tmpW, MAX_ATOM_LEN + 1 )))
{
- SetLastError( ERROR_MORE_DATA );
- return 0;
- }
- if (atom < MAXINTATOM)
- {
- char name[8];
- if (!atom)
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return 0;
- }
- sprintf( name, "#%d", atom );
- len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
- if (!len) buffer[count-1] = 0; /* overflow */
- }
- else
- {
- WCHAR full_name[MAX_ATOM_LEN];
+ char tmp[MAX_ATOM_LEN + 1];
- len = 0;
- SERVER_START_REQ( get_atom_information )
+ len = WideCharToMultiByte( CP_ACP, 0, tmpW, wlen, tmp, MAX_ATOM_LEN + 1, NULL, NULL );
+ c = min(len, count - 1);
+ memcpy(buffer, tmp, c);
+ buffer[c] = '\0';
+ if (len >= count)
{
- req->atom = atom;
- req->table = table;
- wine_server_set_reply( req, full_name, sizeof(full_name) );
- if (!wine_server_call_err( req ))
- {
- len = wine_server_reply_size(reply) / sizeof(WCHAR);
- if (count > len) count = len + 1;
- memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
- buffer[count-1] = 0;
- }
+ len = c;
+ SetLastError( ERROR_MORE_DATA );
}
- SERVER_END_REQ;
- if (!len) return 0;
}
- TRACE( "(%s) %x -> %s\n", table ? "local" : "global", atom, debugstr_w(buffer) );
return len;
}
@@ -541,7 +477,31 @@ static UINT ATOM_GetAtomNameW( ATOM atom
*/
UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
{
- return ATOM_GetAtomNameW( atom, buffer, count, NULL);
+ char ptr[sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR)];
+ ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
+ ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR);
+ NTSTATUS status;
+ UINT length = 0;
+
+ if (count <= 0)
+ {
+ SetLastError( ERROR_MORE_DATA );
+ return 0;
+ }
+ status = NtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
+ if (status) SetLastError( RtlNtStatusToDosError( status ) );
+ else
+ {
+ length = min( abi->NameLength / sizeof(WCHAR), count);
+ memcpy( buffer, abi->Name, length * sizeof(WCHAR) );
+ if (length < abi->NameLength / sizeof(WCHAR))
+ {
+ SetLastError( ERROR_MORE_DATA );
+ length = count;
+ }
+ else buffer[length] = '\0';
+ }
+ return length;
}
@@ -552,5 +512,28 @@ UINT WINAPI GlobalGetAtomNameW( ATOM ato
*/
UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
{
- return ATOM_GetAtomNameW( atom, buffer, count, get_local_table(0) );
+ NTSTATUS status;
+ RTL_ATOM_TABLE table;
+ DWORD length;
+ WCHAR tmp[MAX_ATOM_LEN + 1];
+
+ if (count <= 0)
+ {
+ SetLastError( ERROR_MORE_DATA );
+ return 0;
+ }
+ if (!(table = get_local_table( 0 ))) return 0;
+ length = sizeof(tmp);
+ status = RtlQueryAtomInAtomTable( table, atom, NULL, NULL, tmp, &length );
+ if (status)
+ {
+ SetLastError( RtlNtStatusToDosError( status ) );
+ return 0;
+ }
+ length = min(length, (count - 1) * sizeof(WCHAR));
+ if (length) memcpy(buffer, tmp, length);
+ else SetLastError( ERROR_INSUFFICIENT_BUFFER );
+ length /= sizeof(WCHAR);
+ buffer[length] = '\0';
+ return length;
}
diff --git a/dlls/kernel/tests/atom.c b/dlls/kernel/tests/atom.c
index 5ab53b7..2fbce32 100644
--- a/dlls/kernel/tests/atom.c
+++ b/dlls/kernel/tests/atom.c
@@ -262,10 +262,7 @@ static void test_get_atom_name(void)
{
WCHAR res[20];
- if (len < 7) /* FIXME: temporary before we fix it */
- ok( (len > 1) && (len < 7), "bad length %d\n", len );
- else
- todo_wine ok( (len > 1) && (len < 7), "bad length %d\n", len );
+ ok( (len > 1) && (len < 7), "bad length %d\n", len );
print_integral( res, i );
memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
@@ -277,7 +274,7 @@ static void test_get_atom_name(void)
len = GlobalGetAtomNameW( (ATOM)i, outW, 1);
if (i)
{
- todo_wine ok(len == 1, "succeed (got %u instead of 1)\n", len);
+ ok(len == 1, "succeed (got %u instead of 1)\n", len);
ok(outW[1] == DOUBLE('.'), "buffer overwrite\n");
}
else ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "0 badly handled\n");
@@ -295,13 +292,10 @@ static void test_get_atom_name(void)
ok(outW[255] == '\0', "wrong end of string\n");
memset(outW, '.', sizeof(outW));
len = GlobalGetAtomNameW(atom, outW, 10);
- todo_wine ok(len == 10, "succeeded\n");
+ ok(len == 10, "succeeded\n");
for (i = 0; i < 10; i++)
{
- if (i < 9) /* FIXME: temporary */
- ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
- else
- todo_wine ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
+ ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
}
ok(outW[10] == DOUBLE('.'), "wrote after end of buf\n");
do_initW(inW, "abcdefghij", 256);
@@ -488,7 +482,7 @@ static void test_local_get_atom_name(voi
ok(out[255] == '\0', "wrong end of string\n");
memset(out, '.', sizeof(out));
len = GetAtomNameA(atom, out, 10);
- todo_wine ok(len == 9, "succeeded %d\n", len);
+ ok(len == 9, "succeeded %d\n", len);
for (i = 0; i < 9; i++)
{
ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
@@ -516,10 +510,7 @@ static void test_local_get_atom_name(voi
{
WCHAR res[20];
- if (len < 7) /* FIXME: temporary before we fix it */
- ok( (len > 1) && (len < 7), "bad length %d\n", len );
- else
- todo_wine ok( (len > 1) && (len < 7), "bad length %d\n", len );
+ ok( (len > 1) && (len < 7), "bad length %d\n", len );
print_integral( res, i );
memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
@@ -547,7 +538,7 @@ static void test_local_get_atom_name(voi
ok(outW[255] == '\0', "wrong end of string\n");
memset(outW, '.', sizeof(outW));
len = GetAtomNameW(atom, outW, 10);
- todo_wine ok(len == 9, "succeeded %d\n", len);
+ ok(len == 9, "succeeded %d\n", len);
for (i = 0; i < 9; i++)
{
ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
diff --git a/dlls/ntdll/atom.c b/dlls/ntdll/atom.c
index bdef98b..4d63217 100644
--- a/dlls/ntdll/atom.c
+++ b/dlls/ntdll/atom.c
@@ -98,24 +98,43 @@ NTSTATUS WINAPI RtlDeleteAtomFromAtomTab
}
/******************************************************************
+ * 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[] = {'#','%','d',0};
+ int ret;
+
+ if (!len)
+ {
+ WCHAR tmp[16];
+ return integral_atom_name( tmp, sizeof(tmp)/sizeof(tmp[0]), atom );
+ }
+ len /= sizeof(WCHAR);
+ ret = snprintfW( buffer, len, fmt, atom );
+ if (ret == -1)
+ buffer[--len] = '\0';
+ else
+ len = ret;
+ return len * sizeof(WCHAR);
+}
+
+/******************************************************************
* RtlQueryAtomInAtomTable (NTDLL.@)
*/
NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, ULONG* ref,
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 +144,12 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable(
{
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 +158,17 @@ NTSTATUS WINAPI RtlQueryAtomInAtomTable(
}
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 +392,20 @@ NTSTATUS WINAPI NtQueryInformationAtom(
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 +415,32 @@ NTSTATUS WINAPI NtQueryInformationAtom(
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:
diff --git a/server/atom.c b/server/atom.c
index e42a503..3ad6c04 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -412,10 +412,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 );
diff --git a/server/protocol.def b/server/protocol.def
index 3d055cb..58e369b 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1476,6 +1476,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
---
0.99.9k
More information about the wine-patches
mailing list