- 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