Ejemplo n.º 1
0
int fork(void) {

	size_t rc;
	size_t stacksize;
	char modname[512];/*FIXBUF*/
	HANDLE  hProc,hThread, hArray[2];
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	SECURITY_ATTRIBUTES sa;
	DWORD dwCreationflags;
	unsigned int priority;
	HANDLE h64Parent,h64Child;

#ifndef _M_ALPHA
	unsigned long fork_stack_end;
#endif _M_ALPHA

	__fork_stack_begin =GETSTACKBASE();

#ifndef _M_ALPHA
	__fork_stack_end = &fork_stack_end;
#else
	__fork_stack_end = (unsigned long *)__asm("mov $sp, $0");
#endif /*_M_ALPHA*/

	h64Parent = h64Child = NULL;
	//
	// Create two inheritable events
	//
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor =0;
	sa.bInheritHandle = TRUE;
	if (!__hforkchild)
		__hforkchild = CreateEvent(&sa,TRUE,FALSE,NULL);
	if (!__hforkparent)
		__hforkparent = CreateEvent(&sa,TRUE,FALSE,NULL);

	rc = setjmp(__fork_context);

	if (rc) { // child
#ifdef  _M_IX86
		//
		// Restore old registration
		// -amol 2/2/97
		GETEXCEPTIONREGIST() = (struct _EXCEPTION_REGISTRATION_RECORD*)_old_exr;
#endif // _M_ALPHA
		SetEvent(__hforkchild);

		dprintf("Child ready to rumble\n");
		if(WaitForSingleObject(__hforkparent,FORK_TIMEOUT) != WAIT_OBJECT_0)
			ExitProcess(0xFFFF);

		CloseHandle(__hforkchild);
		CloseHandle(__hforkparent);
		__hforkchild = __hforkparent=0;

		//__asm { int 3};
		restore_fds();

		STR_environ = blk2short(environ);
		environ = short2blk(STR_environ);	/* So that we can free it */

		return 0;
	}
	copy_fds();
	memset(&si,0,sizeof(si));
	si.cb= sizeof(si);

	/*
	 * This f!@#!@% function returns the old value even if the std handles
	 * have been closed.
	 * Skip this step, since we know tcsh will do the right thing later.
	 * 
	 si.hStdInput= GetStdHandle(STD_INPUT_HANDLE);
	 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
	 */

	if (!GetModuleFileName(GetModuleHandle(NULL),modname,512) ) {
		rc = GetLastError();
		return -1;
	}
	dwCreationflags = GetPriorityClass(GetCurrentProcess());
	priority = GetThreadPriority(GetCurrentThread());
	rc = CreateProcess(NULL,
			modname,
			NULL,
			NULL,
			TRUE,
			CREATE_SUSPENDED | dwCreationflags,
			NULL,
			NULL,
			&si,
			&pi);
	if (!rc)  {
		rc = GetLastError();
		return -1;
	}

	ResetEvent(__hforkchild);
	ResetEvent(__hforkparent);

	hProc = pi.hProcess;
	hThread = pi.hThread;


	__forked=1;
	/*
	 * Usage of events in the wow64 case:
	 *
	 * h64Parent : initially non-signalled
	 * h64Child  : initially non-signalled
	 *
	 *    1. Create the events, resume the child thread.
	 *    2. Child opens h64Parent to see if it is a child process in wow64
	 *    3. Child opens and sets h64Child to tell parent it's running. (This
	 *       step is needed because we can't copy to a process created in the
	 *       suspended state on wow64.)
	 *    4. Copy gForkData and then set h64Parent. This tells the child
	 *       that the parameters in the structure are trustworthy.
	 *    5. Wait for h64Child so that we know the child has created the stack
	 *       in dynamic memory.
	 *
	 *   The rest of the fork hack should now proceed as in x86
	 *
	 */
	if (bIsWow64Process) {

		// allocate the heap for the child. this can be done even when
		// the child is suspended. 
		// avoids inexplicable allocation failures in the child.
		if (VirtualAllocEx(hProc,
					__heap_base,
					__heap_size,
					MEM_RESERVE,
					PAGE_READWRITE) == NULL) {
			dprintf("virtual allocex failed %d\n",GetLastError());
			goto error;
		}
		if (VirtualAllocEx(hProc,
					__heap_base,
					__heap_size,
					MEM_COMMIT,
					PAGE_READWRITE) == NULL) {
			dprintf("virtual allocex2 failed %d\n",GetLastError());
			goto error;
		}

		// Do NOT expect existing events
		if (!CreateWow64Events(pi.dwProcessId,&h64Parent,&h64Child,FALSE)) {
			goto error;
		}
		ResumeThread(hThread);

		// wait for the child to tell us it is running
		//if (WaitForSingleObject(h64Child,FORK_TIMEOUT) != WAIT_OBJECT_0) {
		//	rc = GetLastError();
		//	goto error;
		//}
		hArray[0] = h64Child;
		hArray[1] = hProc;

		if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != 
				WAIT_OBJECT_0){

			rc = GetLastError();
			goto error;
		}

	}
	//
	// Copy all the shared data
	//
	if (!WriteProcessMemory(hProc,&gForkData,&gForkData,
				sizeof(ForkData),&rc)) {
		goto error;
	}
	if (rc != sizeof(ForkData)) 
		goto error;

	if (!bIsWow64Process) {
		rc = ResumeThread(hThread);
	}
	// in the wow64 case, the child will be waiting  on h64parent again.
	// set it, and then wait for h64child. This will mean the child has
	// a stack set up at the right location.
	else {
		SetEvent(h64Parent);
		hArray[0] = h64Child;
		hArray[1] = hProc;

		if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != 
				WAIT_OBJECT_0){

			rc = GetLastError();
			goto error;
		}
		CloseHandle(h64Parent);
		CloseHandle(h64Child);
		h64Parent = h64Child = NULL;
	}

	//
	// Wait for the child to start and init itself.
	// The timeout is so that we don't wait too long
	//
	hArray[0] = __hforkchild;
	hArray[1] = hProc;

	if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != WAIT_OBJECT_0){

		int err = GetLastError(); // For debugging purposes
		dprintf("wait failed err %d\n",err);
		goto error;
	}

	// Stop the child again and copy the stack and heap
	//
	SuspendThread(hThread);

	if (!SetThreadPriority(hThread,priority) ) {
		priority =GetLastError();
	}

	// stack
	stacksize = (char*)__fork_stack_begin - (char*)__fork_stack_end;
	if (!WriteProcessMemory(hProc,(char *)__fork_stack_end,
				(char *)__fork_stack_end,
				(u_long)stacksize,
				&rc)){
		goto error;
	}
	//
	// copy heap itself
	if (!WriteProcessMemory(hProc, (void*)__heap_base,(void*)__heap_base, 
				(DWORD)((char*)__heap_top-(char*)__heap_base),
				&rc)){
		goto error;
	}

	rc = fork_copy_user_mem(hProc);

	if(rc) {
		goto error;
	}

	// Release the child.
	SetEvent(__hforkparent);
	rc = ResumeThread(hThread);

	__forked=0;
	dprintf("forked process %d\n",pi.dwProcessId);
	start_sigchild_thread(hProc,pi.dwProcessId);
	close_copied_fds();

	CloseHandle(hThread);
	//
	// return process id to parent.
	return pi.dwProcessId;

error:
	__forked=0;
	SetEvent(__hforkparent);
	ResumeThread(hThread);
	CloseHandle(hProc);
	CloseHandle(hThread);
	if (h64Parent) {
		SetEvent(h64Parent); // don't let child block forever
		CloseHandle(h64Parent);
	}
	if (h64Child)
		CloseHandle(h64Child);
	return -1;
}
Ejemplo n.º 2
0
void silly_entry(void *peb) {
	char * path1=NULL;
	int rc;
	char temp[MAX_PATH+5];
	char buf[MAX_PATH];
	char ptr1[MAX_PATH];
	char ptr2[MAX_PATH];
	char ptr3[MAX_PATH];
	OSVERSIONINFO osver;


	init_wow64();

	// look at the explanation in fork.c for why we do these steps.
	if (bIsWow64Process) {
		HANDLE h64Parent,h64Child;
		char *stk, *end;
		DWORD mb = (1<<20);

		// if we found the events, then we're the product of a fork()
		if (CreateWow64Events(GetCurrentProcessId(),
								&h64Parent,&h64Child,TRUE)) {

			if (!h64Parent || !h64Child)
				return;

			// tell parent we're rolling
			SetEvent(h64Child);

			if(WaitForSingleObject(h64Parent,FORK_TIMEOUT) != WAIT_OBJECT_0) {
				return;
			}

			// if __forked is 0, we shouldn't have found the events
			if (!__forked) 
				return;
		}

		// now create the stack 

		if (!__forked) {
			stk = VirtualAlloc(NULL,mb+65536,MEM_COMMIT,PAGE_READWRITE);
			if (!stk) {
				dprintf("virtual alloc in parent failed %d\n",GetLastError());
				return;
			}
			end = stk + mb + 65536;
			end -= sizeof(char*);

			__fork_stack_begin = end;

			__asm {mov esp,end };

			set_stackbase(end);
			heap_init();
		}
		else { // child process
			stk = (char*)__fork_stack_begin + sizeof(char*)- mb - 65536;

			dprintf("begin is 0x%08x\n",stk);
			end = VirtualAlloc(stk, mb+65536 , MEM_RESERVE , PAGE_READWRITE);
			if (!end) {
				rc = GetLastError();
				dprintf("virtual alloc 1 in child failed %d\n",rc);
				return;
			}
			stk = VirtualAlloc(end, mb+65536 , MEM_COMMIT , PAGE_READWRITE);
			if (!stk) {
				rc = GetLastError();
				dprintf("virtual alloc 2 in child failed %d\n",rc);
				return;
			}
			end = stk + mb + 65536;
			__asm {mov esp, end};
			set_stackbase(end);

			SetEvent(h64Child);

			CloseHandle(h64Parent);
			CloseHandle(h64Child);
		}

	}


	SetFileApisToOEM();

	if (!bIsWow64Process)
		heap_init();


	osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

	if (!GetVersionEx(&osver)) {
		MessageBox(NULL,"GetVersionEx failed","tcsh",MB_ICONHAND);
		ExitProcess(0xFF);
	}
	gdwVersion = osver.dwMajorVersion;


	/* If home is set, we only need to change '\' to '/' */
	rc = GetEnvironmentVariable("HOME",buf,MAX_PATH);
	if (rc && (rc < MAX_PATH)){
		path_slashify(buf);
		(void)SetEnvironmentVariable("HOME",buf);
		goto skippy;
	}
	
	memset(ptr1,0,MAX_PATH);
	memset(ptr2,0,MAX_PATH);
	memset(ptr3,0,MAX_PATH);

	if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
	    GetEnvironmentVariable("USERPROFILE",ptr1,MAX_PATH);
	    GetEnvironmentVariable("HOMEDRIVE",ptr2,MAX_PATH);
	    GetEnvironmentVariable("HOMEPATH",ptr3,MAX_PATH);

		ptr1[MAX_PATH -1] = ptr2[MAX_PATH-1] = ptr3[MAX_PATH-1]= 0;

		if (!ptr1[0] || osver.dwMajorVersion <4) {
			wsprintf(temp,"%s%s",ptr2[0]?ptr2:"C:",ptr3[0]?ptr3:"\\");
		}
		else if (osver.dwMajorVersion >= 4) {
			wsprintf(temp,"%s",ptr1);
		}
	}
	else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {

		rc = GetWindowsDirectory(ptr1,MAX_PATH);
		if (rc > MAX_PATH) {
			MessageBox(NULL,"This should never happen","tcsh",MB_ICONHAND);
			ExitProcess(0xFF);
		}
		wsprintf(temp,"%s",ptr1);
	}
	else {
		MessageBox(NULL,"Unknown platform","tcsh",MB_ICONHAND);
	}
	path_slashify(temp);
	SetEnvironmentVariable("HOME",temp);

skippy:
	gdwPlatform = osver.dwPlatformId;


	rc = GetEnvironmentVariable("Path",path1,0);
	if ( rc !=0) {

		path1 =heap_alloc(rc);

		GetEnvironmentVariable("Path",path1,rc);
		SetEnvironmentVariable("Path",NULL);
		/*SetEnvironmentVariable("PATH",NULL);*/
		SetEnvironmentVariable("PATH",path1);

		heap_free(path1);
	}
	mainCRTStartup(peb);
}