Skip to content

Instantly share code, notes, and snippets.

@justaguywhocodes
Created March 24, 2025 14:33
Show Gist options
  • Save justaguywhocodes/be153f53c864f095e91e93b51438cc24 to your computer and use it in GitHub Desktop.
Save justaguywhocodes/be153f53c864f095e91e93b51438cc24 to your computer and use it in GitHub Desktop.
Here's the updated DLL code that includes proxy authentication. I'll modify it to include proxy settings and credentials:
```cpp
// FileDownloadDLL.cpp
#include <windows.h>
#include <winhttp.h>
#include <string>
#pragma comment(lib, "winhttp.lib")
#ifdef FILEDOWNLOADDLL_EXPORTS
#define FILEDOWNLOADDLL_API __declspec(dllexport)
#else
#define FILEDOWNLOADDLL_API __declspec(dllimport)
#endif
// Structure to hold proxy credentials
struct ProxyConfig {
const wchar_t* proxyAddress; // e.g., L"proxy.mydomain.com:8080"
const wchar_t* username; // Proxy username
const wchar_t* password; // Proxy password
};
// Function to download file with proxy authentication
extern "C" FILEDOWNLOADDLL_API BOOL DownloadFileWithProxy(
const wchar_t* url,
const wchar_t* outputPath,
const ProxyConfig* proxyConfig)
{
BOOL bResult = FALSE;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
// Initialize WinHTTP with proxy settings
hSession = WinHttpOpen(L"FileDownloadDLL/1.0",
WINHTTP_ACCESS_TYPE_NAMED_PROXY,
proxyConfig->proxyAddress,
WINHTTP_NO_PROXY_BYPASS,
0);
if (!hSession) goto cleanup;
// Set proxy credentials if provided
if (proxyConfig->username && proxyConfig->password) {
WinHttpSetCredentials(hSession,
WINHTTP_AUTH_TARGET_PROXY,
WINHTTP_AUTH_SCHEME_BASIC,
proxyConfig->username,
proxyConfig->password,
NULL);
}
// Parse URL components
URL_COMPONENTS urlComp = {0};
urlComp.dwStructSize = sizeof(urlComp);
urlComp.dwSchemeLength = (DWORD)-1;
urlComp.dwHostNameLength = (DWORD)-1;
urlComp.dwUrlPathLength = (DWORD)-1;
if (!WinHttpCrackUrl(url, 0, 0, &urlComp)) goto cleanup;
// Extract hostname
std::wstring hostName(urlComp.lpszHostName, urlComp.dwHostNameLength);
// Connect to server through proxy
hConnect = WinHttpConnect(hSession, hostName.c_str(), INTERNET_DEFAULT_HTTP_PORT, 0);
if (!hConnect) goto cleanup;
// Create HTTP request
std::wstring urlPath(urlComp.lpszUrlPath, urlComp.dwUrlPathLength);
hRequest = WinHttpOpenRequest(hConnect,
L"GET",
urlPath.c_str(),
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
if (!hRequest) goto cleanup;
// Send request
if (!WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0)) {
// Handle proxy authentication if required
DWORD dwStatusCode = 0;
DWORD dwStatusCodeSize = sizeof(dwStatusCode);
WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
WINHTTP_HEADER_NAME_BY_INDEX,
&dwStatusCode,
&dwStatusCodeSize,
WINHTTP_NO_HEADER_INDEX);
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ) {
if (!proxyConfig->username || !proxyConfig->password) {
goto cleanup; // No credentials provided
}
// Retry with credentials
WinHttpSetCredentials(hRequest,
WINHTTP_AUTH_TARGET_PROXY,
WINHTTP_AUTH_SCHEME_BASIC,
proxyConfig->username,
proxyConfig->password,
NULL);
if (!WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0)) {
goto cleanup;
}
} else {
goto cleanup;
}
}
// Receive response
if (!WinHttpReceiveResponse(hRequest, NULL)) goto cleanup;
// Create output file
hFile = CreateFileW(outputPath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) goto cleanup;
// Download and write file
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
BYTE buffer[4096];
do {
if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) break;
if (dwSize == 0) break;
if (!WinHttpReadData(hRequest, buffer, dwSize, &dwDownloaded)) break;
DWORD dwWritten;
WriteFile(hFile, buffer, dwDownloaded, &dwWritten, NULL);
} while (dwSize > 0);
bResult = TRUE;
cleanup:
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
return bResult;
}
// DLL entry point
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
```
Updated header file:
```cpp
// FileDownloadDLL.h
#pragma once
#ifdef FILEDOWNLOADDLL_EXPORTS
#define FILEDOWNLOADDLL_API __declspec(dllexport)
#else
#define FILEDOWNLOADDLL_API __declspec(dllimport)
#endif
struct ProxyConfig {
const wchar_t* proxyAddress;
const wchar_t* username;
const wchar_t* password;
};
extern "C" FILEDOWNLOADDLL_API BOOL DownloadFileWithProxy(
const wchar_t* url,
const wchar_t* outputPath,
const ProxyConfig* proxyConfig);
```
Example usage:
```cpp
#include "FileDownloadDLL.h"
int main()
{
ProxyConfig proxy = {
L"proxy.mydomain.com:8080", // Proxy address and port
L"proxyUsername", // Proxy username
L"proxyPassword" // Proxy password
};
BOOL result = DownloadFileWithProxy(
L"http://myserver.com",
L"C:\\path\\to\\output.bin",
&proxy);
return result ? 0 : 1;
}
```
Key changes and features:
1. Changed access type to `WINHTTP_ACCESS_TYPE_NAMED_PROXY`
2. Added `ProxyConfig` structure to pass proxy details
3. Added proxy authentication support using `WinHttpSetCredentials`
4. Handles proxy authentication challenges (HTTP 407)
5. Supports BASIC authentication scheme (most common for proxies)
6. Maintains the original file download functionality
Notes:
- Replace "proxy.mydomain.com:8080" with your actual proxy address and port
- Use your actual proxy username and password
- This uses BASIC authentication; some proxies might require NTLM or other schemes
- For HTTPS proxies, you might need to add `WINHTTP_FLAG_SECURE` to `WinHttpOpenRequest`
- Error handling could be enhanced to provide specific proxy-related error codes
- The proxy credentials are optional - if NULL, it will attempt without authentication first
To compile, follow the same steps as before, ensuring `FILEDOWNLOADDLL_EXPORTS` is defined in the project settings and linking against `winhttp.lib`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment