1382 lines
41 KiB
C
1382 lines
41 KiB
C
/*
|
|
* Process Hacker Online Checks -
|
|
* Uploader Window
|
|
*
|
|
* Copyright (C) 2010-2013 wj32
|
|
* Copyright (C) 2012-2016 dmex
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "onlnchk.h"
|
|
#include "json-c/json.h"
|
|
|
|
static SERVICE_INFO UploadServiceInfo[] =
|
|
{
|
|
{ UPLOAD_SERVICE_VIRUSTOTAL, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, WINHTTP_FLAG_SECURE, L"???", L"file" },
|
|
{ UPLOAD_SERVICE_JOTTI, L"virusscan.jotti.org", INTERNET_DEFAULT_HTTPS_PORT, WINHTTP_FLAG_SECURE, L"/en-US/submit-file?isAjax=true", L"sample-file[]" },
|
|
{ UPLOAD_SERVICE_CIMA, L"camas.comodo.com", INTERNET_DEFAULT_HTTP_PORT, 0, L"/cgi-bin/submit", L"file" }
|
|
};
|
|
|
|
json_object_ptr json_get_object(json_object_ptr rootObj, const char* key)
|
|
{
|
|
json_object_ptr returnObj;
|
|
|
|
if (json_object_object_get_ex(rootObj, key, &returnObj))
|
|
{
|
|
return returnObj;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
HFONT InitializeFont(
|
|
_In_ HWND hwnd
|
|
)
|
|
{
|
|
LOGFONT logFont;
|
|
|
|
// Create the font handle
|
|
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &logFont, 0))
|
|
{
|
|
HDC hdc;
|
|
|
|
if (hdc = GetDC(hwnd))
|
|
{
|
|
HFONT fontHandle = CreateFont(
|
|
-MulDiv(-14, GetDeviceCaps(hdc, LOGPIXELSY), 72),
|
|
0,
|
|
0,
|
|
0,
|
|
FW_MEDIUM,
|
|
FALSE,
|
|
FALSE,
|
|
FALSE,
|
|
ANSI_CHARSET,
|
|
OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,
|
|
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
|
|
DEFAULT_PITCH,
|
|
logFont.lfFaceName
|
|
);
|
|
|
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)fontHandle, TRUE);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
return fontHandle;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL ReadRequestString(
|
|
_In_ HINTERNET Handle,
|
|
_Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
|
|
_Out_ ULONG *DataLength
|
|
)
|
|
{
|
|
BYTE buffer[PAGE_SIZE];
|
|
PSTR data;
|
|
ULONG allocatedLength;
|
|
ULONG dataLength;
|
|
ULONG returnLength;
|
|
|
|
allocatedLength = sizeof(buffer);
|
|
data = (PSTR)PhAllocate(allocatedLength);
|
|
dataLength = 0;
|
|
|
|
// Zero the buffer
|
|
memset(buffer, 0, PAGE_SIZE);
|
|
|
|
while (WinHttpReadData(Handle, buffer, PAGE_SIZE, &returnLength))
|
|
{
|
|
if (returnLength == 0)
|
|
break;
|
|
|
|
if (allocatedLength < dataLength + returnLength)
|
|
{
|
|
allocatedLength *= 2;
|
|
data = (PSTR)PhReAllocate(data, allocatedLength);
|
|
}
|
|
|
|
// Copy the returned buffer into our pointer
|
|
memcpy(data + dataLength, buffer, returnLength);
|
|
// Zero the returned buffer for the next loop
|
|
//memset(buffer, 0, returnLength);
|
|
|
|
dataLength += returnLength;
|
|
}
|
|
|
|
if (allocatedLength < dataLength + 1)
|
|
{
|
|
allocatedLength++;
|
|
data = (PSTR)PhReAllocate(data, allocatedLength);
|
|
}
|
|
|
|
// Ensure that the buffer is null-terminated.
|
|
data[dataLength] = 0;
|
|
|
|
*DataLength = dataLength;
|
|
*Data = data;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID RaiseUploadError(
|
|
_In_ PUPLOAD_CONTEXT Context,
|
|
_In_ PWSTR Error,
|
|
_In_ ULONG ErrorCode
|
|
)
|
|
{
|
|
if (Context->DialogHandle)
|
|
{
|
|
PostMessage(
|
|
Context->DialogHandle,
|
|
UM_ERROR,
|
|
0,
|
|
(LPARAM)PhFormatString(L"Error: [%lu] %s", ErrorCode, Error)
|
|
);
|
|
}
|
|
}
|
|
|
|
PSERVICE_INFO GetUploadServiceInfo(
|
|
_In_ ULONG Id
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < ARRAYSIZE(UploadServiceInfo); i++)
|
|
{
|
|
if (UploadServiceInfo[i].Id == Id)
|
|
return &UploadServiceInfo[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOLEAN PerformSubRequest(
|
|
_In_ PUPLOAD_CONTEXT Context,
|
|
_In_ PWSTR HostName,
|
|
_In_ INTERNET_PORT HostPort,
|
|
_In_ ULONG HostFlags,
|
|
_In_ PWSTR ObjectName,
|
|
_Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
|
|
_Out_opt_ PULONG DataLength
|
|
)
|
|
{
|
|
BOOLEAN result = FALSE;
|
|
HINTERNET connectHandle = NULL;
|
|
HINTERNET requestHandle = NULL;
|
|
|
|
__try
|
|
{
|
|
// Connect to the online service.
|
|
if (!(connectHandle = WinHttpConnect(
|
|
Context->HttpHandle,
|
|
HostName,
|
|
HostPort,
|
|
0
|
|
)))
|
|
{
|
|
RaiseUploadError(Context, L"Unable to connect to the service", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Create the request.
|
|
if (!(requestHandle = WinHttpOpenRequest(
|
|
connectHandle,
|
|
NULL,
|
|
ObjectName,
|
|
NULL,
|
|
WINHTTP_NO_REFERER,
|
|
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
|
WINHTTP_FLAG_REFRESH | HostFlags
|
|
)))
|
|
{
|
|
RaiseUploadError(Context, L"Unable to create the request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Send the request.
|
|
if (!WinHttpSendRequest(
|
|
requestHandle,
|
|
WINHTTP_NO_ADDITIONAL_HEADERS,
|
|
0,
|
|
WINHTTP_NO_REQUEST_DATA,
|
|
0,
|
|
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
|
|
0
|
|
))
|
|
{
|
|
RaiseUploadError(Context, L"Unable to send the request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Wait for the send request to complete and receive the response.
|
|
if (WinHttpReceiveResponse(requestHandle, NULL))
|
|
{
|
|
BYTE buffer[PAGE_SIZE];
|
|
PSTR data;
|
|
ULONG allocatedLength;
|
|
ULONG dataLength;
|
|
ULONG returnLength;
|
|
|
|
allocatedLength = sizeof(buffer);
|
|
data = PhAllocate(allocatedLength);
|
|
dataLength = 0;
|
|
|
|
while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength))
|
|
{
|
|
if (returnLength == 0)
|
|
break;
|
|
|
|
if (allocatedLength < dataLength + returnLength)
|
|
{
|
|
allocatedLength *= 2;
|
|
data = PhReAllocate(data, allocatedLength);
|
|
}
|
|
|
|
memcpy(data + dataLength, buffer, returnLength);
|
|
dataLength += returnLength;
|
|
}
|
|
|
|
if (allocatedLength < dataLength + 1)
|
|
{
|
|
allocatedLength++;
|
|
data = PhReAllocate(data, allocatedLength);
|
|
}
|
|
|
|
// Ensure that the buffer is null-terminated.
|
|
data[dataLength] = 0;
|
|
|
|
*Data = data;
|
|
|
|
if (DataLength)
|
|
{
|
|
*DataLength = dataLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RaiseUploadError(Context, L"Unable to receive the response", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
result = TRUE;
|
|
}
|
|
__finally
|
|
{
|
|
if (requestHandle)
|
|
WinHttpCloseHandle(requestHandle);
|
|
if (connectHandle)
|
|
WinHttpCloseHandle(connectHandle);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NTSTATUS HashFileAndResetPosition(
|
|
_In_ HANDLE FileHandle,
|
|
_In_ PLARGE_INTEGER FileSize,
|
|
_In_ ULONG Algorithm,
|
|
_Out_ PVOID Hash
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK iosb;
|
|
PH_HASH_CONTEXT hashContext;
|
|
sha256_context sha256;
|
|
ULONG64 bytesRemaining;
|
|
FILE_POSITION_INFORMATION positionInfo;
|
|
UCHAR buffer[PAGE_SIZE];
|
|
|
|
bytesRemaining = FileSize->QuadPart;
|
|
|
|
switch (Algorithm)
|
|
{
|
|
case HASH_SHA1:
|
|
PhInitializeHash(&hashContext, Sha1HashAlgorithm);
|
|
break;
|
|
case HASH_SHA256:
|
|
sha256_starts(&sha256);
|
|
break;
|
|
}
|
|
|
|
while (bytesRemaining)
|
|
{
|
|
status = NtReadFile(
|
|
FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&iosb,
|
|
buffer,
|
|
sizeof(buffer),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
break;
|
|
|
|
switch (Algorithm)
|
|
{
|
|
case HASH_SHA1:
|
|
PhUpdateHash(&hashContext, buffer, (ULONG)iosb.Information);
|
|
break;
|
|
case HASH_SHA256:
|
|
sha256_update(&sha256, (PUCHAR)buffer, (ULONG)iosb.Information);
|
|
break;
|
|
}
|
|
|
|
bytesRemaining -= (ULONG)iosb.Information;
|
|
}
|
|
|
|
if (status == STATUS_END_OF_FILE)
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
switch (Algorithm)
|
|
{
|
|
case HASH_SHA1:
|
|
PhFinalHash(&hashContext, Hash, 20, NULL);
|
|
break;
|
|
case HASH_SHA256:
|
|
sha256_finish(&sha256, Hash);
|
|
break;
|
|
}
|
|
|
|
positionInfo.CurrentByteOffset.QuadPart = 0;
|
|
status = NtSetInformationFile(
|
|
FileHandle,
|
|
&iosb,
|
|
&positionInfo,
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
FilePositionInformation
|
|
);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS UploadFileThreadStart(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG httpStatus = 0;
|
|
ULONG httpStatusLength = sizeof(ULONG);
|
|
ULONG httpPostSeed = 0;
|
|
ULONG totalUploadLength = 0;
|
|
ULONG totalUploadedLength = 0;
|
|
ULONG totalPostHeaderWritten = 0;
|
|
ULONG totalPostFooterWritten = 0;
|
|
ULONG totalWriteLength = 0;
|
|
LARGE_INTEGER timeNow;
|
|
LARGE_INTEGER timeStart;
|
|
ULONG64 timeTicks = 0;
|
|
ULONG64 timeBitsPerSecond = 0;
|
|
|
|
HANDLE fileHandle = INVALID_HANDLE_VALUE;
|
|
IO_STATUS_BLOCK isb;
|
|
PSERVICE_INFO serviceInfo = NULL;
|
|
HINTERNET connectHandle = NULL;
|
|
HINTERNET requestHandle = NULL;
|
|
|
|
PPH_STRING postBoundary = NULL;
|
|
PPH_BYTES asciiPostData = NULL;
|
|
PPH_BYTES asciiFooterData = NULL;
|
|
PH_STRING_BUILDER httpRequestHeaders = { 0 };
|
|
PH_STRING_BUILDER httpPostHeader = { 0 };
|
|
PH_STRING_BUILDER httpPostFooter = { 0 };
|
|
BYTE buffer[PAGE_SIZE];
|
|
|
|
PUPLOAD_CONTEXT context = (PUPLOAD_CONTEXT)Parameter;
|
|
|
|
serviceInfo = GetUploadServiceInfo(context->Service);
|
|
|
|
__try
|
|
{
|
|
// Open the file and check its size.
|
|
status = PhCreateFileWin32(
|
|
&fileHandle,
|
|
context->FileName->Buffer,
|
|
FILE_GENERIC_READ,
|
|
0,
|
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
RaiseUploadError(context, L"Unable to open the file", RtlNtStatusToDosError(status));
|
|
__leave;
|
|
}
|
|
|
|
// Connect to the online service.
|
|
if (!(connectHandle = WinHttpConnect(
|
|
context->HttpHandle,
|
|
serviceInfo->HostName,
|
|
serviceInfo->HostPort,
|
|
0
|
|
)))
|
|
{
|
|
RaiseUploadError(context, L"Unable to connect to the service", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Create the request.
|
|
if (!(requestHandle = WinHttpOpenRequest(
|
|
connectHandle,
|
|
L"POST",
|
|
context->ObjectName->Buffer,
|
|
NULL,
|
|
WINHTTP_NO_REFERER,
|
|
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
|
WINHTTP_FLAG_REFRESH | serviceInfo->HostFlags
|
|
)))
|
|
{
|
|
RaiseUploadError(context, L"Unable to create the request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
if (context->Service == UPLOAD_SERVICE_JOTTI)
|
|
{
|
|
PPH_STRING ajaxHeader;
|
|
|
|
ajaxHeader = PhCreateString(L"X-Requested-With: XMLHttpRequest");
|
|
|
|
WinHttpAddRequestHeaders(
|
|
requestHandle,
|
|
ajaxHeader->Buffer,
|
|
(ULONG)ajaxHeader->Length / sizeof(WCHAR),
|
|
WINHTTP_ADDREQ_FLAG_ADD
|
|
);
|
|
|
|
PhDereferenceObject(ajaxHeader);
|
|
}
|
|
|
|
// Create and POST data.
|
|
PhInitializeStringBuilder(&httpRequestHeaders, MAX_PATH);
|
|
PhInitializeStringBuilder(&httpPostHeader, MAX_PATH);
|
|
PhInitializeStringBuilder(&httpPostFooter, MAX_PATH);
|
|
|
|
// build request boundary string
|
|
postBoundary = PhFormatString(
|
|
L"------------------------%I64u",
|
|
(ULONG64)RtlRandomEx(&httpPostSeed) | ((ULONG64)RtlRandomEx(&httpPostSeed) << 31)
|
|
);
|
|
// build request header string
|
|
PhAppendFormatStringBuilder(
|
|
&httpRequestHeaders,
|
|
L"Content-Type: multipart/form-data; boundary=%s\r\n",
|
|
postBoundary->Buffer
|
|
);
|
|
|
|
if (context->Service == UPLOAD_SERVICE_JOTTI)
|
|
{
|
|
// POST boundary header
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"\r\n--%s\r\n",
|
|
postBoundary->Buffer
|
|
);
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"\r\n\r\n268435456\r\n"
|
|
);
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"--%s\r\n",
|
|
postBoundary->Buffer
|
|
);
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
|
|
serviceInfo->FileNameFieldName,
|
|
context->BaseFileName->Buffer
|
|
);
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"Content-Type: application/x-msdownload\r\n\r\n"
|
|
);
|
|
|
|
// POST boundary footer
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostFooter,
|
|
L"\r\n--%s--\r\n",
|
|
postBoundary->Buffer
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// POST boundary header
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"--%s\r\n",
|
|
postBoundary->Buffer
|
|
);
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
|
|
serviceInfo->FileNameFieldName,
|
|
context->BaseFileName->Buffer
|
|
);
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostHeader,
|
|
L"Content-Type: application/octet-stream\r\n\r\n"
|
|
);
|
|
|
|
// POST boundary footer
|
|
PhAppendFormatStringBuilder(
|
|
&httpPostFooter,
|
|
L"\r\n--%s--\r\n\r\n",
|
|
postBoundary->Buffer
|
|
);
|
|
}
|
|
|
|
// add headers
|
|
if (!WinHttpAddRequestHeaders(
|
|
requestHandle,
|
|
httpRequestHeaders.String->Buffer,
|
|
-1L,
|
|
WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD
|
|
))
|
|
{
|
|
RaiseUploadError(context, L"Unable to add request headers", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// All until now has been just for this; Calculate the total request length.
|
|
totalUploadLength = (ULONG)httpPostHeader.String->Length / sizeof(WCHAR) + context->TotalFileLength + (ULONG)httpPostFooter.String->Length / sizeof(WCHAR);
|
|
|
|
// Send the request.
|
|
if (!WinHttpSendRequest(
|
|
requestHandle,
|
|
WINHTTP_NO_ADDITIONAL_HEADERS,
|
|
0,
|
|
WINHTTP_NO_REQUEST_DATA,
|
|
0,
|
|
totalUploadLength,
|
|
0
|
|
))
|
|
{
|
|
RaiseUploadError(context, L"Unable to send the request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Convert to ASCII
|
|
asciiPostData = PhConvertUtf16ToAscii(httpPostHeader.String->Buffer, '-');
|
|
asciiFooterData = PhConvertUtf16ToAscii(httpPostFooter.String->Buffer, '-');
|
|
|
|
// Start the clock.
|
|
PhQuerySystemTime(&timeStart);
|
|
|
|
// Write the header
|
|
if (!WinHttpWriteData(
|
|
requestHandle,
|
|
asciiPostData->Buffer,
|
|
(ULONG)asciiPostData->Length,
|
|
&totalPostHeaderWritten
|
|
))
|
|
{
|
|
RaiseUploadError(context, L"Unable to write the post header", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Upload the file...
|
|
while (TRUE)
|
|
{
|
|
status = NtReadFile(
|
|
fileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&isb,
|
|
buffer,
|
|
PAGE_SIZE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
break;
|
|
|
|
if (!WinHttpWriteData(requestHandle, buffer, (ULONG)isb.Information, &totalWriteLength))
|
|
{
|
|
RaiseUploadError(context, L"Unable to upload the file data", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
totalUploadedLength += totalWriteLength;
|
|
|
|
// Query the current time
|
|
PhQuerySystemTime(&timeNow);
|
|
|
|
// Calculate the number of ticks
|
|
timeTicks = (timeNow.QuadPart - timeStart.QuadPart) / PH_TICKS_PER_SEC;
|
|
timeBitsPerSecond = totalUploadedLength / __max(timeTicks, 1);
|
|
|
|
{
|
|
FLOAT percent = ((FLOAT)totalUploadedLength / context->TotalFileLength * 100);
|
|
PPH_STRING totalLength = PhFormatSize(context->TotalFileLength, -1);
|
|
PPH_STRING totalUploaded = PhFormatSize(totalUploadedLength, -1);
|
|
PPH_STRING totalSpeed = PhFormatSize(timeBitsPerSecond, -1);
|
|
|
|
PPH_STRING statusMessage = PhFormatString(
|
|
L"%s of %s @ %s/s",
|
|
totalUploaded->Buffer,
|
|
totalLength->Buffer,
|
|
totalSpeed->Buffer
|
|
);
|
|
|
|
Static_SetText(context->StatusHandle, statusMessage->Buffer);
|
|
|
|
// Update the progress bar position
|
|
PostMessage(context->ProgressHandle, PBM_SETPOS, (INT)percent, 0);
|
|
|
|
PhDereferenceObject(statusMessage);
|
|
PhDereferenceObject(totalSpeed);
|
|
PhDereferenceObject(totalLength);
|
|
PhDereferenceObject(totalUploaded);
|
|
}
|
|
}
|
|
|
|
// Write the footer bytes
|
|
if (!WinHttpWriteData(
|
|
requestHandle,
|
|
asciiFooterData->Buffer,
|
|
(ULONG)asciiFooterData->Length,
|
|
&totalPostFooterWritten
|
|
))
|
|
{
|
|
RaiseUploadError(context, L"Unable to write the post footer", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Wait for the send request to complete and receive the response.
|
|
if (!WinHttpReceiveResponse(requestHandle, NULL))
|
|
{
|
|
RaiseUploadError(context, L"Unable to receive the response", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Handle service-specific actions.
|
|
WinHttpQueryHeaders(
|
|
requestHandle,
|
|
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
|
|
NULL,
|
|
&httpStatus,
|
|
&httpStatusLength,
|
|
NULL
|
|
);
|
|
|
|
if (httpStatus == HTTP_STATUS_OK || httpStatus == HTTP_STATUS_REDIRECT_METHOD || httpStatus == HTTP_STATUS_REDIRECT)
|
|
{
|
|
switch (context->Service)
|
|
{
|
|
case UPLOAD_SERVICE_VIRUSTOTAL:
|
|
{
|
|
ULONG bufferLength = 0;
|
|
|
|
// Use WinHttpQueryOption to obtain a buffer size.
|
|
if (!WinHttpQueryOption(requestHandle, WINHTTP_OPTION_URL, NULL, &bufferLength))
|
|
{
|
|
PPH_STRING buffer = PhCreateStringEx(NULL, bufferLength);
|
|
|
|
// Use WinHttpQueryOption again, this time to retrieve the URL in the new buffer
|
|
if (WinHttpQueryOption(requestHandle, WINHTTP_OPTION_URL, buffer->Buffer, &bufferLength))
|
|
{
|
|
// Format the retrieved URL...
|
|
context->LaunchCommand = PhDuplicateString(buffer);
|
|
}
|
|
|
|
PhDereferenceObject(buffer);
|
|
}
|
|
}
|
|
break;
|
|
case UPLOAD_SERVICE_JOTTI:
|
|
{
|
|
PSTR hrefEquals = NULL;
|
|
PSTR quote = NULL;
|
|
PSTR buffer = NULL;
|
|
ULONG bufferLength = 0;
|
|
json_object_ptr rootJsonObject;
|
|
|
|
//This service returns some json that redirects the user to the new location.
|
|
if (!ReadRequestString(requestHandle, &buffer, &bufferLength))
|
|
{
|
|
RaiseUploadError(context, L"Unable to complete the request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
if (rootJsonObject = json_tokener_parse(buffer))
|
|
{
|
|
PSTR redirectUrl = json_object_get_string(json_get_object(rootJsonObject, "redirecturl"));
|
|
|
|
context->LaunchCommand = PhFormatString(
|
|
L"http://virusscan.jotti.org%hs",
|
|
redirectUrl
|
|
);
|
|
|
|
json_object_put(rootJsonObject);
|
|
}
|
|
}
|
|
break;
|
|
case UPLOAD_SERVICE_CIMA:
|
|
{
|
|
PSTR urlEquals = NULL;
|
|
PSTR quote = NULL;
|
|
PSTR buffer = NULL;
|
|
ULONG bufferLength = 0;
|
|
|
|
// This service returns some HTML that redirects the user to the new location.
|
|
if (!ReadRequestString(requestHandle, &buffer, &bufferLength))
|
|
{
|
|
RaiseUploadError(context, L"Unable to complete the CIMA request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// The HTML looks like this:
|
|
// <META http-equiv="Refresh" content="0; url=...">
|
|
urlEquals = strstr(buffer, "url=");
|
|
|
|
if (urlEquals)
|
|
{
|
|
urlEquals += 4;
|
|
quote = strchr(urlEquals, '"');
|
|
|
|
if (quote)
|
|
{
|
|
context->LaunchCommand = PhFormatString(
|
|
L"http://camas.comodo.com%.*S",
|
|
quote - urlEquals,
|
|
urlEquals
|
|
);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RaiseUploadError(context, L"Unable to complete the request", STATUS_FVE_PARTIAL_METADATA);
|
|
__leave;
|
|
}
|
|
|
|
if (!PhIsNullOrEmptyString(context->LaunchCommand))
|
|
{
|
|
PostMessage(context->DialogHandle, UM_LAUNCH, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
RaiseUploadError(context, L"Unable to complete the Launch request (please try again after a few minutes)", ERROR_INVALID_DATA);
|
|
__leave;
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
if (postBoundary)
|
|
{
|
|
PhDereferenceObject(postBoundary);
|
|
}
|
|
|
|
if (asciiFooterData)
|
|
{
|
|
PhDereferenceObject(asciiFooterData);
|
|
}
|
|
|
|
if (asciiPostData)
|
|
{
|
|
PhDereferenceObject(asciiPostData);
|
|
}
|
|
|
|
if (httpPostFooter.String)
|
|
{
|
|
PhDeleteStringBuilder(&httpPostFooter);
|
|
}
|
|
|
|
if (httpPostHeader.String)
|
|
{
|
|
PhDeleteStringBuilder(&httpPostHeader);
|
|
}
|
|
|
|
if (httpRequestHeaders.String)
|
|
{
|
|
PhDeleteStringBuilder(&httpRequestHeaders);
|
|
}
|
|
|
|
if (fileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
NtClose(fileHandle);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS UploadCheckThreadStart(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
BOOLEAN fileExists = FALSE;
|
|
LARGE_INTEGER fileSize64;
|
|
PSTR subRequestBuffer = NULL;
|
|
HINTERNET connectHandle = NULL;
|
|
HINTERNET requestHandle = NULL;
|
|
PSERVICE_INFO serviceInfo = NULL;
|
|
PPH_STRING hashString = NULL;
|
|
PPH_STRING subObjectName = NULL;
|
|
HANDLE fileHandle = INVALID_HANDLE_VALUE;
|
|
|
|
PUPLOAD_CONTEXT context = (PUPLOAD_CONTEXT)Parameter;
|
|
|
|
serviceInfo = GetUploadServiceInfo(context->Service);
|
|
|
|
__try
|
|
{
|
|
// Open the file and check its size.
|
|
status = PhCreateFileWin32(
|
|
&fileHandle,
|
|
context->FileName->Buffer,
|
|
FILE_GENERIC_READ,
|
|
0,
|
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
RaiseUploadError(context, L"Unable to open the file", RtlNtStatusToDosError(status));
|
|
__leave;
|
|
}
|
|
|
|
if (NT_SUCCESS(status = PhGetFileSize(fileHandle, &fileSize64)))
|
|
{
|
|
if (context->Service == UPLOAD_SERVICE_VIRUSTOTAL)
|
|
{
|
|
if (fileSize64.QuadPart > 128 * 1024 * 1024) // 128 MB
|
|
{
|
|
RaiseUploadError(context, L"The file is too large (over 128 MB)", ERROR_FILE_TOO_LARGE);
|
|
__leave;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fileSize64.QuadPart > 20 * 1024 * 1024) // 20 MB
|
|
{
|
|
RaiseUploadError(context, L"The file is too large (over 20 MB)", ERROR_FILE_TOO_LARGE);
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
context->TotalFileLength = fileSize64.LowPart;
|
|
}
|
|
|
|
// Get proxy configuration and create winhttp handle (used for all winhttp sessions + requests).
|
|
{
|
|
PPH_STRING phVersion = NULL;
|
|
PPH_STRING userAgent = NULL;
|
|
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
|
|
|
|
// Create a user agent string.
|
|
phVersion = PhGetPhVersion();
|
|
userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer);
|
|
|
|
// Query the current system proxy
|
|
WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
|
|
|
|
// Open the HTTP session with the system proxy configuration if available
|
|
context->HttpHandle = WinHttpOpen(
|
|
userAgent->Buffer,
|
|
proxyConfig.lpszProxy != NULL ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
|
proxyConfig.lpszProxy,
|
|
proxyConfig.lpszProxyBypass,
|
|
0
|
|
);
|
|
|
|
PhClearReference(&phVersion);
|
|
PhClearReference(&userAgent);
|
|
|
|
if (!context->HttpHandle)
|
|
__leave;
|
|
|
|
if (WindowsVersion >= WINDOWS_8_1)
|
|
{
|
|
// Enable GZIP and DEFLATE support on Windows 8.1 and above using undocumented flags.
|
|
ULONG httpFlags = WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
|
|
|
|
WinHttpSetOption(
|
|
context->HttpHandle,
|
|
WINHTTP_OPTION_DECOMPRESSION,
|
|
&httpFlags,
|
|
sizeof(ULONG)
|
|
);
|
|
}
|
|
}
|
|
|
|
switch (context->Service)
|
|
{
|
|
case UPLOAD_SERVICE_VIRUSTOTAL:
|
|
{
|
|
PSTR uploadUrl = NULL;
|
|
PSTR quote = NULL;
|
|
ULONG bufferLength = 0;
|
|
UCHAR hash[32];
|
|
json_object_ptr rootJsonObject;
|
|
|
|
if (!NT_SUCCESS(status = HashFileAndResetPosition(fileHandle, &fileSize64, HASH_SHA256, hash)))
|
|
{
|
|
RaiseUploadError(context, L"Unable to hash the file", RtlNtStatusToDosError(status));
|
|
__leave;
|
|
}
|
|
|
|
hashString = PhBufferToHexString(hash, 32);
|
|
subObjectName = PhConcatStrings2(L"/file/upload/?sha256=", hashString->Buffer);
|
|
context->LaunchCommand = PhFormatString(L"http://www.virustotal.com/file/%s/analysis/", hashString->Buffer);
|
|
|
|
if (!PerformSubRequest(
|
|
context,
|
|
serviceInfo->HostName,
|
|
serviceInfo->HostPort,
|
|
serviceInfo->HostFlags,
|
|
subObjectName->Buffer,
|
|
&subRequestBuffer,
|
|
&bufferLength
|
|
))
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
if (rootJsonObject = json_tokener_parse(subRequestBuffer))
|
|
{
|
|
json_bool file_Exists;
|
|
PSTR uploadUrl;
|
|
|
|
file_Exists = json_object_get_boolean(json_get_object(rootJsonObject, "file_exists"));
|
|
uploadUrl = json_object_get_string(json_get_object(rootJsonObject, "upload_url"));
|
|
|
|
if (file_Exists)
|
|
{
|
|
fileExists = TRUE;
|
|
}
|
|
|
|
context->ObjectName = PhZeroExtendToUtf16(uploadUrl + strlen("https://www.virustotal.com"));
|
|
|
|
json_object_put(rootJsonObject);
|
|
}
|
|
|
|
// Create the default upload URL
|
|
if (!context->ObjectName)
|
|
context->ObjectName = PhCreateString(serviceInfo->UploadObjectName);
|
|
}
|
|
break;
|
|
case UPLOAD_SERVICE_JOTTI:
|
|
{
|
|
// Create the default upload URL
|
|
if (!context->ObjectName)
|
|
context->ObjectName = PhCreateString(serviceInfo->UploadObjectName);
|
|
}
|
|
break;
|
|
case UPLOAD_SERVICE_CIMA:
|
|
{
|
|
PSTR quote = NULL;
|
|
ULONG bufferLength = 0;
|
|
UCHAR hash[32];
|
|
ULONG status = 0;
|
|
ULONG statusLength = sizeof(statusLength);
|
|
|
|
if (!NT_SUCCESS(status = HashFileAndResetPosition(fileHandle, &fileSize64, HASH_SHA256, hash)))
|
|
{
|
|
RaiseUploadError(context, L"Unable to hash the file", RtlNtStatusToDosError(status));
|
|
__leave;
|
|
}
|
|
|
|
hashString = PhBufferToHexString(hash, 32);
|
|
subObjectName = PhConcatStrings2(L"/cgi-bin/submit?file=", hashString->Buffer);
|
|
context->LaunchCommand = PhFormatString(L"http://camas.comodo.com/cgi-bin/submit?file=%s", hashString->Buffer);
|
|
|
|
// Connect to the CIMA online service.
|
|
if (!(connectHandle = WinHttpConnect(
|
|
context->HttpHandle,
|
|
serviceInfo->HostName,
|
|
INTERNET_DEFAULT_HTTP_PORT,
|
|
0
|
|
)))
|
|
{
|
|
RaiseUploadError(context, L"Unable to connect to the CIMA service", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Create the request.
|
|
if (!(requestHandle = WinHttpOpenRequest(
|
|
connectHandle,
|
|
NULL,
|
|
subObjectName->Buffer,
|
|
NULL,
|
|
WINHTTP_NO_REFERER,
|
|
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
|
WINHTTP_FLAG_REFRESH
|
|
)))
|
|
{
|
|
RaiseUploadError(context, L"Unable to create the CIMA request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Send the request.
|
|
if (!WinHttpSendRequest(
|
|
requestHandle,
|
|
WINHTTP_NO_ADDITIONAL_HEADERS,
|
|
0,
|
|
WINHTTP_NO_REQUEST_DATA,
|
|
0,
|
|
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
|
|
0
|
|
))
|
|
{
|
|
RaiseUploadError(context, L"Unable to send the CIMA request", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
// Wait for the send request to complete and receive the response.
|
|
if (!WinHttpReceiveResponse(requestHandle, NULL))
|
|
{
|
|
RaiseUploadError(context, L"Unable to receive the CIMA response", GetLastError());
|
|
__leave;
|
|
}
|
|
|
|
WinHttpQueryHeaders(
|
|
requestHandle,
|
|
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
|
|
NULL,
|
|
&status,
|
|
&statusLength,
|
|
NULL
|
|
);
|
|
|
|
if (status == HTTP_STATUS_OK)
|
|
{
|
|
fileExists = TRUE;
|
|
}
|
|
|
|
if (!context->ObjectName)
|
|
{
|
|
// Create the default upload URL
|
|
context->ObjectName = PhCreateString(serviceInfo->UploadObjectName);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Do we need to prompt the user?
|
|
if (fileExists && !PhIsNullOrEmptyString(context->LaunchCommand))
|
|
{
|
|
PostMessage(context->DialogHandle, UM_EXISTS, 0, 0);
|
|
__leave;
|
|
}
|
|
|
|
// No existing file found... Start the upload.
|
|
if (!NT_SUCCESS(UploadFileThreadStart(context)))
|
|
__leave;
|
|
}
|
|
__finally
|
|
{
|
|
PhClearReference(&hashString);
|
|
PhClearReference(&subObjectName);
|
|
|
|
if (requestHandle)
|
|
{
|
|
WinHttpCloseHandle(requestHandle);
|
|
}
|
|
|
|
if (connectHandle)
|
|
{
|
|
WinHttpCloseHandle(connectHandle);
|
|
}
|
|
|
|
if (fileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
NtClose(fileHandle);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
INT_PTR CALLBACK UploadDlgProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
PUPLOAD_CONTEXT context = NULL;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
context = (PUPLOAD_CONTEXT)lParam;
|
|
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
|
}
|
|
else
|
|
{
|
|
context = (PUPLOAD_CONTEXT)GetProp(hwndDlg, L"Context");
|
|
|
|
if (uMsg == WM_NCDESTROY)
|
|
{
|
|
PhClearReference(&context->FileName);
|
|
PhClearReference(&context->BaseFileName);
|
|
PhClearReference(&context->WindowFileName);
|
|
PhClearReference(&context->LaunchCommand);
|
|
PhClearReference(&context->ObjectName);
|
|
|
|
if (context->MessageFont)
|
|
DeleteObject(context->MessageFont);
|
|
|
|
if (context->HttpHandle)
|
|
WinHttpCloseHandle(context->HttpHandle);
|
|
|
|
RemoveProp(hwndDlg, L"Context");
|
|
PhFree(context);
|
|
|
|
PostQuitMessage(0);
|
|
}
|
|
}
|
|
|
|
if (!context)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
HANDLE dialogThread = NULL;
|
|
HWND parentWindow = GetParent(hwndDlg);
|
|
|
|
PhCenterWindow(hwndDlg, (IsWindowVisible(parentWindow) && !IsMinimized(parentWindow)) ? parentWindow : NULL);
|
|
|
|
context->DialogHandle = hwndDlg;
|
|
context->StatusHandle = GetDlgItem(hwndDlg, IDC_STATUS);
|
|
context->ProgressHandle = GetDlgItem(hwndDlg, IDC_PROGRESS1);
|
|
context->MessageHandle = GetDlgItem(hwndDlg, IDC_MESSAGE);
|
|
context->MessageFont = InitializeFont(context->MessageHandle);
|
|
context->WindowFileName = PhFormatString(L"Uploading: %s", context->BaseFileName->Buffer);
|
|
context->UploadServiceState = PhUploadServiceChecking;
|
|
|
|
// Reset the window status...
|
|
Static_SetText(context->MessageHandle, context->WindowFileName->Buffer);
|
|
|
|
switch (context->Service)
|
|
{
|
|
case UPLOAD_SERVICE_VIRUSTOTAL:
|
|
Static_SetText(hwndDlg, L"Uploading to VirusTotal...");
|
|
break;
|
|
case UPLOAD_SERVICE_JOTTI:
|
|
Static_SetText(hwndDlg, L"Uploading to Jotti...");
|
|
break;
|
|
case UPLOAD_SERVICE_CIMA:
|
|
Static_SetText(hwndDlg, L"Uploading to Comodo...");
|
|
break;
|
|
}
|
|
|
|
if (dialogThread = PhCreateThread(0, UploadCheckThreadStart, (PVOID)context))
|
|
NtClose(dialogThread);
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDYES:
|
|
{
|
|
context->UploadServiceState = PhUploadServiceMaximum;
|
|
|
|
if (!PhIsNullOrEmptyString(context->LaunchCommand))
|
|
{
|
|
PhShellExecute(hwndDlg, context->LaunchCommand->Buffer, NULL);
|
|
}
|
|
|
|
DestroyWindow(hwndDlg);
|
|
}
|
|
break;
|
|
case IDNO:
|
|
{
|
|
if (context->UploadServiceState == PhUploadServiceViewReport)
|
|
{
|
|
HANDLE dialogThread = NULL;
|
|
|
|
// Set state to uploading...
|
|
context->UploadServiceState = PhUploadServiceUploading;
|
|
|
|
// Reset the window status...
|
|
Static_SetText(context->MessageHandle, context->WindowFileName->Buffer);
|
|
Static_SetText(GetDlgItem(hwndDlg, IDNO), L"Cancel");
|
|
Control_Visible(GetDlgItem(hwndDlg, IDYES), FALSE);
|
|
|
|
// Start the upload thread...
|
|
if (dialogThread = PhCreateThread(0, UploadFileThreadStart, (PVOID)context))
|
|
NtClose(dialogThread);
|
|
}
|
|
else
|
|
{
|
|
context->UploadServiceState = PhUploadServiceMaximum;
|
|
DestroyWindow(hwndDlg);
|
|
}
|
|
}
|
|
break;
|
|
case IDCANCEL:
|
|
{
|
|
context->UploadServiceState = PhUploadServiceMaximum;
|
|
DestroyWindow(hwndDlg);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case WM_CTLCOLORBTN:
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLORSTATIC:
|
|
{
|
|
HDC hDC = (HDC)wParam;
|
|
HWND hwndChild = (HWND)lParam;
|
|
|
|
// Check for our static label and change the color.
|
|
if (GetDlgCtrlID(hwndChild) == IDC_MESSAGE)
|
|
{
|
|
SetTextColor(hDC, RGB(19, 112, 171));
|
|
}
|
|
|
|
// Set a transparent background for the control backcolor.
|
|
SetBkMode(hDC, TRANSPARENT);
|
|
|
|
// set window background color.
|
|
return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
|
|
}
|
|
break;
|
|
case UM_EXISTS:
|
|
{
|
|
context->UploadServiceState = PhUploadServiceViewReport;
|
|
|
|
Static_SetText(GetDlgItem(hwndDlg, IDNO), L"No");
|
|
Control_Visible(GetDlgItem(hwndDlg, IDYES), TRUE);
|
|
|
|
Static_SetText(context->MessageHandle, L"File already analysed.");
|
|
Static_SetText(context->StatusHandle, L"View existing report?");
|
|
}
|
|
break;
|
|
case UM_LAUNCH:
|
|
{
|
|
context->UploadServiceState = PhUploadServiceMaximum;
|
|
|
|
if (!PhIsNullOrEmptyString(context->LaunchCommand))
|
|
{
|
|
PhShellExecute(hwndDlg, context->LaunchCommand->Buffer, NULL);
|
|
}
|
|
|
|
DestroyWindow(hwndDlg);
|
|
}
|
|
break;
|
|
case UM_ERROR:
|
|
{
|
|
PPH_STRING errorMessage = (PPH_STRING)lParam;
|
|
|
|
context->UploadServiceState = PhUploadServiceMaximum;
|
|
|
|
if (errorMessage)
|
|
{
|
|
Static_SetText(GetDlgItem(hwndDlg, IDC_MESSAGE), errorMessage->Buffer);
|
|
PhClearReference(&errorMessage);
|
|
}
|
|
else
|
|
{
|
|
Static_SetText(GetDlgItem(hwndDlg, IDC_MESSAGE), L"Error");
|
|
}
|
|
|
|
Static_SetText(GetDlgItem(hwndDlg, IDC_STATUS), L"");
|
|
Static_SetText(GetDlgItem(hwndDlg, IDNO), L"Close");
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS PhUploadToDialogThreadStart(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
BOOL result;
|
|
MSG message;
|
|
HWND dialogHandle;
|
|
PH_AUTO_POOL autoPool;
|
|
PUPLOAD_CONTEXT context = (PUPLOAD_CONTEXT)Parameter;
|
|
|
|
PhInitializeAutoPool(&autoPool);
|
|
|
|
dialogHandle = CreateDialogParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_PROGRESS),
|
|
PhMainWndHandle,
|
|
UploadDlgProc,
|
|
(LPARAM)Parameter
|
|
);
|
|
|
|
ShowWindow(dialogHandle, SW_SHOW);
|
|
SetForegroundWindow(dialogHandle);
|
|
|
|
while (result = GetMessage(&message, NULL, 0, 0))
|
|
{
|
|
if (result == -1)
|
|
break;
|
|
|
|
if (!IsDialogMessage(dialogHandle, &message))
|
|
{
|
|
TranslateMessage(&message);
|
|
DispatchMessage(&message);
|
|
}
|
|
|
|
PhDrainAutoPool(&autoPool);
|
|
}
|
|
|
|
PhDeleteAutoPool(&autoPool);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID UploadToOnlineService(
|
|
_In_ PPH_STRING FileName,
|
|
_In_ ULONG Service
|
|
)
|
|
{
|
|
HANDLE dialogThread = NULL;
|
|
PUPLOAD_CONTEXT context;
|
|
|
|
context = (PUPLOAD_CONTEXT)PhAllocate(sizeof(UPLOAD_CONTEXT));
|
|
memset(context, 0, sizeof(UPLOAD_CONTEXT));
|
|
|
|
context->Service = Service;
|
|
context->FileName = PhDuplicateString(FileName);
|
|
context->BaseFileName = PhGetBaseName(context->FileName);
|
|
|
|
if (dialogThread = PhCreateThread(0, PhUploadToDialogThreadStart, (PVOID)context))
|
|
NtClose(dialogThread);
|
|
} |