Skip to content

Commit 1d512e4

Browse files
committed
update
1 parent 6402e63 commit 1d512e4

File tree

1 file changed

+63
-56
lines changed

1 file changed

+63
-56
lines changed

aws-runtime/aws-config/mingw/src/aws/sdk/kotlin/runtime/auth/credentials/executeCommandMingw.kt

Lines changed: 63 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,104 +27,110 @@ internal actual suspend fun executeCommand(
2727
memScoped {
2828
// 1) Make a temp file to capture stdout+stderr
2929
val tmpDirBuf = allocArray<UShortVar>(MAX_PATH)
30-
val tmpNameBuf = allocArray<UShortVar>(MAX_PATH)
31-
val gotTmp = GetTempPathW(MAX_PATH, tmpDirBuf) != 0u
32-
if (!gotTmp) error("GetTempPathW failed")
30+
val gotTmp = GetTempPathW(MAX_PATH.toUInt(), tmpDirBuf)
31+
if (gotTmp == 0u) error("GetTempPathW failed")
3332

34-
val gotName = GetTempFileNameW(tmpDirBuf, "KNR".wideCString(this), 0u, tmpNameBuf) != 0u
35-
if (!gotName) error("GetTempFileNameW failed")
36-
val outPath = tmpNameBuf
33+
val tmpNameBuf = allocArray<UShortVar>(MAX_PATH)
34+
val tmpDirStr = tmpDirBuf.toKString()
35+
val gotName = GetTempFileNameW(tmpDirStr, "KNR", 0u, tmpNameBuf)
36+
if (gotName == 0u) error("GetTempFileNameW failed")
37+
val outPath: String = tmpNameBuf.toKString()
3738

38-
// Create the file for the child to write into (inherit handle)
39+
// 2) Create the output file (child inherits this handle)
3940
val sa = alloc<SECURITY_ATTRIBUTES>().apply {
4041
nLength = sizeOf<SECURITY_ATTRIBUTES>().toUInt()
4142
bInheritHandle = TRUE
4243
lpSecurityDescriptor = null
4344
}
45+
4446
val hOut: HANDLE = CreateFileW(
45-
outPath,
46-
(GENERIC_WRITE or FILE_GENERIC_WRITE).toUInt(),
47-
FILE_SHARE_READ or FILE_SHARE_WRITE,
48-
sa.ptr,
49-
CREATE_ALWAYS,
50-
FILE_ATTRIBUTE_NORMAL.toUInt(),
51-
null,
47+
/* lpFileName = */ outPath,
48+
/* dwDesiredAccess = */ GENERIC_WRITE.toUInt(),
49+
/* dwShareMode = */ (FILE_SHARE_READ or FILE_SHARE_WRITE),
50+
/* lpSecurityAttributes = */ sa.ptr,
51+
/* dwCreationDisposition = */ CREATE_ALWAYS,
52+
/* dwFlagsAndAttributes = */ FILE_ATTRIBUTE_NORMAL.toUInt(),
53+
/* hTemplateFile = */ null,
5254
)
53-
if (hOut == INVALID_HANDLE_VALUE) error("CreateFileW failed for temp output")
55+
if (hOut == INVALID_HANDLE_VALUE) error("CreateFileW failed for temp output (GetLastError=${GetLastError()})")
5456

5557
try {
56-
// 2) Build command: use cmd.exe /C "<command>"
57-
// Prefer %ComSpec% if present, else fallback.
58-
val comspecBuf = allocArray<WCHARVar>(MAX_PATH)
59-
val comspecLen = GetEnvironmentVariableW("ComSpec".wideCString(this), comspecBuf, MAX_PATH)
60-
val cmdExe = if (comspecLen > 0u) {
61-
comspecBuf
58+
// 3) Resolve the shell (prefer %ComSpec%)
59+
val comspecBuf = allocArray<UShortVar>(MAX_PATH)
60+
val comspecLen = GetEnvironmentVariableW("ComSpec", comspecBuf, MAX_PATH.toUInt())
61+
val cmdExe: String = if (comspecLen > 0u) {
62+
comspecBuf.toKString()
6263
} else {
63-
"C:\\Windows\\System32\\cmd.exe".wideCString(this)
64+
"C:\\Windows\\System32\\cmd.exe"
6465
}
6566

66-
val cmdLine = (" /C " + command).wideCString(this)
67+
// Build mutable command line buffer for CreateProcessW
68+
// CreateProcessW expects the *command line* buffer to be mutable (it may write into it)
69+
val cmdLineStr = "/C $command"
70+
val cmdLineBuf = cmdLineStr.wideCString(this) // writable buffer from MemScope
6771

68-
// 3) Launch child with redirected stdout/stderr
72+
// 4) Launch child with redirected stdout/stderr
6973
val si = alloc<STARTUPINFOW>().apply {
7074
cb = sizeOf<STARTUPINFOW>().toUInt()
7175
dwFlags = STARTF_USESTDHANDLES.toUInt()
7276
hStdOutput = hOut
7377
hStdError = hOut
74-
hStdInput = GetStdHandle(STD_INPUT_HANDLE) // leave as-is
78+
hStdInput = GetStdHandle(STD_INPUT_HANDLE)
7579
}
7680
val pi = alloc<PROCESS_INFORMATION>()
7781

7882
val created = CreateProcessW(
79-
cmdExe,
80-
cmdLine, // mutable buffer OK; wcstr gives writable copy here
81-
null,
82-
null,
83-
TRUE, // inherit handles (so child gets hOut)
84-
CREATE_NO_WINDOW.toUInt(),
85-
null,
86-
null,
87-
si.ptr,
88-
pi.ptr,
83+
/* lpApplicationName = */ cmdExe,
84+
/* lpCommandLine = */ cmdLineBuf, // mutable
85+
/* lpProcessAttributes = */ null,
86+
/* lpThreadAttributes = */ null,
87+
/* bInheritHandles = */ TRUE,
88+
/* dwCreationFlags = */ CREATE_NO_WINDOW.toUInt(),
89+
/* lpEnvironment = */ null,
90+
/* lpCurrentDirectory = */ null,
91+
/* lpStartupInfo = */ si.ptr,
92+
/* lpProcessInformation= */ pi.ptr,
8993
)
90-
if (created == 0) error("CreateProcessW failed: ${GetLastError()}")
94+
if (created == 0) error("CreateProcessW failed (GetLastError=${GetLastError()})")
9195

9296
try {
93-
// 4) Wait up to timeout; if it times out, terminate
94-
val waitRc = WaitForSingleObject(pi.hProcess, timeoutMillis.toUInt())
95-
if (waitRc == WAIT_TIMEOUT) {
97+
// 5) Wait up to timeout; if it times out, terminate
98+
val waitRc: UInt = WaitForSingleObject(pi.hProcess, timeoutMillis.toUInt())
99+
if (waitRc == WAIT_TIMEOUT.toUInt()) {
96100
TerminateProcess(pi.hProcess, 124u)
97-
// close I/O + process handles and delete temp before throwing
98101
CloseHandle(hOut)
99102
CloseHandle(pi.hThread)
100103
CloseHandle(pi.hProcess)
101-
_wunlink(outPath)
104+
_wunlink(outPath.wideCString(this))
102105
error("Process timed out after ${timeoutMillis}ms")
103106
}
104107

105-
// 5) Get exit code
108+
// 6) Get exit code
106109
val exitCodeVar = alloc<DWORDVar>()
107-
GetExitCodeProcess(pi.hProcess, exitCodeVar.ptr)
110+
if (GetExitCodeProcess(pi.hProcess, exitCodeVar.ptr) == 0) {
111+
// If this fails, propagate a generic error but still try to read output
112+
// (fall through with exitCode = -1)
113+
exitCodeVar.value = 0xFFFFFFFFu
114+
}
108115
val exitCode = exitCodeVar.value.toInt()
109116

110-
// 6) Read the file (up to maxOutputLengthBytes)
111-
// Re-open for reading (child still closed hOut on exit)
117+
// 7) Read back the temp file (bounded)
112118
val hIn: HANDLE = CreateFileW(
113-
outPath,
114-
GENERIC_READ.toUInt(),
115-
FILE_SHARE_READ or FILE_SHARE_WRITE,
116-
null,
117-
OPEN_EXISTING,
118-
FILE_ATTRIBUTE_NORMAL.toUInt(),
119-
null,
119+
/* lpFileName = */ outPath,
120+
/* dwDesiredAccess = */ GENERIC_READ.toUInt(),
121+
/* dwShareMode = */ (FILE_SHARE_READ or FILE_SHARE_WRITE),
122+
/* lpSecurityAttributes = */ null,
123+
/* dwCreationDisposition = */ OPEN_EXISTING,
124+
/* dwFlagsAndAttributes = */ FILE_ATTRIBUTE_NORMAL.toUInt(),
125+
/* hTemplateFile = */ null,
120126
)
121127
if (hIn == INVALID_HANDLE_VALUE) {
122-
// Clean up and bail
123-
_wunlink(outPath)
128+
_wunlink(outPath.wideCString(this))
124129
CloseHandle(pi.hThread)
125130
CloseHandle(pi.hProcess)
126131
return@memScoped exitCode to ""
127132
}
133+
128134
val sb = StringBuilder()
129135
val buf = ByteArray(4096)
130136
val bytesReadVar = alloc<DWORDVar>()
@@ -135,7 +141,7 @@ internal actual suspend fun executeCommand(
135141
if (toRead <= 0) {
136142
// ensure cleanup before throwing
137143
CloseHandle(hIn)
138-
_wunlink(outPath)
144+
_wunlink(outPath.wideCString(this))
139145
throw CredentialsProviderException("Process output exceeded limit of $maxOutputLengthBytes bytes")
140146
}
141147
val n = buf.usePinned {
@@ -148,8 +154,9 @@ internal actual suspend fun executeCommand(
148154
}
149155
} finally {
150156
CloseHandle(hIn)
151-
_wunlink(outPath)
157+
_wunlink(outPath.wideCString(this))
152158
}
159+
153160
exitCode to sb.toString()
154161
} finally {
155162
CloseHandle(pi.hThread)

0 commit comments

Comments
 (0)