kernel32: Implement Process thread attribute lists.
Huw Davies
huw at codeweavers.com
Mon Dec 5 05:41:51 CST 2016
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
dlls/kernel32/kernel32.spec | 6 +--
dlls/kernel32/process.c | 120 +++++++++++++++++++++++++++++++++++++++++
dlls/kernel32/tests/process.c | 123 ++++++++++++++++++++++++++++++++++++++++++
include/winbase.h | 41 ++++++++++++++
4 files changed, 287 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 3c25286..224e6ae 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -367,7 +367,7 @@
# @ stub DeleteFileTransactedA
# @ stub DeleteFileTransactedW
@ stdcall DeleteFileW(wstr)
-# @ stub DeleteProcThreadAttributeList
+@ stdcall DeleteProcThreadAttributeList(ptr)
# @ stub DisableThreadProfiling
@ stdcall DisassociateCurrentThreadFromCallback(ptr) ntdll.TpDisassociateCallback
@ stdcall DeleteTimerQueue(long)
@@ -945,7 +945,7 @@
@ stdcall InitializeCriticalSection(ptr)
@ stdcall InitializeCriticalSectionAndSpinCount(ptr long)
@ stdcall InitializeCriticalSectionEx(ptr long long)
-# @ stub InitializeProcThreadAttributeList
+@ stdcall InitializeProcThreadAttributeList(ptr long long ptr)
@ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead
@ stdcall InitializeSRWLock(ptr) ntdll.RtlInitializeSRWLock
@ stdcall -arch=i386 InterlockedCompareExchange (ptr long long)
@@ -1538,7 +1538,7 @@
@ stdcall UnregisterWait(long)
@ stdcall UnregisterWaitEx(long long)
# @ stub UpdateCalendarDayOfWeek
-# @ stub UpdateProcThreadAttribute
+@ stdcall UpdateProcThreadAttribute(ptr long long ptr long ptr ptr)
@ stdcall UpdateResourceA(long str str long ptr long)
@ stdcall UpdateResourceW(long wstr wstr long ptr long)
@ stub VDMConsoleOperation
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 5b584ac..2130240 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -4087,3 +4087,123 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
+
+struct proc_thread_attr
+{
+ DWORD_PTR attr;
+ SIZE_T size;
+ void *value;
+};
+
+struct _PROC_THREAD_ATTRIBUTE_LIST
+{
+ DWORD mask; /* bitmask of items in list */
+ DWORD size; /* max number of items in list */
+ DWORD count; /* number of items in list */
+ DWORD pad;
+ DWORD_PTR unk;
+ struct proc_thread_attr attrs[1];
+};
+
+/***********************************************************************
+ * InitializeProcThreadAttributeList (KERNEL32.@)
+ */
+BOOL WINAPI InitializeProcThreadAttributeList(struct _PROC_THREAD_ATTRIBUTE_LIST *list,
+ DWORD count, DWORD flags, SIZE_T *size)
+{
+ SIZE_T needed;
+ BOOL ret = FALSE;
+
+ TRACE("(%p %d %x %p)\n", list, count, flags, size);
+
+ needed = FIELD_OFFSET(struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[count]);
+ if (list && *size >= needed)
+ {
+ list->mask = 0;
+ list->size = count;
+ list->count = 0;
+ list->unk = 0;
+ ret = TRUE;
+ }
+ else
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+
+ *size = needed;
+ return ret;
+}
+
+/***********************************************************************
+ * UpdateProcThreadAttribute (KERNEL32.@)
+ */
+BOOL WINAPI UpdateProcThreadAttribute(struct _PROC_THREAD_ATTRIBUTE_LIST *list,
+ DWORD flags, DWORD_PTR attr, void *value, SIZE_T size,
+ void *prev_ret, SIZE_T *size_ret)
+{
+ DWORD mask;
+ struct proc_thread_attr *entry;
+
+ TRACE("(%p %x %08lx %p %ld %p %p)\n", list, flags, attr, value, size, prev_ret, size_ret);
+
+ if (list->count >= list->size)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ return FALSE;
+ }
+
+ switch (attr)
+ {
+ case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
+ if (size != sizeof(HANDLE))
+ {
+ SetLastError(ERROR_BAD_LENGTH);
+ return FALSE;
+ }
+ break;
+
+ case PROC_THREAD_ATTRIBUTE_HANDLE_LIST:
+ if ((size / sizeof(HANDLE)) * sizeof(HANDLE) != size)
+ {
+ SetLastError(ERROR_BAD_LENGTH);
+ return FALSE;
+ }
+ break;
+
+ case PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR:
+ if (size != sizeof(PROCESSOR_NUMBER))
+ {
+ SetLastError(ERROR_BAD_LENGTH);
+ return FALSE;
+ }
+ break;
+
+ default:
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return FALSE;
+ }
+
+ mask = 1 << (attr & PROC_THREAD_ATTRIBUTE_NUMBER);
+
+ if (list->mask & mask)
+ {
+ SetLastError(ERROR_OBJECT_NAME_EXISTS);
+ return FALSE;
+ }
+
+ list->mask |= mask;
+
+ entry = list->attrs + list->count;
+ entry->attr = attr;
+ entry->size = size;
+ entry->value = value;
+ list->count++;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ * DeleteProcThreadAttributeList (KERNEL32.@)
+ */
+void WINAPI DeleteProcThreadAttributeList(struct _PROC_THREAD_ATTRIBUTE_LIST *list)
+{
+ return;
+}
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 5131126..a36ecd6 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -88,6 +88,9 @@ static BOOL (WINAPI *pThread32First)(HANDLE, THREADENTRY32*);
static BOOL (WINAPI *pThread32Next)(HANDLE, THREADENTRY32*);
static BOOL (WINAPI *pGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*,DWORD*);
static SIZE_T (WINAPI *pGetLargePageMinimum)(void);
+static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*);
+static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*);
+static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*);
/* ############################### */
static char base[MAX_PATH];
@@ -252,6 +255,9 @@ static BOOL init(void)
pThread32Next = (void *)GetProcAddress(hkernel32, "Thread32Next");
pGetLogicalProcessorInformationEx = (void *)GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
pGetLargePageMinimum = (void *)GetProcAddress(hkernel32, "GetLargePageMinimum");
+ pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList");
+ pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute");
+ pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList");
return TRUE;
}
@@ -3137,6 +3143,122 @@ static void test_largepages(void)
ok((size == 0) || (size == 2*1024*1024) || (size == 4*1024*1024), "GetLargePageMinimum reports %ld size\n", size);
}
+struct proc_thread_attr
+{
+ DWORD_PTR attr;
+ SIZE_T size;
+ void *value;
+};
+
+struct _PROC_THREAD_ATTRIBUTE_LIST
+{
+ DWORD mask; /* bitmask of items in list */
+ DWORD size; /* max number of items in list */
+ DWORD count; /* number of items in list */
+ DWORD pad;
+ DWORD_PTR unk;
+ struct proc_thread_attr attrs[10];
+};
+
+static void test_ProcThreadAttributeList(void)
+{
+ BOOL ret;
+ SIZE_T size, needed;
+ int i;
+ struct _PROC_THREAD_ATTRIBUTE_LIST list, expect_list;
+ HANDLE handles[4];
+
+ if (!pInitializeProcThreadAttributeList)
+ {
+ win_skip("No support for ProcThreadAttributeList\n");
+ return;
+ }
+
+ for (i = 0; i <= 10; i++)
+ {
+ needed = FIELD_OFFSET(struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[i]);
+ ret = pInitializeProcThreadAttributeList(NULL, i, 0, &size);
+ ok(!ret, "got %d\n", ret);
+ if(i >= 4 && GetLastError() == ERROR_INVALID_PARAMETER) /* Vista only allows a maximium of 3 slots */
+ break;
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d\n", GetLastError());
+ ok(size == needed, "%d: got %ld expect %ld\n", i, size, needed);
+
+ memset(&list, 0xcc, sizeof(list));
+ ret = pInitializeProcThreadAttributeList(&list, i, 0, &size);
+ ok(ret, "got %d\n", ret);
+ ok(list.mask == 0, "%d: got %08x\n", i, list.mask);
+ ok(list.size == i, "%d: got %08x\n", i, list.size);
+ ok(list.count == 0, "%d: got %08x\n", i, list.count);
+ ok(list.unk == 0, "%d: got %08lx\n", i, list.unk);
+ }
+
+ memset(handles, 0, sizeof(handles));
+ memset(&expect_list, 0xcc, sizeof(expect_list));
+ expect_list.mask = 0;
+ expect_list.size = i - 1;
+ expect_list.count = 0;
+ expect_list.unk = 0;
+
+ ret = pUpdateProcThreadAttribute(&list, 0, 0xcafe, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_NOT_SUPPORTED, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) / 2, NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) * 2, NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
+ ok(ret, "got %d\n", ret);
+
+ expect_list.mask |= 1 << ProcThreadAttributeParentProcess;
+ expect_list.attrs[0].attr = PROC_THREAD_ATTRIBUTE_PARENT_PROCESS;
+ expect_list.attrs[0].size = sizeof(handles[0]);
+ expect_list.attrs[0].value = handles;
+ expect_list.count++;
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_OBJECT_NAME_EXISTS, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles) - 1, NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
+ ok(ret, "got %d\n", ret);
+
+ expect_list.mask |= 1 << ProcThreadAttributeHandleList;
+ expect_list.attrs[1].attr = PROC_THREAD_ATTRIBUTE_HANDLE_LIST;
+ expect_list.attrs[1].size = sizeof(handles);
+ expect_list.attrs[1].value = handles;
+ expect_list.count++;
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_OBJECT_NAME_EXISTS, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
+ ok(ret || (!ret && GetLastError() == ERROR_NOT_SUPPORTED), "got %d gle %d\n", ret, GetLastError());
+
+ if (ret)
+ {
+ expect_list.mask |= 1 << ProcThreadAttributeIdealProcessor;
+ expect_list.attrs[2].attr = PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR;
+ expect_list.attrs[2].size = sizeof(PROCESSOR_NUMBER);
+ expect_list.attrs[2].value = handles;
+ expect_list.count++;
+ }
+
+ ok(!memcmp(&list, &expect_list, size), "mismatch\n");
+
+ pDeleteProcThreadAttributeList(&list);
+}
+
START_TEST(process)
{
HANDLE job;
@@ -3210,6 +3332,7 @@ START_TEST(process)
test_session_info();
test_GetLogicalProcessorInformationEx();
test_largepages();
+ test_ProcThreadAttributeList();
/* things that can be tested:
* lookup: check the way program to be executed is searched
diff --git a/include/winbase.h b/include/winbase.h
index 521d2da..eff5972 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1644,6 +1644,44 @@ typedef struct _REASON_CONTEXT
#define RESOURCE_ENUM_MUI_SYSTEM 0x0004
#define RESOURCE_ENUM_VALIDATE 0x0008
+typedef struct _PROC_THREAD_ATTRIBUTE_LIST
+*PPROC_THREAD_ATTRIBUTE_LIST, *LPPROC_THREAD_ATTRIBUTE_LIST;
+
+#define PROC_THREAD_ATTRIBUTE_NUMBER 0x0000ffff
+#define PROC_THREAD_ATTRIBUTE_THREAD 0x00010000
+#define PROC_THREAD_ATTRIBUTE_INPUT 0x00020000
+#define PROC_THREAD_ATTRIBUTE_ADDITIVE 0x00040000
+
+typedef enum _PROC_THREAD_ATTRIBUTE_NUM
+{
+ ProcThreadAttributeParentProcess = 0,
+ ProcThreadAttributeHandleList = 2,
+ ProcThreadAttributeGroupAffinity = 3,
+ ProcThreadAttributeIdealProcessor = 5,
+ ProcThreadAttributeUmsThread = 6,
+ ProcThreadAttributeMitigationPolicy = 7,
+ ProcThreadAttributeSecurityCapabilities = 9,
+ ProcThreadAttributeProtectionLevel = 11,
+ ProcThreadAttributeJobList = 13,
+ ProcThreadAttributeChildProcessPolicy = 14,
+ ProcThreadAttributeAllApplicationPackagesPolicy = 15,
+ ProcThreadAttributeWin32kFilter = 16,
+ ProcThreadAttributeSafeOpenPromptOriginClaim = 17,
+} PROC_THREAD_ATTRIBUTE_NUM;
+
+#define PROC_THREAD_ATTRIBUTE_PARENT_PROCESS (ProcThreadAttributeParentProcess | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_HANDLE_LIST (ProcThreadAttributeHandleList | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY (ProcThreadAttributeGroupAffinity | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR (ProcThreadAttributeIdealProcessor | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_UMS_THREAD (ProcThreadAttributeUmsThread | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_MIGITATION_POLICY (ProcThreadAttributeMitigationPolicy | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES (ProcThreadAttributeSecurityCapabilities | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL (ProcThreadAttributeProtectionLevel | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_JOB_LIST (ProcThreadAttributeJobList | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY (ProcThreadAttributeChildProcessPolicy | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY (ProcThreadAttributeAllApplicationPackagesPolicy | PROC_THREAD_ATTRIBUTE_INPUT)
+#define PROC_THREAD_ATTRIBUTE_WIN32K_FILTER (ProcThreadAttributeWin32kFilter | PROC_THREAD_ATTRIBUTE_INPUT)
+
WINBASEAPI BOOL WINAPI ActivateActCtx(HANDLE,ULONG_PTR *);
WINADVAPI BOOL WINAPI AddAccessAllowedAce(PACL,DWORD,DWORD,PSID);
WINADVAPI BOOL WINAPI AddAccessAllowedAceEx(PACL,DWORD,DWORD,DWORD,PSID);
@@ -1835,6 +1873,7 @@ WINBASEAPI void WINAPI DeleteFiber(LPVOID);
WINBASEAPI BOOL WINAPI DeleteFileA(LPCSTR);
WINBASEAPI BOOL WINAPI DeleteFileW(LPCWSTR);
#define DeleteFile WINELIB_NAME_AW(DeleteFile)
+WINBASEAPI void WINAPI DeleteProcThreadAttributeList(struct _PROC_THREAD_ATTRIBUTE_LIST*);
WINBASEAPI BOOL WINAPI DeleteTimerQueue(HANDLE);
WINBASEAPI BOOL WINAPI DeleteTimerQueueEx(HANDLE,HANDLE);
WINBASEAPI BOOL WINAPI DeleteTimerQueueTimer(HANDLE,HANDLE,HANDLE);
@@ -2233,6 +2272,7 @@ WINBASEAPI VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE);
WINBASEAPI void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
WINBASEAPI BOOL WINAPI InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *,DWORD);
WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(CRITICAL_SECTION *,DWORD,DWORD);
+WINBASEAPI BOOL WINAPI InitializeProcThreadAttributeList(struct _PROC_THREAD_ATTRIBUTE_LIST*,DWORD,DWORD,SIZE_T*);
WINADVAPI BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR,DWORD);
WINADVAPI BOOL WINAPI InitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE);
WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER);
@@ -2565,6 +2605,7 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
WINBASEAPI HRESULT WINAPI UnregisterApplicationRestart(void);
WINBASEAPI BOOL WINAPI UnregisterWait(HANDLE);
WINBASEAPI BOOL WINAPI UnregisterWaitEx(HANDLE,HANDLE);
+WINBASEAPI BOOL WINAPI UpdateProcThreadAttribute(struct _PROC_THREAD_ATTRIBUTE_LIST*,DWORD,DWORD_PTR,void*,SIZE_T,void*,SIZE_T*);
WINBASEAPI BOOL WINAPI UpdateResourceA(HANDLE,LPCSTR,LPCSTR,WORD,LPVOID,DWORD);
WINBASEAPI BOOL WINAPI UpdateResourceW(HANDLE,LPCWSTR,LPCWSTR,WORD,LPVOID,DWORD);
#define UpdateResource WINELIB_NAME_AW(UpdateResource)
--
2.7.4
More information about the wine-patches
mailing list