FreeRDP
Loading...
Searching...
No Matches
procthreadattr.c
1
20#include <winpr/config.h>
21
22#include <winpr/assert.h>
23#include <winpr/error.h>
24#include <winpr/thread.h>
25
26#ifndef _WIN32
27
28#include "thread.h"
29
30#include "../handle/handle.h"
31#include "../log.h"
32#define TAG WINPR_TAG("thread")
33
34BOOL InitializeProcThreadAttributeList(LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
35 DWORD dwAttributeCount, DWORD dwFlags, PSIZE_T lpSize)
36{
37 WINPR_UNUSED(dwFlags);
38
39 if (!lpSize)
40 {
41 SetLastError(ERROR_INVALID_PARAMETER);
42 return FALSE;
43 }
44
45 const SIZE_T required = sizeof(struct WINPR_PROC_THREAD_ATTRIBUTE_LIST) +
46 dwAttributeCount * sizeof(WINPR_PROC_THREAD_ATTRIBUTE_ENTRY);
47
48 /* first call (lpAttributeList == NULL): report the required size and fail, matching real
49 * Windows' documented two-call sizing idiom */
50 if (!lpAttributeList || (*lpSize < required))
51 {
52 *lpSize = required;
53 SetLastError(ERROR_INSUFFICIENT_BUFFER);
54 return FALSE;
55 }
56
57 lpAttributeList->capacity = dwAttributeCount;
58 lpAttributeList->count = 0;
59 return TRUE;
60}
61
62BOOL UpdateProcThreadAttribute(LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
63 WINPR_ATTR_UNUSED DWORD dwFlags, DWORD_PTR Attribute, PVOID lpValue,
64 SIZE_T cbSize, WINPR_ATTR_UNUSED PVOID lpPreviousValue,
65 WINPR_ATTR_UNUSED PSIZE_T lpReturnSize)
66{
67 if (!lpAttributeList || !lpValue)
68 {
69 SetLastError(ERROR_INVALID_PARAMETER);
70 return FALSE;
71 }
72
73 if (lpAttributeList->count >= lpAttributeList->capacity)
74 {
75 WLog_ERR(TAG, "attribute list is full (capacity=%" PRIu32 ")", lpAttributeList->capacity);
76 SetLastError(ERROR_INSUFFICIENT_BUFFER);
77 return FALSE;
78 }
79
80 WINPR_PROC_THREAD_ATTRIBUTE_ENTRY* entry = &lpAttributeList->entries[lpAttributeList->count++];
81 entry->Attribute = Attribute;
82 entry->lpValue = lpValue;
83 entry->cbSize = cbSize;
84
85 if (Attribute == PROC_THREAD_ATTRIBUTE_HANDLE_LIST)
86 {
87 const HANDLE* handles = (const HANDLE*)lpValue;
88 const size_t count = cbSize / sizeof(HANDLE);
89 for (size_t i = 0; i < count; i++)
90 winpr_Handle_AddRef(handles[i]);
91 }
92
93 return TRUE;
94}
95
96VOID DeleteProcThreadAttributeList(LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList)
97{
98 if (!lpAttributeList)
99 return;
100
101 /* the lpAttributeList buffer itself is still the caller's own, allocated from the size
102 * InitializeProcThreadAttributeList() reported - matches real Windows, where
103 * DeleteProcThreadAttributeList() doesn't free that buffer either. Only release the
104 * references UpdateProcThreadAttribute() took on listed handles. */
105 for (DWORD i = 0; i < lpAttributeList->count; i++)
106 {
107 const WINPR_PROC_THREAD_ATTRIBUTE_ENTRY* entry = &lpAttributeList->entries[i];
108 if (entry->Attribute != PROC_THREAD_ATTRIBUTE_HANDLE_LIST)
109 continue;
110
111 const HANDLE* handles = (const HANDLE*)entry->lpValue;
112 const size_t count = entry->cbSize / sizeof(HANDLE);
113 for (size_t h = 0; h < count; h++)
114 (void)winpr_Handle_Release(handles[h]);
115 }
116}
117
118#endif
opaque attribute list built by InitializeProcThreadAttributeList() / UpdateProcThreadAttribute(),...