152 lines
5.7 KiB
Plaintext
152 lines
5.7 KiB
Plaintext
Header_Os_Specific :: struct {
|
|
magic: u32;
|
|
}
|
|
|
|
Read_Channel_Os_Specific :: struct {
|
|
mapping: HANDLE;
|
|
}
|
|
|
|
Write_Channel_Os_Specific :: struct {
|
|
mapping: HANDLE;
|
|
}
|
|
|
|
//
|
|
// Reader stuff:
|
|
//
|
|
|
|
reader_create_channel_os_specific :: (name: string, bytes: s64) -> (success: bool, channel: Read_Channel, already_exists: bool = false) {
|
|
W :: Windows;
|
|
name16 := Utf8.utf8_to_wide(name,, Basic.temp);
|
|
total_bytes := bytes + OFFSET_TO_MESSAGE_DATA;
|
|
|
|
mapping := W.CreateFileMappingW(W.INVALID_HANDLE_VALUE, null, W.PAGE_READWRITE, cast(DWORD)(total_bytes >> 32), cast(DWORD)(total_bytes & 0xffff_ffff), name16);
|
|
|
|
// CreateFileMappingW opens an existing section of the same name and still succeeds.
|
|
// Initializing it would reset a live reader's header and cursors.
|
|
if mapping && W.GetLastError() == W.ERROR_ALREADY_EXISTS {
|
|
W.CloseHandle(mapping);
|
|
return false, .{}, true;
|
|
}
|
|
|
|
// A section created by an elevated process denies this one access: it exists all the same, so
|
|
// this is a second instance, not a reason to run as a first one.
|
|
if !mapping && W.GetLastError() == W.ERROR_ACCESS_DENIED return false, .{}, true;
|
|
|
|
if !mapping {
|
|
nt_status := Windows.RtlGetLastNtStatus();
|
|
error_code, error_string := System.get_error_value_and_string();
|
|
Basic.log_error("Unable to map a view of '%' for % bytes (which is the user-requested % bytes, plus overhead). Error code %, nt_status %, %\n", name, total_bytes, bytes, error_code, Basic.formatInt(nt_status, base=16), error_string);
|
|
return false, .{};
|
|
}
|
|
|
|
pointer := W.MapViewOfFile(mapping, W.FILE_MAP_ALL_ACCESS, 0, 0, cast(u64) total_bytes);
|
|
if !pointer {
|
|
nt_status := Windows.RtlGetLastNtStatus();
|
|
error_code, error_string := System.get_error_value_and_string();
|
|
Basic.log_error("Unable to MapViewOfFile for the channel's memory segment, name '%' bytes '%'. Error code %, nt_status %, %\n", name, bytes, error_code, Basic.formatInt(nt_status, base=16), error_string);
|
|
W.CloseHandle(mapping);
|
|
return false, .{};
|
|
}
|
|
|
|
data := cast(*u8) pointer;
|
|
header_os := cast(*Header_Os_Specific)(data + OFFSET_TO_HEADER_OS_SPECIFIC);
|
|
header_os.magic = (.*) cast(*u32) HEADER_OS_MAGIC.data; // @Endian
|
|
Basic.Initialize(header_os);
|
|
|
|
channel: Read_Channel;
|
|
channel.header = cast(*Header) pointer;
|
|
channel.os_specific.mapping = mapping;
|
|
|
|
return true, channel;
|
|
}
|
|
|
|
reader_release_channel :: (channel: *Read_Channel, channel_name:="unused on windows") -> bool {
|
|
data := cast(*u8) channel.header;
|
|
if !data return false;
|
|
|
|
// header_os := cast(*Header_Os_Specific)(data + OFFSET_TO_HEADER_OS_SPECIFIC);
|
|
// copy := header_os.*;
|
|
|
|
Windows.UnmapViewOfFile(data);
|
|
|
|
os := *channel.os_specific;
|
|
if os.mapping Windows.CloseHandle(os.mapping);
|
|
|
|
return true; // We currently don't check for errors.
|
|
}
|
|
|
|
|
|
//
|
|
// Writer stuff:
|
|
//
|
|
writer_connect :: (name: string, name_not_found_is_quiet := false) -> (success: bool, channel: Write_Channel) {
|
|
W :: Windows;
|
|
name16 := Utf8.utf8_to_wide(name,, Basic.temp);
|
|
|
|
mapping := W.OpenFileMappingW(W.FILE_MAP_ALL_ACCESS, W.BOOL.FALSE, name16);
|
|
|
|
if !mapping {
|
|
nt_status := Windows.RtlGetLastNtStatus();
|
|
error_code, error_string := System.get_error_value_and_string();
|
|
if !name_not_found_is_quiet Basic.log_error("In writer_connect(), unable to map a view of name '%'. Error code %, nt_status %, %\n", name, error_code, Basic.formatInt(nt_status, base=16), error_string);
|
|
return false, .{};
|
|
}
|
|
|
|
header_pointer := W.MapViewOfFile(mapping, W.FILE_MAP_ALL_ACCESS, 0, 0, OFFSET_TO_MESSAGE_DATA);
|
|
if !header_pointer {
|
|
nt_status := Windows.RtlGetLastNtStatus();
|
|
error_code, error_string := System.get_error_value_and_string();
|
|
Basic.log_error("In writer_connect(), unable to MapViewOfFile for the channel's memory segment, name '%'. Error code %, nt_status %, %\n", name, error_code, Basic.formatInt(nt_status, base=16), error_string);
|
|
W.CloseHandle(mapping);
|
|
return false, .{};
|
|
}
|
|
|
|
// Look inside the header to see how big our view should be.
|
|
header_success, actual_bytes := get_size_of_full_mapping_from_stub_header(header_pointer);
|
|
|
|
Windows.UnmapViewOfFile(header_pointer);
|
|
|
|
if !header_success {
|
|
W.CloseHandle(mapping);
|
|
return false, .{};
|
|
}
|
|
|
|
// Now make a new pointer that is the full size.
|
|
header_pointer = W.MapViewOfFile(mapping, W.FILE_MAP_ALL_ACCESS, 0, 0, cast(u64) actual_bytes);
|
|
if !header_pointer {
|
|
nt_status := Windows.RtlGetLastNtStatus();
|
|
error_code, error_string := System.get_error_value_and_string();
|
|
Basic.log_error("In writer_connect(), unable to MapViewOfFile for the channel's memory segment, name '%'. Error code %, nt_status %, %\n", name, error_code, Basic.formatInt(nt_status, base=16), error_string);
|
|
W.CloseHandle(mapping);
|
|
return false, .{};
|
|
}
|
|
|
|
data := cast(*u8) header_pointer;
|
|
header_os := cast(*Header_Os_Specific)(data + OFFSET_TO_HEADER_OS_SPECIFIC);
|
|
|
|
Basic.Initialize(header_os);
|
|
header_os.magic = (.*) cast(*u32) HEADER_OS_MAGIC.data; // @Endian
|
|
|
|
channel: Write_Channel;
|
|
channel.header = cast(*Header) header_pointer;
|
|
channel.os_specific.mapping = mapping;
|
|
|
|
return true, channel;
|
|
}
|
|
|
|
writer_disconnect :: (channel: *Write_Channel) -> bool {
|
|
Windows.UnmapViewOfFile(channel.header);
|
|
Windows.CloseHandle(channel.os_specific.mapping);
|
|
return true;
|
|
}
|
|
|
|
#scope_module
|
|
Windows :: #import "Windows";
|
|
Utf8 :: #import "Windows_Utf8";
|
|
System :: #import "System";
|
|
|
|
HEADER_OS_MAGIC :: "ShmW";
|
|
|
|
HANDLE :: Windows.HANDLE;
|
|
DWORD :: Windows.DWORD;
|