29 {
UPLOAD_SERVICE_JOTTI, L
"virusscan.jotti.org", INTERNET_DEFAULT_HTTP_PORT, 0, L
"/processupload.php", L
"scanfile" },
30 {
UPLOAD_SERVICE_CIMA, L
"camas.comodo.com", INTERNET_DEFAULT_HTTP_PORT, 0, L
"/cgi-bin/submit", L
"file" }
33 static HFONT InitializeFont(
38 NONCLIENTMETRICS metrics = {
sizeof(NONCLIENTMETRICS) };
40 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0))
42 metrics.lfMessageFont.lfHeight = -15;
46 fontHandle = CreateFontIndirect(&metrics.lfMessageFont);
52 GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT),
sizeof(LOGFONT), &font);
56 fontHandle = CreateFontIndirect(&font);
59 SendMessage(hwnd, WM_SETFONT, (WPARAM)fontHandle,
TRUE);
64 static BOOL ReadRequestString(
65 _In_ HINTERNET Handle,
66 _Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
67 _Out_ ULONG *DataLength
72 ULONG allocatedLength;
76 allocatedLength =
sizeof(buffer);
77 data = (PSTR)PhAllocate(allocatedLength);
83 while (WinHttpReadData(Handle, buffer,
PAGE_SIZE, &returnLength))
85 if (returnLength == 0)
88 if (allocatedLength < dataLength + returnLength)
91 data = (PSTR)PhReAllocate(data, allocatedLength);
95 memcpy(data + dataLength, buffer, returnLength);
99 dataLength += returnLength;
102 if (allocatedLength < dataLength + 1)
105 data = (PSTR)PhReAllocate(data, allocatedLength);
109 data[dataLength] = 0;
111 *DataLength = dataLength;
117 static VOID RaiseUploadError(
123 if (Context->DialogHandle)
126 Context->DialogHandle,
140 for (i = 0; i < _countof(UploadServiceInfo); i++)
142 if (UploadServiceInfo[i].Id == Id)
143 return &UploadServiceInfo[i];
149 static BOOLEAN PerformSubRequest(
152 _In_ PWSTR ObjectName,
153 _Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
154 _Out_opt_ PULONG DataLength
157 BOOLEAN result =
FALSE;
158 HINTERNET connectHandle = NULL;
159 HINTERNET requestHandle = NULL;
164 if (!(connectHandle = WinHttpConnect(
167 INTERNET_DEFAULT_HTTP_PORT,
171 RaiseUploadError(Context, L
"Unable to connect to the service", GetLastError());
176 if (!(requestHandle = WinHttpOpenRequest(
182 WINHTTP_DEFAULT_ACCEPT_TYPES,
186 RaiseUploadError(Context, L
"Unable to create the request", GetLastError());
191 if (!WinHttpSendRequest(requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
193 RaiseUploadError(Context, L
"Unable to send the request", GetLastError());
198 if (WinHttpReceiveResponse(requestHandle, NULL))
202 ULONG allocatedLength;
206 allocatedLength =
sizeof(buffer);
207 data = PhAllocate(allocatedLength);
210 while (WinHttpReadData(requestHandle, buffer,
PAGE_SIZE, &returnLength))
212 if (returnLength == 0)
215 if (allocatedLength < dataLength + returnLength)
217 allocatedLength *= 2;
218 data = PhReAllocate(data, allocatedLength);
221 memcpy(data + dataLength, buffer, returnLength);
222 dataLength += returnLength;
225 if (allocatedLength < dataLength + 1)
228 data = PhReAllocate(data, allocatedLength);
232 data[dataLength] = 0;
238 *DataLength = dataLength;
243 RaiseUploadError(Context, L
"Unable to receive the response", GetLastError());
252 WinHttpCloseHandle(requestHandle);
254 WinHttpCloseHandle(connectHandle);
260 static NTSTATUS HashFileAndResetPosition(
261 _In_ HANDLE FileHandle,
262 _In_ PLARGE_INTEGER FileSize,
263 _In_ ULONG Algorithm,
271 ULONG64 bytesRemaining;
275 bytesRemaining = FileSize->QuadPart;
287 while (bytesRemaining)
317 if (status == STATUS_END_OF_FILE)
318 status = STATUS_SUCCESS;
345 static NTSTATUS UploadFileThreadStart(
349 NTSTATUS status = STATUS_SUCCESS;
350 ULONG httpStatus = 0;
351 ULONG httpStatusLength =
sizeof(ULONG);
352 ULONG httpPostSeed = 0;
353 ULONG totalUploadLength = 0;
354 ULONG totalUploadedLength = 0;
355 ULONG totalPostHeaderWritten = 0;
356 ULONG totalPostFooterWritten = 0;
357 ULONG totalWriteLength = 0;
358 LARGE_INTEGER timeNow;
359 LARGE_INTEGER timeStart;
360 ULONG64 timeTicks = 0;
361 ULONG64 timeBitsPerSecond = 0;
363 HANDLE fileHandle = INVALID_HANDLE_VALUE;
366 HINTERNET connectHandle = NULL;
367 HINTERNET requestHandle = NULL;
379 serviceInfo = GetUploadServiceInfo(context->
Service);
389 FILE_SHARE_READ | FILE_SHARE_DELETE,
401 if (!(connectHandle = WinHttpConnect(
408 RaiseUploadError(context, L
"Unable to connect to the service", GetLastError());
413 if (!(requestHandle = WinHttpOpenRequest(
419 WINHTTP_DEFAULT_ACCEPT_TYPES,
420 WINHTTP_FLAG_REFRESH | serviceInfo->
HostFlags
423 RaiseUploadError(context, L
"Unable to create the request", GetLastError());
438 L
"------------------------%I64u",
443 L
"Content-Type: multipart/form-data; boundary=%s\r\n",
452 L
"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
457 L
"Content-Type: application/octet-stream\r\n\r\n"
461 L
"\r\n--%s--\r\n\r\n",
466 if (!WinHttpAddRequestHeaders(requestHandle,
469 WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD
472 RaiseUploadError(context, L
"Unable to add request headers", GetLastError());
480 if (!WinHttpSendRequest(requestHandle,
481 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
482 WINHTTP_NO_REQUEST_DATA, 0,
486 RaiseUploadError(context, L
"Unable to send the request", GetLastError());
498 if (!WinHttpWriteData(
501 (ULONG)asciiPostData->
Length,
502 &totalPostHeaderWritten
505 RaiseUploadError(context, L
"Unable to write the post header", GetLastError());
527 if (!WinHttpWriteData(requestHandle, buffer, (ULONG)isb.
Information, &totalWriteLength))
529 RaiseUploadError(context, L
"Unable to upload the file data", GetLastError());
533 totalUploadedLength += totalWriteLength;
538 timeBitsPerSecond = totalUploadedLength / __max(timeTicks, 1);
541 FLOAT percent = ((FLOAT)totalUploadedLength / context->
TotalFileLength * 100);
548 totalDownloadedLength->
Buffer,
561 PostMessage(context->
ProgressHandle, PBM_SETPOS, (INT)percent, 0);
566 if (!WinHttpWriteData(
569 (ULONG)asciiFooterData->
Length,
570 &totalPostFooterWritten
573 RaiseUploadError(context, L
"Unable to write the post footer", GetLastError());
578 if (!WinHttpReceiveResponse(requestHandle, NULL))
580 RaiseUploadError(context, L
"Unable to receive the response", GetLastError());
587 WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
594 if (httpStatus == HTTP_STATUS_OK || httpStatus == HTTP_STATUS_REDIRECT_METHOD || httpStatus == HTTP_STATUS_REDIRECT)
600 ULONG bufferLength = 0;
603 if (!WinHttpQueryOption(requestHandle, WINHTTP_OPTION_URL, NULL, &bufferLength))
608 if (WinHttpQueryOption(requestHandle, WINHTTP_OPTION_URL, buffer->
Buffer, &bufferLength))
620 PSTR hrefEquals = NULL;
623 ULONG bufferLength = 0;
626 if (!ReadRequestString(requestHandle, &buffer, &bufferLength))
628 RaiseUploadError(context, L
"Unable to complete the request", GetLastError());
633 hrefEquals = strstr(buffer,
"href=\"");
637 quote = strchr(hrefEquals,
'"');
642 L
"http://virusscan.jotti.org%.*S",
650 PSTR tooManyFiles = strstr(buffer,
"Too many files");
656 L
"Unable to scan the file:\n\n"
657 L
"Too many files have been scanned from this IP in a short period. "
658 L
"Please try again later",
669 PSTR urlEquals = NULL;
672 ULONG bufferLength = 0;
675 if (!ReadRequestString(requestHandle, &buffer, &bufferLength))
677 RaiseUploadError(context, L
"Unable to complete the CIMA request", GetLastError());
683 urlEquals = strstr(buffer,
"url=");
688 quote = strchr(urlEquals,
'"');
693 L
"http://camas.comodo.com%.*S",
705 RaiseUploadError(context, L
"Unable to complete the request", STATUS_FVE_PARTIAL_METADATA);
715 RaiseUploadError(context, L
"Unable to complete the Launch request (please try again after a few minutes)", ERROR_INVALID_DATA);
736 if (httpPostFooter.
String)
741 if (httpPostHeader.
String)
746 if (httpRequestHeaders.
String)
751 if (fileHandle != INVALID_HANDLE_VALUE)
760 static NTSTATUS UploadCheckThreadStart(
764 NTSTATUS status = STATUS_SUCCESS;
765 BOOLEAN fileExists =
FALSE;
766 LARGE_INTEGER fileSize64;
767 PSTR subRequestBuffer = NULL;
768 HINTERNET connectHandle = NULL;
769 HINTERNET requestHandle = NULL;
773 HANDLE fileHandle = INVALID_HANDLE_VALUE;
777 serviceInfo = GetUploadServiceInfo(context->
Service);
787 FILE_SHARE_READ | FILE_SHARE_DELETE,
802 if (fileSize64.QuadPart > 128 * 1024 * 1024)
804 RaiseUploadError(context, L
"The file is too large (over 128 MB)", ERROR_FILE_TOO_LARGE);
810 if (fileSize64.QuadPart > 20 * 1024 * 1024)
812 RaiseUploadError(context, L
"The file is too large (over 20 MB)", ERROR_FILE_TOO_LARGE);
824 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
831 WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
836 proxyConfig.lpszProxy != NULL ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
837 proxyConfig.lpszProxy,
838 proxyConfig.lpszProxyBypass,
853 PSTR uploadUrl = NULL;
855 ULONG bufferLength = 0;
858 status = HashFileAndResetPosition(fileHandle, &fileSize64,
HASH_SHA256, hash);
869 if (!PerformSubRequest(context, serviceInfo->
HostName, subObjectName->
Buffer, &subRequestBuffer, &bufferLength))
872 if (strstr(subRequestBuffer,
"\"file_exists\": true"))
877 uploadUrl = strstr(subRequestBuffer,
"\"upload_url\": \"https://www.virustotal.com");
880 RaiseUploadError(context, L
"Unable to complete the request (no upload URL provided)", ERROR_INVALID_DATA);
885 quote = strchr(uploadUrl,
'"');
888 RaiseUploadError(context, L
"Unable to complete the request (invalid upload URL)", ERROR_INVALID_DATA);
901 PSTR uploadId = NULL;
903 ULONG bufferLength = 0;
906 status = HashFileAndResetPosition(fileHandle, &fileSize64,
HASH_SHA1, hash);
916 if (!PerformSubRequest(context, serviceInfo->
HostName, subObjectName->
Buffer, &subRequestBuffer, &bufferLength))
919 if (uploadId = strstr(subRequestBuffer,
"\"id\":"))
922 quote = strchr(uploadId,
'"');
939 ULONG bufferLength = 0;
942 ULONG statusLength =
sizeof(statusLength);
944 status = HashFileAndResetPosition(fileHandle, &fileSize64,
HASH_SHA256, hash);
956 if (!(connectHandle = WinHttpConnect(
959 INTERNET_DEFAULT_HTTP_PORT,
963 RaiseUploadError(context, L
"Unable to connect to the CIMA service", GetLastError());
968 if (!(requestHandle = WinHttpOpenRequest(
974 WINHTTP_DEFAULT_ACCEPT_TYPES,
978 RaiseUploadError(context, L
"Unable to create the CIMA request", GetLastError());
983 if (!WinHttpSendRequest(requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
985 RaiseUploadError(context, L
"Unable to send the CIMA request", GetLastError());
990 if (!WinHttpReceiveResponse(requestHandle, NULL))
992 RaiseUploadError(context, L
"Unable to recieve the CIMA response", GetLastError());
998 WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
1005 if (status == HTTP_STATUS_OK)
1027 if (!
NT_SUCCESS(UploadFileThreadStart(context)))
1037 WinHttpCloseHandle(requestHandle);
1042 WinHttpCloseHandle(connectHandle);
1045 if (fileHandle != INVALID_HANDLE_VALUE)
1047 NtClose(fileHandle);
1054 static INT_PTR CALLBACK UploadDlgProc(
1063 if (uMsg == WM_INITDIALOG)
1066 SetProp(hwndDlg, L
"Context", (HANDLE)context);
1072 if (uMsg == WM_NCDESTROY)
1086 RemoveProp(hwndDlg, L
"Context");
1098 HANDLE dialogThread = NULL;
1099 HWND parentWindow = GetParent(hwndDlg);
1101 PhCenterWindow(hwndDlg, (IsWindowVisible(parentWindow) && !IsIconic(parentWindow)) ? parentWindow : NULL);
1117 Static_SetText(hwndDlg, L
"Uploading to VirusTotal...");
1120 Static_SetText(hwndDlg, L
"Uploading to Jotti...");
1123 Static_SetText(hwndDlg, L
"Uploading to Comodo...");
1127 if (dialogThread =
PhCreateThread(0, UploadCheckThreadStart, (PVOID)context))
1128 NtClose(dialogThread);
1133 switch (LOWORD(wParam))
1151 HANDLE dialogThread = NULL;
1158 Static_SetText(GetDlgItem(hwndDlg, IDNO), L
"Cancel");
1162 if (dialogThread =
PhCreateThread(0, UploadFileThreadStart, (PVOID)context))
1163 NtClose(dialogThread);
1181 case WM_CTLCOLORBTN:
1182 case WM_CTLCOLORDLG:
1183 case WM_CTLCOLORSTATIC:
1185 HDC hDC = (HDC)wParam;
1186 HWND hwndChild = (HWND)lParam;
1191 SetTextColor(hDC, RGB(19, 112, 171));
1195 SetBkMode(hDC, TRANSPARENT);
1198 return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
1205 Static_SetText(GetDlgItem(hwndDlg, IDNO), L
"No");
1208 Static_SetText(context->
MessageHandle, L
"File already analysed.");
1209 Static_SetText(context->
StatusHandle, L
"View existing report?");
1237 Static_SetText(GetDlgItem(hwndDlg,
IDC_MESSAGE), L
"Error");
1240 Static_SetText(GetDlgItem(hwndDlg,
IDC_STATUS), L
"");
1241 Static_SetText(GetDlgItem(hwndDlg, IDNO), L
"Close");
1249 static NTSTATUS PhUploadToDialogThreadStart(
1250 _In_ PVOID Parameter
1261 dialogHandle = CreateDialogParam(
1269 ShowWindow(dialogHandle, SW_SHOW);
1270 SetForegroundWindow(dialogHandle);
1272 while (result = GetMessage(&message, NULL, 0, 0))
1277 if (!IsDialogMessage(dialogHandle, &message))
1279 TranslateMessage(&message);
1280 DispatchMessage(&message);
1287 DestroyWindow(dialogHandle);
1289 return STATUS_SUCCESS;
1297 HANDLE dialogThread = NULL;
1307 if (dialogThread =
PhCreateThread(0, PhUploadToDialogThreadStart, (PVOID)context))
1308 NtClose(dialogThread);