Skip to content

Commit 02b22f9

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 02b22f9

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

CoreFoundation/Base.subproj/CFPlatform.c

Lines changed: 37 additions & 9 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>
@@ -577,15 +578,42 @@ CF_EXPORT CFURLRef CFCopyHomeDirectoryURLForUser(CFStringRef uName) {
577578
return result;
578579
}
579580
#elif TARGET_OS_WIN32
580-
// 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();
581+
if (uName == NULL)
582+
return CFCopyHomeDirectoryURL();
583+
584+
CFStringRef home = NULL;
585+
LPUSER_INFO_1 pBuffer = NULL;
586+
DWORD dwEntriesRead = 0;
587+
DWORD dwEntries = 0;
588+
DWORD dwToken = 0;
589+
NTSTATUS nStatus;
590+
do {
591+
nStatus = NetUserEnum(NULL, 1, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pBuffer,
592+
MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwEntries,
593+
&dwToken);
594+
if (nStatus == NERR_Success || nStatus == ERROR_MORE_DATA) {
595+
for (unsigned uiEntry = 0; !home && uiEntry < dwEntriesRead; ++uiEntry) {
596+
CFStringRef name =
597+
CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault,
598+
pBuffer[uiEntry].usri1_name,
599+
kCFStringEncodingUTF16,
600+
kCFAllocatorNull);
601+
602+
if (CFEqual(uName, name))
603+
home = pBuffer[uiEntry].usri1_home_dir
604+
? CFStringCreateWithCString(kCFAllocatorSystemDefault,
605+
pBuffer[uiEntry].usri1_home_dir,
606+
kCFStringEncodingUTF16)
607+
: CFSTR("");
608+
609+
CFRelease(name);
610+
}
611+
}
612+
NetApiBufferFree(pBuffer);
613+
pBuffer = NULL;
614+
} while (nStatus == ERROR_MORE_DATA);
615+
616+
return home;
589617
#else
590618
#error Dont know how to compute users home directories on this platform
591619
#endif

0 commit comments

Comments
 (0)