Algorithms_in_C 1.0.0
Set of algorithms implemented in C.
Loading...
Searching...
No Matches
fork.h
1/*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) DIGITEO - 2010 - Allan CORNET
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15/*--------------------------------------------------------------------------*/
16#ifndef __FORK_H__
17#define __FORK_H__
18
19/* http://technet.microsoft.com/en-us/library/bb497007.aspx */
20/* http://undocumented.ntinternals.net/ */
21
22#include <setjmp.h>
23#include <windows.h>
24
25#include "bool.h"
26
27/**
28 * simulate fork on Windows
29 */
30int fork(void);
31
32/**
33 * check if symbols to simulate fork are present
34 * and load these symbols
35 */
36BOOL haveLoadedFunctionsForFork(void);
37
38/*--------------------------------------------------------------------------*/
39typedef LONG NTSTATUS;
40/*--------------------------------------------------------------------------*/
42{
43 ULONG ProcessId;
44 UCHAR ObjectTypeNumber;
45 UCHAR Flags;
46 USHORT Handle;
47 PVOID Object;
48 ACCESS_MASK GrantedAccess;
50/*--------------------------------------------------------------------------*/
51typedef struct _OBJECT_ATTRIBUTES
52{
53 ULONG Length;
54 HANDLE RootDirectory;
55 PVOID /* really PUNICODE_STRING */ ObjectName;
56 ULONG Attributes;
57 PVOID SecurityDescriptor; /* type SECURITY_DESCRIPTOR */
58 PVOID SecurityQualityOfService; /* type SECURITY_QUALITY_OF_SERVICE */
60/*--------------------------------------------------------------------------*/
61typedef enum _MEMORY_INFORMATION_
62{
63 MemoryBasicInformation,
64 MemoryWorkingSetList,
65 MemorySectionName,
66 MemoryBasicVlmInformation
67} MEMORY_INFORMATION_CLASS;
68/*--------------------------------------------------------------------------*/
69typedef struct _CLIENT_ID
70{
71 HANDLE UniqueProcess;
72 HANDLE UniqueThread;
74/*--------------------------------------------------------------------------*/
75typedef struct _USER_STACK
76{
77 PVOID FixedStackBase;
78 PVOID FixedStackLimit;
79 PVOID ExpandableStackBase;
80 PVOID ExpandableStackLimit;
81 PVOID ExpandableStackBottom;
83/*--------------------------------------------------------------------------*/
84typedef LONG KPRIORITY;
85typedef ULONG_PTR KAFFINITY;
86typedef KAFFINITY *PKAFFINITY;
87/*--------------------------------------------------------------------------*/
89{
90 NTSTATUS ExitStatus;
91 PVOID TebBaseAddress;
92 CLIENT_ID ClientId;
93 KAFFINITY AffinityMask;
94 KPRIORITY Priority;
95 KPRIORITY BasePriority;
97/*--------------------------------------------------------------------------*/
98typedef enum _SYSTEM_INFORMATION_CLASS
99{
100 SystemHandleInformation = 0x10
101} SYSTEM_INFORMATION_CLASS;
102/*--------------------------------------------------------------------------*/
103typedef NTSTATUS(NTAPI *ZwWriteVirtualMemory_t)(
104 IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer,
105 IN ULONG NumberOfBytesToWrite, OUT PULONG NumberOfBytesWritten OPTIONAL);
106/*--------------------------------------------------------------------------*/
107typedef NTSTATUS(NTAPI *ZwCreateProcess_t)(
108 OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess,
109 IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheriteFromProcessHandle,
110 IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL,
111 IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL);
112/*--------------------------------------------------------------------------*/
113typedef NTSTATUS(WINAPI *ZwQuerySystemInformation_t)(
114 SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation,
115 ULONG SystemInformationLength, PULONG ReturnLength);
116typedef NTSTATUS(NTAPI *ZwQueryVirtualMemory_t)(
117 IN HANDLE ProcessHandle, IN PVOID BaseAddress,
118 IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
119 OUT PVOID MemoryInformation, IN ULONG MemoryInformationLength,
120 OUT PULONG ReturnLength OPTIONAL);
121/*--------------------------------------------------------------------------*/
122typedef NTSTATUS(NTAPI *ZwGetContextThread_t)(IN HANDLE ThreadHandle,
123 OUT PCONTEXT Context);
124typedef NTSTATUS(NTAPI *ZwCreateThread_t)(
125 OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess,
126 IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle,
127 OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext,
128 IN PUSER_STACK UserStack, IN BOOLEAN CreateSuspended);
129/*--------------------------------------------------------------------------*/
130typedef NTSTATUS(NTAPI *ZwResumeThread_t)(IN HANDLE ThreadHandle,
131 OUT PULONG SuspendCount OPTIONAL);
132typedef NTSTATUS(NTAPI *ZwClose_t)(IN HANDLE ObjectHandle);
133typedef NTSTATUS(NTAPI *ZwQueryInformationThread_t)(
134 IN HANDLE ThreadHandle, IN THREAD_INFORMATION_CLASS ThreadInformationClass,
135 OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength,
136 OUT PULONG ReturnLength OPTIONAL);
137/*--------------------------------------------------------------------------*/
138static ZwCreateProcess_t ZwCreateProcess = NULL;
139static ZwQuerySystemInformation_t ZwQuerySystemInformation = NULL;
140static ZwQueryVirtualMemory_t ZwQueryVirtualMemory = NULL;
141static ZwCreateThread_t ZwCreateThread = NULL;
142static ZwGetContextThread_t ZwGetContextThread = NULL;
143static ZwResumeThread_t ZwResumeThread = NULL;
144static ZwClose_t ZwClose = NULL;
145static ZwQueryInformationThread_t ZwQueryInformationThread = NULL;
146static ZwWriteVirtualMemory_t ZwWriteVirtualMemory = NULL;
147/*--------------------------------------------------------------------------*/
148#define NtCurrentProcess() ((HANDLE)-1)
149#define NtCurrentThread() ((HANDLE)-2)
150/* we use really the Nt versions - so the following is just for completeness */
151#define ZwCurrentProcess() NtCurrentProcess()
152#define ZwCurrentThread() NtCurrentThread()
153#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
154#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
155/*--------------------------------------------------------------------------*/
156/* setjmp env for the jump back into the fork() function */
157static jmp_buf jenv;
158/*--------------------------------------------------------------------------*/
159/* entry point for our child thread process - just longjmp into fork */
160static int child_entry(void)
161{
162 longjmp(jenv, 1);
163 return 0;
164}
165/*--------------------------------------------------------------------------*/
166static BOOL haveLoadedFunctionsForFork(void)
167{
168 HMODULE ntdll = GetModuleHandle("ntdll");
169 if (ntdll == NULL)
170 {
171 return FALSE;
172 }
173
174 if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory &&
175 ZwCreateThread && ZwGetContextThread && ZwResumeThread &&
176 ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose)
177 {
178 return TRUE;
179 }
180
181 ZwCreateProcess =
182 (ZwCreateProcess_t)GetProcAddress(ntdll, "ZwCreateProcess");
183 ZwQuerySystemInformation = (ZwQuerySystemInformation_t)GetProcAddress(
184 ntdll, "ZwQuerySystemInformation");
185 ZwQueryVirtualMemory =
186 (ZwQueryVirtualMemory_t)GetProcAddress(ntdll, "ZwQueryVirtualMemory");
187 ZwCreateThread = (ZwCreateThread_t)GetProcAddress(ntdll, "ZwCreateThread");
188 ZwGetContextThread =
189 (ZwGetContextThread_t)GetProcAddress(ntdll, "ZwGetContextThread");
190 ZwResumeThread = (ZwResumeThread_t)GetProcAddress(ntdll, "ZwResumeThread");
191 ZwQueryInformationThread = (ZwQueryInformationThread_t)GetProcAddress(
192 ntdll, "ZwQueryInformationThread");
193 ZwWriteVirtualMemory =
194 (ZwWriteVirtualMemory_t)GetProcAddress(ntdll, "ZwWriteVirtualMemory");
195 ZwClose = (ZwClose_t)GetProcAddress(ntdll, "ZwClose");
196
197 if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory &&
198 ZwCreateThread && ZwGetContextThread && ZwResumeThread &&
199 ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose)
200 {
201 return TRUE;
202 }
203 else
204 {
205 ZwCreateProcess = NULL;
206 ZwQuerySystemInformation = NULL;
207 ZwQueryVirtualMemory = NULL;
208 ZwCreateThread = NULL;
209 ZwGetContextThread = NULL;
210 ZwResumeThread = NULL;
211 ZwQueryInformationThread = NULL;
212 ZwWriteVirtualMemory = NULL;
213 ZwClose = NULL;
214 }
215 return FALSE;
216}
217/*--------------------------------------------------------------------------*/
218int fork(void)
219{
220 HANDLE hProcess = 0, hThread = 0;
221 OBJECT_ATTRIBUTES oa = {sizeof(oa)};
222 MEMORY_BASIC_INFORMATION mbi;
223 CLIENT_ID cid;
225 PNT_TIB tib;
227
228 CONTEXT context = {CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS |
229 CONTEXT_FLOATING_POINT};
230
231 if (setjmp(jenv) != 0)
232 {
233 return 0; /* return as a child */
234 }
235
236 /* check whether the entry points are initilized and get them if necessary
237 */
238 if (!ZwCreateProcess && !haveLoadedFunctionsForFork())
239 {
240 return -1;
241 }
242
243 /* create forked process */
244 ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, NtCurrentProcess(),
245 TRUE, 0, 0, 0);
246
247 /* set the Eip for the child process to our child function */
248 ZwGetContextThread(NtCurrentThread(), &context);
249
250 /* In x64 the Eip and Esp are not present, their x64 counterparts are Rip
251 and Rsp respectively.
252 */
253#if _WIN64
254 context.Rip = (ULONG)child_entry;
255#else
256 context.Eip = (ULONG)child_entry;
257#endif
258
259#if _WIN64
260 ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Rsp,
261 MemoryBasicInformation, &mbi, sizeof mbi, 0);
262#else
263 ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Esp,
264 MemoryBasicInformation, &mbi, sizeof mbi, 0);
265#endif
266
267 stack.FixedStackBase = 0;
268 stack.FixedStackLimit = 0;
269 stack.ExpandableStackBase = (PCHAR)mbi.BaseAddress + mbi.RegionSize;
270 stack.ExpandableStackLimit = mbi.BaseAddress;
271 stack.ExpandableStackBottom = mbi.AllocationBase;
272
273 /* create thread using the modified context and stack */
274 ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess, &cid, &context,
275 &stack, TRUE);
276
277 /* copy exception table */
278 ZwQueryInformationThread(NtCurrentThread(), ThreadMemoryPriority, &tbi,
279 sizeof tbi, 0);
280 tib = (PNT_TIB)tbi.TebBaseAddress;
281 ZwQueryInformationThread(hThread, ThreadMemoryPriority, &tbi, sizeof tbi,
282 0);
283 ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress, &tib->ExceptionList,
284 sizeof tib->ExceptionList, 0);
285
286 /* start (resume really) the child */
287 ZwResumeThread(hThread, 0);
288
289 /* clean up */
290 ZwClose(hThread);
291 ZwClose(hProcess);
292
293 /* exit with child's pid */
294 return (int)cid.UniqueProcess;
295}
296
297#endif /* __FORK_H__ */
298/*--------------------------------------------------------------------------*/
struct buffer Buffer
struct used to store character in certain times
Definition fork.h:70
Definition fork.h:52
Definition fork.h:42
Definition fork.h:89
Definition fork.h:76
Definition 901.c:6