HRESULT CHeader::Parse(const Byte *p) { UInt32 haderSize = Get32(p + 8); if (haderSize < 0x74) return S_FALSE; Version = Get32(p + 0x0C); Flags = Get32(p + 0x10); if (!IsSupported()) return S_FALSE; UInt32 chunkSize = Get32(p + 0x14); if (chunkSize != kChunkSize && chunkSize != 0) return S_FALSE; memcpy(Guid, p + 0x18, 16); PartNumber = Get16(p + 0x28); NumParts = Get16(p + 0x2A); int offset = 0x2C; if (IsNewVersion()) { NumImages = Get32(p + offset); offset += 4; } GetResource(p + offset, OffsetResource); GetResource(p + offset + 0x18, XmlResource); GetResource(p + offset + 0x30, MetadataResource); /* if (IsNewVersion()) { if (haderSize < 0xD0) return S_FALSE; IntegrityResource.Parse(p + offset + 0x4C); BootIndex = Get32(p + 0x48); } */ return S_OK; }
void ProcessLatestUpdate() { WORD majorVersion = 0; WORD minorVersion = 0; WORD buildNumber = 0; WORD revisionNumber = 0; wchar_t szTempFileName[MAX_PATH] { 0 }; wchar_t lpTempPathBuffer[MAX_PATH] = { 0 }; wstring thisFileName = g_moduleFilePath; wstring currentVersion; currentVersion = GetAppVersion(thisFileName.c_str(), &majorVersion, &minorVersion, &buildNumber, &revisionNumber); IWinHttpRequest * pIWinHttpRequest = NULL; BSTR bstrResponse = NULL; HRESULT hr = CoInitialize(NULL); do { VARIANT varFalse; VARIANT varEmpty; CLSID clsid; VariantInit(&varFalse); V_VT(&varFalse) = VT_BOOL; V_BOOL(&varFalse) = VARIANT_FALSE; VariantInit(&varEmpty); V_VT(&varEmpty) = VT_ERROR; hr = CLSIDFromProgID(L"WinHttp.WinHttpRequest.5.1", &clsid); if (SUCCEEDED(hr) == FALSE) { break; } hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IWinHttpRequest, (void **)&pIWinHttpRequest); if (SUCCEEDED(hr) == FALSE) { break; } BSTR bstrMethod = SysAllocString(L"GET"); BSTR bstrUrl = SysAllocString(UPDATE_CHECK_URL); hr = pIWinHttpRequest->Open(bstrMethod, bstrUrl, varFalse); SysFreeString(bstrMethod); SysFreeString(bstrUrl); if (SUCCEEDED(hr) == FALSE) { break; } hr = pIWinHttpRequest->Send(varEmpty); if (SUCCEEDED(hr) == FALSE) { break; } hr = pIWinHttpRequest->get_ResponseText(&bstrResponse); wstring txt = bstrResponse; wstring newUpdateVersion = GetNewVersion(txt); if (newUpdateVersion.length() == 0) { break; } if (newUpdateVersion == currentVersion) { if (g_isConsoleApp == TRUE) { OutputConsole(L"This is the latest version (%s)\n", currentVersion.c_str()); } break; } if (IsNewVersion(majorVersion, minorVersion, buildNumber, revisionNumber, newUpdateVersion) == FALSE) { if (g_isConsoleApp == TRUE) { OutputConsole(L"This is the latest version (%s)\n", L"1.0.0.4"); // currentVersion.c_str()); } break; } // if new, update latest version. // if old, roll-back last stable version. bool is32bit = sizeof(char *) == 4; wstring location = GetUpdateLocation(txt, is32bit); VariantInit(&varEmpty); V_VT(&varEmpty) = VT_ERROR; bstrMethod = SysAllocString(L"GET"); bstrUrl = SysAllocString(location.c_str()); pIWinHttpRequest->Open(bstrMethod, bstrUrl, varFalse); SysFreeString(bstrMethod); SysFreeString(bstrUrl); if (SUCCEEDED(hr) == FALSE) { break; } hr = pIWinHttpRequest->Send(varEmpty); if (SUCCEEDED(hr) == FALSE) { break; } VARIANT varResponse; VariantInit(&varResponse); hr = pIWinHttpRequest->get_ResponseStream(&varResponse); if (SUCCEEDED(hr) == FALSE) { break; } txt = pIWinHttpRequest->GetResponseHeader(L"Content-Type").operator const wchar_t *(); if (txt.find(L"text/html") != -1) { OutputError(L"file not found: %s", location.c_str()); break; } IStream* pStream = NULL; BYTE bBuffer[8192]; DWORD cb, cbRead, cbWritten; if (VT_UNKNOWN == V_VT(&varResponse) || VT_STREAM == V_VT(&varResponse)) { hr = V_UNKNOWN(&varResponse)->QueryInterface(IID_IStream, reinterpret_cast<void**>(&pStream)); } else { break; } if (SUCCEEDED(hr) == FALSE) { break; } DWORD dwRetVal = GetTempPath(MAX_PATH, // length of the buffer lpTempPathBuffer); // buffer for path if (dwRetVal > MAX_PATH || (dwRetVal == 0)) { OutputError(L"GetTempPath failed (%d)", GetLastError()); break; } dwRetVal = GetTempFileName(lpTempPathBuffer, // directory for tmp files L"straw", // temp file name prefix 0, // create unique name szTempFileName); // buffer for name if (dwRetVal == 0) { OutputError(L"GetTempFileName failed (%d)", GetLastError()); break; } bool succeed = true; HANDLE hFile = CreateFile(szTempFileName, GENERIC_WRITE, // Open for writing. 0, // Do not share. NULL, // No security. CREATE_ALWAYS, // Overwrite existing. FILE_ATTRIBUTE_NORMAL, // Normal file. NULL); // No attribute template. if (hFile == INVALID_HANDLE_VALUE) { OutputError(L"Can't open a file: %s", szTempFileName); break; } else { cb = sizeof(bBuffer); hr = pStream->Read(bBuffer, cb, &cbRead); while (SUCCEEDED(hr) && 0 != cbRead) { if (!WriteFile(hFile, bBuffer, cbRead, &cbWritten, NULL)) { OutputError(L"WriteFile fails with 0x%08lx\n", HRESULT_FROM_WIN32(GetLastError())); succeed = false; break; } hr = pStream->Read(bBuffer, cb, &cbRead); } } CloseHandle(hFile); pStream->Release(); VariantClear(&varResponse); if (succeed == true) { wstring oldFileName = thisFileName; oldFileName += currentVersion + L".bak"; ::DeleteFile(oldFileName.c_str()); if (MoveFile(thisFileName.c_str(), oldFileName.c_str()) == FALSE) { OutputError(L"Backup fails (%d)", GetLastError()); break; } if (MoveFile(szTempFileName, thisFileName.c_str()) == FALSE) { OutputError(L"Update fails (%d)", GetLastError()); break; } FireRestartCommand(); } } while (false); if (::PathFileExists(szTempFileName) == TRUE) { ::DeleteFile(szTempFileName); } if (pIWinHttpRequest) { pIWinHttpRequest->Release(); } if (bstrResponse) { SysFreeString(bstrResponse); } CoUninitialize(); }