- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
/* Windows doesn't support the fork() call; so we fake it by invoking
another copy of Wget with the same arguments with which we were
invoked. The child copy of Wget should perform the same initialization
sequence as the parent; so we should have two processes that are
essentially identical. We create a specially named section object that
allows the child to distinguish itself from the parent and is used to
exchange information between the two processes. We use an event object
for synchronization. */
static void
fake_fork (void)
{
char exe[MAX_PATH + 1];
DWORD exe_len, le;
SECURITY_ATTRIBUTES sa;
HANDLE section, event, h[2];
STARTUPINFO si;
PROCESS_INFORMATION pi;
struct fake_fork_info *info;
char *name;
BOOL rv;
section = pi.hProcess = pi.hThread = NULL;
/* Get the fully qualified name of our executable. This is more reliable
than using argv[0]. */
exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
if (!exe_len || (exe_len >= sizeof (exe)))
return;
sa.nLength = sizeof (sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
/* Create an anonymous inheritable event object that starts out
non-signaled. */
event = CreateEvent (&sa, FALSE, FALSE, NULL);
if (!event)
return;
/* Create the child process detached form the current console and in a
suspended state. */
xzero (si);
si.cb = sizeof (si);
rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
CREATE_SUSPENDED | DETACHED_PROCESS,
NULL, NULL, &si, &pi);
if (!rv)
goto cleanup;
/* Create a named section object with a name based on the process id of
the child. */
name = make_section_name (pi.dwProcessId);
section =
CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
sizeof (struct fake_fork_info), name);
le = GetLastError();
xfree (name);
/* Fail if the section object already exists (should not happen). */
if (!section || (le == ERROR_ALREADY_EXISTS))
{
rv = FALSE;
goto cleanup;
}
/* Copy the event handle into the section object. */
info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
if (!info)
{
rv = FALSE;
goto cleanup;
}
info->event = event;
UnmapViewOfFile (info);
/* Start the child process. */
rv = ResumeThread (pi.hThread);
if (!rv)
{
TerminateProcess (pi.hProcess, (DWORD) -1);
goto cleanup;
}
/* Wait for the child to signal to us that it has done its part. If it
terminates before signaling us it's an error. */
h[0] = event;
h[1] = pi.hProcess;
rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
if (!rv)
goto cleanup;
info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
if (!info)
{
rv = FALSE;
goto cleanup;
}
Из исходников wget.
https://git.savannah.gnu.org/cgit/wget.git/tree/src/mswindows.c