如何 运行 在 Winapi 中使用 InternetOpenFile() 下载的 .exe 文件

How to run an .exe file downloaded with InternetOpenFile() in Winapi

我有一个使用 Winapi 编写的 C 应用程序和一个需要下载并执行的 .exe 文件。到目前为止我的代码是:

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);

我读了文件,现在怎么办?如果我尝试将它写入本地文件,它将在第一个 [=13=] 定界符处停止,在我的例子中是在 2 个字母之后。该文件位于 http://students.info.uaic.ro/~alexandru.antochi/exe_1.exe

您必须先将 EXE 文件保存到本地文件,然后才能执行它。您不能从内存中执行 EXE(不编写自己的 EXE 加载程序,或使用第 3 方加载程序)。

InternetReadFile()读取任意数量的数据,所以需要在循环中调用它,直到到达响应的末尾。将 按原样 接收到的每个数据块写入您的本地文件。您声称您的写作 "will stop at the first [=12=] delimiter" 意味着您将接收到的数据写入以空字符结尾的字符串而不是原始二进制数据。二进制文件,尤其是可执行文件,其中包含大量 0x00 字节。所以这是您需要修复的代码中的逻辑错误。

尝试更像这样的东西:

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...

有关详细信息,请参阅 MSDN 文档:

HTTP Sessions

Downloading Resources from the WWW