WinApi HANDLE wrapper and functions to auto-throw WinApi error

This commit is contained in:
Andrew Golovashevich 2025-09-05 00:50:19 +03:00
parent d9d7e3b9c3
commit bcb2ba3dee
5 changed files with 97 additions and 3 deletions

View File

@ -1,5 +1,5 @@
plugins {
kotlin("multiplatform") version "2.1.10"
kotlin("multiplatform") version "2.2.10"
}
group = "ru.landgrafhomyak.utilities"
@ -26,7 +26,7 @@ kotlin {
commonMain {
dependencies {
implementation("ru.landgrafhomyak.utility:highlevel-try-finally:0.6")
implementation("ru.landgrafhomyak.utility:closeable-state-1:1.1")
implementation("ru.landgrafhomyak.utility:closeable-state-1:1.2")
}
}

1
gradle.properties Normal file
View File

@ -0,0 +1 @@
kotlin.mpp.applyDefaultHierarchyTemplate=false

@ -1 +1 @@
Subproject commit bdb1fe56fa79e50850e8072db0b857955d48b479
Subproject commit 4b799c0ecfac0d501ce335147c2ed021e5d4bea9

View File

@ -0,0 +1,35 @@
package ru.landgrafhomyak.utility.kotlin_native_interop_stdlib_0.windows
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlinx.cinterop.ExperimentalForeignApi
import platform.windows.CloseHandle
import platform.windows.HANDLE
import ru.landgrafhomyak.utility.closeable_state_1.CloseableState
import ru.landgrafhomyak.utility.closeable_state_1.HandleWrapper
import ru.landgrafhomyak.utility.closeable_state_1.ManualStateManipulation
@OptIn(ExperimentalForeignApi::class)
public class WindowsHandleWrapper(
handle: HANDLE,
state: CloseableState,
) {
private val _orig = HandleWrapper<HANDLE>(handle, state)
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
@OptIn(ExperimentalContracts::class)
public fun <R> useHandle(method: (HANDLE) -> R): R {
contract {
callsInPlace(method, InvocationKind.EXACTLY_ONCE)
}
return this._orig.useHandle(method)
}
@ManualStateManipulation
public fun close() {
this._orig.close()
zeroToWinApiErr { CloseHandle(this._orig.handle) }
}
}

View File

@ -0,0 +1,58 @@
@file:OptIn(ExperimentalContracts::class)
package ru.landgrafhomyak.utility.kotlin_native_interop_stdlib_0.windows
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlinx.cinterop.ExperimentalForeignApi
import platform.windows.ERROR_SUCCESS
import platform.windows.GetLastError
import platform.windows.NULL
private fun _checkErrnoAndThrow(): Nothing {
val code = GetLastError()
if (code == ERROR_SUCCESS.toUInt())
throw RuntimeException("Function returned error status, but no error set")
WindowsApiException.throwFromLastWindowsErr()
}
public fun Int.zeroToWinApiErr(): Int {
if (this != 0)
return this
_checkErrnoAndThrow()
}
public fun zeroToWinApiErr(call: () -> Int): Int {
contract {
callsInPlace(call, InvocationKind.EXACTLY_ONCE)
}
val status = call()
if (status != 0)
return status
_checkErrnoAndThrow()
}
@OptIn(ExperimentalForeignApi::class)
public fun <R : Any> R?.nullToWinApiErr(): R {
if (this != null && this != NULL)
return this
_checkErrnoAndThrow()
}
@OptIn(ExperimentalForeignApi::class)
public fun <R : Any> nullToWinApiErr(call: () -> R?): R {
contract {
callsInPlace(call, InvocationKind.EXACTLY_ONCE)
}
val ref = call()
if (ref != null && ref != NULL)
return ref
_checkErrnoAndThrow()
}