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 }