I have it working, thanks @RLWA32 , but it seems *SRWLockShared functions failed and only the *SRWLockExclusive worked as intended.

// thread_sync_exercise.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <windows.h>
#include <wininet.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#pragma comment(lib, "wininet.lib")
HANDLE g_fileHandle;
HINTERNET g_hUrl;
HINTERNET g_hInternet;
WCHAR g_status[] = L"START";
// Shared resource
uint64_t global_shared_data = 0;
SRWLOCK g_srw_lock; // Declare the SRW lock globally
struct ForCreateThread {
HANDLE handle_to_file;
HINTERNET hUrl;
HINTERNET hInternet;
//const char* url;
//const char* outputPath;
};
// A function that reads the shared data
DWORD WINAPI ReadSharedData() {
// Acquire the lock for shared access
// No need to initialize here if already done by the main thread
while (wcscmp(g_status, L"COMPLETE") != 0) {
//while (TRUE) {
if (::TryAcquireSRWLockExclusive(&g_srw_lock)) {
//printf("ReadSharedData Acquired\n");
::AcquireSRWLockExclusive(&g_srw_lock);
}
else {
//printf("ReadSharedData failed to acquire\n");
}
// Shared section: Multiple threads can be here at the same time
std::cout << "Thread ID: " << GetCurrentThreadId() << " Total Bytes Downloaded: " << global_shared_data << " (Print Process)\n" << std::endl;
// Release the lock
::ReleaseSRWLockExclusive(&g_srw_lock);
::Sleep(15000);
}
return 42;
}
DWORD WINAPI DownloadFile(LPVOID lpParam) {
ForCreateThread* params = static_cast<ForCreateThread*>(lpParam);
HINTERNET hInternet = params->hInternet;
HINTERNET hUrl = params->hUrl;
BOOL success = FALSE;
DWORD bytesRead = 0;
BYTE buffer[4096];
DWORD bytesWritten = 0;
HANDLE hFile = params->handle_to_file;
//const char* outputPath = params->outputPath;
//const char* url = params->url;
// Read data from URL and write to file
while (::InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
if (!::WriteFile(g_fileHandle, buffer, bytesRead, &bytesWritten, NULL)) {
printf("WriteFile failed: %lu\n", GetLastError());
//goto cleanup;
}
if (::TryAcquireSRWLockExclusive(&g_srw_lock)) {
//printf("DownloadFile acquired\n");
::AcquireSRWLockExclusive(&g_srw_lock);
}
else {
// printf("DownloadFile Failed to acquire\n");
}
global_shared_data = global_shared_data + (uint64_t)bytesWritten;
printf("Thread ID: %lu (Download Process)\n", GetCurrentThreadId());
// Release the lock
::ReleaseSRWLockExclusive(&g_srw_lock);
::Sleep(10000);
}
printf("\nDownload completed successfully!\n");
wcscpy_s(g_status, 20, L"COMPLETE");
printf("gloabl status: %ws", g_status);
return 42;
}
int main() {
::InitializeSRWLock(&g_srw_lock); // Initialize only once in a real application
const char* url = "http://127.0.0.1:8000/a-guide-to-kernel-exploitation.pdf";
const char* outputPath = "downloaded_file.pdf";
BOOL success = FALSE;
DWORD bytesRead = 0;
BYTE buffer[4096];
DWORD bytesWritten = 0;
// Initialize WinINet
g_hInternet = ::InternetOpenA("WinINet Downloader/1.0",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if (!g_hInternet) {
printf("InternetOpenA failed: %lu\n", GetLastError());
//goto cleanup;
}
// Open URL
g_hUrl = ::InternetOpenUrlA(g_hInternet, url, NULL, 0,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, 0);
if (!g_hUrl) {
printf("InternetOpenUrlA failed: %lu\n", GetLastError());
//goto cleanup;
}
// Create output file
g_fileHandle = ::CreateFile(
L"downloaded_file.pdf",
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);//https://stackoverflow.com/questions/1576187/can-createfile-open-one-file-at-the-same-time-in-two-different-thread
if (g_fileHandle == INVALID_HANDLE_VALUE) {
printf("CreateFileA failed: %lu\n", GetLastError());
//goto cleanup;
return 1;
}
printf("Downloading %s to %s...\n", url, outputPath);
ForCreateThread* params = new ForCreateThread();
params->handle_to_file = g_fileHandle;
//params->url = "http://127.0.0.1:8000/a-guide-to-kernel-exploitation.pdf";
//params->outputPath = "a-guide-to-kernel-exploitation.pdf";
params->hUrl = g_hUrl;
params->hInternet = g_hInternet;
HANDLE hThread[2];
hThread[0] = CreateThread(
NULL, // Default security attributes
0, // Default stack size
(LPTHREAD_START_ROUTINE)DownloadFile, // Thread function
(LPVOID)params, // Pointer to the parameters structure
0, // Default creation flags
NULL // Don't need thread ID
);
hThread[1] = CreateThread(
NULL, // Default security attributes
0, // Default stack size
(LPTHREAD_START_ROUTINE)ReadSharedData, // Thread function
NULL, // Pointer to the parameters structure
0, // Default creation flags
NULL // Don't need thread ID
);
// Wait for all three threads to finish
WaitForMultipleObjects(
2, // number of objects in the array
hThread, // array of object handles
TRUE, // bWaitAll: TRUE to wait for all objects to be signaled
INFINITE // dwMilliseconds: INFINITE to wait indefinitely
);
::CloseHandle(hThread[0]);
::CloseHandle(hThread[1]);
return 0;
}
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu
// Tips for Getting Started:
// 1. Use the Solution Explorer window to add/manage files
// 2. Use the Team Explorer window to connect to source control
// 3. Use the Output window to see build output and other messages
// 4. Use the Error List window to view errors
// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file