Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ An implementation of [openkal](https://github.com/mcpplibs/openkal) for Windows.

```toml
[dependencies]
openkal = "0.16.0"
openkal = "0.17.0"

[target.'cfg(windows)'.dependencies]
openkal-windows = "0.12.0"
openkal-windows = "0.13.0"
```

Its purpose is as much to test the specification as to be used. openkal was
Expand Down
4 changes: 2 additions & 2 deletions mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-windows"
version = "0.12.0"
version = "0.13.0"
description = "An implementation of openkal for Windows, written on the Win32 interfaces and the object manager beneath them, using no C runtime symbol."
license = "Apache-2.0"

Expand Down Expand Up @@ -62,7 +62,7 @@ provides-interfaces = [
]

[dependencies]
openkal = "0.16.0"
openkal = "0.17.0"

# The package contributes definitions and no modules. The interface it
# implements is declared by the specification package, which this package
Expand Down
21 changes: 17 additions & 4 deletions port/kernel32.def
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
LIBRARY KERNEL32.dll
EXPORTS
AcquireSRWLockExclusive
AssignProcessToJobObject
CancelIoEx
CloseHandle
CreateEventW
CreateFileW
CreateJobObjectW
CreatePipe
CreateProcessW
CreateSymbolicLinkW
CreateThread
DeleteProcThreadAttributeList
DeviceIoControl
ExitProcess
FlushFileBuffers
FlushInstructionCache
FreeEnvironmentStringsW
Expand All @@ -20,6 +26,7 @@ GetConsoleMode
GetConsoleScreenBufferInfo
GetCurrentDirectoryW
GetCurrentProcess
GetCurrentProcessId
GetCurrentThreadId
GetCurrentThreadStackLimits
GetEnvironmentStringsW
Expand All @@ -29,9 +36,13 @@ GetFinalPathNameByHandleW
GetHandleInformation
GetLastError
GetLogicalDriveStringsW
GetLogicalDrives
GetModuleFileNameW
GetOverlappedResult
GetProcAddress
GetProcessHeap
GetProcessId
GetProcessTimes
GetStdHandle
GetSystemInfo
GetSystemTimePreciseAsFileTime
Expand All @@ -41,25 +52,27 @@ InitializeProcThreadAttributeList
LoadLibraryW
LocalFree
MultiByteToWideChar
OpenProcess
PeekNamedPipe
QueryPerformanceCounter
QueryPerformanceFrequency
ReadFile
ReleaseSRWLockExclusive
ResumeThread
SetConsoleCtrlHandler
SetConsoleMode
SetFilePointerEx
SetHandleInformation
SetInformationJobObject
Sleep
SwitchToThread
TerminateProcess
CreateJobObjectW
AssignProcessToJobObject
TerminateJobObject
SetConsoleCtrlHandler
TerminateProcess
UpdateProcThreadAttribute
VirtualAlloc
VirtualFree
VirtualProtect
WaitForSingleObject
WideCharToMultiByte
WriteConsoleW
WriteFile
29 changes: 29 additions & 0 deletions src/endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,24 @@ inline network_calls* net_or_null() {
return ensure_network() ? &net_calls() : nullptr;
}

// WHETHER THIS SYSTEM OFFERS THE LOCAL FAMILY (0.17): sockets bound to a name in
// the file system, from version 10 1803 on. Asked once, by making one.
inline bool local_family_available() {
// Two contexts asking at once both probe, and both find the same answer.
static volatile int known = 0; // 0 not asked, 1 yes, -1 no
int v = known;
if (v == 0) {
network_calls* n = net_or_null();
v = -1;
if (n) {
const SOCKET s = n->socket(1 /* AF_UNIX */, 1 /* SOCK_STREAM */, 0, nullptr, 0, 0x01 /* WSA_FLAG_OVERLAPPED */);
if (s != INVALID_SOCKET) { n->close(s); v = 1; }
}
known = v;
}
return v == 1;
}

// Whether a stream handle is a socket, version 0.13. GetFileType reports
// FILE_TYPE_PIPE for both a socket and an ordinary named pipe on this system,
// so the two cannot be told apart by that alone; getsockname succeeds only
Expand All @@ -197,6 +215,15 @@ inline bool is_socket_handle(void* h) {
return n->sockname(reinterpret_cast<SOCKET>(h), &ss, &len) == 0;
}

// The sockets whose read direction this program ended (kal_net_shutdown, 0.17).
// A read upon one is the end of input, which the other two systems report and
// this one does not: an overlapped receive pending at `shutdown(SD_RECEIVE)'
// stays pending, and a later one fails with an error rather than ending. The
// record is this implementation's, so the answer does not depend on which
// error the system chose (src/net.cpp).
void note_read_ended(SOCKET s, bool ended);
bool read_ended(SOCKET s);

// ── addresses ───────────────────────────────────────────────────────────────

// The port is carried in host order by kal_endpoint and in network order by the
Expand Down Expand Up @@ -287,6 +314,8 @@ inline int from_system(const ksockaddr_storage& in, kal_endpoint& out) {
return kal_ok;
}

// A connection made at a name (0.17) has no address and port to state.
if (head->family == 1 /* AF_UNIX */ || head->family == 0) return kal_err_not_supported;
return kal_err_invalid;
}

Expand Down
23 changes: 23 additions & 0 deletions src/env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,27 @@ kal_intptr kal_env_var_at(kal_uintptr index, char* out, kal_uintptr cap) {
return give(g_entry[index], g_name_len[index], out, cap);
}

// THE IMAGE THIS SYSTEM STARTED (0.17): the name its loader recorded for the
// program's own module, the full path the process was created from.
// A program built for its environment was loaded by nothing the interface
// names (clause 12: only an image has a loader to name).
kal_intptr kal_env_loader(char* out, kal_uintptr cap) {
(void)out; (void)cap;
return -kal_err_not_found;
}

kal_intptr kal_env_image(char* out, kal_uintptr cap) {
wchar_t wide[okw::kMaxName];
const DWORD n = GetModuleFileNameW(nullptr, wide, okw::kMaxName);
if (n == 0 || n >= okw::kMaxName) return -kal_err_not_found;
char narrow[3 * okw::kMaxName];
const okw_uptr len = okw::narrow(wide, n, narrow, sizeof narrow, false);
return give(narrow, len, out, cap);
}

// For conventions only, as the declaration restricts it.
kal_intptr kal_env_system(char* out, kal_uintptr cap) {
return give("windows", 7, out, cap);
}

}
26 changes: 26 additions & 0 deletions src/exec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ void kal_exec_free(void* p, kal_uintptr size) {
// must change published bytes need not abandon the region.
// This system grants executable memory to every program; nothing here is
// withheld from an artifact for the way it was produced.
// PART OF A REGION (0.17). This system reserves in sixty-four kibibytes and
// protects in pages; the second is what a part is measured in.
kal_uintptr kal_exec_granularity(void) {
static kal_uintptr page = 0;
if (page == 0) {
SYSTEM_INFO si{};
GetSystemInfo(&si);
page = si.dwPageSize ? si.dwPageSize : kPage;
}
return page;
}

int kal_exec_publish_part(void* region, kal_uintptr offset, kal_uintptr size) {
const kal_uintptr g = kal_exec_granularity();
if (region == nullptr || size == 0 || (offset & (g - 1)) != 0 || (size & (g - 1)) != 0
|| (reinterpret_cast<kal_uintptr>(region) & (g - 1)) != 0)
return kal_err_invalid;
void* at = static_cast<char*>(region) + offset;
DWORD previous = 0;
if (!VirtualProtect(at, size, PAGE_EXECUTE_READ, &previous))
return okw::translate_win32(GetLastError());
if (!FlushInstructionCache(GetCurrentProcess(), at, size))
return okw::translate_win32(GetLastError());
return kal_ok;
}

kal_uintptr kal_exec_props(void) {
return KAL_EXEC_PROP_REPUBLISH | KAL_EXEC_PROP_AVAILABLE;
}
Expand Down
Loading
Loading