summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-03-05 09:57:29 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-03-05 09:57:29 (GMT)
commit1f7d2aae34515de9d6d64ab799f670a1ce5141fc (patch)
tree70b43a73aac6cd2c756bf315e7abee22f77ce22d /win
parente13edcba869deda8b613854d533c106c9855b61d (diff)
parentc862e5709590a9330c9b814109a0fbfd70f027cb (diff)
downloadtcl-1f7d2aae34515de9d6d64ab799f670a1ce5141fc.zip
tcl-1f7d2aae34515de9d6d64ab799f670a1ce5141fc.tar.gz
tcl-1f7d2aae34515de9d6d64ab799f670a1ce5141fc.tar.bz2
Bug [9c5a00c69d]. Fix ~user on Windows
Diffstat (limited to 'win')
-rw-r--r--win/tclWinFile.c73
1 files changed, 35 insertions, 38 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c
index 9a6c5f1..639cd72 100644
--- a/win/tclWinFile.c
+++ b/win/tclWinFile.c
@@ -1458,22 +1458,43 @@ TclpGetUserHome(
if (domain == NULL) {
const char *ptr;
- /*
- * No domain. Firstly check it's the current user
- */
-
+ /*
+ * Treat the current user as a special case because the general case
+ * below does not properly retrieve the path. The NetUserGetInfo
+ * call returns an empty path and the code defaults to the user's
+ * name in the profiles directory. On modern Windows systems, this
+ * is generally wrong as when the account is a Microsoft account,
+ * for example abcdefghi@outlook.com, the directory name is
+ * abcde and not abcdefghi.
+ *
+ * Note we could have just used env(USERPROFILE) here but
+ * the intent is to retrieve (as on Unix) the system's view
+ * of the home irrespective of environment settings of HOME
+ * and USERPROFILE.
+ *
+ * Fixing this for the general user needs more investigating but
+ * at least for the current user we can use a direct call.
+ */
ptr = TclpGetUserName(&ds);
if (ptr != NULL && strcasecmp(name, ptr) == 0) {
- /*
- * Try safest and fastest way to get current user home
- */
-
- ptr = TclGetEnv("HOME", &ds);
- if (ptr != NULL) {
- Tcl_JoinPath(1, &ptr, bufferPtr);
- rc = 1;
- result = Tcl_DStringValue(bufferPtr);
- }
+ HANDLE hProcess;
+ WCHAR buf[MAX_PATH];
+ DWORD nChars = sizeof(buf) / sizeof(buf[0]);
+ /* Sadly GetCurrentProcessToken not in Win 7 so slightly longer */
+ hProcess = GetCurrentProcess(); /* Need not be closed */
+ if (hProcess) {
+ HANDLE hToken;
+ if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
+ if (GetUserProfileDirectoryW(hToken, buf, &nChars)) {
+ Tcl_WinTCharToUtf((TCHAR *)buf,
+ (nChars-1)*sizeof(WCHAR),
+ bufferPtr);
+ result = Tcl_DStringValue(bufferPtr);
+ rc = 1;
+ }
+ CloseHandle(hToken);
+ }
+ }
}
Tcl_DStringFree(&ds);
} else {
@@ -1542,30 +1563,6 @@ TclpGetUserHome(
if (wDomain != NULL) {
NetApiBufferFree((void *) wDomain);
}
- if (result == NULL) {
- /*
- * Look in the "Password Lists" section of system.ini for the local
- * user. There are also entries in that section that begin with a "*"
- * character that are used by Windows for other purposes; ignore user
- * names beginning with a "*".
- */
-
- char buf[MAX_PATH];
-
- if (name[0] != '*') {
- if (GetPrivateProfileStringA("Password Lists", name, "", buf,
- MAX_PATH, "system.ini") > 0) {
- /*
- * User exists, but there is no such thing as a home directory
- * in system.ini. Return "{Windows drive}:/".
- */
-
- GetWindowsDirectoryA(buf, MAX_PATH);
- Tcl_DStringAppend(bufferPtr, buf, 3);
- result = Tcl_DStringValue(bufferPtr);
- }
- }
- }
return result;
}