root/lang/c/AutoUpdater/trunk/recipes/Copy.c @ 38013

Revision 38013, 11.1 kB (checked in by saturday06, 4 years ago)

sedai

Line 
1#ifndef _UNICODE
2#error
3#endif
4
5#include <windows.h>
6#include <tchar.h>
7#include <commctrl.h>
8
9
10/* http://msdn.microsoft.com/en-us/library/bb531404.aspx */
11/* swap _M_IX86 and _M_X64 */
12#if defined _M_X64
13#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
14#elif defined _M_IX86
15#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
16#elif defined _M_IA64
17#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
18#else
19#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
20#endif
21
22/* http://msdn.microsoft.com/en-us/library/1fdeehz6%28v=VS.80%29.aspx */
23void *memset(void *dest_, int c, size_t count) {
24    size_t i = 0;
25    unsigned char* dest = (unsigned char*)dest_;
26        if (!dest_) {
27                return dest_;
28        }
29    for (i = 0; i < count; ++i) {
30        dest[i] = (unsigned char)c;
31    }
32    return dest_;
33}
34
35HANDLE LogFile = INVALID_HANDLE_VALUE;
36
37int AUI_Debug(const TCHAR* format, ...) {
38    TCHAR output[1024]; /* http://msdn.microsoft.com/en-us/library/ms647550%28VS.85%29.aspx */
39    va_list ap;
40    va_start(ap, format);
41    wvsprintf(output, format, ap);
42    va_end(ap);
43    OutputDebugString(output);
44    if (LogFile != INVALID_HANDLE_VALUE) {
45        DWORD written = 0;
46        WriteFile(LogFile, output, lstrlen(output) * sizeof(output[0]), &written, NULL);
47        FlushFileBuffers(LogFile);
48    }
49    return 0;
50}
51
52TCHAR* AUI_PathAppend(const TCHAR* base, const TCHAR* append) {
53    TCHAR* result = NULL;
54    int result_len = 0;
55   
56    result_len = lstrlen(base) + 1 + lstrlen(append) + 1;
57    result = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, result_len * sizeof(TCHAR));
58    if (!result) {
59        return NULL;
60    }
61    lstrcpy(result, base);
62   
63    {
64        size_t base_len = lstrlen(base);
65        if (base_len >= 1) {
66            TCHAR last = base[base_len - 1];
67            if (last != '/' && last != '\\') {
68                lstrcat(result, _T("\\"));
69            }
70        }
71    }
72   
73    lstrcat(result, append);
74    return result;
75}
76
77BOOL CopyDirectory(const TCHAR* from, const TCHAR* to) {
78    TCHAR* glob = NULL;
79        WIN32_FIND_DATA find_data;
80    HANDLE hFind = NULL;
81    BOOL result = TRUE;
82
83    if (!from || !to) {
84        return FALSE;
85    }
86
87    glob = AUI_PathAppend(from, _T("*"));
88        hFind = FindFirstFile(glob, &find_data);
89        if( INVALID_HANDLE_VALUE == hFind ) {
90                return FALSE;
91        }
92
93        do {
94        TCHAR* from2 = NULL;
95        TCHAR* to2 = NULL;
96
97        AUI_Debug(_T("<%s>\n"), find_data.cFileName);
98
99        if (CompareString(LOCALE_USER_DEFAULT, 0, find_data.cFileName, -1, _T("."), -1) == CSTR_EQUAL) {
100            continue;
101        }
102        if (CompareString(LOCALE_USER_DEFAULT, 0, find_data.cFileName, -1, _T(".."), -1) == CSTR_EQUAL) {
103            continue;
104        }
105
106        from2 = AUI_PathAppend(from, find_data.cFileName);
107        to2 = AUI_PathAppend(to, find_data.cFileName);
108
109        AUI_Debug(_T("%s -> %s\n"), from2, to2);
110
111                if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) {
112            AUI_Debug(_T("dir error\n"));
113            result = result && CreateDirectory(to2, NULL) && CopyDirectory(from2, to2);
114        } else if(!CopyFile(from2, to2, FALSE)) {
115            AUI_Debug(_T("file error\n"));
116            result = FALSE;
117                }
118
119        HeapFree(GetProcessHeap(), 0, to2);
120        HeapFree(GetProcessHeap(), 0, from2);
121
122    } while(FindNextFile(hFind, &find_data));
123
124    AUI_Debug(_T("end\n"));
125        FindClose(hFind);
126    HeapFree(GetProcessHeap(), 0, glob);
127        return result;
128}
129
130int main(void) {
131    HANDLE hFile = NULL;
132    HANDLE hProcess = NULL;
133    DWORD bytes = 0;
134    DWORD bytes_got = 0;
135    TCHAR* data = NULL;
136    TCHAR* new_program = NULL;
137    TCHAR* new_program_cd = NULL;
138    TCHAR* update_from = NULL;
139    TCHAR* update_to = NULL;
140    TCHAR* clean_after = NULL;
141    TCHAR* pid_string = NULL;
142    DWORD pid = 0;
143    int complete = 0;
144    TCHAR* clean_command = NULL;
145    TCHAR* temp_path = NULL;
146    TCHAR* log_full_path = NULL;
147    PVOID log_name = NULL;
148    TCHAR* command = NULL;
149
150    InitCommonControls();
151
152    {
153        size_t temp_path_chars = GetTempPath(0, NULL);
154        temp_path = (TCHAR*)HeapAlloc(GetProcessHeap(),
155            HEAP_ZERO_MEMORY, (temp_path_chars * sizeof(TCHAR)));
156        if (!temp_path) {
157            goto clean_up;
158        }
159        GetTempPath(temp_path_chars, temp_path);
160    }
161
162    {
163        unsigned int arg = 0;
164        arg = GetCurrentProcessId();
165        if (FormatMessage(
166                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
167                _T("AutoUpdaterLog.%1!x!.txt"),
168                0,
169                0,
170                (TCHAR*)&log_name,
171                0,
172                (va_list*)&arg)) {
173            log_full_path = AUI_PathAppend(temp_path, (TCHAR*)log_name);
174            if (log_full_path) {
175                LogFile = CreateFile(log_full_path, GENERIC_WRITE,
176                    FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
177            }
178        }
179    }
180
181    AUI_Debug(_T("***** UpdaterProcess start: pid=0x%x *****\n"), GetCurrentProcessId());
182
183
184    hFile = CreateFile(_T("AutoUpdater.txt"), GENERIC_READ, 0, NULL,
185        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
186
187    if (hFile == INVALID_HANDLE_VALUE) {
188        AUI_Debug(_T("config file not found\n"));
189        goto clean_up;
190    }
191
192    bytes = GetFileSize(hFile, NULL);
193    data = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytes + (/* null terminate */ sizeof(TCHAR)));
194    if (!data) {
195        goto clean_up;
196    }
197
198    if (ReadFile(hFile, data, bytes, &bytes_got, NULL) == 0) {
199        goto clean_up;
200    }
201
202    {
203        TCHAR* lines[6];
204        size_t i = 0;
205        size_t data_count = (bytes / sizeof(data[0]));
206        unsigned line = 0;
207        memset(lines, 0, sizeof(lines));
208        for (i = 0; i < data_count; ++i) {
209            if (data[i] == _T('\r')) {
210                data[i] = 0;
211            } else if (data[i] == _T('\n')) {
212                data[i] = 0;
213                if (i + 1 >= data_count) {
214                    continue;
215                }
216                if (line >= sizeof(lines) / sizeof(lines[0])) {
217                    break;
218                }
219                lines[line] = &data[i + 1];
220                line++;
221            }
222        }
223        pid_string     = lines[0];
224        update_from    = lines[1];
225        update_to      = lines[2];
226        new_program    = lines[3];
227        new_program_cd = lines[4];
228        clean_after    = lines[5];
229    }
230
231    AUI_Debug(_T("pid=%s, from=%s, to=%s\nnewproc=%s, cd=%s clean=%s\n"),
232        pid_string, update_from, update_to, new_program, new_program_cd, clean_after);
233   
234    if (pid_string) {
235        int i = 0;
236        for (i = 0; pid_string[i]; ++i) {
237            if (pid_string[i] < _T('0') || _T('9') < pid_string[i]) {
238                AUI_Debug(_T("pid error\n"));
239                goto clean_up;
240            }
241            pid = pid * 10;
242            pid += pid_string[i] - _T('0');
243        }
244    }
245
246    if (clean_after) {
247        TCHAR comspec[MAX_PATH];
248        TCHAR rd_command[] = _T("\"%s\" /c rd /s /q \"%s\"");
249        size_t clean_command_len = 0;
250        if (GetEnvironmentVariable(_T("COMSPEC"), comspec, sizeof(comspec) / sizeof(comspec[0])) == 0) {
251            goto clean_up;
252        }
253
254        clean_command_len = lstrlen(comspec) + lstrlen(rd_command) + lstrlen(clean_after);
255        clean_command = (TCHAR*)HeapAlloc(GetProcessHeap(),
256            HEAP_ZERO_MEMORY, clean_command_len * sizeof(TCHAR));
257        if (!clean_command) {
258            goto clean_up;
259        }
260        wsprintf(clean_command, rd_command, comspec, clean_after);
261    }
262
263    AUI_Debug(L"waiting\n");
264    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, pid);
265    if (hProcess) {
266        WaitForSingleObject(hProcess, INFINITE);
267    }
268
269    AUI_Debug(L"start copy\n");
270
271    if (CopyDirectory(update_from, update_to)) {
272        complete = 1;
273    }
274
275clean_up:
276    if (new_program && new_program_cd) {
277        TCHAR* arg = NULL;
278        TCHAR command_format[] = _T("\"%s\" %s");
279        TCHAR complete_arg[] = _T("UPDATE_COMPLETE");
280        TCHAR error_arg[] = _T("UPDATE_ERROR");
281        int command_len = 0;
282        SetLastError(0);
283        if (complete) {
284            arg = complete_arg;
285        } else {
286            arg = error_arg;
287        }
288        command_len = lstrlen(command_format);
289        command_len += lstrlen(new_program);
290        command_len += lstrlen(arg);
291
292        command = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (unsigned)command_len * sizeof(TCHAR));
293        if (command) {
294            wsprintf(command, command_format, new_program, arg);
295        }
296    }
297
298    if (command && new_program_cd) {
299        STARTUPINFO si;
300        PROCESS_INFORMATION pi;
301        DWORD e;
302        memset(&si, 0, sizeof(si));
303        si.cb = sizeof(si);
304        memset(&pi, 0, sizeof(pi));
305
306                SetLastError(0);
307        CreateProcess(NULL, command, NULL, NULL, FALSE, 0, NULL, new_program_cd, &si, &pi);
308        e = GetLastError();
309        AUI_Debug(_T("CreateProcess(): command=%s, cd=%s, error=%d\n"), command, new_program_cd, e);
310
311        CloseHandle(pi.hThread);
312        CloseHandle(pi.hProcess);
313    }
314
315        if (hFile != INVALID_HANDLE_VALUE) {
316            CloseHandle(hFile);
317        }
318        if (hProcess) {
319                CloseHandle(hProcess);
320        }
321
322    if (log_name) {
323        LocalFree(log_name);
324    }
325
326    if (clean_command) {
327        STARTUPINFO si;
328        PROCESS_INFORMATION pi;
329        memset(&si, 0, sizeof(si));
330        si.cb = sizeof(si);
331        si.dwFlags = STARTF_USESHOWWINDOW;
332        si.wShowWindow = SW_HIDE;
333        memset(&pi, 0, sizeof(pi));
334        AUI_Debug(_T("CreateProcess(del): command=%s, cd=%s\n"), clean_command, temp_path);
335        CreateProcess(NULL, clean_command, NULL, NULL, FALSE, 0, NULL, temp_path, &si, &pi);
336            CloseHandle(pi.hThread);
337            CloseHandle(pi.hProcess);
338    }
339
340    if (LogFile != INVALID_HANDLE_VALUE) {
341        CloseHandle(LogFile);
342        if (complete) {
343            //DeleteFile(log_full_path);
344        }
345    }
346
347    /*
348
349    if (log_full_path) {
350        HeapFree(GetProcessHeap(), 0, log_full_path);
351    }
352
353    if (data) {
354        HeapFree(GetProcessHeap(), 0, data);
355    }
356    if (command) {
357        HeapFree(GetProcessHeap(), 0, command);
358    }
359    if (clean_command) {
360        HeapFree(GetProcessHeap(), 0, clean_command);
361    }
362    if (temp_path) {
363        HeapFree(GetProcessHeap(), 0, clean_cd);
364    }
365    */   
366
367    return 0;
368}
369
370
371
Note: See TracBrowser for help on using the browser.