working fork() on windows vista and newer

fork.c 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. #define _WIN32_WINNT 0x0600
  17. #define WIN32_LEAN_AND_MEAN
  18. #include <windows.h>
  19. #include <winnt.h>
  20. #include <ntdef.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <process.h>
  24. #ifdef __MINGW32__
  25. typedef struct _CLIENT_ID {
  26. PVOID UniqueProcess;
  27. PVOID UniqueThread;
  28. } CLIENT_ID, *PCLIENT_ID;
  29. typedef struct _SECTION_IMAGE_INFORMATION {
  30. PVOID EntryPoint;
  31. ULONG StackZeroBits;
  32. ULONG StackReserved;
  33. ULONG StackCommit;
  34. ULONG ImageSubsystem;
  35. WORD SubSystemVersionLow;
  36. WORD SubSystemVersionHigh;
  37. ULONG Unknown1;
  38. ULONG ImageCharacteristics;
  39. ULONG ImageMachineType;
  40. ULONG Unknown2[3];
  41. } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
  42. typedef struct _RTL_USER_PROCESS_INFORMATION {
  43. ULONG Size;
  44. HANDLE Process;
  45. HANDLE Thread;
  46. CLIENT_ID ClientId;
  47. SECTION_IMAGE_INFORMATION ImageInformation;
  48. } RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION;
  49. #define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001
  50. #define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002
  51. #define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004
  52. #define RTL_CLONE_PARENT 0
  53. #define RTL_CLONE_CHILD 297
  54. #endif
  55. typedef NTSTATUS (*RtlCloneUserProcess_f)(ULONG ProcessFlags,
  56. PSECURITY_DESCRIPTOR ProcessSecurityDescriptor /* optional */,
  57. PSECURITY_DESCRIPTOR ThreadSecurityDescriptor /* optional */,
  58. HANDLE DebugPort /* optional */,
  59. PRTL_USER_PROCESS_INFORMATION ProcessInformation);
  60. pid_t fork(void)
  61. {
  62. HMODULE mod;
  63. RtlCloneUserProcess_f clone_p;
  64. RTL_USER_PROCESS_INFORMATION process_info;
  65. NTSTATUS result;
  66. mod = GetModuleHandle("ntdll.dll");
  67. if (!mod)
  68. return -ENOSYS;
  69. clone_p = GetProcAddress(mod, "RtlCloneUserProcess");
  70. if (clone_p == NULL)
  71. return -ENOSYS;
  72. /* lets do this */
  73. result = clone_p(RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED | RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES, NULL, NULL, NULL, &process_info);
  74. if (result == RTL_CLONE_PARENT)
  75. {
  76. HANDLE me = GetCurrentProcess();
  77. pid_t child_pid;
  78. child_pid = GetProcessId(process_info.Process);
  79. ResumeThread(process_info.Thread);
  80. CloseHandle(process_info.Process);
  81. CloseHandle(process_info.Thread);
  82. return child_pid;
  83. }
  84. else if (result == RTL_CLONE_CHILD)
  85. {
  86. /* fix stdio */
  87. AllocConsole();
  88. return 0;
  89. }
  90. else
  91. return -1;
  92. /* NOTREACHED */
  93. return -1;
  94. }
  95. #ifdef __TEST__
  96. int main(int argc, const char *argv[])
  97. {
  98. pid_t pid = fork();
  99. switch (pid) {
  100. case 0:
  101. {
  102. FILE *f = fopen("C:/Users/nenolod/Documents/forktest.dat", "w");
  103. fprintf(f, "ok\n");
  104. fclose(f);
  105. break;
  106. }
  107. default:
  108. printf("child %d\n", pid);
  109. while (1) { Sleep(1000); }
  110. break;
  111. }
  112. }
  113. #endif