1 module photon.windows.support;
2 version(Windows):
3 import core.sys.windows.core;
4 
5 //opaque structs
6 struct UMS_COMPLETION_LIST;
7 struct UMS_CONTEXT;
8 struct PROC_THREAD_ATTRIBUTE_LIST;
9 
10 struct UMS_SCHEDULER_STARTUP_INFO {
11     ULONG                      UmsVersion;
12     UMS_COMPLETION_LIST*       CompletionList;
13     UmsSchedulerProc           SchedulerProc;
14     PVOID                      SchedulerParam;
15 }
16 
17 struct UMS_CREATE_THREAD_ATTRIBUTES {
18   DWORD UmsVersion;
19   PVOID UmsContext;
20   PVOID UmsCompletionList;
21 }
22 
23 enum UMS_SCHEDULER_REASON: uint {
24   UmsSchedulerStartup = 0,
25   UmsSchedulerThreadBlocked = 1,
26   UmsSchedulerThreadYield = 2
27 }
28 
29 enum UMS_VERSION =  0x0100;
30 enum
31     PROC_THREAD_ATTRIBUTE_NUMBER = 0x0000FFFF,
32     PROC_THREAD_ATTRIBUTE_THREAD = 0x00010000,    // Attribute may be used with thread creation
33     PROC_THREAD_ATTRIBUTE_INPUT = 0x00020000,     // Attribute is input only
34     PROC_THREAD_ATTRIBUTE_ADDITIVE = 0x00040000;  // Attribute may be "accumulated," e.g. bitmasks, counters, etc.
35 
36 enum
37     ProcThreadAttributeParentProcess                = 0,
38     ProcThreadAttributeHandleList                   = 2,
39     ProcThreadAttributeGroupAffinity                = 3,
40     ProcThreadAttributePreferredNode                = 4,
41     ProcThreadAttributeIdealProcessor               = 5,
42     ProcThreadAttributeUmsThread                    = 6,
43     ProcThreadAttributeMitigationPolicy             = 7;
44 
45  enum UMS_THREAD_INFO_CLASS: uint { 
46   UmsThreadInvalidInfoClass  = 0,
47   UmsThreadUserContext       = 1,
48   UmsThreadPriority          = 2,
49   UmsThreadAffinity          = 3,
50   UmsThreadTeb               = 4,
51   UmsThreadIsSuspended       = 5,
52   UmsThreadIsTerminated      = 6,
53   UmsThreadMaxInfoClass      = 7
54 }
55 
56 uint ProcThreadAttributeValue(uint Number, bool Thread, bool Input, bool Additive)
57 {
58     return (Number & PROC_THREAD_ATTRIBUTE_NUMBER) | 
59      (Thread != FALSE ? PROC_THREAD_ATTRIBUTE_THREAD : 0) | 
60      (Input != FALSE ? PROC_THREAD_ATTRIBUTE_INPUT : 0) | 
61      (Additive != FALSE ? PROC_THREAD_ATTRIBUTE_ADDITIVE : 0);
62 }
63 
64 enum PROC_THREAD_ATTRIBUTE_UMS_THREAD = ProcThreadAttributeValue(ProcThreadAttributeUmsThread, true, true, false);
65 
66 extern(Windows) BOOL EnterUmsSchedulingMode(UMS_SCHEDULER_STARTUP_INFO* SchedulerStartupInfo);
67 extern(Windows) BOOL UmsThreadYield(PVOID SchedulerParam);
68 extern(Windows) BOOL DequeueUmsCompletionListItems(UMS_COMPLETION_LIST* UmsCompletionList, DWORD WaitTimeOut, UMS_CONTEXT** UmsThreadList);
69 extern(Windows) UMS_CONTEXT* GetNextUmsListItem(UMS_CONTEXT* UmsContext);
70 extern(Windows) BOOL ExecuteUmsThread(UMS_CONTEXT* UmsThread);
71 extern(Windows) BOOL CreateUmsCompletionList(UMS_COMPLETION_LIST** UmsCompletionList);
72 extern(Windows) BOOL CreateUmsThreadContext(UMS_CONTEXT** lpUmsThread);
73 extern(Windows) BOOL DeleteUmsThreadContext(UMS_CONTEXT* UmsThread);
74 extern(Windows) BOOL QueryUmsThreadInformation(
75     UMS_CONTEXT*          UmsThread,
76     UMS_THREAD_INFO_CLASS UmsThreadInfoClass,
77     PVOID                 UmsThreadInformation,
78     ULONG                 UmsThreadInformationLength,
79     PULONG                ReturnLength
80 );
81 
82 extern(Windows) BOOL InitializeProcThreadAttributeList(
83   PROC_THREAD_ATTRIBUTE_LIST* lpAttributeList,
84   DWORD                        dwAttributeCount,
85   DWORD                        dwFlags,
86   PSIZE_T                      lpSize
87 );
88 
89 extern(Windows) VOID DeleteProcThreadAttributeList(PROC_THREAD_ATTRIBUTE_LIST* lpAttributeList);
90 extern(Windows) BOOL UpdateProcThreadAttribute(
91   PROC_THREAD_ATTRIBUTE_LIST* lpAttributeList,
92   DWORD                        dwFlags,
93   DWORD_PTR                    Attribute,
94   PVOID                        lpValue,
95   SIZE_T                       cbSize,
96   PVOID                        lpPreviousValue,
97   PSIZE_T                      lpReturnSize
98 );
99 
100 extern(Windows) HANDLE CreateRemoteThreadEx(
101   HANDLE                       hProcess,
102   PSECURITY_ATTRIBUTES        lpThreadAttributes,
103   SIZE_T                       dwStackSize,
104   LPTHREAD_START_ROUTINE       lpStartAddress,
105   LPVOID                       lpParameter,
106   DWORD                        dwCreationFlags,
107   PROC_THREAD_ATTRIBUTE_LIST*  lpAttributeList,
108   LPDWORD                      lpThreadId
109 );
110 
111 enum STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000;
112 
113 alias UmsSchedulerProc = extern(Windows) VOID function(UMS_SCHEDULER_REASON Reason, ULONG_PTR ActivationPayload, PVOID SchedulerParam);
114 
115 void outputToConsole(const(wchar)[] msg)
116 {
117     HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
118     uint size = cast(uint)msg.length;
119     WriteConsole(output, msg.ptr, size, &size, null);
120 }
121 
122 void logf(T...)(const(wchar)[] fmt, T args)
123 {
124     debug try {
125         formattedWrite(&outputToConsole, fmt, args);
126     }
127     catch (Exception e) {
128         outputToConsole("ARGH!"w);
129     }
130 }