Skip to content

Commit 5d9e2e0

Browse files
committed
Base: add support for querying user home directory on Windows
The user profile directory is not possible to access without the user token for the `GetUserProfileDirectoryW`. Instead, we can iterate the users matching a particular filter (e.g. local users). This allows us to at least query some user home directory. Unfortunately, this would disallow querying of users from a domain controller. This resolves an immediate issue of SPM tests depending on the ability to query profile information for a user.
1 parent cce3d9a commit 5d9e2e0

File tree

1 file changed

+46
-8
lines changed

1 file changed

+46
-8
lines changed

CoreFoundation/Base.subproj/CFPlatform.c

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727

2828
#if TARGET_OS_WIN32
29+
#include <lm.h>
2930
#include <shellapi.h>
3031
#include <shlobj.h>
3132
#include <WinIoCtl.h>
@@ -578,14 +579,51 @@ CF_EXPORT CFURLRef CFCopyHomeDirectoryURLForUser(CFStringRef uName) {
578579
}
579580
#elif TARGET_OS_WIN32
580581
// This code can only get the directory for the current user
581-
CFStringRef userName = uName ? CFCopyUserName() : NULL;
582-
if (uName && !CFEqual(uName, userName)) {
583-
CFLog(kCFLogLevelError, CFSTR("CFCopyHomeDirectoryURLForUser(): Unable to get home directory for other user"));
584-
if (userName) CFRelease(userName);
585-
return NULL;
586-
}
587-
if (userName) CFRelease(userName);
588-
return CFCopyHomeDirectoryURL();
582+
if (!uName)
583+
return NULL;
584+
585+
CFStringRef username = CFCopyUserName();
586+
if (CFEqual(uName, username)) {
587+
if (username)
588+
CFRelease(username);
589+
return CFCopyHomeDirectoryURL();
590+
}
591+
592+
CFStringRef home = NULL;
593+
LPUSER_INFO_1 pBuffer = NULL;
594+
DWORD dwEntriesRead = 0;
595+
DWORD dwEntries = 0;
596+
DWORD dwToken = 0;
597+
NTSTATUS nStatus;
598+
do {
599+
nStatus = NetUserEnum(NULL, 1, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pBuffer,
600+
MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwEntries,
601+
&dwToken);
602+
if (nStatus == NERR_Success || nStatus == ERROR_MORE_DATA) {
603+
for (unsigned uiEntry = 0; !home && uiEntry < dwEntriesRead; ++uiEntry) {
604+
CFStringRef name =
605+
CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault,
606+
pBuffer[uiEntry].usri1_name,
607+
kCFStringEncodingUTF16,
608+
kCFAllocatorNull);
609+
610+
if (CFEqual(uName, name))
611+
home = pBuffer[uiEntry].usri1_home_dir
612+
? CFStringCreateWithCString(kCFAllocatorSystemDefault,
613+
pBuffer[uiEntry].usri1_home_dir,
614+
kCFStringEncodingUTF16)
615+
: CFSTR("");
616+
617+
CFRelease(name);
618+
}
619+
}
620+
NetApiBufferFree(pBuffer);
621+
pBuffer = NULL;
622+
} while (nStatus == ERROR_MORE_DATA);
623+
624+
if (username)
625+
CFRelease(username);
626+
return home;
589627
#else
590628
#error Dont know how to compute users home directories on this platform
591629
#endif

0 commit comments

Comments
 (0)