// updater.c\r
// Copyright (C) 2014 Suguru Kawamoto\r
// ソフトウェア自動更新\r
+// コードの再利用のため表記はwchar_t型だが実体はchar型でUTF-8\r
\r
#include <tchar.h>\r
#include <ws2tcpip.h>\r
#include "socketwrapper.h"\r
#include "protectprocess.h"\r
#include "mbswrapper.h"\r
+#include "apiemulator.h"\r
\r
typedef struct\r
{\r
BYTE ListHash[64];\r
} UPDATE_HASH;\r
\r
-BOOL DownloadFileViaHTTP(void* pOut, DWORD Length, DWORD* pLength, LPCWSTR UserAgent, LPCWSTR ServerName, LPCWSTR ObjectName)\r
+#define UPDATE_LIST_FILE_FLAG_DIRECTORY 0x00000001\r
+\r
+typedef struct\r
+{\r
+ DWORD Flags;\r
+ CHAR SrcPath[128];\r
+ BYTE SrcHash[64];\r
+ CHAR DstPath[128];\r
+ FILETIME Timestamp;\r
+} UPDATE_LIST_FILE;\r
+\r
+typedef struct\r
+{\r
+ DWORD Version;\r
+ CHAR VersionString[32];\r
+ CHAR Description[1024];\r
+ DWORD FileCount;\r
+ UPDATE_LIST_FILE File[1];\r
+} UPDATE_LIST;\r
+\r
+#define UPDATE_MAX_LIST_SIZE 1048576\r
+#define UPDATE_MAX_FILE_SIZE 16777216\r
+\r
+BOOL ReadFileViaHTTPW(void* pOut, DWORD Length, DWORD* pLength, LPCWSTR UserAgent, LPCWSTR ServerName, LPCWSTR ObjectName)\r
{\r
BOOL bResult;\r
HINTERNET hSession;\r
return bResult;\r
}\r
\r
+BOOL ReadFileViaHTTP(void* pOut, DWORD Length, DWORD* pLength, LPCSTR UserAgent, LPCSTR ServerName, LPCSTR ObjectName)\r
+{\r
+ BOOL r;\r
+ wchar_t* pw0;\r
+ wchar_t* pw1;\r
+ wchar_t* pw2;\r
+ pw0 = DuplicateMtoW(UserAgent, -1);\r
+ pw1 = DuplicateMtoW(ServerName, -1);\r
+ pw2 = DuplicateMtoW(ObjectName, -1);\r
+ r = ReadFileViaHTTPW(pOut, Length, pLength, pw0, pw1, pw2);\r
+ FreeDuplicatedString(pw0);\r
+ FreeDuplicatedString(pw1);\r
+ FreeDuplicatedString(pw2);\r
+ return r;\r
+}\r
+\r
+BOOL SaveMemoryToFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, FILETIME* pTimestamp)\r
+{\r
+ BOOL bResult;\r
+ HANDLE hFile;\r
+ bResult = FALSE;\r
+ if((hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)\r
+ {\r
+ if(WriteFile(hFile, pData, Size, &Size, NULL))\r
+ {\r
+ if(pTimestamp)\r
+ {\r
+ if(SetFileTime(hFile, NULL, NULL, pTimestamp))\r
+ bResult = TRUE;\r
+ }\r
+ else\r
+ bResult = TRUE;\r
+ }\r
+ CloseHandle(hFile);\r
+ }\r
+ return bResult;\r
+}\r
+\r
+BOOL LoadMemoryFromFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, DWORD* pReadSize, FILETIME* pTimestamp)\r
+{\r
+ BOOL bResult;\r
+ HANDLE hFile;\r
+ LARGE_INTEGER li;\r
+ bResult = FALSE;\r
+ if((hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)\r
+ {\r
+ if(GetFileSizeEx(hFile, &li))\r
+ {\r
+ if(li.QuadPart <= (LONGLONG)Size)\r
+ {\r
+ if(ReadFile(hFile, pData, Size, pReadSize, NULL))\r
+ {\r
+ if(*pReadSize == li.LowPart)\r
+ {\r
+ if(pTimestamp)\r
+ {\r
+ if(GetFileTime(hFile, NULL, NULL, pTimestamp))\r
+ bResult = TRUE;\r
+ }\r
+ else\r
+ bResult = TRUE;\r
+ }\r
+ }\r
+ }\r
+ CloseHandle(hFile);\r
+ }\r
+ }\r
+ return bResult;\r
+}\r
+\r
+BOOL CopyAllFilesInDirectory(LPCTSTR From, LPCTSTR To)\r
+{\r
+ BOOL bResult;\r
+ TCHAR* pFrom;\r
+ TCHAR* pTo;\r
+ SHFILEOPSTRUCT fop;\r
+ bResult = FALSE;\r
+ if(pFrom = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(From) + _tcslen(_T("\\*")) + 2)))\r
+ {\r
+ _tcscpy(pFrom, From);\r
+ _tcsncpy(pFrom + _tcslen(pFrom), _T("\\*"), _tcslen(_T("\\*")) + 2);\r
+ if(pTo = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(To) + 2)))\r
+ {\r
+ _tcsncpy(pTo, To, _tcslen(To) + 2);\r
+ memset(&fop, 0, sizeof(SHFILEOPSTRUCT));\r
+ fop.wFunc = FO_COPY;\r
+ fop.pFrom = pFrom;\r
+ fop.pTo = pTo;\r
+ fop.fFlags = FOF_NO_UI;\r
+ if(SHFileOperation(&fop) == 0)\r
+ bResult = TRUE;\r
+ free(pTo);\r
+ }\r
+ free(pFrom);\r
+ }\r
+ return bResult;\r
+}\r
+\r
+BOOL DeleteDirectoryAndContents(LPCTSTR Path)\r
+{\r
+ BOOL bResult;\r
+ TCHAR* pFrom;\r
+ SHFILEOPSTRUCT fop;\r
+ bResult = FALSE;\r
+ if(pFrom = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(Path) + 2)))\r
+ {\r
+ _tcsncpy(pFrom, Path, _tcslen(Path) + 2);\r
+ memset(&fop, 0, sizeof(SHFILEOPSTRUCT));\r
+ fop.wFunc = FO_DELETE;\r
+ fop.pFrom = pFrom;\r
+ fop.fFlags = FOF_NO_UI;\r
+ if(SHFileOperation(&fop) == 0)\r
+ bResult = TRUE;\r
+ free(pFrom);\r
+ }\r
+ return bResult;\r
+}\r
+\r
+DWORD ListUpdateFile(UPDATE_LIST* pList, DWORD MaxCount, LPCTSTR ServerPath, LPCTSTR ReferenceDir, LPCTSTR Path)\r
+{\r
+ DWORD Result;\r
+ TCHAR Temp1[MAX_PATH];\r
+ TCHAR Temp2[MAX_PATH];\r
+ TCHAR Temp3[MAX_PATH];\r
+ HANDLE hFind;\r
+ WIN32_FIND_DATA Find;\r
+ void* pBuf;\r
+ DWORD Length;\r
+ FILETIME Time;\r
+ BYTE Hash[64];\r
+ Result = 0;\r
+ if(!Path)\r
+ Path = _T("");\r
+ if(_tcslen(ReferenceDir) + _tcslen(Path) + _tcslen(_T("\\*")) < MAX_PATH)\r
+ {\r
+ _tcscpy(Temp1, ReferenceDir);\r
+ _tcscat(Temp1, Path);\r
+ _tcscat(Temp1, _T("\\*"));\r
+ if((hFind = FindFirstFile(Temp1, &Find)) != INVALID_HANDLE_VALUE)\r
+ {\r
+ do\r
+ {\r
+ if(_tcscmp(Find.cFileName, _T(".")) != 0 && _tcscmp(Find.cFileName, _T("..")) != 0)\r
+ {\r
+ if(_tcslen(ServerPath) + _tcslen(_T("/")) + _tcslen(Find.cFileName) < 128 && _tcslen(Path) + _tcslen(_T("\\")) + _tcslen(Find.cFileName) < 128)\r
+ {\r
+ _tcscpy(Temp1, ServerPath);\r
+ _tcscat(Temp1, _T("/"));\r
+ _tcscat(Temp1, Find.cFileName);\r
+ _tcscpy(Temp2, Path);\r
+ _tcscat(Temp2, _T("\\"));\r
+ _tcscat(Temp2, Find.cFileName);\r
+ if(_tcslen(ReferenceDir) + _tcslen(Temp2) < MAX_PATH)\r
+ {\r
+ _tcscpy(Temp3, ReferenceDir);\r
+ _tcscat(Temp3, Temp2);\r
+ if((Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))\r
+ {\r
+ if(!(Find.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))\r
+ {\r
+ if(pList)\r
+ {\r
+ memset(&pList->File[pList->FileCount], 0, sizeof(UPDATE_LIST_FILE));\r
+ pList->File[pList->FileCount].Flags = UPDATE_LIST_FILE_FLAG_DIRECTORY;\r
+ _tcscpy(pList->File[pList->FileCount].DstPath, Temp2);\r
+ pList->FileCount++;\r
+ }\r
+ Result++;\r
+ if(Result >= MaxCount)\r
+ break;\r
+ Result += ListUpdateFile(pList, MaxCount, Temp1, ReferenceDir, Temp2);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if(pList)\r
+ {\r
+ if(pBuf = malloc(UPDATE_MAX_FILE_SIZE))\r
+ {\r
+ if(LoadMemoryFromFileWithTimestamp(Temp3, pBuf, UPDATE_MAX_FILE_SIZE, &Length, &Time))\r
+ {\r
+ if(GetHashSHA512(pBuf, Length, &Hash))\r
+ {\r
+ memset(&pList->File[pList->FileCount], 0, sizeof(UPDATE_LIST_FILE));\r
+ _tcscpy(pList->File[pList->FileCount].SrcPath, Temp1);\r
+ memcpy(&pList->File[pList->FileCount].SrcHash, &Hash, 64);\r
+ _tcscpy(pList->File[pList->FileCount].DstPath, Temp2);\r
+ pList->File[pList->FileCount].Timestamp = Time;\r
+ pList->FileCount++;\r
+ }\r
+ }\r
+ free(pBuf);\r
+ }\r
+ }\r
+ Result++;\r
+ if(Result >= MaxCount)\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ while(FindNextFile(hFind, &Find));\r
+ FindClose(hFind);\r
+ }\r
+ }\r
+ return Result;\r
+}\r
+\r
+// FFFTPの更新情報を作成\r
+BOOL BuildUpdates(LPCTSTR PrivateKeyFile, LPCTSTR Password, LPCTSTR ServerPath, LPCTSTR HashFile, LPCTSTR ListFile, DWORD Version, LPCTSTR VersionString, LPCTSTR Description)\r
+{\r
+ BOOL bResult;\r
+ char PrivateKey[4096];\r
+ DWORD Length;\r
+ TCHAR Name[MAX_PATH];\r
+ TCHAR* p;\r
+ UPDATE_LIST* pList;\r
+ UPDATE_HASH Hash;\r
+ BYTE Buf[1024];\r
+ bResult = FALSE;\r
+ memset(PrivateKey, 0, sizeof(PrivateKey));\r
+ if(LoadMemoryFromFileWithTimestamp(PrivateKeyFile, &PrivateKey, sizeof(PrivateKey) - sizeof(char), &Length, NULL))\r
+ {\r
+ if(GetModuleFileName(NULL, Name, MAX_PATH) > 0)\r
+ {\r
+ if(p = _tcsrchr(Name, _T('\\')))\r
+ *p = _T('\0');\r
+ if(pList = (UPDATE_LIST*)malloc(UPDATE_MAX_LIST_SIZE))\r
+ {\r
+ memset(pList, 0, UPDATE_MAX_LIST_SIZE);\r
+ pList->Version = Version;\r
+ _tcscpy(pList->VersionString, VersionString);\r
+ _tcscpy(pList->Description, Description);\r
+ ListUpdateFile(pList, (UPDATE_MAX_LIST_SIZE - sizeof(UPDATE_LIST)) / sizeof(UPDATE_LIST_FILE) + 1, ServerPath, Name, NULL);\r
+ Length = (pList->FileCount - 1) * sizeof(UPDATE_LIST_FILE) + sizeof(UPDATE_LIST);\r
+ if(SaveMemoryToFileWithTimestamp(ListFile, pList, Length, NULL))\r
+ {\r
+ memcpy(&Hash.Signature, UPDATE_SIGNATURE, 64);\r
+ if(GetHashSHA512(pList, Length, &Hash.ListHash))\r
+ {\r
+ if(EncryptSignature(PrivateKey, Password, &Hash, sizeof(UPDATE_HASH), &Buf, sizeof(Buf), &Length))\r
+ {\r
+ if(SaveMemoryToFileWithTimestamp(HashFile, &Buf, Length, NULL))\r
+ bResult = TRUE;\r
+ }\r
+ }\r
+ }\r
+ free(pList);\r
+ }\r
+ }\r
+ }\r
+ return bResult;\r
+}\r
+\r
// FFFTPの更新情報を確認\r
-BOOL CheckForUpdates(BOOL bDownload, LPCTSTR DownloadDir)\r
+BOOL CheckForUpdates(BOOL bDownload, LPCTSTR DownloadDir, DWORD* pVersion, LPTSTR pVersionString, LPTSTR pDescription)\r
{\r
BOOL bResult;\r
DWORD Length;\r
- BYTE Buf1[4096];\r
+ BYTE Buf1[1024];\r
BYTE Buf2[1024];\r
+ void* pBuf;\r
UPDATE_HASH UpdateHash;\r
BYTE Hash[64];\r
+ UPDATE_LIST* pUpdateList;\r
bResult = FALSE;\r
- if(DownloadFileViaHTTP(&Buf1, sizeof(Buf1), &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_HASH_PATH))\r
+ if(ReadFileViaHTTP(&Buf1, sizeof(Buf1), &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_HASH_PATH))\r
{\r
- if(DecryptSignature(UPDATE_RSA_PUBLIC_KEY, &Buf1, Length, &Buf2, sizeof(Buf2), &Length))\r
+ if(DecryptSignature(UPDATE_RSA_PUBLIC_KEY, NULL, &Buf1, Length, &Buf2, sizeof(Buf2), &Length))\r
{\r
if(Length == sizeof(UPDATE_HASH))\r
{\r
memcpy(&UpdateHash, &Buf2, sizeof(UPDATE_HASH));\r
if(memcmp(&UpdateHash.Signature, UPDATE_SIGNATURE, 64) == 0)\r
{\r
- if(DownloadFileViaHTTP(&Buf1, sizeof(Buf1), &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_LIST_PATH))\r
+ if(pBuf = malloc(UPDATE_MAX_LIST_SIZE))\r
{\r
- GetHashSHA512(&Buf1, Length, &Hash);\r
- if(memcmp(&Hash, &UpdateHash.ListHash, 64) == 0)\r
+ if(ReadFileViaHTTP(pBuf, UPDATE_MAX_LIST_SIZE, &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_LIST_PATH))\r
{\r
- // TODO: 更新情報を解析\r
- bResult = TRUE;\r
- if(bDownload)\r
- bResult = PrepareUpdates(&Buf1, Length, DownloadDir);\r
+ if(GetHashSHA512(pBuf, Length, &Hash))\r
+ {\r
+ if(memcmp(&Hash, &UpdateHash.ListHash, 64) == 0)\r
+ {\r
+ if(Length >= sizeof(UPDATE_LIST))\r
+ {\r
+ bResult = TRUE;\r
+ pUpdateList = (UPDATE_LIST*)pBuf;\r
+ if(pUpdateList->Version > *pVersion)\r
+ {\r
+ *pVersion = pUpdateList->Version;\r
+ _tcscpy(pVersionString, pUpdateList->VersionString);\r
+ _tcscpy(pDescription, pUpdateList->Description);\r
+ }\r
+ if(bDownload)\r
+ bResult = PrepareUpdates(pBuf, Length, DownloadDir);\r
+ }\r
+ }\r
+ }\r
}\r
+ free(pBuf);\r
}\r
}\r
}\r
BOOL PrepareUpdates(void* pList, DWORD ListLength, LPCTSTR DownloadDir)\r
{\r
BOOL bResult;\r
+ UPDATE_LIST* pUpdateList;\r
+ void* pBuf;\r
+ TCHAR LocalDir[MAX_PATH];\r
+ TCHAR* p;\r
+ DWORD i;\r
+ BOOL b;\r
+ TCHAR Path[MAX_PATH];\r
+ DWORD Length;\r
+ BYTE Hash[64];\r
bResult = FALSE;\r
- // TODO: 更新情報を解析\r
- // TODO: 更新するファイルをダウンロード\r
+ if(ListLength >= sizeof(UPDATE_LIST))\r
+ {\r
+ pUpdateList = (UPDATE_LIST*)pList;\r
+ if((pUpdateList->FileCount - 1) * sizeof(UPDATE_LIST_FILE) + sizeof(UPDATE_LIST) >= ListLength)\r
+ {\r
+ bResult = TRUE;\r
+ DeleteDirectoryAndContents(DownloadDir);\r
+ CreateDirectory(DownloadDir, NULL);\r
+ if(pBuf = malloc(UPDATE_MAX_FILE_SIZE))\r
+ {\r
+ if(GetModuleFileName(NULL, LocalDir, MAX_PATH) > 0)\r
+ {\r
+ if(p = _tcsrchr(LocalDir, _T('\\')))\r
+ *p = _T('\0');\r
+ }\r
+ else\r
+ _tcscpy(LocalDir, _T("."));\r
+ for(i = 0; i < pUpdateList->FileCount; i++)\r
+ {\r
+ b = FALSE;\r
+ if(pUpdateList->File[i].Flags & UPDATE_LIST_FILE_FLAG_DIRECTORY)\r
+ {\r
+ _tcscpy(Path, DownloadDir);\r
+ _tcscat(Path, pUpdateList->File[i].DstPath);\r
+ if(CreateDirectory(Path, NULL))\r
+ b = TRUE;\r
+ }\r
+ if(strlen(pUpdateList->File[i].SrcPath) > 0)\r
+ {\r
+ _tcscpy(Path, LocalDir);\r
+ _tcscat(Path, pUpdateList->File[i].DstPath);\r
+ if(LoadMemoryFromFileWithTimestamp(Path, pBuf, UPDATE_MAX_FILE_SIZE, &Length, NULL))\r
+ {\r
+ if(GetHashSHA512(pBuf, Length, &Hash))\r
+ {\r
+ if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
+ b = TRUE;\r
+ }\r
+ }\r
+ if(!b)\r
+ {\r
+ if(ReadFileViaHTTP(pBuf, UPDATE_MAX_FILE_SIZE, &Length, HTTP_USER_AGENT, UPDATE_SERVER, pUpdateList->File[i].SrcPath))\r
+ {\r
+ if(GetHashSHA512(pBuf, Length, &Hash))\r
+ {\r
+ if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
+ {\r
+ _tcscpy(Path, DownloadDir);\r
+ _tcscat(Path, pUpdateList->File[i].DstPath);\r
+ if(SaveMemoryToFileWithTimestamp(Path, pBuf, Length, &pUpdateList->File[i].Timestamp))\r
+ b = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if(!b)\r
+ {\r
+ bResult = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ free(pBuf);\r
+ }\r
+ }\r
+ }\r
return bResult;\r
}\r
\r
// FFFTPを更新\r
-BOOL ApplyUpdates(LPCTSTR DestinationDir)\r
+BOOL ApplyUpdates(LPCTSTR DestinationDir, LPCTSTR BackupDirName)\r
{\r
BOOL bResult;\r
+ TCHAR Source[MAX_PATH];\r
+ TCHAR Backup[MAX_PATH];\r
+ TCHAR DestinationBackup[MAX_PATH];\r
+ TCHAR* p;\r
bResult = FALSE;\r
- // TODO:\r
+ if(GetModuleFileName(NULL, Source, MAX_PATH) > 0)\r
+ {\r
+ if(p = _tcsrchr(Source, _T('\\')))\r
+ *p = _T('\0');\r
+ _tcscpy(Backup, Source);\r
+ _tcscat(Backup, _T("\\"));\r
+ _tcscat(Backup, BackupDirName);\r
+ DeleteDirectoryAndContents(Backup);\r
+ if(CreateDirectory(Backup, NULL))\r
+ {\r
+ if(CopyAllFilesInDirectory(DestinationDir, Backup))\r
+ {\r
+ _tcscpy(DestinationBackup, DestinationDir);\r
+ _tcscat(DestinationBackup, _T("\\"));\r
+ _tcscat(DestinationBackup, BackupDirName);\r
+ if(CopyAllFilesInDirectory(Source, DestinationDir))\r
+ {\r
+ DeleteDirectoryAndContents(DestinationBackup);\r
+ bResult = TRUE;\r
+ }\r
+ else\r
+ {\r
+ DeleteDirectoryAndContents(DestinationBackup);\r
+ CopyAllFilesInDirectory(Backup, DestinationDir);\r
+ }\r
+ }\r
+ }\r
+ }\r
return bResult;\r
}\r
\r
-// 更新用のプロセスを起動\r
-BOOL StartUpdateProcess(LPCTSTR Path, LPCTSTR CommandLine)\r
+// 更新するファイルをダウンロード\r
+BOOL CleanupUpdates(LPCTSTR DownloadDir)\r
{\r
BOOL bResult;\r
bResult = FALSE;\r
- if(ShellExecute(NULL, "open", Path, CommandLine, NULL, SW_SHOW) > (HINSTANCE)32)\r
+ if(DeleteDirectoryAndContents(DownloadDir))\r
bResult = TRUE;\r
return bResult;\r
}\r
\r
+// 更新用のプロセスを起動\r
+BOOL StartUpdateProcess(LPCTSTR DownloadDir, LPCTSTR CommandLine)\r
+{\r
+ BOOL bResult;\r
+ TCHAR Name[MAX_PATH];\r
+ TCHAR* p;\r
+ TCHAR Path[MAX_PATH];\r
+ bResult = FALSE;\r
+ if(GetModuleFileName(NULL, Name, MAX_PATH) > 0)\r
+ {\r
+ if(p = _tcsrchr(Name, _T('\\')))\r
+ p++;\r
+ else\r
+ p = Name;\r
+ _tcscpy(Path, DownloadDir);\r
+ _tcscat(Path, _T("\\"));\r
+ _tcscat(Path, p);\r
+ if(ShellExecute(NULL, _T("open"), Path, CommandLine, NULL, SW_SHOW) > (HINSTANCE)32)\r
+ bResult = TRUE;\r
+ }\r
+ return bResult;\r
+}\r
+\r
// 更新用のプロセスを管理者権限で起動\r
// Windows XP以前など起動できない場合は現在のプロセスで処理を続行\r
-BOOL StartUpdateProcessAsAdministrator(LPCTSTR CommandLine, LPCTSTR Keyword)\r
+BOOL RestartUpdateProcessAsAdministrator(LPCTSTR CommandLine, LPCTSTR Keyword)\r
{\r
BOOL bResult;\r
TCHAR* NewCommandLine;\r
{\r
_tcscpy(NewCommandLine, CommandLine);\r
_tcscat(NewCommandLine, Keyword);\r
- GetModuleFileName(NULL, Path, MAX_PATH);\r
- memset(&Info, 0, sizeof(SHELLEXECUTEINFO));\r
- Info.cbSize = sizeof(SHELLEXECUTEINFO);\r
- Info.fMask = SEE_MASK_NOCLOSEPROCESS;\r
- Info.lpVerb = "runas";\r
- Info.lpFile = Path;\r
- Info.lpParameters = NewCommandLine;\r
- Info.nShow = SW_SHOW;\r
- if(ShellExecuteEx(&Info))\r
+ if(GetModuleFileName(NULL, Path, MAX_PATH) > 0)\r
{\r
- WaitForSingleObject(Info.hProcess, INFINITE);\r
- CloseHandle(Info.hProcess);\r
- bResult = TRUE;\r
+ memset(&Info, 0, sizeof(SHELLEXECUTEINFO));\r
+ Info.cbSize = sizeof(SHELLEXECUTEINFO);\r
+ Info.fMask = SEE_MASK_NOCLOSEPROCESS;\r
+ if(IsUserAnAdmin())\r
+ Info.lpVerb = _T("open");\r
+ else\r
+ Info.lpVerb = _T("runas");\r
+ Info.lpFile = Path;\r
+ Info.lpParameters = NewCommandLine;\r
+ Info.nShow = SW_SHOW;\r
+ if(ShellExecuteEx(&Info))\r
+ {\r
+ WaitForSingleObject(Info.hProcess, INFINITE);\r
+ CloseHandle(Info.hProcess);\r
+ bResult = TRUE;\r
+ }\r
}\r
free(NewCommandLine);\r
}\r