[PATCH 3/4] [NtDll]: tests for
NtQueryInformationThread(ThreadDescriptorTableEntry)
Eric Pouech
eric.pouech at wanadoo.fr
Sat Nov 4 04:52:40 CST 2006
A+
---
dlls/ntdll/tests/selector.c | 90 ++++++++++++++++++++++++++++++++++++++++---
1 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/tests/selector.c b/dlls/ntdll/tests/selector.c
index 0c7402d..b843c5e 100644
--- a/dlls/ntdll/tests/selector.c
+++ b/dlls/ntdll/tests/selector.c
@@ -32,9 +32,17 @@ #ifdef __i386__
*/
static int (WINAPI *pNtQueryInformationProcess)(HANDLE,DWORD,VOID*,DWORD,DWORD*);
static int (WINAPI *pNtSetInformationProcess)(HANDLE,DWORD,VOID*,DWORD);
+static int (WINAPI *pNtQueryInformationThread)(HANDLE,DWORD,VOID*,DWORD,DWORD*);
#if defined(__GNUC__)
+static unsigned short get_cs(void)
+{
+ unsigned short res;
+ __asm__("movw %%cs,%w0" : "=r"(res));
+ return res;
+}
+
#include <setjmp.h>
static jmp_buf jb;
@@ -68,6 +76,8 @@ static DWORD low_read_mem(WORD sel, DWOR
#elif defined(_MSC_VER)
+static unsigned short get_cs(void) { __asm mov ax, cs; }
+
static DWORD low_read_mem(WORD sel, DWORD offst)
{
__asm push gs;
@@ -243,6 +253,52 @@ static BOOL compare_ldt(const LDT_ENTRY*
return ret;
}
+static void test_fail_thread(BOOL with_empty_ldt, unsigned first_ldt)
+{
+ DWORD buf[12];
+ THREAD_DESCRIPTOR_INFORMATION* tdi = (void*)buf;
+ NTSTATUS status;
+ DWORD dw;
+
+ tdi->Selector = get_cs() & ~3;
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+
+ tdi->Selector = get_cs() | 3;
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+
+ tdi->Selector = get_cs();
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 4, &dw);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Wrong status %x\n", status);
+
+ /* try out of bounds entry */
+ tdi->Selector = LDT(8192, 3);
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ if (with_empty_ldt)
+ todo_wine ok(status == STATUS_NO_LDT, "Wrong status %x (empty)\n", status);
+ else
+ ok(status == STATUS_ACCESS_VIOLATION, "Wrong status %x (used)\n", status);
+
+ /* we assume last LDT entry is unused */
+ tdi->Selector = LDT(8191, 3);
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ if (with_empty_ldt)
+ todo_wine ok(status == STATUS_NO_LDT, "Wrong status %x (empty)\n", status);
+ else
+ ok(status == STATUS_ACCESS_VIOLATION, "Wrong status %x (used)\n", status);
+
+ ok(first_ldt > 0, "First ldt shouldn't be zero\n");
+ tdi->Selector = LDT(first_ldt - 1, 3);
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ if (with_empty_ldt)
+ todo_wine ok(status == STATUS_NO_LDT, "Wrong status %x (empty)\n", status);
+ else
+ ok(status == STATUS_SUCCESS, "Wrong status %x (used)\n", status);
+}
+
static void fill_ldt(LDT_ENTRY* le, DWORD base, DWORD npages)
{
le->BaseLow = base & 0xFFFF;
@@ -261,13 +317,14 @@ static void fill_ldt(LDT_ENTRY* le, DWOR
static void test_new_ldt(unsigned entry)
{
- LDT_ENTRY le;
- DWORD test;
- DWORD ret;
- DWORD buf[12];
- PROCESS_LDT_INFORMATION* pli = (PROCESS_LDT_INFORMATION*)buf;
- NTSTATUS status;
- DWORD dw;
+ LDT_ENTRY le;
+ DWORD test;
+ DWORD ret;
+ DWORD buf[12];
+ PROCESS_LDT_INFORMATION* pli = (PROCESS_LDT_INFORMATION*)buf;
+ THREAD_DESCRIPTOR_INFORMATION* tdi = (THREAD_DESCRIPTOR_INFORMATION*)buf;
+ NTSTATUS status;
+ DWORD dw;
/* create a new ldt of one page, which contains test */
fill_ldt(&le, (DWORD)&test, 1);
@@ -295,6 +352,14 @@ static void test_new_ldt(unsigned entry)
ok(ret == 0x4321, "Wrong value for read %x\n", ret);
memset(buf, 0, sizeof(buf));
+ tdi->Selector = LDT(entry, 3);
+ dw = 0;
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "wrong dw value %d\n", dw);
+ ok(compare_ldt(&tdi->Entry, &le), "Wrong LE value\n");
+
+ memset(buf, 0, sizeof(buf));
pli->dwSelector = PROC_LDT(entry);
pli->dwSize = 8;
dw = 0;
@@ -320,6 +385,14 @@ static void test_new_ldt(unsigned entry)
ok(status == STATUS_SUCCESS, "should have set LDT (%x)\n", status);
memset(buf, 0, sizeof(buf));
+ tdi->Selector = LDT(entry + 1, 3);
+ dw = 0;
+ status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, buf, 12, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "wrong dw value %d\n", dw);
+ ok(compare_ldt(&tdi->Entry, &le), "Wrong LE value\n");
+
+ memset(buf, 0, sizeof(buf));
pli->dwSelector = PROC_LDT(entry);
pli->dwSize = 8;
dw = 0;
@@ -385,12 +458,15 @@ #ifdef __i386__
#define X(f) p##f = (void*)GetProcAddress(h, #f); if (!p##f) {printf("Cannot load " #f "\n"); return;}
X(NtQueryInformationProcess);
X(NtSetInformationProcess);
+ X(NtQueryInformationThread);
#undef X
/* first, find an unused selector */
entry = find_unused_ldt_entry();
if (entry >= 8192) return;
test_fail_process(entry);
+ test_fail_thread(TRUE, entry);
test_new_ldt(entry);
+ test_fail_thread(FALSE, entry);
#endif /* __i386__ */
}
More information about the wine-patches
mailing list