[PATCH 1/4] [NTDLL]: added ldt query on processes
Eric Pouech
eric.pouech at wanadoo.fr
Sat Nov 4 04:52:29 CST 2006
- NtQueryInformationProcess: implemented ProcessLdtInformation class
A+
---
dlls/ntdll/process.c | 48 ++++++++++++
dlls/ntdll/tests/Makefile.in | 1
dlls/ntdll/tests/selector.c | 164 ++++++++++++++++++++++++++++++++++++++++++
include/winternl.h | 6 ++
4 files changed, 217 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c
index 5af750d..7b8fcaa 100644
--- a/dlls/ntdll/process.c
+++ b/dlls/ntdll/process.c
@@ -34,6 +34,7 @@ #include "windef.h"
#include "winternl.h"
#include "ntdll_misc.h"
#include "wine/server.h"
+#include "wine/library.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -104,7 +105,6 @@ NTSTATUS WINAPI NtQueryInformationProces
UNIMPLEMENTED_INFO_CLASS(ProcessRaisePriority);
UNIMPLEMENTED_INFO_CLASS(ProcessExceptionPort);
UNIMPLEMENTED_INFO_CLASS(ProcessAccessToken);
- UNIMPLEMENTED_INFO_CLASS(ProcessLdtInformation);
UNIMPLEMENTED_INFO_CLASS(ProcessLdtSize);
UNIMPLEMENTED_INFO_CLASS(ProcessDefaultHardErrorMode);
UNIMPLEMENTED_INFO_CLASS(ProcessIoPortHandlers);
@@ -291,6 +291,50 @@ NTSTATUS WINAPI NtQueryInformationProces
}
else ret = STATUS_INFO_LENGTH_MISMATCH;
break;
+ case ProcessLdtInformation:
+#ifdef __i386__
+ if (ProcessHandle != GetCurrentProcess())
+ {
+ FIXME("Unsupported yet on other processes\n");
+ ret = STATUS_NOT_IMPLEMENTED;
+ }
+ else if ((ProcessInformationLength & 7) == 0)
+ {
+ PROCESS_LDT_INFORMATION* pli = ProcessInformation;
+ LDT_ENTRY le;
+
+ /* only works for clean LDT indexes */
+ if ((pli->dwSelector & 7) != 0)
+ ret = STATUS_INVALID_LDT_OFFSET;
+ else if (ProcessInformationLength < 2 * sizeof(DWORD) + pli->dwSize)
+ ret = STATUS_INFO_LENGTH_MISMATCH;
+ else if ((pli->dwSize % sizeof(LDT_ENTRY)) != 0)
+ ret = STATUS_INVALID_LDT_SIZE;
+ else
+ {
+ int i;
+
+ len = 2 * sizeof(DWORD);
+ for (i = 0; i < pli->dwSize / sizeof(LDT_ENTRY); i++)
+ {
+ wine_ldt_get_entry(pli->dwSelector + (i << 3) + 4, &le);
+ if (!wine_ldt_is_empty(&le))
+ {
+ len += sizeof(LDT_ENTRY);
+ pli->ldt[i] = le;
+ }
+ }
+ /* FIXME: it should return the full LDT size, but we don't
+ * properly handle this field yet
+ */
+ pli->dwSize = 0;
+ }
+ }
+ else ret = STATUS_INFO_LENGTH_MISMATCH;
+#else
+ ret = STATUS_NOT_IMPLEMENTED;
+#endif
+ break;
default:
FIXME("(%p,info_class=%d,%p,0x%08x,%p) Unknown information class\n",
ProcessHandle,ProcessInformationClass,
@@ -300,7 +344,7 @@ NTSTATUS WINAPI NtQueryInformationProces
break;
}
- if (ReturnLength) *ReturnLength = len;
+ if (ret == STATUS_SUCCESS && ReturnLength) *ReturnLength = len;
return ret;
}
diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in
index cccc4c5..de923fa 100644
--- a/dlls/ntdll/tests/Makefile.in
+++ b/dlls/ntdll/tests/Makefile.in
@@ -21,6 +21,7 @@ CTESTS = \
rtl.c \
rtlbitmap.c \
rtlstr.c \
+ selector.c \
string.c \
time.c
diff --git a/dlls/ntdll/tests/selector.c b/dlls/ntdll/tests/selector.c
new file mode 100644
index 0000000..4d3ea92
--- /dev/null
+++ b/dlls/ntdll/tests/selector.c
@@ -0,0 +1,164 @@
+/*
+ * LDT and GDT tests
+ *
+ * Copyright 2006 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#include <ntstatus.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <stdio.h>
+#include <winternl.h>
+#include "wine/test.h"
+
+#ifdef __i386__
+
+/* TODO:
+ * - test the dwSize value returned from ProcessLdtInformation (should be the total
+ * LDT size, but we don't handle it yet correctly)
+ */
+static int (WINAPI *pNtQueryInformationProcess)(HANDLE,DWORD,VOID*,DWORD,DWORD*);
+
+#define __SEL(x,r) (((x) << 3) | ((r) & 3))
+#define LDT(x,r) (__SEL((x), (r)) | 4)
+#define GDT(x,r) __SEL((x), (r))
+/* in Process related APIs, we can only pass LDT, but in form of
+ * entry in the LDT table
+ */
+#define PROC_LDT(x) __SEL((x), 0)
+
+static unsigned find_unused_ldt_entry(void)
+{
+ DWORD buf[4];
+ PROCESS_LDT_INFORMATION* pli = (PROCESS_LDT_INFORMATION*)buf;
+ NTSTATUS status;
+ DWORD dw;
+ unsigned entry;
+
+ /* Wine cannot use the first 512 slots :-/ */
+ for (entry = 512; entry < 8192; entry++)
+ {
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 8;
+ memset(&pli->ldt[0], 0, sizeof(LDT_ENTRY));
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 16, &dw);
+ if (status == STATUS_SUCCESS && !pli->ldt->HighWord.Bits.Pres)
+ break;
+ }
+ ok(entry < 8192, "Couldn't find an unused slot in LDT\n");
+ return entry;
+}
+
+static void test_fail_process(unsigned entry)
+{
+ DWORD buf[12];
+ PROCESS_LDT_INFORMATION* pli = (PROCESS_LDT_INFORMATION*)buf;
+ NTSTATUS status;
+ DWORD dw;
+
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 8;
+ dw = 0x12345678;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 16, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 0, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = LDT(entry, 3);
+ pli->dwSize = 8;
+ dw = 0x12345678;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 16, &dw);
+ ok(status == STATUS_INVALID_LDT_OFFSET, "Wrong status %x\n", status);
+ ok(dw == 0x12345678, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 8, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = LDT(entry, 0);
+ pli->dwSize = 8;
+ dw = 0x12345678;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 16, &dw);
+ ok(status == STATUS_INVALID_LDT_OFFSET, "Wrong status %x\n", status);
+ ok(dw == 0x12345678, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 8, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 8;
+ dw = 0;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf,8, &dw);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Wrong status %x\n", status);
+ ok(pli->dwSize == 8, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 8;
+ dw = 0;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 24, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 0, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 16;
+ dw = 0;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 24, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 0, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 0;
+ dw = 0;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 16, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 0, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+ pli->dwSelector = PROC_LDT(entry);
+ pli->dwSize = 32;
+ dw = 0x4321;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 24, &dw);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Wrong status %x\n", status);
+ ok(dw == 0x4321, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 32, "Wrong pli->dwSize value %d\n", pli->dwSize);
+
+
+ pli->dwSelector = PROC_LDT(8192);
+ pli->dwSize = 8;
+ dw = 0;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessLdtInformation, buf, 16, &dw);
+ ok(status == STATUS_SUCCESS, "Wrong status %x\n", status);
+ ok(dw == 8, "Wrong dw value %d\n", dw);
+ ok(pli->dwSize == 0, "Wrong pli->dwSize value %d\n", pli->dwSize);
+}
+#endif /* __i386__ */
+
+START_TEST(selector)
+{
+#ifdef __i386__
+ HANDLE h;
+ unsigned entry;
+
+ h = LoadLibrary("ntdll.dll");
+
+ if (!h) return;
+#define X(f) p##f = (void*)GetProcAddress(h, #f); if (!p##f) {printf("Cannot load " #f "\n"); return;}
+ X(NtQueryInformationProcess);
+#undef X
+ /* first, find an unused selector */
+ entry = find_unused_ldt_entry();
+ if (entry >= 8192) return;
+
+ test_fail_process(entry);
+#endif /* __i386__ */
+}
diff --git a/include/winternl.h b/include/winternl.h
index 304f5af..4373ffd 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -976,6 +976,12 @@ typedef struct _PROCESS_PRIORITY_CLASS {
UCHAR PriorityClass;
} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;
+typedef struct _PROCESS_LDT_INFORMATION {
+ DWORD dwSelector;
+ DWORD dwSize; /* number of bytes for ldt[] array */
+ LDT_ENTRY ldt[1]; /* in fact, as many as dwNumber */
+} PROCESS_LDT_INFORMATION;
+
typedef struct _RTL_HEAP_DEFINITION {
ULONG Length; /* = sizeof(RTL_HEAP_DEFINITION) */
More information about the wine-patches
mailing list