Windows: fix some heap corruptions, fix msvc not building with unicode flags, fix os.getwd, fix mscrazy using a less recent installation
parent
0bbefca875
commit
32aae80a64
|
@ -7,3 +7,7 @@
|
|||
*.exe
|
||||
*.o
|
||||
.*.c
|
||||
|
||||
*.obj
|
||||
|
||||
*.pdb
|
||||
|
|
|
@ -32,25 +32,24 @@ struct MsvcResult {
|
|||
|
||||
struct FindResult {
|
||||
sdk_ver int
|
||||
windows_sdk_root byteptr
|
||||
windows_sdk_um_library_path byteptr
|
||||
windows_sdk_ucrt_library_path byteptr
|
||||
vs_exe_path byteptr
|
||||
vs_library_path byteptr
|
||||
windows_sdk_root *u16
|
||||
windows_sdk_um_library_path *u16
|
||||
windows_sdk_ucrt_library_path *u16
|
||||
vs_exe_path *u16
|
||||
vs_library_path *u16
|
||||
}
|
||||
|
||||
fn C.find_visual_studio_and_windows_sdk() *FindResult
|
||||
fn C.wide_string_to_narrow_temp(byteptr) byteptr
|
||||
|
||||
fn find_msvc() *MsvcResult {
|
||||
$if windows {
|
||||
r := C.find_visual_studio_and_windows_sdk()
|
||||
|
||||
windows_sdk_root := tos_clone(C.wide_string_to_narrow_temp(r.windows_sdk_root))
|
||||
ucrt_lib_folder := tos_clone(C.wide_string_to_narrow_temp(r.windows_sdk_ucrt_library_path))
|
||||
um_lib_folder := tos_clone(C.wide_string_to_narrow_temp(r.windows_sdk_um_library_path))
|
||||
vs_lib_folder := tos_clone(C.wide_string_to_narrow_temp(r.vs_library_path))
|
||||
exe_folder := tos_clone(C.wide_string_to_narrow_temp(r.vs_exe_path))
|
||||
windows_sdk_root := string_from_wide(r.windows_sdk_root)
|
||||
ucrt_lib_folder := string_from_wide(r.windows_sdk_ucrt_library_path)
|
||||
um_lib_folder := string_from_wide(r.windows_sdk_um_library_path)
|
||||
vs_lib_folder := string_from_wide(r.vs_library_path)
|
||||
exe_folder := string_from_wide(r.vs_exe_path)
|
||||
|
||||
mut ucrt_include_folder := ucrt_lib_folder.replace('Lib', 'Include')
|
||||
mut vs_include_folder := vs_lib_folder.replace('lib', 'include')
|
||||
|
@ -88,7 +87,7 @@ fn find_msvc() *MsvcResult {
|
|||
pub fn cc_msvc(v *V) {
|
||||
r := find_msvc()
|
||||
|
||||
mut a := ['-w', '/volatile:ms'] // arguments for the C compiler
|
||||
mut a := ['-w', '/volatile:ms', '/D_UNICODE', '/DUNICODE'] // arguments for the C compiler
|
||||
|
||||
// cl.exe is stupid so these are in a different order to the ones below!
|
||||
|
||||
|
@ -274,6 +273,6 @@ fn build_thirdparty_obj_file_with_msvc(flag string) {
|
|||
|
||||
println('$cfiles')
|
||||
|
||||
res := os.exec('""$msvc.exe_path\\cl.exe" /volatile:ms /Z7 $include_string /c $cfiles /Fo"$obj_path""')
|
||||
res := os.exec('""$msvc.exe_path\\cl.exe" /volatile:ms /Z7 $include_string /c $cfiles /Fo"$obj_path" /D_UNICODE /DUNICODE"')
|
||||
println(res)
|
||||
}
|
|
@ -1,24 +1,3 @@
|
|||
#define MICROSOFT_CRAZINESS_IMPLEMENTATION
|
||||
|
||||
#include "microsoft_craziness.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Never hang around to a pointer from this function
|
||||
// This is not thread safe
|
||||
char *wide_string_to_narrow_temp(wchar_t *wc) {
|
||||
static char buffer[10000][10];
|
||||
static int counter = 0;
|
||||
|
||||
char *cur_buffer = buffer[counter++];
|
||||
|
||||
int len = wcslen(wc);
|
||||
int c = wcstombs(cur_buffer, wc, len);
|
||||
cur_buffer[c] = 0;
|
||||
|
||||
// something assert len == c
|
||||
|
||||
return cur_buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
#include "microsoft_craziness.h"
|
|
@ -338,6 +338,7 @@ wchar_t *find_windows_kit_root_with_key(HKEY key, wchar_t *version) {
|
|||
DWORD length =
|
||||
required_length + 2; // The +2 is for the maybe optional zero later on.
|
||||
// Probably we are over-allocating.
|
||||
|
||||
wchar_t *value = (wchar_t *)malloc(length);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
@ -350,8 +351,8 @@ wchar_t *find_windows_kit_root_with_key(HKEY key, wchar_t *version) {
|
|||
// The documentation says that if the string for some reason was not stored
|
||||
// with zero-termination, we need to manually terminate it. Sigh!!
|
||||
|
||||
if (value[length]) {
|
||||
value[length + 1] = 0;
|
||||
if (value[required_length / 2 - 1]) {
|
||||
value[required_length / 2] = 0;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -521,6 +522,13 @@ bool find_visual_studio_2017_by_fighting_through_microsoft_craziness(
|
|||
if (!instances)
|
||||
return false;
|
||||
|
||||
// SetupInstance will return the installations in the order they were made
|
||||
// - this results in 2017 being got before 2019 and we dont want this
|
||||
// so get all the installations first, parse the versions and pick the best
|
||||
BSTR best_path = NULL;
|
||||
Version_Data best_version;
|
||||
best_version.best_name = NULL;
|
||||
|
||||
bool found_visual_studio_2017 = false;
|
||||
while (1) {
|
||||
ULONG found = 0;
|
||||
|
@ -529,81 +537,95 @@ bool find_visual_studio_2017_by_fighting_through_microsoft_craziness(
|
|||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
BSTR vs_version;
|
||||
hr = CALL_STDMETHOD(instance, GetInstallationVersion, &vs_version);
|
||||
|
||||
win10_best(vs_version, vs_version, &best_version);
|
||||
|
||||
BSTR bstr_inst_path;
|
||||
hr = CALL_STDMETHOD(instance, GetInstallationPath, &bstr_inst_path);
|
||||
CALL_STDMETHOD_(instance, Release);
|
||||
if (hr != S_OK)
|
||||
continue;
|
||||
|
||||
wchar_t *tools_filename = concat2(
|
||||
bstr_inst_path,
|
||||
L"\\VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
|
||||
SysFreeString(bstr_inst_path);
|
||||
|
||||
FILE *f;
|
||||
errno_t open_result = _wfopen_s(&f, tools_filename, L"rt");
|
||||
free(tools_filename);
|
||||
if (open_result != 0)
|
||||
continue;
|
||||
if (!f)
|
||||
// Do this here to get instance->Release() called
|
||||
if (lstrcmpW(best_version.best_name, vs_version))
|
||||
continue;
|
||||
|
||||
LARGE_INTEGER tools_file_size;
|
||||
HANDLE file_handle = (HANDLE)_get_osfhandle(_fileno(f));
|
||||
BOOL success = GetFileSizeEx(file_handle, &tools_file_size);
|
||||
if (!success) {
|
||||
fclose(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t version_bytes =
|
||||
(tools_file_size.QuadPart + 1) *
|
||||
2; // Warning: This multiplication by 2 presumes there is no
|
||||
// variable-length encoding in the wchars (wacky characters in the
|
||||
// file could betray this expectation).
|
||||
wchar_t *version = (wchar_t *)malloc(version_bytes);
|
||||
|
||||
wchar_t *read_result = fgetws(version, version_bytes, f);
|
||||
fclose(f);
|
||||
if (!read_result)
|
||||
continue;
|
||||
|
||||
wchar_t *version_tail = wcschr(version, '\n');
|
||||
if (version_tail)
|
||||
*version_tail = 0; // Stomp the data, because nobody cares about it.
|
||||
|
||||
wchar_t *library_path =
|
||||
concat4(bstr_inst_path, L"\\VC\\Tools\\MSVC\\", version, L"\\lib\\x64");
|
||||
wchar_t *library_file =
|
||||
concat2(library_path,
|
||||
L"\\vcruntime.lib"); // @Speed: Could have library_path point to
|
||||
// this string, with a smaller count, to
|
||||
// save on memory flailing!
|
||||
|
||||
if (os_file_exists(library_file)) {
|
||||
wchar_t *link_exe_path = concat4(bstr_inst_path, L"\\VC\\Tools\\MSVC\\",
|
||||
version, L"\\bin\\Hostx64\\x64");
|
||||
free(version);
|
||||
|
||||
result->vs_exe_path = link_exe_path;
|
||||
result->vs_library_path = library_path;
|
||||
found_visual_studio_2017 = true;
|
||||
break;
|
||||
}
|
||||
|
||||
free(version);
|
||||
|
||||
/*
|
||||
Ryan Saunderson said:
|
||||
"Clang uses the 'SetupInstance->GetInstallationVersion' /
|
||||
ISetupHelper->ParseVersion to find the newest version and then reads the
|
||||
tools file to define the tools path - which is definitely better than
|
||||
what i did."
|
||||
|
||||
So... @Incomplete: Should probably pick the newest version...
|
||||
*/
|
||||
best_path = bstr_inst_path;
|
||||
}
|
||||
|
||||
if (best_path == NULL)
|
||||
goto failed;
|
||||
|
||||
// result->vs_root_path = _wcsdup(best_path);
|
||||
|
||||
wchar_t *tools_filename =
|
||||
concat2(best_path,
|
||||
L"\\VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
|
||||
|
||||
FILE *f;
|
||||
errno_t open_result = _wfopen_s(&f, tools_filename, L"rt");
|
||||
free(tools_filename);
|
||||
if (open_result != 0)
|
||||
return false;
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
LARGE_INTEGER tools_file_size;
|
||||
HANDLE file_handle = (HANDLE)_get_osfhandle(_fileno(f));
|
||||
BOOL success = GetFileSizeEx(file_handle, &tools_file_size);
|
||||
if (!success) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t version_bytes =
|
||||
(tools_file_size.QuadPart + 1) *
|
||||
2; // Warning: This multiplication by 2 presumes there is no
|
||||
// variable-length encoding in the wchars (wacky characters in the file
|
||||
// could betray this expectation).
|
||||
wchar_t *version = (wchar_t *)malloc(version_bytes);
|
||||
|
||||
wchar_t *read_result = fgetws(version, version_bytes, f);
|
||||
fclose(f);
|
||||
if (!read_result)
|
||||
return false;
|
||||
|
||||
wchar_t *version_tail = wcschr(version, '\n');
|
||||
if (version_tail)
|
||||
*version_tail = 0; // Stomp the data, because nobody cares about it.
|
||||
|
||||
wchar_t *library_path =
|
||||
concat4(best_path, L"\\VC\\Tools\\MSVC\\", version, L"\\lib\\x64");
|
||||
wchar_t *library_file = concat2(
|
||||
library_path, L"\\vcruntime.lib"); // @Speed: Could have library_path
|
||||
// point to this string, with a smaller
|
||||
// count, to save on memory flailing!
|
||||
|
||||
if (os_file_exists(library_file)) {
|
||||
wchar_t *link_exe_path = concat4(best_path, L"\\VC\\Tools\\MSVC\\", version,
|
||||
L"\\bin\\Hostx64\\x64");
|
||||
|
||||
result->vs_exe_path = link_exe_path;
|
||||
result->vs_library_path = library_path;
|
||||
|
||||
found_visual_studio_2017 = true;
|
||||
}
|
||||
|
||||
free(version);
|
||||
SysFreeString(best_path);
|
||||
|
||||
/*
|
||||
Ryan Saunderson said:
|
||||
"Clang uses the 'SetupInstance->GetInstallationVersion' /
|
||||
ISetupHelper->ParseVersion to find the newest version and then reads the
|
||||
tools file to define the tools path - which is definitely better than what
|
||||
i did." So... @Incomplete: Should probably pick the newest version...
|
||||
*/
|
||||
|
||||
failed:
|
||||
|
||||
CALL_STDMETHOD_(instances, Release);
|
||||
return found_visual_studio_2017;
|
||||
}
|
||||
|
|
|
@ -703,9 +703,9 @@ pub fn chdir(path string) {
|
|||
|
||||
pub fn getwd() string {
|
||||
$if windows {
|
||||
max := 512 // MAX_PATH * sizeof(wchar_t)
|
||||
max := 1024 // MAX_PATH * sizeof(wchar_t)
|
||||
buf := &u16(malloc(max))
|
||||
if C._wgetcwd(buf, max) == 0 {
|
||||
if C._wgetcwd(buf, max/2) == 0 {
|
||||
return ''
|
||||
}
|
||||
return string_from_wide(buf)
|
||||
|
|
Loading…
Reference in New Issue