1 /*-
2  * Copyright (c) 2009 Michihiro NAKAJIMA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "archive_platform.h"
27 
28 #if defined(_WIN32) && !defined(__CYGWIN__)
29 
30 #include "filter_fork.h"
31 
32 pid_t
33 __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
34 {
35 	HANDLE childStdout[2], childStdin[2], childStdinWr, childStdoutRd;
36 	SECURITY_ATTRIBUTES secAtts;
37 	STARTUPINFO staInfo;
38 	PROCESS_INFORMATION childInfo;
39 	char cmd[MAX_PATH];
40 	DWORD mode;
41 
42 	secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
43 	secAtts.bInheritHandle = TRUE;
44 	secAtts.lpSecurityDescriptor = NULL;
45 	if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0)
46 		goto fail;
47 	if (DuplicateHandle(GetCurrentProcess(), childStdout[0],
48 	    GetCurrentProcess(), &childStdoutRd, 0, FALSE,
49 	    DUPLICATE_SAME_ACCESS) == 0) {
50 		CloseHandle(childStdout[0]);
51 		CloseHandle(childStdout[1]);
52 		goto fail;
53 	}
54 	CloseHandle(childStdout[0]);
55 
56 	if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) {
57 		CloseHandle(childStdoutRd);
58 		CloseHandle(childStdout[1]);
59 		goto fail;
60 	}
61 
62 	if (DuplicateHandle(GetCurrentProcess(), childStdin[1],
63 	    GetCurrentProcess(), &childStdinWr, 0, FALSE,
64 	    DUPLICATE_SAME_ACCESS) == 0) {
65 		CloseHandle(childStdoutRd);
66 		CloseHandle(childStdout[1]);
67 		CloseHandle(childStdin[0]);
68 		CloseHandle(childStdin[1]);
69 		goto fail;
70 	}
71 	CloseHandle(childStdin[1]);
72 
73 	memset(&staInfo, 0, sizeof(staInfo));
74 	staInfo.cb = sizeof(staInfo);
75 	staInfo.hStdOutput = childStdout[1];
76 	staInfo.hStdInput = childStdin[0];
77 	staInfo.wShowWindow = SW_HIDE;
78 	staInfo.dwFlags = STARTF_USEFILLATTRIBUTE | STARTF_USECOUNTCHARS |
79 	    STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
80 	strncpy(cmd, path, sizeof(cmd)-1);
81 	cmd[sizeof(cmd)-1] = '\0';
82 	if (CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
83 	    &staInfo, &childInfo) == 0) {
84 		CloseHandle(childStdoutRd);
85 		CloseHandle(childStdout[1]);
86 		CloseHandle(childStdin[0]);
87 		CloseHandle(childStdinWr);
88 		goto fail;
89 	}
90 	WaitForInputIdle(childInfo.hProcess, INFINITE);
91 	CloseHandle(childInfo.hProcess);
92 	CloseHandle(childInfo.hThread);
93 
94 	mode = PIPE_NOWAIT;
95 	SetNamedPipeHandleState(childStdoutRd, &mode, NULL, NULL);
96 	*child_stdout = _open_osfhandle((intptr_t)childStdoutRd, _O_RDONLY);
97 	*child_stdin = _open_osfhandle((intptr_t)childStdinWr, _O_WRONLY);
98 
99 	return (childInfo.dwProcessId);
100 
101 fail:
102 	return (-1);
103 }
104 
105 void
106 __archive_check_child(int in, int out)
107 {
108 	(void)in; /* UNSED */
109 	(void)out; /* UNSED */
110 	Sleep(100);
111 }
112 
113 #endif /* _WIN32 && !__CYGWIN__ */
114