I have a C app written using Winapi and an .exe
file that I need to download and execute. My code so far is:
if (NULL == (hRequest = HttpOpenRequest(hHTTP, "GET", "/~alexandru.antochi/exe_1.exe", NULL, NULL, rgpszAcceptTypes, NULL, INTERNET_FLAG_NO_COOKIES || INTERNET_FLAG_NO_AUTH)))
{
_error("HttpOpenRequest error.");
}
if (HttpSendRequest(hRequest, NULL, NULL, NULL, NULL))
{
if (InternetReadFile(hRequest, &buffer, 65536, &bytesRead))
{
if (bytesRead == 65536)
{
printf("Warning: .exe file too big. Ignoring");
continue;
}
}
}
else
{
_error("Could not send HTTP request.");
}
closeHandles(2, hRequest, hHTTP);
I read the file, what now? If I try to write it in a local file, it will stop at the first \0
delimiter, which is after 2 letters in my case. The file can be found at http://students.info.uaic.ro/~alexandru.antochi/exe_1.exe
You must save the EXE file to a local file before you can execute it. You can't execute an EXE from memory (without writing your own EXE loader, or using a 3rd party one).
InternetReadFile()
reads arbitrary amounts of data, so you need to call it in a loop until the end of the response is reached. Write each block of data that is received as-is to your local file. Your claim that your writing "will stop at the first \0
delimiter" means that you are writing the received data as null-terminated strings instead of as raw binary data. Binary files, especially executable files, contain plenty of 0x00 bytes in them. So this is a logic bug in your code that you need to fix.
Try something more like this instead:
HINTERNET hInternet = InternetOpen(...);
if (!hInternet)
{
_error("InternetOpen error.");
}
HINTERNET hHTTP = InternetConnect(hInternet, "students.info.uaic.ro", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hHTTP)
{
InternetCloseHandle(hInternet);
_error("InternetConnect error.");
}
const char* rgpszAcceptTypes[] = {"application/vnd.microsoft.portable-executable", "application/octet-stream", "application/x-msdownload", NULL};
HINTERNET hRequest = HttpOpenRequest(hHTTP, "GET", "/~alexandru.antochi/exe_1.exe", NULL, NULL, rgpszAcceptTypes, NULL, INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_AUTH);
if (!hRequest)
{
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("HttpOpenRequest error.");
}
if (!HttpSendRequest(hRequest, NULL, NULL, NULL, NULL))
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("Could not send HTTP request.");
}
DWORD statusCode;
DWORD size = sizeof(statusCode), index = 0;
if (!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &statusCode, &size, &index))
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("HttpQueryInfo error.");
}
if (statusCode != 200)
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("HTTP request failed.");
}
HANDLE hFile = CreateFile("C:\\path to\\exe_1.exe" , GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("Could not create local file.");
}
BYTE buffer[1024];
DWORD bytesRead, bytesWritten;
do
{
if (!InternetReadFile(hRequest, buffer, sizeof(buffer), &bytesRead))
{
CloseHandle(hFile);
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("Could not read HTTP response.");
}
if (bytesRead == 0)
break;
if (!WriteFile(hFile, buffer, bytesRead, &bytesWritten))
{
CloseHandle(hFile);
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
_error("Could not write to local file.");
}
}
while (true);
CloseHandle(hFile);
InternetCloseHandle(hRequest);
InternetCloseHandle(hHTTP);
InternetCloseHandle(hInternet);
// use EXE file as needed...
Refer to MSDN documentation for more details: