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;