/* IMASM Macro Precompiler Copyright (C) 2003 Joe Fisher, Shiny Technologies, LLC http://www.shinytechnologies.com Portions Copyright (C) 2003 Joseph Zbiciak. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "..\main.h" #define NUL '\0' const char *const license_string = "IMASM Macro Precompiler\n" "imasm -help for help\n" "\n" "Copyright (C) 2003 Joe Fisher, Shiny Technologies, LLC\n" "Portions Copyright (C) 2003 Joseph Zbiciak\n" "\n" "http://www.shinytechnologies.com\n" "\n" "This program is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU General Public License\n" "as published by the Free Software Foundation; either version 2\n" "of the License, or (at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, " "USA.\n"; int stricmp_(const char *str1, const char *str2) { while (tolower(*str1) == tolower(*str2)) { if (*str1 == NUL) { return 0; } str1++; str2++; } if (tolower(*str1) > tolower(*str2)) { return 1; } return -1; } void OutputHelp() { cout << "IMASM Macro Precompiler ver " << IMASMVERSION << endl << endl; cout << "Usage:" << endl; cout << "imasm : Run in GUI mode" << endl; cout << "imasm inputfile : Run in GUI mode and load filename into editor" << endl; cout << "imasm inputfile outputfile : Parse file with no GUI" << endl; cout << "imasm -l" << endl; cout << "imasm /l : Display GPL License" << endl; cout << endl << "Copyright (C) 2003 Joe Fisher, Joe Zbiciak" << endl; cout << "http://www.shinytechnologies.com" << endl << endl; cout << "Distributed under the GNU GPL" << endl; } void OutputLicense() { cout << license_string << endl; } BOOL CreateChildProcess(char *szFile) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); // Create the child process. BOOL bRet = CreateProcess( NULL, szFile, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited 0, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &si, // STARTUPINFO pointer &pi); // receives PROCESS_INFORMATION return bRet; } void DoChildProcess(char *szCmd) { HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRdDup; HANDLE hChildStdoutRd, hChildStdoutWr; HANDLE hChildStdinWrDup; HANDLE hSaveStdout, hSaveStdin; BOOL fSuccess; // Set the bInheritHandle flag so pipe handles are inherited. SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; try { // The steps for redirecting child process's STDOUT: // 1. Save current STDOUT, to be restored later. // 2. Create anonymous pipe to be STDOUT for child process. // 3. Set STDOUT of the parent process to be write handle to // the pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the read handle and // close the inheritable read handle. // Save the handle to the current STDOUT. hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Create a pipe for the child process's STDOUT. if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) { throw ("Stdout pipe creation failed\n"); } // Set a write handle to the pipe to be STDOUT. if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) { throw ("Redirecting STDOUT failed"); } // Create noninheritable read handle and close the inheritable read // handle. fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS); if (!fSuccess) { throw ("DuplicateHandle failed"); } CloseHandle(hChildStdoutRd); // The steps for redirecting child process's STDIN: // 1. Save current STDIN, to be restored later. // 2. Create anonymous pipe to be STDIN for child process. // 3. Set STDIN of the parent to be the read handle to the // pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the write handle, // and close the inheritable write handle. // Save the handle to the current STDIN. hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); // Create a pipe for the child process's STDIN. if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { throw ("Stdin pipe creation failed\n"); } // Set a read handle to the pipe to be STDIN. if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) { throw ("Redirecting Stdin failed"); } // Duplicate the write handle to the pipe so it is not inherited. fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, // not inherited DUPLICATE_SAME_ACCESS); if (!fSuccess) { throw ("DuplicateHandle failed"); } // Now create the child process. if (!CreateChildProcess(szCmd)) { throw ("Create process failed"); } // After process creation, restore the saved STDIN and STDOUT. if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) { throw ("Re-redirecting Stdin failed\n"); } if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) { throw ("Re-redirecting Stdout failed\n"); } // Close the write end of the pipe before reading from the // read end of the pipe. CloseHandle(hChildStdoutWr); CloseHandle(hChildStdinWr); } catch (char *szError) { cout << szError << endl; return; } DWORD dwRead, dwWritten; char chBuff[MAX_PATH]; int i = 0; // Read output from the child process while (1) { if (!ReadFile(hChildStdoutRdDup, chBuff, MAX_PATH, &dwRead, NULL)) { break; } if (dwRead > 0) { WriteFile(hSaveStdout, &chBuff, dwRead, &dwWritten, 0); } } } int main(int argc, char *argv[]) { char szCmd[MAX_PATH] = ""; int i; if (argc > 3) { cout << endl << "Error, Invalid number of arguments. " << endl << endl; OutputHelp(); return 0; } if (argc > 1) { if ( (stricmp_(argv[1], "-help") == 0) || (stricmp_(argv[1], "/help") == 0) || (stricmp_(argv[1], "-?") == 0) || (stricmp_(argv[1], "/?") == 0)) { OutputHelp(); return 0; } else if ( (stricmp_(argv[1], "-l") == 0) || (stricmp_(argv[1], "/l") == 0)) { OutputLicense(); return 0; } } // Spawn the process here strcpy(szCmd, ".\\imasm.exe "); for (i = 1; i < argc; i++) { strcat(szCmd, argv[i]); strcat(szCmd, " "); } DoChildProcess(szCmd); cout << "Thanks for using IMASM ver " << IMASMVERSION << endl; return 0; }