mirror of
https://github.com/apple/swift-foundation.git
synced 2025-05-23 05:50:12 +08:00
Use fallback home directory on Windows (#854)
* Use %SystemDrive\Users\Public as fallback home directory on Windows * Update to ALLUSERSPROFILE * Fix test failure * Fix iOS test failure
This commit is contained in:
parent
c15a5e1f5c
commit
ebb00b8077
@ -369,33 +369,27 @@ extension String {
|
|||||||
#if !NO_FILESYSTEM
|
#if !NO_FILESYSTEM
|
||||||
internal static func homeDirectoryPath(forUser user: String? = nil) -> String {
|
internal static func homeDirectoryPath(forUser user: String? = nil) -> String {
|
||||||
#if os(Windows)
|
#if os(Windows)
|
||||||
func GetUserProfile() -> String? {
|
|
||||||
return "USERPROFILE".withCString(encodedAs: UTF16.self) { pwszVariable in
|
|
||||||
let dwLength: DWORD = GetEnvironmentVariableW(pwszVariable, nil, 0)
|
|
||||||
// Ensure that `USERPROFILE` is defined.
|
|
||||||
if dwLength == 0 { return nil }
|
|
||||||
return withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) {
|
|
||||||
guard GetEnvironmentVariableW(pwszVariable, $0.baseAddress, dwLength) == dwLength - 1 else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return String(decodingCString: $0.baseAddress!, as: UTF16.self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let user {
|
if let user {
|
||||||
|
func fallbackUserDirectory() -> String {
|
||||||
|
guard let fallback = ProcessInfo.processInfo.environment["ALLUSERSPROFILE"] else {
|
||||||
|
fatalError("Unable to find home directory for user \(user) and ALLUSERSPROFILE environment variable is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
return user.withCString(encodedAs: UTF16.self) { pwszUserName in
|
return user.withCString(encodedAs: UTF16.self) { pwszUserName in
|
||||||
var cbSID: DWORD = 0
|
var cbSID: DWORD = 0
|
||||||
var cchReferencedDomainName: DWORD = 0
|
var cchReferencedDomainName: DWORD = 0
|
||||||
var eUse: SID_NAME_USE = SidTypeUnknown
|
var eUse: SID_NAME_USE = SidTypeUnknown
|
||||||
guard LookupAccountNameW(nil, pwszUserName, nil, &cbSID, nil, &cchReferencedDomainName, &eUse) else {
|
guard LookupAccountNameW(nil, pwszUserName, nil, &cbSID, nil, &cchReferencedDomainName, &eUse) else {
|
||||||
fatalError("unable to lookup SID for user \(user)")
|
return fallbackUserDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
return withUnsafeTemporaryAllocation(of: CChar.self, capacity: Int(cbSID)) { pSID in
|
return withUnsafeTemporaryAllocation(of: CChar.self, capacity: Int(cbSID)) { pSID in
|
||||||
return withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(cchReferencedDomainName)) { pwszReferencedDomainName in
|
return withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(cchReferencedDomainName)) { pwszReferencedDomainName in
|
||||||
guard LookupAccountNameW(nil, pwszUserName, pSID.baseAddress, &cbSID, pwszReferencedDomainName.baseAddress, &cchReferencedDomainName, &eUse) else {
|
guard LookupAccountNameW(nil, pwszUserName, pSID.baseAddress, &cbSID, pwszReferencedDomainName.baseAddress, &cchReferencedDomainName, &eUse) else {
|
||||||
fatalError("unable to lookup SID for user \(user)")
|
return fallbackUserDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
var pwszSID: LPWSTR? = nil
|
var pwszSID: LPWSTR? = nil
|
||||||
@ -425,7 +419,7 @@ extension String {
|
|||||||
|
|
||||||
var hToken: HANDLE? = nil
|
var hToken: HANDLE? = nil
|
||||||
guard OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) else {
|
guard OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) else {
|
||||||
guard let UserProfile = GetUserProfile() else {
|
guard let UserProfile = ProcessInfo.processInfo.environment["UserProfile"] else {
|
||||||
fatalError("unable to evaluate `%UserProfile%`")
|
fatalError("unable to evaluate `%UserProfile%`")
|
||||||
}
|
}
|
||||||
return UserProfile
|
return UserProfile
|
||||||
|
@ -897,4 +897,19 @@ final class FileManagerTests : XCTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testHomeDirectoryForNonExistantUser() throws {
|
||||||
|
#if canImport(Darwin) && !os(macOS)
|
||||||
|
throw XCTSkip("This test is not applicable on this platform")
|
||||||
|
#else
|
||||||
|
#if os(Windows)
|
||||||
|
let fallbackPath = URL(filePath: try XCTUnwrap(ProcessInfo.processInfo.environment["ALLUSERSPROFILE"]), directoryHint: .isDirectory)
|
||||||
|
#else
|
||||||
|
let fallbackPath = URL(filePath: "/var/empty", directoryHint: .isDirectory)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XCTAssertEqual(FileManager.default.homeDirectory(forUser: ""), fallbackPath)
|
||||||
|
XCTAssertEqual(FileManager.default.homeDirectory(forUser: UUID().uuidString), fallbackPath)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user