@@ -82,38 +82,68 @@ CFURLRef _Nullable _CFKnownLocationCreatePreferencesURLForUser(CFKnownLocationUs
8282
8383 switch (user ) {
8484 case _kCFKnownLocationUserAny : {
85- DWORD size = 0 ;
86- GetAllUsersProfileDirectoryW (NULL , & size );
87-
88- wchar_t * path = (wchar_t * )malloc (size * sizeof (wchar_t ));
89- GetAllUsersProfileDirectoryW (path , & size );
90-
91- CFStringRef allUsersPath = CFStringCreateWithCharacters (kCFAllocatorSystemDefault , path , size - 1 );
92- free (path );
93-
94- location = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , allUsersPath , kCFURLWindowsPathStyle , true);
95- CFRelease (allUsersPath );
85+ // Try SHGetKnownFolderPath first (preferred method)
86+ wchar_t * path = NULL ;
87+ HRESULT hr = SHGetKnownFolderPath (& FOLDERID_ProgramData , 0 , NULL , & path );
88+
89+ if (SUCCEEDED (hr ) && path != NULL ) {
90+ CFStringRef allUsersPath = CFStringCreateWithCharacters (kCFAllocatorSystemDefault , path , wcslen (path ));
91+ CoTaskMemFree (path );
92+
93+ location = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , allUsersPath , kCFURLWindowsPathStyle , true);
94+ CFRelease (allUsersPath );
95+ } else {
96+ // Fallback to environment variable
97+ if (path != NULL ) {
98+ CoTaskMemFree (path );
99+ }
100+
101+ const char * programData = __CFgetenv ("ProgramData" );
102+ if (programData == NULL ) {
103+ programData = __CFgetenv ("ALLUSERSPROFILE" );
104+ }
105+
106+ if (programData != NULL ) {
107+ CFStringRef envPath = CFStringCreateWithCString (kCFAllocatorSystemDefault , programData , kCFStringEncodingUTF8 );
108+ if (envPath != NULL ) {
109+ location = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , envPath , kCFURLWindowsPathStyle , true);
110+ CFRelease (envPath );
111+ }
112+ }
113+ }
96114 break ;
97115 }
98116 case _kCFKnownLocationUserCurrent :
99- username = CFGetUserName ();
100- // The above API returns a non-NULL CFStringRef. The failed result is an empty string.
101- // We need to check for that case and fall through to the next case.
102- Boolean isEmpty = CFEqual (username , CFSTR ("" ));
103- CFRelease (username );
104- if (!isEmpty ) {
105- break ;
106- }
107- // fallthrough.
117+ // Leaving this case unhandled (fallthrough) on WinNT.
118+ // Reason (according to `./include/CFKnownLocations.h`):
119+ // The username parameter is ignored for any user constant other than …ByName.
120+ // …ByName with a NULL username is the same as …Current.
108121 case _kCFKnownLocationUserByName : {
122+ // Try SHGetKnownFolderPath first (preferred method)
109123 wchar_t * path = NULL ;
110- SHGetKnownFolderPath (& FOLDERID_LocalAppData , 0 , NULL , & path );
124+ HRESULT hr = SHGetKnownFolderPath (& FOLDERID_LocalAppData , 0 , NULL , & path );
111125
112- CFStringRef userPath = CFStringCreateWithCharacters (kCFAllocatorSystemDefault , path , wcslen (path ));
113- CoTaskMemFree (path );
114-
115- location = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , userPath , kCFURLWindowsPathStyle , true);
116- CFRelease (userPath );
126+ if (SUCCEEDED (hr ) && path != NULL ) {
127+ CFStringRef userPath = CFStringCreateWithCharacters (kCFAllocatorSystemDefault , path , wcslen (path ));
128+ CoTaskMemFree (path );
129+
130+ location = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , userPath , kCFURLWindowsPathStyle , true);
131+ CFRelease (userPath );
132+ } else {
133+ // Fallback to environment variable
134+ if (path != NULL ) {
135+ CoTaskMemFree (path );
136+ }
137+
138+ const char * localAppData = __CFgetenv ("LOCALAPPDATA" );
139+ if (localAppData != NULL ) {
140+ CFStringRef envPath = CFStringCreateWithCString (kCFAllocatorSystemDefault , localAppData , kCFStringEncodingUTF8 );
141+ if (envPath != NULL ) {
142+ location = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , envPath , kCFURLWindowsPathStyle , true);
143+ CFRelease (envPath );
144+ }
145+ }
146+ }
117147 break ;
118148 }
119149 }
0 commit comments