1 /*
2 
3 IMASM Macro Precompiler
4 
5 Copyright (C) 2003  Joe Fisher, Shiny Technologies, LLC
6 http://www.shinytechnologies.com
7 Portions Copyright (C) 2003  Joseph Zbiciak.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 
23 */
24 
25 #include <windows.h>
26 #include <iostream.h>
27 #include <ctype.h>
28 
29 #include "..\main.h"
30 
31 #define NUL '\0'
32 
33 const char *const license_string =
34     "IMASM Macro Precompiler\n"
35     "imasm -help for help\n"
36     "\n"
37     "Copyright (C) 2003  Joe Fisher, Shiny Technologies, LLC\n"
38     "Portions Copyright (C) 2003  Joseph Zbiciak\n"
39     "\n"
40     "http://www.shinytechnologies.com\n"
41     "\n"
42     "This program is free software; you can redistribute it and/or\n"
43     "modify it under the terms of the GNU General Public License\n"
44     "as published by the Free Software Foundation; either version 2\n"
45     "of the License, or (at your option) any later version.\n"
46     "\n"
47     "This program is distributed in the hope that it will be useful,\n"
48     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
49     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
50     "GNU General Public License for more details.\n"
51     "\n"
52     "You should have received a copy of the GNU General Public License\n"
53     "along with this program; if not, write to the Free Software\n"
54     "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, "
55     "USA.\n";
56 
stricmp_(const char * str1,const char * str2)57 int stricmp_(const char *str1, const char *str2)
58 {
59 	while (tolower(*str1) == tolower(*str2))
60 	{
61 		if (*str1 == NUL)
62 		{
63 			return 0;
64 		}
65 
66 		str1++;
67 		str2++;
68 	}
69 
70 	if (tolower(*str1) > tolower(*str2))
71 	{
72 		return 1;
73 	}
74 
75 	return -1;
76 }
77 
OutputHelp()78 void OutputHelp()
79 {
80 	cout << "IMASM Macro Precompiler ver " << IMASMVERSION << endl << endl;
81 
82 	cout << "Usage:" << endl;
83 	cout << "imasm                      : Run in GUI mode" << endl;
84 	cout << "imasm inputfile            : Run in GUI mode and load filename into editor" << endl;
85 	cout << "imasm inputfile outputfile : Parse file with no GUI" << endl;
86 	cout << "imasm -l" << endl;
87 	cout << "imasm /l                   : Display GPL License" << endl;
88 
89 	cout << endl << "Copyright (C) 2003  Joe Fisher, Joe Zbiciak" << endl;
90 	cout << "http://www.shinytechnologies.com" << endl << endl;
91 	cout << "Distributed under the GNU GPL" << endl;
92 }
93 
OutputLicense()94 void OutputLicense()
95 {
96 	cout << license_string << endl;
97 }
98 
CreateChildProcess(char * szFile)99 BOOL CreateChildProcess(char *szFile)
100 {
101 	STARTUPINFO si;
102 	PROCESS_INFORMATION pi;
103 
104 	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
105 	ZeroMemory(&si, sizeof(STARTUPINFO));
106 	si.cb = sizeof(STARTUPINFO);
107 
108 	// Create the child process.
109 	BOOL bRet =  CreateProcess(	NULL,
110 								szFile,	// command line
111 								NULL,	// process security attributes
112 								NULL,	// primary thread security attributes
113 								TRUE,	// handles are inherited
114 								0,		// creation flags
115 								NULL,	// use parent's environment
116 								NULL,	// use parent's current directory
117 								&si,	// STARTUPINFO pointer
118 								&pi);	// receives PROCESS_INFORMATION
119 
120 
121 	return bRet;
122 }
123 
DoChildProcess(char * szCmd)124 void DoChildProcess(char *szCmd)
125 {
126 	HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRdDup;
127 	HANDLE hChildStdoutRd, hChildStdoutWr;
128 	HANDLE hChildStdinWrDup;
129 	HANDLE hSaveStdout, hSaveStdin;
130 
131 	BOOL fSuccess;
132 
133 	// Set the bInheritHandle flag so pipe handles are inherited.
134 	SECURITY_ATTRIBUTES saAttr;
135 
136 	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
137 	saAttr.bInheritHandle = TRUE;
138 	saAttr.lpSecurityDescriptor = NULL;
139 
140 	try
141 	{
142 		// The steps for redirecting child process's STDOUT:
143 		//     1. Save current STDOUT, to be restored later.
144 		//     2. Create anonymous pipe to be STDOUT for child process.
145 		//     3. Set STDOUT of the parent process to be write handle to
146 		//        the pipe, so it is inherited by the child process.
147 		//     4. Create a noninheritable duplicate of the read handle and
148 		//        close the inheritable read handle.
149 
150 		// Save the handle to the current STDOUT.
151 
152 		hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
153 
154 		// Create a pipe for the child process's STDOUT.
155 		if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
156 		{
157 			throw ("Stdout pipe creation failed\n");
158 		}
159 
160 		// Set a write handle to the pipe to be STDOUT.
161 
162 		if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
163 		{
164 			throw ("Redirecting STDOUT failed");
165 		}
166 
167 		// Create noninheritable read handle and close the inheritable read
168 		// handle.
169 		fSuccess = DuplicateHandle(	GetCurrentProcess(),
170 									hChildStdoutRd,
171 									GetCurrentProcess(),
172 									&hChildStdoutRdDup,
173 									0,
174 									FALSE,
175 									DUPLICATE_SAME_ACCESS);
176 
177 		if (!fSuccess)
178 		{
179 			throw ("DuplicateHandle failed");
180 		}
181 
182 		CloseHandle(hChildStdoutRd);
183 
184 		// The steps for redirecting child process's STDIN:
185 		//     1.  Save current STDIN, to be restored later.
186 		//     2.  Create anonymous pipe to be STDIN for child process.
187 		//     3.  Set STDIN of the parent to be the read handle to the
188 		//         pipe, so it is inherited by the child process.
189 		//     4.  Create a noninheritable duplicate of the write handle,
190 		//         and close the inheritable write handle.
191 
192 		// Save the handle to the current STDIN.
193 
194 		hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
195 
196 		// Create a pipe for the child process's STDIN.
197 
198 		if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
199 		{
200 			throw ("Stdin pipe creation failed\n");
201 		}
202 
203 		// Set a read handle to the pipe to be STDIN.
204 
205 		if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
206 		{
207 			throw ("Redirecting Stdin failed");
208 		}
209 
210 		// Duplicate the write handle to the pipe so it is not inherited.
211 
212 		fSuccess = DuplicateHandle(GetCurrentProcess(),
213 							  hChildStdinWr,
214 							  GetCurrentProcess(),
215 							  &hChildStdinWrDup,
216 							  0,
217 							  FALSE,                  // not inherited
218 							  DUPLICATE_SAME_ACCESS);
219 		if (!fSuccess)
220 		{
221 			throw ("DuplicateHandle failed");
222 		}
223 
224 		// Now create the child process.
225 		if (!CreateChildProcess(szCmd))
226 		{
227 			throw ("Create process failed");
228 		}
229 
230 		// After process creation, restore the saved STDIN and STDOUT.
231 		if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
232 		{
233 			throw ("Re-redirecting Stdin failed\n");
234 		}
235 
236 		if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
237 		{
238 			throw ("Re-redirecting Stdout failed\n");
239 		}
240 
241 		// Close the write end of the pipe before reading from the
242 		// read end of the pipe.
243 		CloseHandle(hChildStdoutWr);
244 		CloseHandle(hChildStdinWr);
245 	}
246 	catch (char *szError)
247 	{
248 		cout << szError << endl;
249 		return;
250 	}
251 
252 	DWORD dwRead, dwWritten;
253 	char chBuff[MAX_PATH];
254 	int i = 0;
255 
256 	// Read output from the child process
257 	while (1)
258 	{
259 		if (!ReadFile(hChildStdoutRdDup, chBuff, MAX_PATH, &dwRead, NULL))
260 		{
261 			break;
262 		}
263 
264 		if (dwRead > 0)
265 		{
266 			WriteFile(hSaveStdout, &chBuff, dwRead, &dwWritten, 0);
267 		}
268 	}
269 }
270 
main(int argc,char * argv[])271 int main(int argc, char *argv[])
272 {
273 	char szCmd[MAX_PATH] = "";
274 	int i;
275 
276 	if (argc > 3)
277 	{
278 		cout << endl << "Error, Invalid number of arguments. " << endl << endl;
279 		OutputHelp();
280 		return 0;
281 	}
282 
283 	if (argc > 1)
284 	{
285 		if (
286 			(stricmp_(argv[1], "-help") == 0) ||
287 			(stricmp_(argv[1], "/help") == 0) ||
288 			(stricmp_(argv[1], "-?") == 0) ||
289 			(stricmp_(argv[1], "/?") == 0))
290 		{
291 			OutputHelp();
292 			return 0;
293 		}
294 		else if (
295 			(stricmp_(argv[1], "-l") == 0) ||
296 			(stricmp_(argv[1], "/l") == 0))
297 		{
298 			OutputLicense();
299 			return 0;
300 		}
301 	}
302 
303 	// Spawn the process here
304 	strcpy(szCmd, ".\\imasm.exe ");
305 	for (i = 1; i < argc; i++)
306 	{
307 		strcat(szCmd, argv[i]);
308 		strcat(szCmd, " ");
309 	}
310 
311 	DoChildProcess(szCmd);
312 
313 	cout << "Thanks for using IMASM ver " << IMASMVERSION << endl;
314 	return 0;
315 }