/*============================================================================ ** COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED. **============================================================================ ** ** Project/Product : JATS ( core)devl) ** Filename : gunzip.cpp ** Author(s) : dpurdie ** Created : 08-Mar-18 ** ** Description : Implement gunzip by invoking gzip with a -d option ** ** ** Information : ** Compiler : ANSI C++ ** Target : ** ***==========================================================================*/ // //#include "stdafx.h" #include #include #include using namespace std; /*---------------------------------------------------------------------------- ** FUNCTION : ArgvQuote ** ** DESCRIPTION : Append an argument to a string with correct ** quoting for passing as a command line argument This routine appends the given argument to a command line such that CommandLineToArgvW will return the argument string unchanged. Arguments in a command line should be separated by spaces; this function does not add these spaces. ** ** INPUTS : Argument - Supplies the argument to encode ** CommandLine - Append to this string ** Force - True: Force quotes ** ** RETURNS : Nothing ** ----------------------------------------------------------------------------*/ void ArgvQuote( const std::wstring& Argument,std::wstring& CommandLine, bool Force ) { // // Unless we're told otherwise, don't quote unless we actually // need to do so --- hopefully avoid problems if programs won't // parse quotes properly // if (Force == false && Argument.empty() == false && Argument.find_first_of(L" \t\n\v\"") == Argument.npos) { CommandLine.append(Argument); } else { CommandLine.append(L"\""); for (std::wstring::const_iterator It = Argument.begin(); ; ++It) { unsigned NumberBackslashes = 0; while (It != Argument.end() && *It == L'\\') { ++It; ++NumberBackslashes; } if (It == Argument.end()) { // // Escape all backslashes, but let the terminating // double quotation mark we add below be interpreted // as a metacharacter. // CommandLine.append(NumberBackslashes * 2, L'\\'); break; } else if (*It == L'"') { // // Escape all backslashes and the following // double quotation mark. // CommandLine.append(NumberBackslashes * 2 + 1, L'\\'); CommandLine.append(1, *It); } else { // // Backslashes aren't special here. // CommandLine.append(NumberBackslashes, L'\\'); CommandLine.append(1, *It); } } CommandLine.append(L"\""); } } /*---------------------------------------------------------------------------- ** FUNCTION : s2ws ** ** DESCRIPTION : String to Wide String ** ** ** INPUTS : str - std:string ** ** RETURNS : A widestring ** ----------------------------------------------------------------------------*/ std::wstring s2ws(const std::string& str) { int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); std::wstring wstrTo(size_needed, 0); MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); return wstrTo; } /*---------------------------------------------------------------------------- ** FUNCTION : main ** ** DESCRIPTION : Invoke gzip with a '-d' option ** ** ** INPUTS : As per gzip ** ** RETURNS : Exit code of the gzip utility ** ----------------------------------------------------------------------------*/ int main(int argc, char** argv) { BOOL rv; // // Replace gunzip.exe with gzip.exe -d // // Retrieve the command line arguments as an array of pointers to strings // First string will be the program path // // Remove program name - keep path // Assume we will find the gzip in the same location us this program or via the same path mechanism // Handle aaaa\bbbb\cccc // aaaa/bbbb/ccccc // cccc // std::wstring arg = s2ws(argv[0]); int index = arg.find_last_of(L"\\", arg.size()); if (index == std::string::npos) { index = arg.find_last_of(L"/", arg.size()); if (index == std::string::npos) { index = -1; } } arg.erase(index + 1); arg.append(L"gzip.exe"); // // Convert the arglist into a fully quoted command line string // Inserting a '-d' option // std::wstring args = wstring(); ArgvQuote(arg, args, FALSE); args.append(L" "); ArgvQuote(L"-d", args, FALSE); for (int ii = 1; ii < argc; ii++) { args.append(L" "); ArgvQuote(s2ws(argv[ii]), args, FALSE); } //std::wcout << L"Cmd:" << args << std::endl; // additional information STARTUPINFO si; PROCESS_INFORMATION pi; DWORD exitStatus = 250; // set the size of the structures ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); // start the program up rv = CreateProcess ( NULL, // the path (LPWSTR)args.c_str(), // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable TRUE, // Set handle inheritance to TRUE 0, // Opens file in a separate console NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi // Pointer to PROCESS_INFORMATION structure ); if (!rv) { DWORD eCode = GetLastError(); exitStatus = eCode; //std::wcout << L"CreateProcess Error:" << eCode << std::endl; return exitStatus; } // Close process and thread handles. WaitForSingleObject(pi.hProcess, INFINITE); rv = GetExitCodeProcess(pi.hProcess, &exitStatus); if (!rv) { DWORD eCode = GetLastError(); //std::wcout << L"GetExitCodeProcess Error:" << eCode << std::endl; exitStatus = 248; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); //std::wcout << L"Exit Status:" << exitStatus << std::endl; return exitStatus; }