Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save justaguywhocodes/7f9ec3e6f9f8a30470c280d0cc787dcb to your computer and use it in GitHub Desktop.
Save justaguywhocodes/7f9ec3e6f9f8a30470c280d0cc787dcb to your computer and use it in GitHub Desktop.
Here's the modified DLL that makes the download call when a thread attaches to the DLL. I've moved the download logic into a separate function and added the call in DllMain during DLL_THREAD_ATTACH:
```cpp
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
// Define default parameters as constants
const wchar_t* DEFAULT_PROXY_ADDRESS = L"proxy.example.com";
const DWORD DEFAULT_PROXY_PORT = 8080;
const wchar_t* DEFAULT_PROXY_USERNAME = L"username";
const wchar_t* DEFAULT_PROXY_PASSWORD = L"password";
const wchar_t* DEFAULT_OUTPUT_PATH = L"C:\\downloaded_file.txt";
BOOL PerformDownload(
LPCWSTR proxyAddress,
DWORD proxyPort,
LPCWSTR proxyUsername,
LPCWSTR proxyPassword,
LPCWSTR outputFilePath
) {
BOOL bResult = FALSE;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
// Initialize WinHTTP session
hSession = WinHttpOpen(
L"FileDownloader/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0
);
if (!hSession) goto cleanup;
// Set up proxy information
WINHTTP_PROXY_INFO proxyInfo = {0};
proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
proxyInfo.lpszProxy = (LPWSTR)proxyAddress;
proxyInfo.lpszProxyBypass = NULL;
if (!WinHttpSetOption(
hSession,
WINHTTP_OPTION_PROXY,
&proxyInfo,
sizeof(proxyInfo)
)) goto cleanup;
// Set proxy credentials if provided
if (proxyUsername && proxyPassword) {
WinHttpSetCredentials(
hSession,
WINHTTP_AUTH_TARGET_PROXY,
WINHTTP_AUTH_SCHEME_BASIC,
proxyUsername,
proxyPassword,
NULL
);
}
// Connect to the server
hConnect = WinHttpConnect(
hSession,
L"test.com",
INTERNET_DEFAULT_HTTPS_PORT,
0
);
if (!hConnect) goto cleanup;
// Create HTTP request
hRequest = WinHttpOpenRequest(
hConnect,
L"GET",
L"/file.txt",
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE
);
if (!hRequest) goto cleanup;
// Send request
if (!WinHttpSendRequest(
hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0
)) goto cleanup;
// Receive response
if (!WinHttpReceiveResponse(hRequest, NULL)) goto cleanup;
// Check status code
DWORD statusCode = 0;
DWORD statusCodeSize = sizeof(statusCode);
WinHttpQueryHeaders(
hRequest,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&statusCode,
&statusCodeSize,
NULL
);
if (statusCode != 200) goto cleanup;
// Create output file
hFile = CreateFileW(
outputFilePath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) goto cleanup;
// Download and write file
DWORD bytesRead = 0;
BYTE buffer[4096];
while (WinHttpReadData(hRequest, buffer, sizeof(buffer), &bytesRead)) {
if (bytesRead == 0) break;
DWORD bytesWritten;
WriteFile(hFile, buffer, bytesRead, &bytesWritten, NULL);
}
bResult = TRUE;
cleanup:
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
return bResult;
}
// Still exporting the function for manual calls if needed
extern "C" {
__declspec(dllexport) BOOL DownloadFile(
LPCWSTR proxyAddress,
DWORD proxyPort,
LPCWSTR proxyUsername,
LPCWSTR proxyPassword,
LPCWSTR outputFilePath
) {
return PerformDownload(proxyAddress, proxyPort, proxyUsername, proxyPassword, outputFilePath);
}
}
// DLL entry point with thread attach handling
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
// Initialize any process-wide resources if needed
break;
case DLL_THREAD_ATTACH:
// Perform download when a thread attaches
PerformDownload(
DEFAULT_PROXY_ADDRESS,
DEFAULT_PROXY_PORT,
DEFAULT_PROXY_USERNAME,
DEFAULT_PROXY_PASSWORD,
DEFAULT_OUTPUT_PATH
);
break;
case DLL_THREAD_DETACH:
// Clean up thread-specific resources if needed
break;
case DLL_PROCESS_DETACH:
// Clean up process-wide resources if needed
break;
}
return TRUE;
}
```
Key changes made:
1. Moved the download logic into a separate `PerformDownload` function
2. Added default constants for proxy settings and output path
3. Implemented the download call in `DLL_THREAD_ATTACH` case of DllMain
4. Kept the exported `DownloadFile` function for manual calls
5. Maintained proper resource cleanup
Important notes:
1. Be cautious with operations in DllMain:
- Windows imposes restrictions on what can be safely done in DllMain
- Network operations like this might be problematic in some scenarios
- Consider using a separate thread or initialization function instead if you encounter issues
2. The default parameters are hardcoded as constants
- You should replace them with your actual proxy details
- Consider making them configurable if needed
3. Error handling:
- The function returns BOOL but doesn't provide detailed error information
- You might want to add logging or error reporting if needed
To use this DLL:
- When any thread attaches to the DLL, it will automatically attempt to download the file
- You can still call DownloadFile manually if needed
- Make sure to update the DEFAULT_ constants with your actual proxy settings
If you need a different approach (like moving the download to a separate thread or adding configuration options), let me know!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment