progress toward hello world without libc in windows

master
Andrew Kelley 2017-06-04 10:08:55 -04:00
parent e5b90651ba
commit 199bbb6292
11 changed files with 2727 additions and 134 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
zig-cache/
build/
build-release/
build-windows/
/.cproject
/.project
/.settings/

View File

@ -233,7 +233,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux.zig" DESTINATION "${ZIG_STD_DEST
install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/error.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")

View File

@ -332,75 +332,71 @@ static void construct_linker_job_coff(LinkJob *lj) {
find_libc_lib_path(g);
}
lj->args.append("-NOLOGO");
if (g->zig_target.arch.arch == ZigLLVM_x86) {
lj->args.append("-m");
lj->args.append("i386pe");
lj->args.append("-MACHINE:X86");
} else if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
lj->args.append("-m");
lj->args.append("i386pep");
lj->args.append("-MACHINE:X64");
} else if (g->zig_target.arch.arch == ZigLLVM_arm) {
lj->args.append("-m");
lj->args.append("thumb2pe");
lj->args.append("-MACHINE:ARM");
}
if (g->windows_subsystem_windows) {
lj->args.append("--subsystem");
lj->args.append("windows");
lj->args.append("/SUBSYSTEM:windows");
} else if (g->windows_subsystem_console) {
lj->args.append("--subsystem");
lj->args.append("console");
lj->args.append("/SUBSYSTEM:console");
}
bool dll = g->out_type == OutTypeLib;
bool shared = !g->is_static && dll;
if (g->is_static) {
lj->args.append("-Bstatic");
} else {
if (dll) {
lj->args.append("--dll");
} else if (shared) {
lj->args.append("--shared");
}
lj->args.append("-Bdynamic");
if (dll || shared) {
lj->args.append("-e");
if (g->zig_target.arch.arch == ZigLLVM_x86) {
lj->args.append("_DllMainCRTStartup@12");
} else {
lj->args.append("DllMainCRTStartup");
}
lj->args.append("--enable-auto-image-base");
}
}
//bool dll = g->out_type == OutTypeLib;
//bool shared = !g->is_static && dll;
//if (g->is_static) {
// lj->args.append("-Bstatic");
//} else {
// if (dll) {
// lj->args.append("--dll");
// } else if (shared) {
// lj->args.append("--shared");
// }
// lj->args.append("-Bdynamic");
// if (dll || shared) {
// lj->args.append("-e");
// if (g->zig_target.arch.arch == ZigLLVM_x86) {
// lj->args.append("_DllMainCRTStartup@12");
// } else {
// lj->args.append("DllMainCRTStartup");
// }
// lj->args.append("--enable-auto-image-base");
// }
//}
lj->args.append("-o");
lj->args.append(buf_ptr(&lj->out_file));
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&lj->out_file))));
if (lj->link_in_crt) {
if (shared || dll) {
lj->args.append(get_libc_file(g, "dllcrt2.o"));
} else {
if (g->windows_linker_unicode) {
lj->args.append(get_libc_file(g, "crt2u.o"));
} else {
lj->args.append(get_libc_file(g, "crt2.o"));
}
}
lj->args.append(get_libc_static_file(g, "crtbegin.o"));
zig_panic("TODO link in c runtime");
//if (shared || dll) {
// lj->args.append(get_libc_file(g, "dllcrt2.o"));
//} else {
// if (g->windows_linker_unicode) {
// lj->args.append(get_libc_file(g, "crt2u.o"));
// } else {
// lj->args.append(get_libc_file(g, "crt2.o"));
// }
//}
//lj->args.append(get_libc_static_file(g, "crtbegin.o"));
} else {
lj->args.append("-NODEFAULTLIB");
lj->args.append("-ENTRY:_start");
}
for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
const char *lib_dir = g->lib_dirs.at(i);
lj->args.append("-L");
lj->args.append(lib_dir);
lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
}
if (g->link_libc) {
lj->args.append("-L");
lj->args.append(buf_ptr(g->libc_lib_dir));
lj->args.append("-L");
lj->args.append(buf_ptr(g->libc_static_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))));
}
for (size_t i = 0; i < g->link_objects.length; i += 1) {

View File

@ -30,14 +30,14 @@ pub coldcc fn panic(comptime format: []const u8, args: ...) -> noreturn {
}
%%io.stderr.printf(format ++ "\n", args);
%%writeStackTrace(&io.stderr, &global_allocator, io.stderr.isTty(), 1);
%%writeStackTrace(&io.stderr, &global_allocator, io.stderr.isTty() %% false, 1);
%%io.stderr.flush();
os.abort();
}
pub fn printStackTrace() -> %void {
%return writeStackTrace(&io.stderr, &global_allocator, io.stderr.isTty(), 1);
%return writeStackTrace(&io.stderr, &global_allocator, io.stderr.isTty() %% false, 1);
%return io.stderr.flush();
}
@ -48,6 +48,9 @@ const RESET = "\x1b[0m";
pub var user_main_fn: ?fn() -> %void = null;
error PathNotFound;
error InvalidDebugInfo;
pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty_color: bool,
ignore_frame_count: usize) -> %void
{

View File

@ -3,6 +3,7 @@ const Os = builtin.Os;
const system = switch(builtin.os) {
Os.linux => @import("os/linux.zig"),
Os.darwin => @import("os/darwin.zig"),
Os.windows => @import("os/windows/index.zig"),
else => @compileError("Unsupported OS"),
};
@ -15,18 +16,27 @@ const mem = @import("mem.zig");
const Buffer = @import("buffer.zig").Buffer;
const fmt = @import("fmt.zig");
const is_posix = builtin.os != builtin.Os.windows;
const is_windows = builtin.os == builtin.Os.windows;
pub var stdin = InStream {
.fd = system.STDIN_FILENO,
.fd = if (is_posix) system.STDIN_FILENO else {},
.handle_id = if (is_windows) system.STD_INPUT_HANDLE else {},
.handle = if (is_windows) null else {},
};
pub var stdout = OutStream {
.fd = system.STDOUT_FILENO,
.fd = if (is_posix) system.STDOUT_FILENO else {},
.handle_id = if (is_windows) system.STD_OUTPUT_HANDLE else {},
.handle = if (is_windows) null else {},
.buffer = undefined,
.index = 0,
};
pub var stderr = OutStream {
.fd = system.STDERR_FILENO,
.fd = if (is_posix) system.STDERR_FILENO else {},
.handle_id = if (is_windows) system.STD_ERROR_HANDLE else {},
.handle = if (is_windows) null else {},
.buffer = undefined,
.index = 0,
};
@ -58,6 +68,7 @@ error PathNotFound;
error NoMem;
error Unseekable;
error EndOfFile;
error NoStdHandles;
pub const OpenRead = 0b0001;
pub const OpenWrite = 0b0010;
@ -65,7 +76,9 @@ pub const OpenCreate = 0b0100;
pub const OpenTruncate = 0b1000;
pub const OutStream = struct {
fd: i32,
fd: if (is_posix) i32 else void,
handle_id: if (is_windows) system.DWORD else void,
handle: if (is_windows) ?system.HANDLE else void,
buffer: [os.page_size]u8,
index: usize,
@ -81,17 +94,20 @@ pub const OutStream = struct {
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
/// Call close to clean up.
pub fn openMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) -> %OutStream {
switch (builtin.os) {
Os.linux, Os.darwin, Os.macosx, Os.ios => {
const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC;
const fd = %return os.posixOpen(path, flags, mode, allocator);
return OutStream {
.fd = fd,
.index = 0,
.buffer = undefined,
};
},
else => @compileError("Unsupported OS"),
if (is_posix) {
const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC;
const fd = %return os.posixOpen(path, flags, mode, allocator);
return OutStream {
.fd = fd,
.handle = {},
.handle_id = {},
.index = 0,
.buffer = undefined,
};
} else if (is_windows) {
@compileError("TODO: windows OutStream.openMode");
} else {
@compileError("Unsupported OS");
}
}
@ -105,7 +121,7 @@ pub const OutStream = struct {
pub fn write(self: &OutStream, bytes: []const u8) -> %void {
if (bytes.len >= self.buffer.len) {
%return self.flush();
return os.posixWrite(self.fd, bytes);
return self.unbufferedWrite(bytes);
}
var src_index: usize = 0;
@ -151,10 +167,10 @@ pub const OutStream = struct {
}
pub fn flush(self: &OutStream) -> %void {
if (self.index != 0) {
%return os.posixWrite(self.fd, self.buffer[0..self.index]);
self.index = 0;
}
if (self.index == 0)
return;
return self.unbufferedWrite(self.buffer[0..self.index]);
}
pub fn close(self: &OutStream) {
@ -162,15 +178,50 @@ pub const OutStream = struct {
os.posixClose(self.fd);
}
pub fn isTty(self: &const OutStream) -> bool {
return os.posix.isatty(self.fd);
pub fn isTty(self: &OutStream) -> %bool {
if (is_posix) {
return system.isatty(self.fd);
} else if (is_windows) {
return os.windowsIsTty(%return self.getHandle());
} else {
@compileError("Unsupported OS");
}
}
fn getHandle(self: &OutStream) -> %system.HANDLE {
if (self.handle) |handle| return handle;
if (system.GetStdHandle(self.handle_id)) |handle| {
if (handle == system.INVALID_HANDLE_VALUE) {
return error.Unexpected;
}
self.handle = handle;
return handle;
} else {
return error.NoStdHandles;
}
}
fn unbufferedWrite(self: &OutStream, bytes: []const u8) -> %void {
if (is_posix) {
%return os.posixWrite(self.fd, self.buffer[0..self.index]);
self.index = 0;
} else if (is_windows) {
const handle = %return self.getHandle();
%return os.windowsWrite(handle, self.buffer[0..self.index]);
self.index = 0;
} else {
@compileError("Unsupported OS");
}
}
};
// TODO created a BufferedInStream struct and move some of this code there
// BufferedInStream API goes on top of minimal InStream API.
pub const InStream = struct {
fd: i32,
fd: if (is_posix) i32 else void,
handle_id: if (is_windows) system.DWORD else void,
handle: if (is_windows) ?system.HANDLE else void,
/// `path` may need to be copied in memory to add a null terminating byte. In this case
/// a fixed size buffer of size std.os.max_noalloc_path_len is an attempted solution. If the fixed
@ -178,54 +229,57 @@ pub const InStream = struct {
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
/// Call close to clean up.
pub fn open(path: []const u8, allocator: ?&mem.Allocator) -> %InStream {
switch (builtin.os) {
Os.linux, Os.darwin, Os.macosx, Os.ios => {
const flags = system.O_LARGEFILE|system.O_RDONLY;
const fd = %return os.posixOpen(path, flags, 0, allocator);
return InStream {
.fd = fd,
};
},
else => @compileError("Unsupported OS"),
if (is_posix) {
const flags = system.O_LARGEFILE|system.O_RDONLY;
const fd = %return os.posixOpen(path, flags, 0, allocator);
return InStream {
.fd = fd,
.handle_id = {},
.handle = {},
};
} else if (is_windows) {
@compileError("TODO windows InStream.open");
} else {
@compileError("Unsupported OS");
}
}
/// Upon success, the stream is in an uninitialized state. To continue using it,
/// you must use the open() function.
pub fn close(self: &InStream) {
switch (builtin.os) {
Os.linux, Os.darwin, Os.macosx, Os.ios => {
os.posixClose(self.fd);
},
else => @compileError("Unsupported OS"),
if (is_posix) {
os.posixClose(self.fd);
} else {
@compileError("Unsupported OS");
}
}
/// Returns the number of bytes read. If the number read is smaller than buf.len, then
/// the stream reached End Of File.
pub fn read(is: &InStream, buf: []u8) -> %usize {
switch (builtin.os) {
Os.linux, Os.darwin => {
var index: usize = 0;
while (index < buf.len) {
const amt_read = system.read(is.fd, &buf[index], buf.len - index);
const read_err = system.getErrno(amt_read);
if (read_err > 0) {
switch (read_err) {
errno.EINTR => continue,
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.EBADF => return error.BadFd,
errno.EIO => return error.Io,
else => return error.Unexpected,
}
if (is_posix) {
var index: usize = 0;
while (index < buf.len) {
const amt_read = system.read(is.fd, &buf[index], buf.len - index);
const read_err = system.getErrno(amt_read);
if (read_err > 0) {
switch (read_err) {
errno.EINTR => continue,
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.EBADF => return error.BadFd,
errno.EIO => return error.Io,
else => return error.Unexpected,
}
if (amt_read == 0) return index;
index += amt_read;
}
return index;
},
else => @compileError("Unsupported OS"),
if (amt_read == 0) return index;
index += amt_read;
}
return index;
} else if (is_windows) {
@compileError("TODO windows read impl");
} else {
@compileError("Unsupported OS");
}
}
@ -361,8 +415,27 @@ pub const InStream = struct {
}
}
pub fn isTty(self: &const InStream) -> bool {
return os.posix.isatty(self.fd);
pub fn isTty(self: &InStream) -> %bool {
if (is_posix) {
return system.isatty(self.fd);
} else if (is_windows) {
return os.windowsIsTty(%return self.getHandle());
} else {
@compileError("Unsupported OS");
}
}
fn getHandle(self: &InStream) -> %system.HANDLE {
if (self.handle) |handle| return handle;
if (system.GetStdHandle(self.handle_id)) |handle| {
if (handle == system.INVALID_HANDLE_VALUE) {
return error.Unexpected;
}
self.handle = handle;
return handle;
} else {
return error.NoStdHandles;
}
}
};

View File

@ -165,6 +165,8 @@ pub const ChildProcess = struct {
.stdin = if (stdin == StdIo.Pipe) {
io.OutStream {
.fd = stdin_pipe[1],
.handle = {},
.handle_id = {},
.buffer = undefined,
.index = 0,
}
@ -174,6 +176,8 @@ pub const ChildProcess = struct {
.stdout = if (stdout == StdIo.Pipe) {
io.InStream {
.fd = stdout_pipe[0],
.handle = {},
.handle_id = {},
}
} else {
null
@ -181,6 +185,8 @@ pub const ChildProcess = struct {
.stderr = if (stderr == StdIo.Pipe) {
io.InStream {
.fd = stderr_pipe[0],
.handle = {},
.handle_id = {},
}
} else {
null

View File

@ -1,12 +1,11 @@
const builtin = @import("builtin");
const Os = builtin.Os;
pub const windows = @import("windows.zig");
pub const windows = @import("windows/index.zig");
pub const darwin = @import("darwin.zig");
pub const linux = @import("linux.zig");
pub const posix = switch(builtin.os) {
Os.linux => linux,
Os.darwin, Os.macosx, Os.ios => darwin,
Os.windows => windows,
else => @compileError("Unsupported OS"),
};
@ -113,6 +112,9 @@ pub coldcc fn abort() -> noreturn {
_ = posix.raise(posix.SIGKILL);
while (true) {}
},
Os.windows => {
windows.ExitProcess(1);
},
else => @compileError("Unsupported OS"),
}
}
@ -132,7 +134,12 @@ pub fn posixClose(fd: i32) {
error WouldBlock;
error FileClosed;
error DestinationAddressRequired;
error DiskQuota;
error FileTooBig;
error FileSystem;
error NoSpaceLeft;
error BrokenPipe;
error Unexpected;
/// Calls POSIX write, and keeps trying if it gets interrupted.
pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
@ -151,7 +158,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
errno.EIO => error.FileSystem,
errno.ENOSPC => error.NoSpaceLeft,
errno.EPERM => error.AccessDenied,
errno.EPIPE => error.PipeFail,
errno.EPIPE => error.BrokenPipe,
else => error.Unexpected,
}
}
@ -159,6 +166,49 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
}
}
error SystemResources;
error OperationAborted;
error IoPending;
error BrokenPipe;
pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void {
if (!windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null)) {
return switch (windows.GetLastError()) {
windows.ERROR.INVALID_USER_BUFFER => error.SystemResources,
windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources,
windows.ERROR.OPERATION_ABORTED => error.OperationAborted,
windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources,
windows.ERROR.IO_PENDING => error.IoPending,
windows.ERROR.BROKEN_PIPE => error.BrokenPipe,
else => error.Unexpected,
};
}
}
pub fn windowsIsTty(handle: windows.HANDLE) -> bool {
if (windowsIsCygwinPty(handle))
return true;
var out: windows.DWORD = undefined;
return windows.GetConsoleMode(handle, &out);
}
pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool {
const size = @sizeOf(windows.FILE_NAME_INFO);
var name_info_bytes = []u8{0} ** (size + windows.MAX_PATH);
if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo,
@ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len)))
{
return true;
}
const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]);
const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)];
const name_wide = ([]u16)(name_bytes);
return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or
mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null;
}
/// ::file_path may need to be copied in memory to add a null terminating byte. In this case
/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed

View File

@ -1,17 +0,0 @@
pub extern fn CryptAcquireContext(phProv: &HCRYPTPROV, pszContainer: LPCTSTR,
pszProvider: LPCTSTR, dwProvType: DWORD, dwFlags: DWORD) -> bool;
pub extern fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> bool;
pub extern fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: &BYTE) -> bool;
pub const PROV_RSA_FULL = 1;
pub const BYTE = u8;
pub const DWORD = u32;
// TODO something about unicode WCHAR vs char
pub const TCHAR = u8;
pub const LPCTSTR = ?&const TCHAR;
pub const ULONG_PTR = usize;
pub const HCRYPTPROV = ULONG_PTR;

2379
std/os/windows/error.zig Normal file

File diff suppressed because it is too large Load Diff

102
std/os/windows/index.zig Normal file
View File

@ -0,0 +1,102 @@
pub const ERROR = @import("error.zig");
pub extern fn CryptAcquireContext(phProv: &HCRYPTPROV, pszContainer: LPCTSTR,
pszProvider: LPCTSTR, dwProvType: DWORD, dwFlags: DWORD) -> bool;
pub extern fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> bool;
pub extern fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: &BYTE) -> bool;
pub extern fn ExitProcess(exit_code: UINT) -> noreturn;
pub extern fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool;
/// Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis.
/// Multiple threads do not overwrite each other's last-error code.
pub extern fn GetLastError() -> DWORD;
/// Retrieves file information for the specified file.
pub extern fn GetFileInformationByHandleEx(in_hFile: HANDLE, in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
out_lpFileInformation: &c_void, in_dwBufferSize: DWORD) -> bool;
/// Retrieves a handle to the specified standard device (standard input, standard output, or standard error).
pub extern fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE;
/// Reads data from the specified file or input/output (I/O) device. Reads occur at the position specified by the file pointer if supported by the device.
/// This function is designed for both synchronous and asynchronous operations. For a similar function designed solely for asynchronous operation, see ReadFileEx.
pub extern fn ReadFile(in_hFile: HANDLE, out_lpBuffer: LPVOID, in_nNumberOfBytesToRead: DWORD,
out_lpNumberOfBytesRead: &DWORD, in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
/// Writes data to the specified file or input/output (I/O) device.
/// This function is designed for both synchronous and asynchronous operation. For a similar function designed solely for asynchronous operation, see WriteFileEx.
pub extern fn WriteFile(in_hFile: HANDLE, in_lpBuffer: &const c_void, in_nNumberOfBytesToWrite: DWORD,
out_lpNumberOfBytesWritten: ?&DWORD, in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
pub const PROV_RSA_FULL = 1;
pub const BOOL = bool;
pub const BYTE = u8;
pub const DWORD = u32;
pub const FLOAT = f32;
pub const HANDLE = &c_void;
pub const HCRYPTPROV = ULONG_PTR;
pub const LPCTSTR = &const TCHAR;
pub const LPDWORD = &DWORD;
pub const LPVOID = &c_void;
pub const PVOID = &c_void;
pub const TCHAR = u8; // TODO something about unicode WCHAR vs char
pub const UINT = c_uint;
pub const ULONG_PTR = usize;
pub const WCHAR = u16;
pub const LPCVOID = &const c_void;
/// The standard input device. Initially, this is the console input buffer, CONIN$.
pub const STD_INPUT_HANDLE = @maxValue(DWORD) - 10 + 1;
/// The standard output device. Initially, this is the active console screen buffer, CONOUT$.
pub const STD_OUTPUT_HANDLE = @maxValue(DWORD) - 11 + 1;
/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.
pub const STD_ERROR_HANDLE = @maxValue(DWORD) - 12 + 1;
pub const INVALID_HANDLE_VALUE = @intToPtr(HANDLE, 0xFFFFFFFFFFFFFFFF);
pub const OVERLAPPED = extern struct {
Internal: ULONG_PTR,
InternalHigh: ULONG_PTR,
Pointer: PVOID,
hEvent: HANDLE,
};
pub const LPOVERLAPPED = &OVERLAPPED;
pub const MAX_PATH = 260;
// TODO issue #305
pub const FILE_INFO_BY_HANDLE_CLASS = u32;
pub const FileBasicInfo = 0;
pub const FileStandardInfo = 1;
pub const FileNameInfo = 2;
pub const FileRenameInfo = 3;
pub const FileDispositionInfo = 4;
pub const FileAllocationInfo = 5;
pub const FileEndOfFileInfo = 6;
pub const FileStreamInfo = 7;
pub const FileCompressionInfo = 8;
pub const FileAttributeTagInfo = 9;
pub const FileIdBothDirectoryInfo = 10;
pub const FileIdBothDirectoryRestartInfo = 11;
pub const FileIoPriorityHintInfo = 12;
pub const FileRemoteProtocolInfo = 13;
pub const FileFullDirectoryInfo = 14;
pub const FileFullDirectoryRestartInfo = 15;
pub const FileStorageInfo = 16;
pub const FileAlignmentInfo = 17;
pub const FileIdInfo = 18;
pub const FileIdExtdDirectoryInfo = 19;
pub const FileIdExtdDirectoryRestartInfo = 20;
pub const FILE_NAME_INFO = extern struct {
FileNameLength: DWORD,
FileName: [1]WCHAR,
};

View File

@ -9,7 +9,6 @@ const want_main_symbol = std.target.linking_libc;
const want_start_symbol = !want_main_symbol;
const posix_exit = std.os.posix.exit;
extern fn ExitProcess(exit_code: c_uint) -> noreturn;
var argc_ptr: &usize = undefined;
@ -41,7 +40,7 @@ fn callMainAndExit() -> noreturn {
fn exit(failure: bool) -> noreturn {
if (builtin.os == builtin.Os.windows) {
ExitProcess(c_uint(failure));
std.os.windows.ExitProcess(c_uint(failure));
} else {
posix_exit(i32(failure));
}