@@ -64,15 +64,18 @@ public enum Library: Sendable {
64
64
}
65
65
66
66
public static func locate< T> ( _ pointer: T . Type ) -> Path {
67
- let outPointer : UnsafeMutablePointer < CInterop . PlatformChar >
68
67
#if os(Windows)
69
68
var handle : HMODULE ?
70
- GetModuleHandleExW ( DWORD ( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) , unsafeBitCast ( pointer, to: LPCWSTR ? . self) , & handle)
71
- let capacity = 260
72
- outPointer = . allocate( capacity: capacity)
73
- defer { outPointer. deallocate ( ) }
74
- GetModuleFileNameW ( handle, outPointer, DWORD ( capacity) )
69
+ guard GetModuleHandleExW ( DWORD ( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) , unsafeBitCast ( pointer, to: LPCWSTR ? . self) , & handle) else {
70
+ return Path ( " " )
71
+ }
72
+ do {
73
+ return try Path ( SWB_GetModuleFileNameW ( handle) )
74
+ } catch {
75
+ return Path ( " " )
76
+ }
75
77
#else
78
+ let outPointer : UnsafeMutablePointer < CInterop . PlatformChar >
76
79
var info = Dl_info ( )
77
80
#if os(Android)
78
81
dladdr ( unsafeBitCast ( pointer, to: UnsafeMutableRawPointer . self) , & info)
@@ -81,8 +84,8 @@ public enum Library: Sendable {
81
84
dladdr ( unsafeBitCast ( pointer, to: UnsafeMutableRawPointer ? . self) , & info)
82
85
outPointer = UnsafeMutablePointer ( mutating: info. dli_fname)
83
86
#endif
84
- #endif
85
87
return Path ( platformString: outPointer)
88
+ #endif
86
89
}
87
90
}
88
91
@@ -114,3 +117,32 @@ public struct LibraryHandle: @unchecked Sendable {
114
117
self . rawValue = rawValue
115
118
}
116
119
}
120
+
121
+ #if os(Windows)
122
+ @_spi ( Testing) public func SWB_GetModuleFileNameW( _ hModule: HMODULE ? ) throws -> String {
123
+ #if DEBUG
124
+ var bufferCount = Int ( 1 ) // force looping
125
+ #else
126
+ var bufferCount = Int ( MAX_PATH)
127
+ #endif
128
+ while true {
129
+ if let result = try withUnsafeTemporaryAllocation ( of: WCHAR . self, capacity: bufferCount, { buffer in
130
+ switch ( GetModuleFileNameW ( hModule, buffer. baseAddress!, DWORD ( buffer. count) ) , GetLastError ( ) ) {
131
+ case ( 1 ..< DWORD ( bufferCount) , DWORD ( ERROR_SUCCESS) ) :
132
+ guard let result = String . decodeCString ( buffer. baseAddress!, as: UTF16 . self) ? . result else {
133
+ throw Win32Error ( DWORD ( ERROR_ILLEGAL_CHARACTER) )
134
+ }
135
+ return result
136
+ case ( DWORD ( bufferCount) , DWORD ( ERROR_INSUFFICIENT_BUFFER) ) :
137
+ bufferCount += Int ( MAX_PATH)
138
+ return nil
139
+ case ( _, let errorCode) :
140
+ throw Win32Error ( errorCode)
141
+ }
142
+ } ) {
143
+ return result
144
+ }
145
+ }
146
+ preconditionFailure ( " unreachable " )
147
+ }
148
+ #endif
0 commit comments