Browse Source

Initial commit

William Pitcock 7 years ago
commit
78c7a9da3f
1 changed files with 132 additions and 0 deletions
  1. 132
    0
      fork.c

+ 132
- 0
fork.c View File

@@ -0,0 +1,132 @@
1
+/*
2
+ * fork.c
3
+ * Experimental fork() on Windows.  Requires NT 6 subsystem or
4
+ * newer.
5
+ *
6
+ * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>
7
+ *
8
+ * Permission to use, copy, modify, and/or distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * This software is provided 'as is' and without any warranty, express or
13
+ * implied.  In no event shall the authors be liable for any damages arising
14
+ * from the use of this software.
15
+ */
16
+
17
+#define _WIN32_WINNT 0x0600
18
+#define WIN32_LEAN_AND_MEAN
19
+#include <windows.h>
20
+#include <winnt.h>
21
+#include <ntdef.h>
22
+#include <stdio.h>
23
+#include <errno.h>
24
+#include <process.h>
25
+
26
+#ifdef __MINGW32__
27
+typedef struct _CLIENT_ID {
28
+	PVOID UniqueProcess;
29
+	PVOID UniqueThread;
30
+} CLIENT_ID, *PCLIENT_ID;
31
+
32
+typedef struct _SECTION_IMAGE_INFORMATION {
33
+	PVOID EntryPoint;
34
+	ULONG StackZeroBits;
35
+	ULONG StackReserved;
36
+	ULONG StackCommit;
37
+	ULONG ImageSubsystem;
38
+	WORD SubSystemVersionLow;
39
+	WORD SubSystemVersionHigh;
40
+	ULONG Unknown1;
41
+	ULONG ImageCharacteristics;
42
+	ULONG ImageMachineType;
43
+	ULONG Unknown2[3];
44
+} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
45
+
46
+typedef struct _RTL_USER_PROCESS_INFORMATION {
47
+	ULONG Size;
48
+	HANDLE Process;
49
+	HANDLE Thread;
50
+	CLIENT_ID ClientId;
51
+	SECTION_IMAGE_INFORMATION ImageInformation;
52
+} RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION;
53
+
54
+#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED	0x00000001
55
+#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES		0x00000002
56
+#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE		0x00000004
57
+
58
+#define RTL_CLONE_PARENT				0
59
+#define RTL_CLONE_CHILD					297
60
+
61
+#endif
62
+
63
+typedef NTSTATUS (*RtlCloneUserProcess_f)(ULONG ProcessFlags,
64
+	PSECURITY_DESCRIPTOR ProcessSecurityDescriptor /* optional */,
65
+	PSECURITY_DESCRIPTOR ThreadSecurityDescriptor /* optional */,
66
+	HANDLE DebugPort /* optional */,
67
+	PRTL_USER_PROCESS_INFORMATION ProcessInformation);
68
+
69
+pid_t fork(void)
70
+{
71
+	HMODULE mod;
72
+	RtlCloneUserProcess_f clone_p;
73
+	RTL_USER_PROCESS_INFORMATION process_info;
74
+	NTSTATUS result;
75
+
76
+	mod = GetModuleHandle("ntdll.dll");
77
+	if (!mod)
78
+		return -ENOSYS;
79
+
80
+	clone_p = GetProcAddress(mod, "RtlCloneUserProcess");
81
+	if (clone_p == NULL)
82
+		return -ENOSYS;
83
+
84
+	/* lets do this */
85
+	result = clone_p(RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED | RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES, NULL, NULL, NULL, &process_info);
86
+
87
+	if (result == RTL_CLONE_PARENT)
88
+	{
89
+		HANDLE me = GetCurrentProcess();
90
+		pid_t child_pid;
91
+
92
+		child_pid = GetProcessId(process_info.Process);
93
+
94
+		ResumeThread(process_info.Thread);
95
+		CloseHandle(process_info.Process);
96
+		CloseHandle(process_info.Thread);
97
+
98
+		return child_pid;
99
+	}
100
+	else if (result == RTL_CLONE_CHILD)
101
+	{
102
+		/* fix stdio */
103
+		AllocConsole();
104
+		return 0;
105
+	}
106
+	else
107
+		return -1;
108
+
109
+	/* NOTREACHED */
110
+	return -1;
111
+}
112
+
113
+#ifdef __TEST__
114
+int main(int argc, const char *argv[])
115
+{
116
+	pid_t pid = fork();
117
+
118
+	switch (pid) {
119
+	case 0:
120
+	{
121
+		FILE *f = fopen("C:/Users/nenolod/Documents/forktest.dat", "w");
122
+		fprintf(f, "ok\n");
123
+		fclose(f);
124
+		break;
125
+	}
126
+	default:
127
+		printf("child %d\n", pid);
128
+		while (1) { Sleep(1000); }
129
+		break;
130
+	}
131
+}
132
+#endif