OSDN Git Service

Fix bugs of drag-and-drop handling.
[ffftp/ffftp.git] / updater.c
1 // updater.c\r
2 // Copyright (C) 2014 Suguru Kawamoto\r
3 // ソフトウェア自動更新\r
4 // コードの再利用のため表記はwchar_t型だが実体はchar型でUTF-8\r
5 \r
6 #include <tchar.h>\r
7 #include <ws2tcpip.h>\r
8 #include <windows.h>\r
9 #include <mmsystem.h>\r
10 typedef SOCKADDR_STORAGE_XP SOCKADDR_STORAGE;\r
11 typedef SOCKADDR_STORAGE *PSOCKADDR_STORAGE, FAR *LPSOCKADDR_STORAGE;\r
12 #include <winhttp.h>\r
13 \r
14 #include "updater.h"\r
15 #include "socketwrapper.h"\r
16 #include "protectprocess.h"\r
17 #include "mbswrapper.h"\r
18 #include "apiemulator.h"\r
19 \r
20 typedef struct\r
21 {\r
22         BYTE Signature[64];\r
23         BYTE ListHash[64];\r
24 } UPDATE_HASH;\r
25 \r
26 #define UPDATE_LIST_FILE_FLAG_DIRECTORY 0x00000001\r
27 \r
28 typedef struct\r
29 {\r
30         DWORD Flags;\r
31         CHAR SrcPath[128];\r
32         BYTE SrcHash[64];\r
33         CHAR DstPath[128];\r
34         FILETIME Timestamp;\r
35 } UPDATE_LIST_FILE;\r
36 \r
37 typedef struct\r
38 {\r
39         DWORD Version;\r
40         CHAR VersionString[32];\r
41         CHAR Description[1024];\r
42         DWORD FileCount;\r
43         UPDATE_LIST_FILE File[1];\r
44 } UPDATE_LIST;\r
45 \r
46 #define UPDATE_MAX_LIST_SIZE 1048576\r
47 #define UPDATE_MAX_FILE_SIZE 16777216\r
48 \r
49 BOOL ReadFileViaHTTPW(void* pOut, DWORD Length, DWORD* pLength, LPCWSTR UserAgent, LPCWSTR ServerName, LPCWSTR ObjectName)\r
50 {\r
51         BOOL bResult;\r
52         HINTERNET hSession;\r
53         HINTERNET hConnect;\r
54         HINTERNET hRequest;\r
55         bResult = FALSE;\r
56         if(hSession = WinHttpOpen(UserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0))\r
57         {\r
58                 if(hConnect = WinHttpConnect(hSession, ServerName, INTERNET_DEFAULT_HTTP_PORT, 0))\r
59                 {\r
60                         if(hRequest = WinHttpOpenRequest(hConnect, L"GET", ObjectName, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0))\r
61                         {\r
62                                 if(WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))\r
63                                 {\r
64                                         if(WinHttpReceiveResponse(hRequest, NULL))\r
65                                         {\r
66                                                 if(WinHttpQueryDataAvailable(hRequest, pLength))\r
67                                                 {\r
68                                                         if(*pLength <= Length)\r
69                                                         {\r
70                                                                 if(WinHttpReadData(hRequest, pOut, Length, pLength))\r
71                                                                         bResult = TRUE;\r
72                                                         }\r
73                                                 }\r
74                                         }\r
75                                 }\r
76                                 WinHttpCloseHandle(hRequest);\r
77                         }\r
78                         WinHttpCloseHandle(hConnect);\r
79                 }\r
80                 WinHttpCloseHandle(hSession);\r
81         }\r
82         return bResult;\r
83 }\r
84 \r
85 BOOL ReadFileViaHTTP(void* pOut, DWORD Length, DWORD* pLength, LPCSTR UserAgent, LPCSTR ServerName, LPCSTR ObjectName)\r
86 {\r
87         BOOL r;\r
88         wchar_t* pw0;\r
89         wchar_t* pw1;\r
90         wchar_t* pw2;\r
91         pw0 = DuplicateMtoW(UserAgent, -1);\r
92         pw1 = DuplicateMtoW(ServerName, -1);\r
93         pw2 = DuplicateMtoW(ObjectName, -1);\r
94         r = ReadFileViaHTTPW(pOut, Length, pLength, pw0, pw1, pw2);\r
95         FreeDuplicatedString(pw0);\r
96         FreeDuplicatedString(pw1);\r
97         FreeDuplicatedString(pw2);\r
98         return r;\r
99 }\r
100 \r
101 BOOL SaveMemoryToFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, FILETIME* pTimestamp)\r
102 {\r
103         BOOL bResult;\r
104         HANDLE hFile;\r
105         bResult = FALSE;\r
106         if((hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)\r
107         {\r
108                 if(WriteFile(hFile, pData, Size, &Size, NULL))\r
109                 {\r
110                         if(pTimestamp)\r
111                         {\r
112                                 if(SetFileTime(hFile, NULL, NULL, pTimestamp))\r
113                                         bResult = TRUE;\r
114                         }\r
115                         else\r
116                                 bResult = TRUE;\r
117                 }\r
118                 CloseHandle(hFile);\r
119         }\r
120         return bResult;\r
121 }\r
122 \r
123 BOOL LoadMemoryFromFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, DWORD* pReadSize, FILETIME* pTimestamp)\r
124 {\r
125         BOOL bResult;\r
126         HANDLE hFile;\r
127         LARGE_INTEGER li;\r
128         bResult = FALSE;\r
129         if((hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)\r
130         {\r
131                 if(GetFileSizeEx(hFile, &li))\r
132                 {\r
133                         if(li.QuadPart <= (LONGLONG)Size)\r
134                         {\r
135                                 if(ReadFile(hFile, pData, Size, pReadSize, NULL))\r
136                                 {\r
137                                         if(*pReadSize == li.LowPart)\r
138                                         {\r
139                                                 if(pTimestamp)\r
140                                                 {\r
141                                                         if(GetFileTime(hFile, NULL, NULL, pTimestamp))\r
142                                                                 bResult = TRUE;\r
143                                                 }\r
144                                                 else\r
145                                                         bResult = TRUE;\r
146                                         }\r
147                                 }\r
148                         }\r
149                         CloseHandle(hFile);\r
150                 }\r
151         }\r
152         return bResult;\r
153 }\r
154 \r
155 BOOL CopyAllFilesInDirectory(LPCTSTR From, LPCTSTR To)\r
156 {\r
157         BOOL bResult;\r
158         TCHAR* pFrom;\r
159         TCHAR* pTo;\r
160         SHFILEOPSTRUCT fop;\r
161         bResult = FALSE;\r
162         if(pFrom = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(From) + _tcslen(_T("\\*")) + 2)))\r
163         {\r
164                 _tcscpy(pFrom, From);\r
165                 _tcsncpy(pFrom + _tcslen(pFrom), _T("\\*"), _tcslen(_T("\\*")) + 2);\r
166                 if(pTo = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(To) + 2)))\r
167                 {\r
168                         _tcsncpy(pTo, To, _tcslen(To) + 2);\r
169                         memset(&fop, 0, sizeof(SHFILEOPSTRUCT));\r
170                         fop.wFunc = FO_COPY;\r
171                         fop.pFrom = pFrom;\r
172                         fop.pTo = pTo;\r
173                         fop.fFlags = FOF_NO_UI;\r
174                         if(SHFileOperation(&fop) == 0)\r
175                                 bResult = TRUE;\r
176                         free(pTo);\r
177                 }\r
178                 free(pFrom);\r
179         }\r
180         return bResult;\r
181 }\r
182 \r
183 BOOL DeleteDirectoryAndContents(LPCTSTR Path)\r
184 {\r
185         BOOL bResult;\r
186         TCHAR* pFrom;\r
187         SHFILEOPSTRUCT fop;\r
188         bResult = FALSE;\r
189         if(pFrom = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(Path) + 2)))\r
190         {\r
191                 _tcsncpy(pFrom, Path, _tcslen(Path) + 2);\r
192                 memset(&fop, 0, sizeof(SHFILEOPSTRUCT));\r
193                 fop.wFunc = FO_DELETE;\r
194                 fop.pFrom = pFrom;\r
195                 fop.fFlags = FOF_NO_UI;\r
196                 if(SHFileOperation(&fop) == 0)\r
197                         bResult = TRUE;\r
198                 free(pFrom);\r
199         }\r
200         return bResult;\r
201 }\r
202 \r
203 DWORD ListUpdateFile(UPDATE_LIST* pList, DWORD MaxCount, LPCTSTR ServerPath, LPCTSTR ReferenceDir, LPCTSTR Path)\r
204 {\r
205         DWORD Result;\r
206         TCHAR Temp1[MAX_PATH];\r
207         TCHAR Temp2[MAX_PATH];\r
208         TCHAR Temp3[MAX_PATH];\r
209         HANDLE hFind;\r
210         WIN32_FIND_DATA Find;\r
211         void* pBuf;\r
212         DWORD Length;\r
213         FILETIME Time;\r
214         BYTE Hash[64];\r
215         Result = 0;\r
216         if(!Path)\r
217                 Path = _T("");\r
218         if(_tcslen(ReferenceDir) + _tcslen(Path) + _tcslen(_T("\\*")) < MAX_PATH)\r
219         {\r
220                 _tcscpy(Temp1, ReferenceDir);\r
221                 _tcscat(Temp1, Path);\r
222                 _tcscat(Temp1, _T("\\*"));\r
223                 if((hFind = FindFirstFile(Temp1, &Find)) != INVALID_HANDLE_VALUE)\r
224                 {\r
225                         do\r
226                         {\r
227                                 if(_tcscmp(Find.cFileName, _T(".")) != 0 && _tcscmp(Find.cFileName, _T("..")) != 0)\r
228                                 {\r
229                                         if(_tcslen(ServerPath) + _tcslen(_T("/")) + _tcslen(Find.cFileName) < 128 && _tcslen(Path) + _tcslen(_T("\\")) + _tcslen(Find.cFileName) < 128)\r
230                                         {\r
231                                                 _tcscpy(Temp1, ServerPath);\r
232                                                 _tcscat(Temp1, _T("/"));\r
233                                                 _tcscat(Temp1, Find.cFileName);\r
234                                                 _tcscpy(Temp2, Path);\r
235                                                 _tcscat(Temp2, _T("\\"));\r
236                                                 _tcscat(Temp2, Find.cFileName);\r
237                                                 if(_tcslen(ReferenceDir) + _tcslen(Temp2) < MAX_PATH)\r
238                                                 {\r
239                                                         _tcscpy(Temp3, ReferenceDir);\r
240                                                         _tcscat(Temp3, Temp2);\r
241                                                         if((Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))\r
242                                                         {\r
243                                                                 if(!(Find.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))\r
244                                                                 {\r
245                                                                         if(pList)\r
246                                                                         {\r
247                                                                                 memset(&pList->File[pList->FileCount], 0, sizeof(UPDATE_LIST_FILE));\r
248                                                                                 pList->File[pList->FileCount].Flags = UPDATE_LIST_FILE_FLAG_DIRECTORY;\r
249                                                                                 _tcscpy(pList->File[pList->FileCount].DstPath, Temp2);\r
250                                                                                 pList->FileCount++;\r
251                                                                         }\r
252                                                                         Result++;\r
253                                                                         if(Result >= MaxCount)\r
254                                                                                 break;\r
255                                                                         Result += ListUpdateFile(pList, MaxCount, Temp1, ReferenceDir, Temp2);\r
256                                                                 }\r
257                                                         }\r
258                                                         else\r
259                                                         {\r
260                                                                 if(pList)\r
261                                                                 {\r
262                                                                         if(pBuf = malloc(UPDATE_MAX_FILE_SIZE))\r
263                                                                         {\r
264                                                                                 if(LoadMemoryFromFileWithTimestamp(Temp3, pBuf, UPDATE_MAX_FILE_SIZE, &Length, &Time))\r
265                                                                                 {\r
266                                                                                         if(GetHashSHA512(pBuf, Length, &Hash))\r
267                                                                                         {\r
268                                                                                                 memset(&pList->File[pList->FileCount], 0, sizeof(UPDATE_LIST_FILE));\r
269                                                                                                 _tcscpy(pList->File[pList->FileCount].SrcPath, Temp1);\r
270                                                                                                 memcpy(&pList->File[pList->FileCount].SrcHash, &Hash, 64);\r
271                                                                                                 _tcscpy(pList->File[pList->FileCount].DstPath, Temp2);\r
272                                                                                                 pList->File[pList->FileCount].Timestamp = Time;\r
273                                                                                                 pList->FileCount++;\r
274                                                                                         }\r
275                                                                                 }\r
276                                                                                 free(pBuf);\r
277                                                                         }\r
278                                                                 }\r
279                                                                 Result++;\r
280                                                                 if(Result >= MaxCount)\r
281                                                                         break;\r
282                                                         }\r
283                                                 }\r
284                                         }\r
285                                 }\r
286                         }\r
287                         while(FindNextFile(hFind, &Find));\r
288                         FindClose(hFind);\r
289                 }\r
290         }\r
291         return Result;\r
292 }\r
293 \r
294 // FFFTPの更新情報を作成\r
295 BOOL BuildUpdates(LPCTSTR PrivateKeyFile, LPCTSTR Password, LPCTSTR ServerPath, LPCTSTR HashFile, LPCTSTR ListFile, DWORD Version, LPCTSTR VersionString, LPCTSTR Description)\r
296 {\r
297         BOOL bResult;\r
298         char PrivateKey[4096];\r
299         DWORD Length;\r
300         TCHAR Name[MAX_PATH];\r
301         TCHAR* p;\r
302         UPDATE_LIST* pList;\r
303         UPDATE_HASH Hash;\r
304         BYTE Buf[1024];\r
305         bResult = FALSE;\r
306         memset(PrivateKey, 0, sizeof(PrivateKey));\r
307         if(LoadMemoryFromFileWithTimestamp(PrivateKeyFile, &PrivateKey, sizeof(PrivateKey) - sizeof(char), &Length, NULL))\r
308         {\r
309                 if(GetModuleFileName(NULL, Name, MAX_PATH) > 0)\r
310                 {\r
311                         if(p = _tcsrchr(Name, _T('\\')))\r
312                                 *p = _T('\0');\r
313                         if(pList = (UPDATE_LIST*)malloc(UPDATE_MAX_LIST_SIZE))\r
314                         {\r
315                                 memset(pList, 0, UPDATE_MAX_LIST_SIZE);\r
316                                 pList->Version = Version;\r
317                                 _tcscpy(pList->VersionString, VersionString);\r
318                                 _tcscpy(pList->Description, Description);\r
319                                 ListUpdateFile(pList, (UPDATE_MAX_LIST_SIZE - sizeof(UPDATE_LIST)) / sizeof(UPDATE_LIST_FILE) + 1, ServerPath, Name, NULL);\r
320                                 Length = (pList->FileCount - 1) * sizeof(UPDATE_LIST_FILE) + sizeof(UPDATE_LIST);\r
321                                 if(SaveMemoryToFileWithTimestamp(ListFile, pList, Length, NULL))\r
322                                 {\r
323                                         memcpy(&Hash.Signature, UPDATE_SIGNATURE, 64);\r
324                                         if(GetHashSHA512(pList, Length, &Hash.ListHash))\r
325                                         {\r
326                                                 if(EncryptSignature(PrivateKey, Password, &Hash, sizeof(UPDATE_HASH), &Buf, sizeof(Buf), &Length))\r
327                                                 {\r
328                                                         if(SaveMemoryToFileWithTimestamp(HashFile, &Buf, Length, NULL))\r
329                                                                 bResult = TRUE;\r
330                                                 }\r
331                                         }\r
332                                 }\r
333                                 free(pList);\r
334                         }\r
335                 }\r
336         }\r
337         return bResult;\r
338 }\r
339 \r
340 // FFFTPの更新情報を確認\r
341 BOOL CheckForUpdates(BOOL bDownload, LPCTSTR DownloadDir, DWORD* pVersion, LPTSTR pVersionString, LPTSTR pDescription)\r
342 {\r
343         BOOL bResult;\r
344         DWORD Length;\r
345         BYTE Buf1[1024];\r
346         BYTE Buf2[1024];\r
347         void* pBuf;\r
348         UPDATE_HASH UpdateHash;\r
349         BYTE Hash[64];\r
350         UPDATE_LIST* pUpdateList;\r
351         bResult = FALSE;\r
352         if(ReadFileViaHTTP(&Buf1, sizeof(Buf1), &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_HASH_PATH))\r
353         {\r
354                 if(DecryptSignature(UPDATE_RSA_PUBLIC_KEY, NULL, &Buf1, Length, &Buf2, sizeof(Buf2), &Length))\r
355                 {\r
356                         if(Length == sizeof(UPDATE_HASH))\r
357                         {\r
358                                 memcpy(&UpdateHash, &Buf2, sizeof(UPDATE_HASH));\r
359                                 if(memcmp(&UpdateHash.Signature, UPDATE_SIGNATURE, 64) == 0)\r
360                                 {\r
361                                         if(pBuf = malloc(UPDATE_MAX_LIST_SIZE))\r
362                                         {\r
363                                                 if(ReadFileViaHTTP(pBuf, UPDATE_MAX_LIST_SIZE, &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_LIST_PATH))\r
364                                                 {\r
365                                                         if(GetHashSHA512(pBuf, Length, &Hash))\r
366                                                         {\r
367                                                                 if(memcmp(&Hash, &UpdateHash.ListHash, 64) == 0)\r
368                                                                 {\r
369                                                                         if(Length >= sizeof(UPDATE_LIST))\r
370                                                                         {\r
371                                                                                 bResult = TRUE;\r
372                                                                                 pUpdateList = (UPDATE_LIST*)pBuf;\r
373                                                                                 if(pUpdateList->Version > *pVersion)\r
374                                                                                 {\r
375                                                                                         *pVersion = pUpdateList->Version;\r
376                                                                                         _tcscpy(pVersionString, pUpdateList->VersionString);\r
377                                                                                         _tcscpy(pDescription, pUpdateList->Description);\r
378                                                                                 }\r
379                                                                                 if(bDownload)\r
380                                                                                         bResult = PrepareUpdates(pBuf, Length, DownloadDir);\r
381                                                                         }\r
382                                                                 }\r
383                                                         }\r
384                                                 }\r
385                                                 free(pBuf);\r
386                                         }\r
387                                 }\r
388                         }\r
389                 }\r
390         }\r
391         return bResult;\r
392 }\r
393 \r
394 // 更新するファイルをダウンロード\r
395 BOOL PrepareUpdates(void* pList, DWORD ListLength, LPCTSTR DownloadDir)\r
396 {\r
397         BOOL bResult;\r
398         UPDATE_LIST* pUpdateList;\r
399         void* pBuf;\r
400         TCHAR LocalDir[MAX_PATH];\r
401         TCHAR* p;\r
402         DWORD i;\r
403         BOOL b;\r
404         TCHAR Path[MAX_PATH];\r
405         DWORD Length;\r
406         BYTE Hash[64];\r
407         bResult = FALSE;\r
408         if(ListLength >= sizeof(UPDATE_LIST))\r
409         {\r
410                 pUpdateList = (UPDATE_LIST*)pList;\r
411                 if((pUpdateList->FileCount - 1) * sizeof(UPDATE_LIST_FILE) + sizeof(UPDATE_LIST) >= ListLength)\r
412                 {\r
413                         bResult = TRUE;\r
414                         DeleteDirectoryAndContents(DownloadDir);\r
415                         CreateDirectory(DownloadDir, NULL);\r
416                         if(pBuf = malloc(UPDATE_MAX_FILE_SIZE))\r
417                         {\r
418                                 if(GetModuleFileName(NULL, LocalDir, MAX_PATH) > 0)\r
419                                 {\r
420                                         if(p = _tcsrchr(LocalDir, _T('\\')))\r
421                                                 *p = _T('\0');\r
422                                 }\r
423                                 else\r
424                                         _tcscpy(LocalDir, _T("."));\r
425                                 for(i = 0; i < pUpdateList->FileCount; i++)\r
426                                 {\r
427                                         b = FALSE;\r
428                                         if(pUpdateList->File[i].Flags & UPDATE_LIST_FILE_FLAG_DIRECTORY)\r
429                                         {\r
430                                                 _tcscpy(Path, DownloadDir);\r
431                                                 _tcscat(Path, pUpdateList->File[i].DstPath);\r
432                                                 if(CreateDirectory(Path, NULL))\r
433                                                         b = TRUE;\r
434                                         }\r
435                                         if(strlen(pUpdateList->File[i].SrcPath) > 0)\r
436                                         {\r
437                                                 _tcscpy(Path, LocalDir);\r
438                                                 _tcscat(Path, pUpdateList->File[i].DstPath);\r
439                                                 if(LoadMemoryFromFileWithTimestamp(Path, pBuf, UPDATE_MAX_FILE_SIZE, &Length, NULL))\r
440                                                 {\r
441                                                         if(GetHashSHA512(pBuf, Length, &Hash))\r
442                                                         {\r
443                                                                 if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
444                                                                         b = TRUE;\r
445                                                         }\r
446                                                 }\r
447                                                 if(!b)\r
448                                                 {\r
449                                                         if(ReadFileViaHTTP(pBuf, UPDATE_MAX_FILE_SIZE, &Length, HTTP_USER_AGENT, UPDATE_SERVER, pUpdateList->File[i].SrcPath))\r
450                                                         {\r
451                                                                 if(GetHashSHA512(pBuf, Length, &Hash))\r
452                                                                 {\r
453                                                                         if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
454                                                                         {\r
455                                                                                 _tcscpy(Path, DownloadDir);\r
456                                                                                 _tcscat(Path, pUpdateList->File[i].DstPath);\r
457                                                                                 if(SaveMemoryToFileWithTimestamp(Path, pBuf, Length, &pUpdateList->File[i].Timestamp))\r
458                                                                                         b = TRUE;\r
459                                                                         }\r
460                                                                 }\r
461                                                         }\r
462                                                 }\r
463                                         }\r
464                                         if(!b)\r
465                                         {\r
466                                                 bResult = FALSE;\r
467                                                 break;\r
468                                         }\r
469                                 }\r
470                                 free(pBuf);\r
471                         }\r
472                 }\r
473         }\r
474         return bResult;\r
475 }\r
476 \r
477 // FFFTPを更新\r
478 BOOL ApplyUpdates(LPCTSTR DestinationDir, LPCTSTR BackupDirName)\r
479 {\r
480         BOOL bResult;\r
481         TCHAR Source[MAX_PATH];\r
482         TCHAR Backup[MAX_PATH];\r
483         TCHAR DestinationBackup[MAX_PATH];\r
484         TCHAR* p;\r
485         bResult = FALSE;\r
486         if(GetModuleFileName(NULL, Source, MAX_PATH) > 0)\r
487         {\r
488                 if(p = _tcsrchr(Source, _T('\\')))\r
489                         *p = _T('\0');\r
490                 _tcscpy(Backup, Source);\r
491                 _tcscat(Backup, _T("\\"));\r
492                 _tcscat(Backup, BackupDirName);\r
493                 DeleteDirectoryAndContents(Backup);\r
494                 if(CreateDirectory(Backup, NULL))\r
495                 {\r
496                         if(CopyAllFilesInDirectory(DestinationDir, Backup))\r
497                         {\r
498                                 _tcscpy(DestinationBackup, DestinationDir);\r
499                                 _tcscat(DestinationBackup, _T("\\"));\r
500                                 _tcscat(DestinationBackup, BackupDirName);\r
501                                 if(CopyAllFilesInDirectory(Source, DestinationDir))\r
502                                 {\r
503                                         DeleteDirectoryAndContents(DestinationBackup);\r
504                                         bResult = TRUE;\r
505                                 }\r
506                                 else\r
507                                 {\r
508                                         DeleteDirectoryAndContents(DestinationBackup);\r
509                                         CopyAllFilesInDirectory(Backup, DestinationDir);\r
510                                 }\r
511                         }\r
512                 }\r
513         }\r
514         return bResult;\r
515 }\r
516 \r
517 // 更新するファイルをダウンロード\r
518 BOOL CleanupUpdates(LPCTSTR DownloadDir)\r
519 {\r
520         BOOL bResult;\r
521         bResult = FALSE;\r
522         if(DeleteDirectoryAndContents(DownloadDir))\r
523                 bResult = TRUE;\r
524         return bResult;\r
525 }\r
526 \r
527 // 更新用のプロセスを起動\r
528 BOOL StartUpdateProcess(LPCTSTR DownloadDir, LPCTSTR CommandLine)\r
529 {\r
530         BOOL bResult;\r
531         TCHAR Name[MAX_PATH];\r
532         TCHAR* p;\r
533         TCHAR Path[MAX_PATH];\r
534         bResult = FALSE;\r
535         if(GetModuleFileName(NULL, Name, MAX_PATH) > 0)\r
536         {\r
537                 if(p = _tcsrchr(Name, _T('\\')))\r
538                         p++;\r
539                 else\r
540                         p = Name;\r
541                 _tcscpy(Path, DownloadDir);\r
542                 _tcscat(Path, _T("\\"));\r
543                 _tcscat(Path, p);\r
544                 if(ShellExecute(NULL, _T("open"), Path, CommandLine, NULL, SW_SHOW) > (HINSTANCE)32)\r
545                         bResult = TRUE;\r
546         }\r
547         return bResult;\r
548 }\r
549 \r
550 // 更新用のプロセスを管理者権限で起動\r
551 // Windows XP以前など起動できない場合は現在のプロセスで処理を続行\r
552 BOOL RestartUpdateProcessAsAdministrator(LPCTSTR CommandLine, LPCTSTR Keyword)\r
553 {\r
554         BOOL bResult;\r
555         TCHAR* NewCommandLine;\r
556         TCHAR Path[MAX_PATH];\r
557         SHELLEXECUTEINFO Info;\r
558         bResult = FALSE;\r
559         if(_tcslen(CommandLine) < _tcslen(Keyword) || _tcscmp(CommandLine + _tcslen(CommandLine) - _tcslen(Keyword), Keyword) != 0)\r
560         {\r
561                 if(NewCommandLine = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(CommandLine) + _tcslen(Keyword) + 1)))\r
562                 {\r
563                         _tcscpy(NewCommandLine, CommandLine);\r
564                         _tcscat(NewCommandLine, Keyword);\r
565                         if(GetModuleFileName(NULL, Path, MAX_PATH) > 0)\r
566                         {\r
567                                 memset(&Info, 0, sizeof(SHELLEXECUTEINFO));\r
568                                 Info.cbSize = sizeof(SHELLEXECUTEINFO);\r
569                                 Info.fMask = SEE_MASK_NOCLOSEPROCESS;\r
570                                 if(IsUserAnAdmin())\r
571                                         Info.lpVerb = _T("open");\r
572                                 else\r
573                                         Info.lpVerb = _T("runas");\r
574                                 Info.lpFile = Path;\r
575                                 Info.lpParameters = NewCommandLine;\r
576                                 Info.nShow = SW_SHOW;\r
577                                 if(ShellExecuteEx(&Info))\r
578                                 {\r
579                                         WaitForSingleObject(Info.hProcess, INFINITE);\r
580                                         CloseHandle(Info.hProcess);\r
581                                         bResult = TRUE;\r
582                                 }\r
583                         }\r
584                         free(NewCommandLine);\r
585                 }\r
586         }\r
587         return bResult;\r
588 }\r
589 \r