/* * fork.c * Experimental fork() on Windows. Requires NT 6 subsystem or * newer. * * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * This software is provided 'as is' and without any warranty, express or * implied. In no event shall the authors be liable for any damages arising * from the use of this software. */#define _WIN32_WINNT 0x0600#define WIN32_LEAN_AND_MEAN#include<windows.h>#include<winnt.h>#include<ntdef.h>#include<stdio.h>#include<errno.h>#include<process.h>#ifdef __MINGW32__typedefstruct_CLIENT_ID{PVOIDUniqueProcess;PVOIDUniqueThread;}CLIENT_ID,*PCLIENT_ID;typedefstruct_SECTION_IMAGE_INFORMATION{PVOIDEntryPoint;ULONGStackZeroBits;ULONGStackReserved;ULONGStackCommit;ULONGImageSubsystem;WORDSubSystemVersionLow;WORDSubSystemVersionHigh;ULONGUnknown1;ULONGImageCharacteristics;ULONGImageMachineType;ULONGUnknown2[3];}SECTION_IMAGE_INFORMATION,*PSECTION_IMAGE_INFORMATION;typedefstruct_RTL_USER_PROCESS_INFORMATION{ULONGSize;HANDLEProcess;HANDLEThread;CLIENT_IDClientId;SECTION_IMAGE_INFORMATIONImageInformation;}RTL_USER_PROCESS_INFORMATION,*PRTL_USER_PROCESS_INFORMATION;#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004#define RTL_CLONE_PARENT 0#define RTL_CLONE_CHILD 297#endiftypedefNTSTATUS(*RtlCloneUserProcess_f)(ULONGProcessFlags,PSECURITY_DESCRIPTORProcessSecurityDescriptor/* optional */,PSECURITY_DESCRIPTORThreadSecurityDescriptor/* optional */,HANDLEDebugPort/* optional */,PRTL_USER_PROCESS_INFORMATIONProcessInformation);pid_tfork(void){HMODULEmod;RtlCloneUserProcess_fclone_p;RTL_USER_PROCESS_INFORMATIONprocess_info;NTSTATUSresult;mod=GetModuleHandle("ntdll.dll");if(!mod)return-ENOSYS;clone_p=GetProcAddress(mod,"RtlCloneUserProcess");if(clone_p==NULL)return-ENOSYS;/* lets do this */result=clone_p(RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED|RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES,NULL,NULL,NULL,&process_info);if(result==RTL_CLONE_PARENT){HANDLEme=GetCurrentProcess();pid_tchild_pid;child_pid=GetProcessId(process_info.Process);ResumeThread(process_info.Thread);CloseHandle(process_info.Process);CloseHandle(process_info.Thread);returnchild_pid;}elseif(result==RTL_CLONE_CHILD){/* fix stdio */AllocConsole();return0;}elsereturn-1;/* NOTREACHED */return-1;}#ifdef __TEST__intmain(intargc,constchar*argv[]){pid_tpid=fork();switch(pid){case0:{FILE*f=fopen("C:/Users/nenolod/Documents/forktest.dat","w");fprintf(f,"ok\n");fclose(f);break;}default:printf("child %d\n",pid);while(1){Sleep(1000);}break;}}#endif