Windows: fix some heap corruptions, fix msvc not building with unicode flags, fix os.getwd, fix mscrazy using a less recent installation

pull/1295/head
Emily Hudson 2019-07-24 14:00:26 +01:00 committed by Alexander Medvednikov
parent 0bbefca875
commit 32aae80a64
5 changed files with 108 additions and 104 deletions

4
.gitignore vendored
View File

@ -7,3 +7,7 @@
*.exe
*.o
.*.c
*.obj
*.pdb

View File

@ -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)
}

View File

@ -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

View File

@ -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;
}

View File

@ -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)