Windows: Make it easier to run on NT 3.51

This commit is contained in:
UnknownShadow200 2022-03-20 22:59:03 +11:00
parent 305649bda6
commit e467ae89da
3 changed files with 52 additions and 36 deletions

View File

@ -351,7 +351,7 @@ static void Http_SetCurlOpts(struct HttpRequest* req) {
} }
static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) { static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) {
wchar_t urlStr[NATIVE_STR_LEN]; char urlStr[NATIVE_STR_LEN];
void* post_data = req->data; void* post_data = req->data;
CURLcode res; CURLcode res;
if (!curlSupported) return ERR_NOT_SUPPORTED; if (!curlSupported) return ERR_NOT_SUPPORTED;
@ -402,6 +402,7 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) {
#define _UNICODE #define _UNICODE
#endif #endif
#include <windows.h> #include <windows.h>
#include "Errors.h"
/* === BEGIN wininet.h === */ /* === BEGIN wininet.h === */
#define INETAPI DECLSPEC_IMPORT #define INETAPI DECLSPEC_IMPORT
@ -427,17 +428,17 @@ typedef WORD INTERNET_PORT;
#define HTTP_QUERY_RAW_HEADERS 21 #define HTTP_QUERY_RAW_HEADERS 21
#define INTERNET_OPTION_SECURITY_FLAGS 31 #define INTERNET_OPTION_SECURITY_FLAGS 31
INETAPI BOOL WINAPI InternetCloseHandle(HINTERNET hInternet); static BOOL (WINAPI *_InternetCloseHandle)(HINTERNET hInternet);
INETAPI HINTERNET WINAPI InternetConnectA(HINTERNET hInternet, PCSTR serverName, INTERNET_PORT serverPort, PCSTR userName, PCSTR password, DWORD service, DWORD flags, DWORD_PTR context); static HINTERNET (WINAPI *_InternetConnectA)(HINTERNET hInternet, PCSTR serverName, INTERNET_PORT serverPort, PCSTR userName, PCSTR password, DWORD service, DWORD flags, DWORD_PTR context);
INETAPI HINTERNET WINAPI InternetOpenA(PCSTR agent, DWORD accessType, PCSTR lpszProxy, PCSTR proxyBypass, DWORD flags); static HINTERNET (WINAPI *_InternetOpenA)(PCSTR agent, DWORD accessType, PCSTR lpszProxy, PCSTR proxyBypass, DWORD flags);
INETAPI BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD option, PVOID buffer, DWORD* bufferLength); static BOOL (WINAPI *_InternetQueryOptionA)(HINTERNET hInternet, DWORD option, PVOID buffer, DWORD* bufferLength);
INETAPI BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD option, PVOID buffer, DWORD bufferLength); static BOOL (WINAPI *_InternetSetOptionA)(HINTERNET hInternet, DWORD option, PVOID buffer, DWORD bufferLength);
INETAPI BOOL WINAPI InternetQueryDataAvailable(HINTERNET hFile, DWORD* numBytesAvailable, DWORD flags, DWORD_PTR context); static BOOL (WINAPI *_InternetQueryDataAvailable)(HINTERNET hFile, DWORD* numBytesAvailable, DWORD flags, DWORD_PTR context);
INETAPI BOOL WINAPI InternetReadFile(HINTERNET hFile, PVOID buffer, DWORD numBytesToRead, DWORD* numBytesRead); static BOOL (WINAPI *_InternetReadFile)(HINTERNET hFile, PVOID buffer, DWORD numBytesToRead, DWORD* numBytesRead);
INETAPI BOOL WINAPI HttpQueryInfoA(HINTERNET hRequest, DWORD infoLevel, PVOID buffer, DWORD* bufferLength, DWORD* index); static BOOL (WINAPI *_HttpQueryInfoA)(HINTERNET hRequest, DWORD infoLevel, PVOID buffer, DWORD* bufferLength, DWORD* index);
INETAPI BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hRequest, PCSTR headers, DWORD headersLength, DWORD modifiers); static BOOL (WINAPI *_HttpAddRequestHeadersA)(HINTERNET hRequest, PCSTR headers, DWORD headersLength, DWORD modifiers);
INETAPI HINTERNET WINAPI HttpOpenRequestA(HINTERNET hConnect, PCSTR verb, PCSTR objectName, PCSTR version, PCSTR referrer, PCSTR* acceptTypes, DWORD flags, DWORD_PTR context); static HINTERNET (WINAPI *_HttpOpenRequestA)(HINTERNET hConnect, PCSTR verb, PCSTR objectName, PCSTR version, PCSTR referrer, PCSTR* acceptTypes, DWORD flags, DWORD_PTR context);
INETAPI BOOL WINAPI HttpSendRequestA(HINTERNET hRequest, PCSTR headers, DWORD headersLength, PVOID optional, DWORD optionalLength); static BOOL (WINAPI *_HttpSendRequestA)(HINTERNET hRequest, PCSTR headers, DWORD headersLength, PVOID optional, DWORD optionalLength);
/* === END wininet.h === */ /* === END wininet.h === */
/* caches connections to web servers */ /* caches connections to web servers */
@ -498,7 +499,7 @@ static void HttpCache_MakeEntry(const cc_string* url, struct HttpCacheEntry* ent
/* Inserts entry into the cache at the given index */ /* Inserts entry into the cache at the given index */
static cc_result HttpCache_Insert(int i, struct HttpCacheEntry* e) { static cc_result HttpCache_Insert(int i, struct HttpCacheEntry* e) {
HINTERNET conn; HINTERNET conn;
conn = InternetConnectA(hInternet, e->Address.buffer, e->Port, NULL, NULL, conn = _InternetConnectA(hInternet, e->Address.buffer, e->Port, NULL, NULL,
INTERNET_SERVICE_HTTP, e->Https ? INTERNET_FLAG_SECURE : 0, 0); INTERNET_SERVICE_HTTP, e->Https ? INTERNET_FLAG_SECURE : 0, 0);
if (!conn) return GetLastError(); if (!conn) return GetLastError();
@ -530,17 +531,31 @@ static cc_result HttpCache_Lookup(struct HttpCacheEntry* e) {
/* TODO: Should we be consistent in which entry gets evicted? */ /* TODO: Should we be consistent in which entry gets evicted? */
i = (cc_uint8)Stopwatch_Measure() % HTTP_CACHE_ENTRIES; i = (cc_uint8)Stopwatch_Measure() % HTTP_CACHE_ENTRIES;
InternetCloseHandle(http_cache[i].Handle); _InternetCloseHandle(http_cache[i].Handle);
return HttpCache_Insert(i, e); return HttpCache_Insert(i, e);
} }
static void* wininet_lib;
cc_bool Http_DescribeError(cc_result res, cc_string* dst) { cc_bool Http_DescribeError(cc_result res, cc_string* dst) {
return Platform_DescribeErrorExt(res, dst, "wininet.dll"); return Platform_DescribeErrorExt(res, dst, wininet_lib);
} }
static void HttpBackend_Init(void) { static void HttpBackend_Init(void) {
static const struct DynamicLibSym funcs[] = {
DynamicLib_Sym(InternetCloseHandle),
DynamicLib_Sym(InternetConnectA), DynamicLib_Sym(InternetOpenA),
DynamicLib_Sym(InternetSetOptionA), DynamicLib_Sym(InternetQueryOptionA),
DynamicLib_Sym(InternetReadFile), DynamicLib_Sym(InternetQueryDataAvailable),
DynamicLib_Sym(HttpOpenRequestA), DynamicLib_Sym(HttpSendRequestA),
DynamicLib_Sym(HttpQueryInfoA), DynamicLib_Sym(HttpAddRequestHeadersA)
};
static const cc_string wininet = String_FromConst("wininet.dll");
DynamicLib_LoadAll(&wininet, funcs, Array_Elems(funcs), &wininet_lib);
if (!wininet_lib) return;
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */ /* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
hInternet = InternetOpenA(GAME_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); hInternet = _InternetOpenA(GAME_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet) Logger_Abort2(GetLastError(), "Failed to init WinINet"); if (!hInternet) Logger_Abort2(GetLastError(), "Failed to init WinINet");
} }
@ -549,7 +564,7 @@ static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_st
String_InitArray(tmp, tmpBuffer); String_InitArray(tmp, tmpBuffer);
String_Format2(&tmp, "%c: %s\r\n", key, value); String_Format2(&tmp, "%c: %s\r\n", key, value);
HttpAddRequestHeadersA((HINTERNET)req->meta, tmp.buffer, tmp.length, _HttpAddRequestHeadersA((HINTERNET)req->meta, tmp.buffer, tmp.length,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE); HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
} }
@ -565,31 +580,33 @@ static cc_result Http_StartRequest(struct HttpRequest* req, cc_string* url) {
String_InitArray_NT(path, pathBuffer); String_InitArray_NT(path, pathBuffer);
HttpCache_MakeEntry(url, &entry, &path); HttpCache_MakeEntry(url, &entry, &path);
pathBuffer[path.length] = '\0'; pathBuffer[path.length] = '\0';
if (!wininet_lib) return ERR_NOT_SUPPORTED;
if ((res = HttpCache_Lookup(&entry))) return res; if ((res = HttpCache_Lookup(&entry))) return res;
flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_COOKIES; flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_COOKIES;
if (entry.Https) flags |= INTERNET_FLAG_SECURE; if (entry.Https) flags |= INTERNET_FLAG_SECURE;
handle = HttpOpenRequestA(entry.Handle, verbs[req->requestType], pathBuffer, NULL, NULL, NULL, flags, 0); handle = _HttpOpenRequestA(entry.Handle, verbs[req->requestType], pathBuffer, NULL, NULL, NULL, flags, 0);
/* Fallback for Windows 95 which returns ERROR_INVALID_PARAMETER */ /* Fallback for Windows 95 which returns ERROR_INVALID_PARAMETER */
if (!handle) { if (!handle) {
flags &= ~INTERNET_FLAG_NO_UI; /* INTERNET_FLAG_NO_UI unsupported on Windows 95 */ flags &= ~INTERNET_FLAG_NO_UI; /* INTERNET_FLAG_NO_UI unsupported on Windows 95 */
handle = HttpOpenRequestA(entry.Handle, verbs[req->requestType], pathBuffer, NULL, NULL, NULL, flags, 0); handle = _HttpOpenRequestA(entry.Handle, verbs[req->requestType], pathBuffer, NULL, NULL, NULL, flags, 0);
if (!handle) return GetLastError(); if (!handle) return GetLastError();
} }
req->meta = handle; req->meta = handle;
bufferLen = sizeof(flags); bufferLen = sizeof(flags);
InternetQueryOptionA(handle, INTERNET_OPTION_SECURITY_FLAGS, (void*)&bufferLen, &flags); _InternetQueryOptionA(handle, INTERNET_OPTION_SECURITY_FLAGS, (void*)&bufferLen, &flags);
/* Users have had issues in the past with revocation servers randomly being offline, */ /* Users have had issues in the past with revocation servers randomly being offline, */
/* which caused all https:// requests to fail. So just skip revocation check. */ /* which caused all https:// requests to fail. So just skip revocation check. */
flags |= SECURITY_FLAG_IGNORE_REVOCATION; flags |= SECURITY_FLAG_IGNORE_REVOCATION;
if (!httpsVerify) flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA; if (!httpsVerify) flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
InternetSetOptionA(handle, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)); _InternetSetOptionA(handle, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
Http_SetRequestHeaders(req); Http_SetRequestHeaders(req);
return HttpSendRequestA(handle, NULL, 0, req->data, req->size) ? 0 : GetLastError(); return _HttpSendRequestA(handle, NULL, 0, req->data, req->size) ? 0 : GetLastError();
} }
/* Gets headers from a HTTP response */ /* Gets headers from a HTTP response */
@ -597,7 +614,7 @@ static cc_result Http_ProcessHeaders(struct HttpRequest* req, HINTERNET handle)
cc_string left, line; cc_string left, line;
char buffer[8192]; char buffer[8192];
DWORD len = 8192; DWORD len = 8192;
if (!HttpQueryInfoA(handle, HTTP_QUERY_RAW_HEADERS, buffer, &len, NULL)) return GetLastError(); if (!_HttpQueryInfoA(handle, HTTP_QUERY_RAW_HEADERS, buffer, &len, NULL)) return GetLastError();
left = String_Init(buffer, len, len); left = String_Init(buffer, len, len);
while (left.length) { while (left.length) {
@ -613,11 +630,11 @@ static cc_result Http_DownloadData(struct HttpRequest* req, HINTERNET handle) {
Http_BufferInit(req); Http_BufferInit(req);
for (;;) { for (;;) {
if (!InternetQueryDataAvailable(handle, &avail, 0, 0)) return GetLastError(); if (!_InternetQueryDataAvailable(handle, &avail, 0, 0)) return GetLastError();
if (!avail) break; if (!avail) break;
Http_BufferEnsure(req, avail); Http_BufferEnsure(req, avail);
if (!InternetReadFile(handle, &req->data[req->size], avail, &read)) return GetLastError(); if (!_InternetReadFile(handle, &req->data[req->size], avail, &read)) return GetLastError();
if (!read) break; if (!read) break;
Http_BufferExpanded(req, read); Http_BufferExpanded(req, read);
} }
@ -635,14 +652,14 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) {
handle = req->meta; handle = req->meta;
http_curProgress = HTTP_PROGRESS_FETCHING_DATA; http_curProgress = HTTP_PROGRESS_FETCHING_DATA;
res = Http_ProcessHeaders(req, handle); res = Http_ProcessHeaders(req, handle);
if (res) { InternetCloseHandle(handle); return res; } if (res) { _InternetCloseHandle(handle); return res; }
if (req->requestType != REQUEST_TYPE_HEAD) { if (req->requestType != REQUEST_TYPE_HEAD) {
res = Http_DownloadData(req, handle); res = Http_DownloadData(req, handle);
if (res) { InternetCloseHandle(handle); return res; } if (res) { _InternetCloseHandle(handle); return res; }
} }
return InternetCloseHandle(handle) ? 0 : GetLastError(); return _InternetCloseHandle(handle) ? 0 : GetLastError();
} }
#elif defined CC_BUILD_ANDROID #elif defined CC_BUILD_ANDROID
/*########################################################################################################################* /*########################################################################################################################*

View File

@ -37,7 +37,7 @@ extern const cc_result ReturnCode_DirectoryExists;
int Platform_EncodeUtf16(void* data, const cc_string* src); int Platform_EncodeUtf16(void* data, const cc_string* src);
/* Converts a null terminated WCHAR* to char* in-place */ /* Converts a null terminated WCHAR* to char* in-place */
void Platform_Utf16ToAnsi(void* data); void Platform_Utf16ToAnsi(void* data);
cc_bool Platform_DescribeErrorExt(cc_result res, cc_string* dst, const char* file); cc_bool Platform_DescribeErrorExt(cc_result res, cc_string* dst, void* lib);
#else #else
/* Encodes a string in UTF8 format, also null terminating the string. */ /* Encodes a string in UTF8 format, also null terminating the string. */
/* Returns the number of bytes written, excluding trailing NULL terminator. */ /* Returns the number of bytes written, excluding trailing NULL terminator. */

View File

@ -360,10 +360,12 @@ void Platform_LoadSysFonts(void) {
char winFolder[FILENAME_SIZE]; char winFolder[FILENAME_SIZE];
WCHAR winTmp[FILENAME_SIZE]; WCHAR winTmp[FILENAME_SIZE];
UINT winLen; UINT winLen;
/* System folder path may not be C:/Windows */
cc_string dirs[1]; cc_string dirs[2];
String_InitArray(dirs[0], winFolder); String_InitArray(dirs[0], winFolder);
dirs[1] = String_FromReadonly("C:/WINNT35/system");
/* System folder path may not be C:/Windows */
winLen = GetWindowsDirectoryW(winTmp, FILENAME_SIZE); winLen = GetWindowsDirectoryW(winTmp, FILENAME_SIZE);
if (winLen) { if (winLen) {
String_AppendUtf16(&dirs[0], winTmp, winLen * 2); String_AppendUtf16(&dirs[0], winTmp, winLen * 2);
@ -815,13 +817,10 @@ void Platform_Free(void) {
HeapDestroy(heap); HeapDestroy(heap);
} }
cc_bool Platform_DescribeErrorExt(cc_result res, cc_string* dst, const char* file) { cc_bool Platform_DescribeErrorExt(cc_result res, cc_string* dst, void* lib) {
WCHAR chars[NATIVE_STR_LEN]; WCHAR chars[NATIVE_STR_LEN];
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
void* lib = NULL; if (lib) flags |= FORMAT_MESSAGE_FROM_HMODULE;
if (file) lib = GetModuleHandleA(file);
if (lib) flags |= FORMAT_MESSAGE_FROM_HMODULE;
res = FormatMessageW(flags, lib, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), res = FormatMessageW(flags, lib, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
chars, NATIVE_STR_LEN, NULL); chars, NATIVE_STR_LEN, NULL);