Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6800 dpurdie 1
/*============================================================================ 
2
** COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
3
**============================================================================
4
**
5
**  Project/Product :  JATS ( core)devl)
6
**  Filename        : gunzip.cpp
7
**  Author(s)       : dpurdie
8
**  Created         : 08-Mar-18
9
**
10
**  Description     : Implement gunzip by invoking gzip with a -d option
11
**
12
**
13
**  Information     :
14
**   Compiler       : ANSI C++
15
**   Target         : 
16
**
17
***==========================================================================*/
18
 
19
//
20
//#include "stdafx.h"
21
#include <Windows.h>
22
#include <string>
23
#include <iostream>
24
using namespace std;
25
 
26
/*----------------------------------------------------------------------------
27
** FUNCTION           : ArgvQuote
28
**
29
** DESCRIPTION        : Append an argument to a string with correct
30
**                      quoting for passing as a command line argument 
31
 
32
                        This routine appends the given argument to a command line such
33
                        that CommandLineToArgvW will return the argument string unchanged.
34
                        Arguments in a command line should be separated by spaces; this
35
                        function does not add these spaces.
36
**
37
** INPUTS             : Argument        - Supplies the argument to encode
38
**                      CommandLine     - Append to this string
39
**                      Force           - True: Force quotes
40
** 
41
** RETURNS            : Nothing
42
**
43
----------------------------------------------------------------------------*/
44
 
45
void ArgvQuote( const std::wstring& Argument,std::wstring& CommandLine, bool Force )
46
{
47
    //
48
    // Unless we're told otherwise, don't quote unless we actually
49
    // need to do so --- hopefully avoid problems if programs won't
50
    // parse quotes properly
51
    //
52
 
53
    if (Force == false &&
54
        Argument.empty() == false &&
55
        Argument.find_first_of(L" \t\n\v\"") == Argument.npos)
56
    {
57
        CommandLine.append(Argument);
58
    }
59
    else {
60
        CommandLine.append(L"\"");
61
 
62
        for (std::wstring::const_iterator It = Argument.begin(); ; ++It) {
63
            unsigned NumberBackslashes = 0;
64
 
65
            while (It != Argument.end() && *It == L'\\') {
66
                ++It;
67
                ++NumberBackslashes;
68
            }
69
 
70
            if (It == Argument.end()) {
71
 
72
                //
73
                // Escape all backslashes, but let the terminating
74
                // double quotation mark we add below be interpreted
75
                // as a metacharacter.
76
                //
77
 
78
                CommandLine.append(NumberBackslashes * 2, L'\\');
79
                break;
80
            }
81
            else if (*It == L'"') {
82
 
83
                //
84
                // Escape all backslashes and the following
85
                // double quotation mark.
86
                //
87
 
88
                CommandLine.append(NumberBackslashes * 2 + 1, L'\\');
89
                CommandLine.append(1, *It);
90
            }
91
            else {
92
 
93
                //
94
                // Backslashes aren't special here.
95
                //
96
 
97
                CommandLine.append(NumberBackslashes, L'\\');
98
                CommandLine.append(1, *It);
99
            }
100
        }
101
 
102
        CommandLine.append(L"\"");
103
    }
104
}
105
 
106
/*----------------------------------------------------------------------------
107
** FUNCTION           : s2ws
108
**
109
** DESCRIPTION        : String to Wide String
110
**
111
**
112
** INPUTS             : str - std:string
113
**
114
** RETURNS            : A widestring
115
**
116
----------------------------------------------------------------------------*/
117
std::wstring s2ws(const std::string& str)
118
{
119
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
120
    std::wstring wstrTo(size_needed, 0);
121
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
122
    return wstrTo;
123
}
124
 
125
/*----------------------------------------------------------------------------
126
** FUNCTION           : main
127
**
128
** DESCRIPTION        : Invoke gzip with a '-d' option
129
**
130
**
131
** INPUTS             : As per gzip
132
**
133
** RETURNS            : Exit code of the gzip utility
134
**
135
----------------------------------------------------------------------------*/
136
 
137
int main(int argc, char** argv)
138
{
139
    BOOL    rv;
140
    //
141
    //  Replace gunzip.exe with gzip.exe -d
142
    //
143
    //  Retrieve the command line arguments as an array of pointers to strings
144
    //  First string will be the program path
145
    //
146
    //  Remove program name - keep path
147
    //  Assume we will find the gzip in the same location us this program or via the same path mechanism
148
    //  Handle aaaa\bbbb\cccc
149
    //         aaaa/bbbb/ccccc
150
    //         cccc
151
    //
152
    std::wstring arg = s2ws(argv[0]);
153
    int index = arg.find_last_of(L"\\", arg.size());
154
    if (index == std::string::npos) {
155
        index = arg.find_last_of(L"/", arg.size());
156
        if (index == std::string::npos) {
157
            index = -1;
158
        }
159
    }
160
    arg.erase(index + 1);
161
    arg.append(L"gzip.exe");
162
 
163
    //
164
    //  Convert the arglist into a fully quoted command line string
165
    //  Inserting a '-d' option
166
    //
167
    std::wstring args = wstring();
168
    ArgvQuote(arg, args, FALSE);
169
    args.append(L" ");
170
    ArgvQuote(L"-d", args, FALSE);
171
    for (int ii = 1; ii < argc; ii++) {
172
        args.append(L" ");
173
        ArgvQuote(s2ws(argv[ii]), args, FALSE);
174
    }
175
 
176
    //std::wcout << L"Cmd:" << args << std::endl;
177
 
178
    // additional information
179
    STARTUPINFO si;
180
    PROCESS_INFORMATION pi;
181
    DWORD exitStatus = 250;
182
 
183
    // set the size of the structures
184
    ZeroMemory(&si, sizeof(si));
185
    ZeroMemory(&pi, sizeof(pi));
186
 
187
    // start the program up
188
    rv = CreateProcess
189
    (
190
        NULL,                   // the path
191
        (LPWSTR)args.c_str(),   // Command line
192
        NULL,                   // Process handle not inheritable
193
        NULL,                   // Thread handle not inheritable
194
        TRUE,                   // Set handle inheritance to TRUE
195
        0,                      // Opens file in a separate console
196
        NULL,                   // Use parent's environment block
197
        NULL,                   // Use parent's starting directory 
198
        &si,                    // Pointer to STARTUPINFO structure
199
        &pi                     // Pointer to PROCESS_INFORMATION structure
200
    );
201
    if (!rv) {
202
        DWORD eCode = GetLastError();
203
        exitStatus = eCode;
204
        //std::wcout << L"CreateProcess Error:" << eCode << std::endl;
205
        return exitStatus;
206
    }
207
 
208
    // Close process and thread handles.
209
    WaitForSingleObject(pi.hProcess, INFINITE);
210
    rv = GetExitCodeProcess(pi.hProcess, &exitStatus);
211
    if (!rv) {
212
        DWORD eCode = GetLastError();
213
        //std::wcout << L"GetExitCodeProcess Error:" << eCode << std::endl;
214
        exitStatus = 248;
215
    }
216
    CloseHandle(pi.hProcess);
217
    CloseHandle(pi.hThread);
218
    //std::wcout << L"Exit Status:" << exitStatus << std::endl;
219
    return exitStatus;
220
}
221
 
222
 
223