diff --git a/src/all_types.hpp b/src/all_types.hpp index 318e6b2c11..0b314a4c1e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -35,6 +35,7 @@ struct IrInstruction; struct IrInstructionCast; struct IrBasicBlock; struct ScopeDecls; +struct ZigWindowsSDK; struct IrGotoItem { AstNode *source_node; @@ -1461,17 +1462,17 @@ struct CodeGen { bool have_winmain_crt_startup; bool have_dllmain_crt_startup; bool have_pub_panic; + ZigList libc_lib_dirs_list; Buf *libc_lib_dir; Buf *libc_static_lib_dir; Buf *libc_include_dir; - Buf *msvc_lib_dir; - Buf *kernel32_lib_dir; Buf *zig_lib_dir; Buf *zig_std_dir; Buf *zig_c_headers_dir; Buf *zig_std_special_dir; Buf *dynamic_linker; Buf *ar_path; + ZigWindowsSDK *win_sdk; Buf triple_str; BuildMode build_mode; bool is_test_build; diff --git a/src/analyze.cpp b/src/analyze.cpp index 89ce5df6b4..4d971465da 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2015 Andrew Kelley * * This file is part of zig, which is MIT licensed. @@ -3371,65 +3371,57 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { } void find_libc_include_path(CodeGen *g) { +#ifdef ZIG_OS_WINDOWS if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) { + if (g->win_sdk == nullptr) { + if (os_find_windows_sdk(&g->win_sdk)) { + zig_panic("Unable to determine Windows SDK path."); + } + } + + if (g->zig_target.os == ZigLLVM_Win32) { + if (os_get_win32_ucrt_include_path(g->win_sdk, g->libc_include_dir)) { + zig_panic("Unable to determine libc include path."); + } + } + } + return; +#endif + // TODO find libc at runtime for other operating systems + if(!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) { zig_panic("Unable to determine libc include path."); } } void find_libc_lib_path(CodeGen *g) { #ifdef ZIG_OS_WINDOWS - if (!g->msvc_lib_dir && g->zig_target.os == ZigLLVM_Win32) { - Buf *msvc_lib_dir; - if (g->zig_target.arch.arch == ZigLLVM_arm) { - msvc_lib_dir = buf_create_from_str("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\arm"); - } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) { - msvc_lib_dir = buf_create_from_str("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64"); - } else if (g->zig_target.arch.arch == ZigLLVM_x86) { - msvc_lib_dir = buf_create_from_str("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib"); - } else { - zig_panic("unable to determine msvc lib path"); + if (g->zig_target.os == ZigLLVM_Win32) { + if (g->win_sdk == nullptr) { + if (os_find_windows_sdk(&g->win_sdk)) { + zig_panic("Unable to determine Windows SDK path."); + } } - Buf *test_path = buf_alloc(); - os_path_join(msvc_lib_dir, buf_create_from_str("vcruntime.lib"), test_path); - bool result; - int err; - if ((err = os_file_exists(test_path, &result))) { - result = false; - } - if (result) { - g->msvc_lib_dir = msvc_lib_dir; - } else { - zig_panic("Unable to determine msvc lib path."); - } - } - if (!g->kernel32_lib_dir && g->zig_target.os == ZigLLVM_Win32) { - Buf *kernel32_lib_dir; - if (g->zig_target.arch.arch == ZigLLVM_arm) { - kernel32_lib_dir = buf_create_from_str( - "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\arm"); - } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) { - kernel32_lib_dir = buf_create_from_str( - "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x64"); - } else if (g->zig_target.arch.arch == ZigLLVM_x86) { - kernel32_lib_dir = buf_create_from_str( - "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x86"); - } else { - zig_panic("unable to determine kernel32 lib path"); + Buf* vc_lib_dir = buf_alloc(); + if (os_get_win32_vcruntime_path(vc_lib_dir, g->zig_target.arch.arch)) { + zig_panic("Unable to determine vcruntime path."); } - Buf *test_path = buf_alloc(); - os_path_join(kernel32_lib_dir, buf_create_from_str("kernel32.lib"), test_path); - bool result; - int err; - if ((err = os_file_exists(test_path, &result))) { - result = false; + + Buf* ucrt_lib_path = buf_alloc(); + if (os_get_win32_ucrt_lib_path(g->win_sdk, ucrt_lib_path, g->zig_target.arch.arch)) { + zig_panic("Unable to determine ucrt path."); } - if (result) { - g->kernel32_lib_dir = kernel32_lib_dir; - } else { - zig_panic("Unable to determine kernel32 lib path."); + + Buf* kern_lib_path = buf_alloc(); + if (os_get_win32_kern32_path(g->win_sdk, kern_lib_path, g->zig_target.arch.arch)) { + zig_panic("Unable to determine kernel32 path."); } + + g->libc_lib_dirs_list.append(vc_lib_dir); + g->libc_lib_dirs_list.append(ucrt_lib_path); + g->libc_lib_dirs_list.append(kern_lib_path); } + return; #endif // later we can handle this better by reporting an error via the normal mechanism diff --git a/src/codegen.cpp b/src/codegen.cpp index 1dc8205c8e..78baede270 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -85,7 +85,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->external_prototypes.init(8); g->is_test_build = false; g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); - buf_resize(&g->global_asm, 0); // reserve index 0 to indicate no error @@ -106,31 +105,25 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->zig_std_special_dir = buf_alloc(); os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); - if (target) { // cross compiling, so we can't rely on all the configured stuff since // that's for native compilation g->zig_target = *target; resolve_target_object_format(&g->zig_target); - g->dynamic_linker = buf_create_from_str(""); g->libc_lib_dir = buf_create_from_str(""); g->libc_static_lib_dir = buf_create_from_str(""); g->libc_include_dir = buf_create_from_str(""); - g->msvc_lib_dir = nullptr; - g->kernel32_lib_dir = nullptr; g->each_lib_rpath = false; } else { // native compilation, we can rely on the configuration stuff g->is_native_target = true; get_native_target(&g->zig_target); - g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER); g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR); g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR); g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR); - g->msvc_lib_dir = nullptr; // find it at runtime - g->kernel32_lib_dir = nullptr; // find it at runtime + #ifdef ZIG_EACH_LIB_RPATH g->each_lib_rpath = true; #endif @@ -228,14 +221,6 @@ void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) { g->libc_include_dir = libc_include_dir; } -void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) { - g->msvc_lib_dir = msvc_lib_dir; -} - -void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) { - g->kernel32_lib_dir = kernel32_lib_dir; -} - void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) { g->dynamic_linker = dynamic_linker; } @@ -244,6 +229,14 @@ void codegen_add_lib_dir(CodeGen *g, const char *dir) { g->lib_dirs.append(dir); } +void codegen_set_ucrt_lib_dir(CodeGen *g, Buf *ucrt_lib_dir) { + g->libc_lib_dirs_list.append(ucrt_lib_dir); +} + +void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) { + g->libc_lib_dirs_list.append(kernel32_lib_dir); +} + void codegen_add_rpath(CodeGen *g, const char *name) { g->rpath_list.append(buf_create_from_str(name)); } diff --git a/src/codegen.hpp b/src/codegen.hpp index 5c54e9bce8..fb1a0d7d0b 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -30,7 +30,7 @@ void codegen_set_out_name(CodeGen *codegen, Buf *out_name); void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir); void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir); void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); -void codegen_set_msvc_lib_dir(CodeGen *codegen, Buf *msvc_lib_dir); +void codegen_set_ucrt_lib_dir(CodeGen *g, Buf *ucrt_lib_dir); void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir); void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole); diff --git a/src/link.cpp b/src/link.cpp index a4e5b2dd25..4ec974623f 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -402,19 +402,25 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&lj->out_file)))); if (g->libc_link_lib != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); - - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); + if (g->libc_link_lib != nullptr) { + for (uint32_t i = 0; i < g->libc_lib_dirs_list.length; ++i) { + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dirs_list.items[i])))); + } + } } if (lj->link_in_crt) { const char *lib_str = g->is_static ? "lib" : ""; const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; - Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); - lj->args.append(buf_ptr(cmt_lib_name)); + if (g->is_static) { + Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); + lj->args.append(buf_ptr(cmt_lib_name)); + } + else { + Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); + lj->args.append(buf_ptr(msvcrt_lib_name)); + } Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); lj->args.append(buf_ptr(vcruntime_lib_name)); @@ -422,6 +428,9 @@ static void construct_linker_job_coff(LinkJob *lj) { Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); lj->args.append(buf_ptr(crt_lib_name)); + //Visual C++ 2015 Conformance Changes + //https://msdn.microsoft.com/en-us/library/bb531344.aspx + lj->args.append("legacy_stdio_definitions.lib"); //if (shared || dll) { // lj->args.append(get_libc_file(g, "dllcrt2.o")); diff --git a/src/main.cpp b/src/main.cpp index 358f1cf255..b3622a4e43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -758,7 +758,7 @@ int main(int argc, char **argv) { if (libc_include_dir) codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir)); if (msvc_lib_dir) - codegen_set_msvc_lib_dir(g, buf_create_from_str(msvc_lib_dir)); + codegen_set_ucrt_lib_dir(g, buf_create_from_str(msvc_lib_dir)); if (kernel32_lib_dir) codegen_set_kernel32_lib_dir(g, buf_create_from_str(kernel32_lib_dir)); if (dynamic_linker) diff --git a/src/os.cpp b/src/os.cpp index 2fcafead6e..a52601670c 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -26,6 +26,7 @@ #include #include #include +#include "windows_com.hpp" typedef SSIZE_T ssize_t; #else @@ -999,3 +1000,321 @@ void os_stderr_set_color(TermColor color) { set_color_posix(color); #endif } + +#if defined ZIG_OS_WINDOWS +int os_find_windows_sdk(ZigWindowsSDK **out_sdk) { + ZigWindowsSDK *result_sdk = allocate(1); + buf_resize(&result_sdk->path10, 0); + buf_resize(&result_sdk->path81, 0); + + HKEY key; + HRESULT rc; + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &key); + if (rc != ERROR_SUCCESS) { + return ErrorFileNotFound; + } + + { + DWORD tmp_buf_len = MAX_PATH; + buf_resize(&result_sdk->path10, tmp_buf_len); + rc = RegQueryValueEx(key, "KitsRoot10", NULL, NULL, (LPBYTE)buf_ptr(&result_sdk->path10), &tmp_buf_len); + if (rc == ERROR_FILE_NOT_FOUND) { + buf_resize(&result_sdk->path10, 0); + } else { + buf_resize(&result_sdk->path10, tmp_buf_len); + } + } + { + DWORD tmp_buf_len = MAX_PATH; + buf_resize(&result_sdk->path81, tmp_buf_len); + rc = RegQueryValueEx(key, "KitsRoot81", NULL, NULL, (LPBYTE)buf_ptr(&result_sdk->path81), &tmp_buf_len); + if (rc == ERROR_FILE_NOT_FOUND) { + buf_resize(&result_sdk->path81, 0); + } else { + buf_resize(&result_sdk->path81, tmp_buf_len); + } + } + + if (buf_len(&result_sdk->path10) != 0) { + Buf *sdk_lib_dir = buf_sprintf("%s\\Lib\\*", buf_ptr(&result_sdk->path10)); + + // enumerate files in sdk path looking for latest version + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFileA(buf_ptr(sdk_lib_dir), &ffd); + if (hFind == INVALID_HANDLE_VALUE) { + return ErrorFileNotFound; + } + int v0 = 0, v1 = 0, v2 = 0, v3 = 0; + bool found_version_dir = false; + for (;;) { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + int c0 = 0, c1 = 0, c2 = 0, c3 = 0; + sscanf(ffd.cFileName, "%d.%d.%d.%d", &c0, &c1, &c2, &c3); + if ((c0 > v0) || (c1 > v1) || (c2 > v2) || (c3 > v3)) { + v0 = c0, v1 = c1, v2 = c2, v3 = c3; + buf_init_from_str(&result_sdk->version10, ffd.cFileName); + found_version_dir = true; + } + } + if (FindNextFile(hFind, &ffd) == 0) { + FindClose(hFind); + break; + } + } + if (!found_version_dir) { + buf_resize(&result_sdk->path10, 0); + } + } + + if (buf_len(&result_sdk->path81) != 0) { + Buf *sdk_lib_dir = buf_sprintf("%s\\Lib\\winv*", buf_ptr(&result_sdk->path81)); + + // enumerate files in sdk path looking for latest version + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFileA(buf_ptr(sdk_lib_dir), &ffd); + if (hFind == INVALID_HANDLE_VALUE) { + return ErrorFileNotFound; + } + int v0 = 0, v1 = 0; + bool found_version_dir = false; + for (;;) { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + int c0 = 0, c1 = 0; + sscanf(ffd.cFileName, "winv%d.%d", &c0, &c1); + if ((c0 > v0) || (c1 > v1)) { + v0 = c0, v1 = c1; + buf_init_from_str(&result_sdk->version81, ffd.cFileName); + found_version_dir = true; + } + } + if (FindNextFile(hFind, &ffd) == 0) { + FindClose(hFind); + break; + } + } + if (!found_version_dir) { + buf_resize(&result_sdk->path81, 0); + } + } + + *out_sdk = result_sdk; + return 0; +} + +int os_get_win32_vcruntime_path(Buf* output_buf, ZigLLVM_ArchType platform_type) { + buf_resize(output_buf, 0); + //COM Smart Pointerse requires explicit scope + { + HRESULT rc; + rc = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (rc != S_OK) { + goto com_done; + } + + //This COM class is installed when a VS2017 + ISetupConfigurationPtr setup_config; + rc = setup_config.CreateInstance(__uuidof(SetupConfiguration)); + if (rc != S_OK) { + goto com_done; + } + + IEnumSetupInstancesPtr all_instances; + rc = setup_config->EnumInstances(&all_instances); + if (rc != S_OK) { + goto com_done; + } + + ISetupInstance* curr_instance; + ULONG found_inst; + while ((rc = all_instances->Next(1, &curr_instance, &found_inst) == S_OK)) { + BSTR bstr_inst_path; + rc = curr_instance->GetInstallationPath(&bstr_inst_path); + if (rc != S_OK) { + goto com_done; + } + //BSTRs are UTF-16 encoded, so we need to convert the string & adjust the length + UINT bstr_path_len = *((UINT*)bstr_inst_path - 1); + ULONG tmp_path_len = bstr_path_len / 2 + 1; + char* conv_path = (char*)bstr_inst_path; + char *tmp_path = (char*)alloca(tmp_path_len); + memset(tmp_path, 0, tmp_path_len); + uint32_t c = 0; + for (uint32_t i = 0; i < bstr_path_len; i += 2) { + tmp_path[c] = conv_path[i]; + ++c; + assert(c != tmp_path_len); + } + + buf_append_str(output_buf, tmp_path); + buf_append_char(output_buf, '\\'); + + Buf* tmp_buf = buf_alloc(); + buf_append_buf(tmp_buf, output_buf); + buf_append_str(tmp_buf, "VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"); + FILE* tools_file = fopen(buf_ptr(tmp_buf), "r"); + if (!tools_file) { + goto com_done; + } + memset(tmp_path, 0, tmp_path_len); + fgets(tmp_path, tmp_path_len, tools_file); + strtok(tmp_path, " \r\n"); + fclose(tools_file); + buf_appendf(output_buf, "VC\\Tools\\MSVC\\%s\\lib\\", tmp_path); + switch (platform_type) { + case ZigLLVM_x86: + buf_append_str(output_buf, "x86\\"); + break; + case ZigLLVM_x86_64: + buf_append_str(output_buf, "x64\\"); + break; + case ZigLLVM_arm: + buf_append_str(output_buf, "arm\\"); + break; + default: + zig_panic("Attemped to use vcruntime for non-supported platform."); + } + buf_resize(tmp_buf, 0); + buf_append_buf(tmp_buf, output_buf); + buf_append_str(tmp_buf, "vcruntime.lib"); + + if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { + return 0; + } + } + } + +com_done:; + HKEY key; + HRESULT rc; + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key); + if (rc != ERROR_SUCCESS) { + return ErrorFileNotFound; + } + + DWORD dw_type = 0; + DWORD cb_data = 0; + rc = RegQueryValueEx(key, "14.0", NULL, &dw_type, NULL, &cb_data); + if ((rc == ERROR_FILE_NOT_FOUND) || (REG_SZ != dw_type)) { + return ErrorFileNotFound; + } + + Buf* tmp_buf = buf_alloc_fixed(cb_data); + RegQueryValueExA(key, "14.0", NULL, NULL, (LPBYTE)buf_ptr(tmp_buf), &cb_data); + //RegQueryValueExA returns the length of the string INCLUDING the null terminator + buf_resize(tmp_buf, cb_data-1); + buf_append_str(tmp_buf, "VC\\Lib\\"); + switch (platform_type) { + case ZigLLVM_x86: + //x86 is in the root of the Lib folder + break; + case ZigLLVM_x86_64: + buf_append_str(tmp_buf, "amd64\\"); + break; + case ZigLLVM_arm: + buf_append_str(tmp_buf, "arm\\"); + break; + default: + zig_panic("Attemped to use vcruntime for non-supported platform."); + } + + buf_append_buf(output_buf, tmp_buf); + buf_append_str(tmp_buf, "vcruntime.lib"); + + if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { + return 0; + } else { + buf_resize(output_buf, 0); + return ErrorFileNotFound; + } +} + +int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { + buf_resize(output_buf, 0); + buf_appendf(output_buf, "%s\\Lib\\%s\\ucrt\\", buf_ptr(&sdk->path10), buf_ptr(&sdk->version10)); + switch (platform_type) { + case ZigLLVM_x86: + buf_append_str(output_buf, "x86\\"); + break; + case ZigLLVM_x86_64: + buf_append_str(output_buf, "x64\\"); + break; + case ZigLLVM_arm: + buf_append_str(output_buf, "arm\\"); + break; + default: + zig_panic("Attemped to use vcruntime for non-supported platform."); + } + Buf* tmp_buf = buf_alloc(); + buf_init_from_buf(tmp_buf, output_buf); + buf_append_str(tmp_buf, "ucrt.lib"); + if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { + return 0; + } + else { + buf_resize(output_buf, 0); + return ErrorFileNotFound; + } +} + +int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { + buf_resize(output_buf, 0); + buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", buf_ptr(&sdk->path10), buf_ptr(&sdk->version10)); + if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) { + return 0; + } + else { + buf_resize(output_buf, 0); + return ErrorFileNotFound; + } +} + +int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { + { + buf_resize(output_buf, 0); + buf_appendf(output_buf, "%s\\Lib\\%s\\um\\", buf_ptr(&sdk->path10), buf_ptr(&sdk->version10)); + switch (platform_type) { + case ZigLLVM_x86: + buf_append_str(output_buf, "x86\\"); + break; + case ZigLLVM_x86_64: + buf_append_str(output_buf, "x64\\"); + break; + case ZigLLVM_arm: + buf_append_str(output_buf, "arm\\"); + break; + default: + zig_panic("Attemped to use vcruntime for non-supported platform."); + } + Buf* tmp_buf = buf_alloc(); + buf_init_from_buf(tmp_buf, output_buf); + buf_append_str(tmp_buf, "kernel32.lib"); + if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { + return 0; + } + } + { + buf_resize(output_buf, 0); + buf_appendf(output_buf, "%s\\Lib\\%s\\um\\", buf_ptr(&sdk->path81), buf_ptr(&sdk->version81)); + switch (platform_type) { + case ZigLLVM_x86: + buf_append_str(output_buf, "x86\\"); + break; + case ZigLLVM_x86_64: + buf_append_str(output_buf, "x64\\"); + break; + case ZigLLVM_arm: + buf_append_str(output_buf, "arm\\"); + break; + default: + zig_panic("Attemped to use vcruntime for non-supported platform."); + } + Buf* tmp_buf = buf_alloc(); + buf_init_from_buf(tmp_buf, output_buf); + buf_append_str(tmp_buf, "kernel32.lib"); + if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { + return 0; + } + } + return ErrorFileNotFound; +} +#endif diff --git a/src/os.hpp b/src/os.hpp index 1aac885363..12b319cc08 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -11,6 +11,7 @@ #include "list.hpp" #include "buffer.hpp" #include "error.hpp" +#include "zig_llvm.hpp" #include #include @@ -85,6 +86,20 @@ int os_self_exe_path(Buf *out_path); #define ZIG_OS_UNKNOWN #endif +struct ZigWindowsSDK { + Buf path10; + Buf version10; + Buf path81; + Buf version81; +}; +#if defined(ZIG_OS_WINDOWS) +int os_find_windows_sdk(ZigWindowsSDK **out_sdk); +int os_get_win32_vcruntime_path(Buf *output_buf, ZigLLVM_ArchType platform_type); +int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf); +int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); +int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); +#endif + #if defined(__x86_64__) #define ZIG_ARCH_X86_64 #else diff --git a/src/parsec.cpp b/src/parsec.cpp index 586e95bc75..09f5be0fa7 100644 --- a/src/parsec.cpp +++ b/src/parsec.cpp @@ -138,9 +138,9 @@ static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, As static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); - if (container->type == NodeTypeSymbol) { - assert(container->data.symbol_expr.symbol != nullptr); - } + if (container->type == NodeTypeSymbol) { + assert(container->data.symbol_expr.symbol != nullptr); + } node->data.field_access_expr.struct_expr = container; node->data.field_access_expr.field_name = field_name; return node; diff --git a/src/util.hpp b/src/util.hpp index bf997bb08a..73608b3b08 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -48,17 +48,17 @@ static inline void zig_unreachable(void) { #if defined(_MSC_VER) static inline int clzll(unsigned long long mask) { - unsigned long lz; + unsigned long lz; #if defined(_WIN64) - if (_BitScanReverse64(&lz, mask)) - return static_cast(63 - lz); - zig_unreachable(); + if (_BitScanReverse64(&lz, mask)) + return static_cast(63 - lz); + zig_unreachable(); #else - if (_BitScanReverse(&lz, mask >> 32)) - lz += 32; - else - _BitScanReverse(&lz, mask & 0xffffffff); - return 63 - lz; + if (_BitScanReverse(&lz, mask >> 32)) + lz += 32; + else + _BitScanReverse(&lz, mask & 0xffffffff); + return 63 - lz; #endif } #else diff --git a/src/windows_com.hpp b/src/windows_com.hpp new file mode 100644 index 0000000000..4c807218c0 --- /dev/null +++ b/src/windows_com.hpp @@ -0,0 +1,901 @@ +// The MIT License(MIT) +// Copyright(C) Microsoft Corporation.All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#pragma once + +// Windows headers +#include +#include +#include +#include + +// COM support header files +#include + +// Constants +// +#ifndef E_NOTFOUND +#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND) +#endif + +#ifndef E_FILENOTFOUND +#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) +#endif + +#ifndef E_NOTSUPPORTED +#define E_NOTSUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) +#endif + +// Enumerations +// +/// +/// The state of an instance. +/// +enum InstanceState +{ + /// + /// The instance state has not been determined. + /// + eNone = 0, + + /// + /// The instance installation path exists. + /// + eLocal = 1, + + /// + /// A product is registered to the instance. + /// + eRegistered = 2, + + /// + /// No reboot is required for the instance. + /// + eNoRebootRequired = 4, + + /// + /// No errors were reported for the instance. + /// + eNoErrors = 8, + + /// + /// The instance represents a complete install. + /// + eComplete = UINT_MAX, +}; + +// Forward interface declarations +// +#ifndef __ISetupInstance_FWD_DEFINED__ +#define __ISetupInstance_FWD_DEFINED__ +typedef struct ISetupInstance ISetupInstance; +#endif + +#ifndef __ISetupInstance2_FWD_DEFINED__ +#define __ISetupInstance2_FWD_DEFINED__ +typedef struct ISetupInstance2 ISetupInstance2; +#endif + +#ifndef __ISetupInstanceCatalog_FWD_DEFINED__ +#define __ISetupInstanceCatalog_FWD_DEFINED__ +typedef struct ISetupInstanceCatalog ISetupInstanceCatalog; +#endif + +#ifndef __ISetupLocalizedProperties_FWD_DEFINED__ +#define __ISetupLocalizedProperties_FWD_DEFINED__ +typedef struct ISetupLocalizedProperties ISetupLocalizedProperties; +#endif + +#ifndef __IEnumSetupInstances_FWD_DEFINED__ +#define __IEnumSetupInstances_FWD_DEFINED__ +typedef struct IEnumSetupInstances IEnumSetupInstances; +#endif + +#ifndef __ISetupConfiguration_FWD_DEFINED__ +#define __ISetupConfiguration_FWD_DEFINED__ +typedef struct ISetupConfiguration ISetupConfiguration; +#endif + +#ifndef __ISetupConfiguration2_FWD_DEFINED__ +#define __ISetupConfiguration2_FWD_DEFINED__ +typedef struct ISetupConfiguration2 ISetupConfiguration2; +#endif + +#ifndef __ISetupPackageReference_FWD_DEFINED__ +#define __ISetupPackageReference_FWD_DEFINED__ +typedef struct ISetupPackageReference ISetupPackageReference; +#endif + +#ifndef __ISetupHelper_FWD_DEFINED__ +#define __ISetupHelper_FWD_DEFINED__ +typedef struct ISetupHelper ISetupHelper; +#endif + +#ifndef __ISetupErrorState_FWD_DEFINED__ +#define __ISetupErrorState_FWD_DEFINED__ +typedef struct ISetupErrorState ISetupErrorState; +#endif + +#ifndef __ISetupErrorState2_FWD_DEFINED__ +#define __ISetupErrorState2_FWD_DEFINED__ +typedef struct ISetupErrorState2 ISetupErrorState2; +#endif + +#ifndef __ISetupFailedPackageReference_FWD_DEFINED__ +#define __ISetupFailedPackageReference_FWD_DEFINED__ +typedef struct ISetupFailedPackageReference ISetupFailedPackageReference; +#endif + +#ifndef __ISetupFailedPackageReference2_FWD_DEFINED__ +#define __ISetupFailedPackageReference2_FWD_DEFINED__ +typedef struct ISetupFailedPackageReference2 ISetupFailedPackageReference2; +#endif + +#ifndef __ISetupPropertyStore_FWD_DEFINED__ +#define __ISetupPropertyStore_FWD_DEFINED__ +typedef struct ISetupPropertyStore ISetupPropertyStore; +#endif + +#ifndef __ISetupLocalizedPropertyStore_FWD_DEFINED__ +#define __ISetupLocalizedPropertyStore_FWD_DEFINED__ +typedef struct ISetupLocalizedPropertyStore ISetupLocalizedPropertyStore; +#endif + +// Forward class declarations +// +#ifndef __SetupConfiguration_FWD_DEFINED__ +#define __SetupConfiguration_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class SetupConfiguration SetupConfiguration; +#endif + +#endif + +#ifndef _MSC_VER +#define _Deref_out_opt_ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + // Interface definitions + // + EXTERN_C const IID IID_ISetupInstance; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Information about an instance of a product. + /// + struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E") DECLSPEC_NOVTABLE ISetupInstance : public IUnknown + { + /// + /// Gets the instance identifier (should match the name of the parent instance directory). + /// + /// The instance identifier. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist. + STDMETHOD(GetInstanceId)( + _Out_ BSTR* pbstrInstanceId + ) = 0; + + /// + /// Gets the local date and time when the installation was originally installed. + /// + /// The local date and time when the installation was originally installed. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(GetInstallDate)( + _Out_ LPFILETIME pInstallDate + ) = 0; + + /// + /// Gets the unique name of the installation, often indicating the branch and other information used for telemetry. + /// + /// The unique name of the installation, often indicating the branch and other information used for telemetry. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(GetInstallationName)( + _Out_ BSTR* pbstrInstallationName + ) = 0; + + /// + /// Gets the path to the installation root of the product. + /// + /// The path to the installation root of the product. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(GetInstallationPath)( + _Out_ BSTR* pbstrInstallationPath + ) = 0; + + /// + /// Gets the version of the product installed in this instance. + /// + /// The version of the product installed in this instance. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(GetInstallationVersion)( + _Out_ BSTR* pbstrInstallationVersion + ) = 0; + + /// + /// Gets the display name (title) of the product installed in this instance. + /// + /// The LCID for the display name. + /// The display name (title) of the product installed in this instance. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(GetDisplayName)( + _In_ LCID lcid, + _Out_ BSTR* pbstrDisplayName + ) = 0; + + /// + /// Gets the description of the product installed in this instance. + /// + /// The LCID for the description. + /// The description of the product installed in this instance. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(GetDescription)( + _In_ LCID lcid, + _Out_ BSTR* pbstrDescription + ) = 0; + + /// + /// Resolves the optional relative path to the root path of the instance. + /// + /// A relative path within the instance to resolve, or NULL to get the root path. + /// The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined. + STDMETHOD(ResolvePath)( + _In_opt_z_ LPCOLESTR pwszRelativePath, + _Out_ BSTR* pbstrAbsolutePath + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupInstance2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Information about an instance of a product. + /// + struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C") DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance + { + /// + /// Gets the state of the instance. + /// + /// The state of the instance. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist. + STDMETHOD(GetState)( + _Out_ InstanceState* pState + ) = 0; + + /// + /// Gets an array of package references registered to the instance. + /// + /// Pointer to an array of . + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined. + STDMETHOD(GetPackages)( + _Out_ LPSAFEARRAY* ppsaPackages + ) = 0; + + /// + /// Gets a pointer to the that represents the registered product. + /// + /// Pointer to an instance of . This may be NULL if does not return . + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined. + STDMETHOD(GetProduct)( + _Outptr_result_maybenull_ ISetupPackageReference** ppPackage + ) = 0; + + /// + /// Gets the relative path to the product application, if available. + /// + /// The relative path to the product application, if available. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist. + STDMETHOD(GetProductPath)( + _Outptr_result_maybenull_ BSTR* pbstrProductPath + ) = 0; + + /// + /// Gets the error state of the instance, if available. + /// + /// The error state of the instance, if available. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist. + STDMETHOD(GetErrors)( + _Outptr_result_maybenull_ ISetupErrorState** ppErrorState + ) = 0; + + /// + /// Gets a value indicating whether the instance can be launched. + /// + /// Whether the instance can be launched. + /// Standard HRESULT indicating success or failure. + /// + /// An instance could have had errors during install but still be launched. Some features may not work correctly, but others will. + /// + STDMETHOD(IsLaunchable)( + _Out_ VARIANT_BOOL* pfIsLaunchable + ) = 0; + + /// + /// Gets a value indicating whether the instance is complete. + /// + /// Whether the instance is complete. + /// Standard HRESULT indicating success or failure. + /// + /// An instance is complete if it had no errors during install, resume, or repair. + /// + STDMETHOD(IsComplete)( + _Out_ VARIANT_BOOL* pfIsComplete + ) = 0; + + /// + /// Gets product-specific properties. + /// + /// A pointer to an instance of . This may be NULL if no properties are defined. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist. + STDMETHOD(GetProperties)( + _Outptr_result_maybenull_ ISetupPropertyStore** ppProperties + ) = 0; + + /// + /// Gets the directory path to the setup engine that installed the instance. + /// + /// The directory path to the setup engine that installed the instance. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist. + STDMETHOD(GetEnginePath)( + _Outptr_result_maybenull_ BSTR* pbstrEnginePath + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupInstanceCatalog; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Information about a catalog used to install an instance. + /// + struct DECLSPEC_UUID("9AD8E40F-39A2-40F1-BF64-0A6C50DD9EEB") DECLSPEC_NOVTABLE ISetupInstanceCatalog : public IUnknown + { + /// + /// Gets catalog information properties. + /// + /// A pointer to an instance of . + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property does not exist. + STDMETHOD(GetCatalogInfo)( + _Out_ ISetupPropertyStore** ppCatalogInfo + ) = 0; + + /// + /// Gets a value indicating whether the catalog is a prerelease. + /// + /// Whether the catalog for the instance is a prerelease version. + /// Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property does not exist. + STDMETHOD(IsPrerelease)( + _Out_ VARIANT_BOOL* pfIsPrerelease + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupLocalizedProperties; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Provides localized properties of an instance of a product. + /// + struct DECLSPEC_UUID("F4BD7382-FE27-4AB4-B974-9905B2A148B0") DECLSPEC_NOVTABLE ISetupLocalizedProperties : public IUnknown + { + /// + /// Gets localized product-specific properties. + /// + /// A pointer to an instance of . This may be NULL if no properties are defined. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetLocalizedProperties)( + _Outptr_result_maybenull_ ISetupLocalizedPropertyStore** ppLocalizedProperties + ) = 0; + + /// + /// Gets localized channel-specific properties. + /// + /// A pointer to an instance of . This may be NULL if no channel properties are defined. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetLocalizedChannelProperties)( + _Outptr_result_maybenull_ ISetupLocalizedPropertyStore** ppLocalizedChannelProperties + ) = 0; + }; +#endif + + EXTERN_C const IID IID_IEnumSetupInstances; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// An enumerator of installed objects. + /// + struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848") DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown + { + /// + /// Retrieves the next set of product instances in the enumeration sequence. + /// + /// The number of product instances to retrieve. + /// A pointer to an array of . + /// A pointer to the number of product instances retrieved. If is 1 this parameter may be NULL. + /// S_OK if the number of elements were fetched, S_FALSE if nothing was fetched (at end of enumeration), E_INVALIDARG if is greater than 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an could not be allocated. + STDMETHOD(Next)( + _In_ ULONG celt, + _Out_writes_to_(celt, *pceltFetched) ISetupInstance** rgelt, + _Out_opt_ _Deref_out_range_(0, celt) ULONG* pceltFetched + ) = 0; + + /// + /// Skips the next set of product instances in the enumeration sequence. + /// + /// The number of product instances to skip. + /// S_OK if the number of elements could be skipped; otherwise, S_FALSE; + STDMETHOD(Skip)( + _In_ ULONG celt + ) = 0; + + /// + /// Resets the enumeration sequence to the beginning. + /// + /// Always returns S_OK; + STDMETHOD(Reset)(void) = 0; + + /// + /// Creates a new enumeration object in the same state as the current enumeration object: the new object points to the same place in the enumeration sequence. + /// + /// A pointer to a pointer to a new interface. If the method fails, this parameter is undefined. + /// S_OK if a clone was returned; otherwise, E_OUTOFMEMORY. + STDMETHOD(Clone)( + _Deref_out_opt_ IEnumSetupInstances** ppenum + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupConfiguration; + +#if defined(__cplusplus) && !defined(CINTERFACE) + +#ifdef __GNUC__ + __CRT_UUID_DECL(ISetupConfiguration, 0x42843719, 0xDB4C, 0x46C2, 0x8E, 0x7C, 0x64, 0xF1, 0x81, 0x6E, 0xFD, 0x5B); +#endif + + /// + /// Gets information about product instances installed on the machine. + /// + struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B") DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown + { + /// + /// Enumerates all launchable product instances installed. + /// + /// An enumeration of completed, installed product instances. + /// Standard HRESULT indicating success or failure. + STDMETHOD(EnumInstances)( + _Out_ IEnumSetupInstances** ppEnumInstances + ) = 0; + + /// + /// Gets the instance for the current process path. + /// + /// The instance for the current process path. + /// + /// The instance for the current process path, or E_NOTFOUND if not found. + /// The may indicate the instance is invalid. + /// + /// + /// The returned instance may not be launchable. + /// + STDMETHOD(GetInstanceForCurrentProcess)( + _Out_ ISetupInstance** ppInstance + ) = 0; + + /// + /// Gets the instance for the given path. + /// + /// The instance for the given path. + /// + /// The instance for the given path, or E_NOTFOUND if not found. + /// The may indicate the instance is invalid. + /// + /// + /// The returned instance may not be launchable. + /// + STDMETHOD(GetInstanceForPath)( + _In_z_ LPCWSTR wzPath, + _Out_ ISetupInstance** ppInstance + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupConfiguration2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Gets information about product instances. + /// + struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D") DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration + { + /// + /// Enumerates all product instances. + /// + /// An enumeration of all product instances. + /// Standard HRESULT indicating success or failure. + STDMETHOD(EnumAllInstances)( + _Out_ IEnumSetupInstances** ppEnumInstances + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupPackageReference; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// A reference to a package. + /// + struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5") DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown + { + /// + /// Gets the general package identifier. + /// + /// The general package identifier. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetId)( + _Out_ BSTR* pbstrId + ) = 0; + + /// + /// Gets the version of the package. + /// + /// The version of the package. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetVersion)( + _Out_ BSTR* pbstrVersion + ) = 0; + + /// + /// Gets the target process architecture of the package. + /// + /// The target process architecture of the package. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetChip)( + _Out_ BSTR* pbstrChip + ) = 0; + + /// + /// Gets the language and optional region identifier. + /// + /// The language and optional region identifier. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetLanguage)( + _Out_ BSTR* pbstrLanguage + ) = 0; + + /// + /// Gets the build branch of the package. + /// + /// The build branch of the package. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetBranch)( + _Out_ BSTR* pbstrBranch + ) = 0; + + /// + /// Gets the type of the package. + /// + /// The type of the package. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetType)( + _Out_ BSTR* pbstrType + ) = 0; + + /// + /// Gets the unique identifier consisting of all defined tokens. + /// + /// The unique identifier consisting of all defined tokens. + /// Standard HRESULT indicating success or failure, including E_UNEXPECTED if no Id was defined (required). + STDMETHOD(GetUniqueId)( + _Out_ BSTR* pbstrUniqueId + ) = 0; + + /// + /// Gets a value indicating whether the package refers to an external extension. + /// + /// A value indicating whether the package refers to an external extension. + /// Standard HRESULT indicating success or failure, including E_UNEXPECTED if no Id was defined (required). + STDMETHOD(GetIsExtension)( + _Out_ VARIANT_BOOL* pfIsExtension + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupHelper; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Helper functions. + /// + /// + /// You can query for this interface from the class. + /// + struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c") DECLSPEC_NOVTABLE ISetupHelper : public IUnknown + { + /// + /// Parses a dotted quad version string into a 64-bit unsigned integer. + /// + /// The dotted quad version string to parse, e.g. 1.2.3.4. + /// A 64-bit unsigned integer representing the version. You can compare this to other versions. + /// Standard HRESULT indicating success or failure, including E_INVALIDARG if the version is not valid. + STDMETHOD(ParseVersion)( + _In_ LPCOLESTR pwszVersion, + _Out_ PULONGLONG pullVersion + ) = 0; + + /// + /// Parses a dotted quad version string into a 64-bit unsigned integer. + /// + /// The string containing 1 or 2 dotted quad version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer. + /// A 64-bit unsigned integer representing the minimum version, which may be 0. You can compare this to other versions. + /// A 64-bit unsigned integer representing the maximum version, which may be MAXULONGLONG. You can compare this to other versions. + /// Standard HRESULT indicating success or failure, including E_INVALIDARG if the version range is not valid. + STDMETHOD(ParseVersionRange)( + _In_ LPCOLESTR pwszVersionRange, + _Out_ PULONGLONG pullMinVersion, + _Out_ PULONGLONG pullMaxVersion + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupErrorState; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Information about the error state of an instance. + /// + struct DECLSPEC_UUID("46DCCD94-A287-476A-851E-DFBC2FFDBC20") DECLSPEC_NOVTABLE ISetupErrorState : public IUnknown + { + /// + /// Gets an array of failed package references. + /// + /// Pointer to an array of , if packages have failed. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetFailedPackages)( + _Outptr_result_maybenull_ LPSAFEARRAY* ppsaFailedPackages + ) = 0; + + /// + /// Gets an array of skipped package references. + /// + /// Pointer to an array of , if packages have been skipped. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetSkippedPackages)( + _Outptr_result_maybenull_ LPSAFEARRAY* ppsaSkippedPackages + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupErrorState2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Information about the error state of an instance. + /// + struct DECLSPEC_UUID("9871385B-CA69-48F2-BC1F-7A37CBF0B1EF") DECLSPEC_NOVTABLE ISetupErrorState2 : public ISetupErrorState + { + /// + /// Gets the path to the error log. + /// + /// The path to the error log. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetErrorLogFilePath)( + _Outptr_result_maybenull_ BSTR* pbstrErrorLogFilePath + ) = 0; + + /// + /// Gets the path to the main setup log. + /// + /// The path to the main setup log. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetLogFilePath)( + _Outptr_result_maybenull_ BSTR* pbstrLogFilePath + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupFailedPackageReference; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// A reference to a failed package. + /// + struct DECLSPEC_UUID("E73559CD-7003-4022-B134-27DC650B280F") DECLSPEC_NOVTABLE ISetupFailedPackageReference : public ISetupPackageReference + { + }; + +#endif + + EXTERN_C const IID IID_ISetupFailedPackageReference2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// A reference to a failed package. + /// + struct DECLSPEC_UUID("0FAD873E-E874-42E3-B268-4FE2F096B9CA") DECLSPEC_NOVTABLE ISetupFailedPackageReference2 : public ISetupFailedPackageReference + { + /// + /// Gets the path to the optional package log. + /// + /// The path to the optional package log. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetLogFilePath)( + _Outptr_result_maybenull_ BSTR* pbstrLogFilePath + ) = 0; + + /// + /// Gets the description of the package failure. + /// + /// The description of the package failure. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetDescription)( + _Outptr_result_maybenull_ BSTR* pbstrDescription + ) = 0; + + /// + /// Gets the signature to use for feedback reporting. + /// + /// The signature to use for feedback reporting. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetSignature)( + _Outptr_result_maybenull_ BSTR* pbstrSignature + ) = 0; + + /// + /// Gets the array of details for this package failure. + /// + /// Pointer to an array of details as BSTRs. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetDetails)( + _Out_ LPSAFEARRAY* ppsaDetails + ) = 0; + + /// + /// Gets an array of packages affected by this package failure. + /// + /// Pointer to an array of for packages affected by this package failure. This may be NULL. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetAffectedPackages)( + _Out_ LPSAFEARRAY* ppsaAffectedPackages + ) = 0; + }; + +#endif + + EXTERN_C const IID IID_ISetupPropertyStore; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Provides named properties. + /// + /// + /// You can get this from an , , or derivative. + /// + struct DECLSPEC_UUID("C601C175-A3BE-44BC-91F6-4568D230FC83") DECLSPEC_NOVTABLE ISetupPropertyStore : public IUnknown + { + /// + /// Gets an array of property names in this property store. + /// + /// Pointer to an array of property names as BSTRs. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetNames)( + _Out_ LPSAFEARRAY* ppsaNames + ) = 0; + + /// + /// Gets the value of a named property in this property store. + /// + /// The name of the property to get. + /// The value of the property. + /// Standard HRESULT indicating success or failure, including E_NOTFOUND if the property is not defined or E_NOTSUPPORTED if the property type is not supported. + STDMETHOD(GetValue)( + _In_ LPCOLESTR pwszName, + _Out_ LPVARIANT pvtValue + ) = 0; + }; + +#endif + + EXTERN_C const IID IID_ISetupLocalizedPropertyStore; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// + /// Provides localized named properties. + /// + /// + /// You can get this from an . + /// + struct DECLSPEC_UUID("5BB53126-E0D5-43DF-80F1-6B161E5C6F6C") DECLSPEC_NOVTABLE ISetupLocalizedPropertyStore : public IUnknown + { + /// + /// Gets an array of property names in this property store. + /// + /// The LCID for the property names. + /// Pointer to an array of property names as BSTRs. + /// Standard HRESULT indicating success or failure. + STDMETHOD(GetNames)( + _In_ LCID lcid, + _Out_ LPSAFEARRAY* ppsaNames + ) = 0; + + /// + /// Gets the value of a named property in this property store. + /// + /// The name of the property to get. + /// The LCID for the property. + /// The value of the property. + /// Standard HRESULT indicating success or failure, including E_NOTFOUND if the property is not defined or E_NOTSUPPORTED if the property type is not supported. + STDMETHOD(GetValue)( + _In_ LPCOLESTR pwszName, + _In_ LCID lcid, + _Out_ LPVARIANT pvtValue + ) = 0; + }; + +#endif + + // Class declarations + // + EXTERN_C const CLSID CLSID_SetupConfiguration; + +#ifdef __cplusplus + +#ifdef __GNUC__ + __CRT_UUID_DECL(SetupConfiguration, 0x177F0C4A, 0x1CD3, 0x4DE7, 0xA3, 0x2C, 0x71, 0xDB, 0xBB, 0x9F, 0xA3, 0x6D); +#endif + + /// + /// This class implements , , and . + /// + class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration; +#endif + // Function declarations + // + /// + /// Gets an that provides information about product instances installed on the machine. + /// + /// The that provides information about product instances installed on the machine. + /// Reserved for future use. + /// Standard HRESULT indicating success or failure. + STDMETHODIMP GetSetupConfiguration( + _Out_ ISetupConfiguration** ppConfiguration, + _Reserved_ LPVOID pReserved + ); + +#ifdef __cplusplus +} +#endif + +_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance)); +_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2)); +_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances)); +_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration)); +_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2)); +_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper)); +_COM_SMARTPTR_TYPEDEF(ISetupPackageReference, __uuidof(ISetupPackageReference)); +_COM_SMARTPTR_TYPEDEF(ISetupPropertyStore, __uuidof(ISetupPropertyStore)); +_COM_SMARTPTR_TYPEDEF(ISetupInstanceCatalog, __uuidof(ISetupInstanceCatalog));