[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