summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2015-10-06 14:25:36 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2015-10-06 14:25:36 (GMT)
commit40ba2e067496a7fab51129617bbcd0f5553f285f (patch)
tree413fc6b0166b78eebf5341d3e76025cad73600ea /win
parent1781dd91805d388923c459d467c95112a815d1bf (diff)
downloadtcl-40ba2e067496a7fab51129617bbcd0f5553f285f.zip
tcl-40ba2e067496a7fab51129617bbcd0f5553f285f.tar.gz
tcl-40ba2e067496a7fab51129617bbcd0f5553f285f.tar.bz2
Fix [b42a851475]: file normalize ~user returns wrong directory on Windows
Diffstat (limited to 'win')
-rwxr-xr-xwin/tclWinFile.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c
index fe30c55..73a2183 100755
--- a/win/tclWinFile.c
+++ b/win/tclWinFile.c
@@ -17,6 +17,7 @@
#include <winioctl.h>
#include <shlobj.h>
#include <lmaccess.h> /* For TclpGetUserHome(). */
+#include <userenv.h> /* For TclpGetUserHome(). */
/*
* The number of 100-ns intervals between the Windows system epoch (1601-01-01
@@ -177,6 +178,10 @@ typedef NET_API_STATUS NET_API_FUNCTION NETAPIBUFFERFREEPROC(LPVOID Buffer);
typedef NET_API_STATUS NET_API_FUNCTION NETGETDCNAMEPROC(
LPWSTR servername, LPWSTR domainname, LPBYTE *bufptr);
+typedef BOOL WINAPI GETPROFILESDIRECTORYPROC(
+ LPWSTR lpProfilesDir, LPDWORD lpcchSize
+);
+
/*
* Declarations for local functions defined in this file:
*/
@@ -1418,15 +1423,18 @@ TclpGetUserHome(
{
char *result;
HINSTANCE netapiInst;
+ HINSTANCE userenvInst;
result = NULL;
Tcl_DStringInit(bufferPtr);
netapiInst = LoadLibraryA("netapi32.dll");
- if (netapiInst != NULL) {
+ userenvInst = LoadLibraryA("userenv.dll");
+ if (netapiInst != NULL && userenvInst != NULL) {
NETAPIBUFFERFREEPROC *netApiBufferFreeProc;
NETGETDCNAMEPROC *netGetDCNameProc;
NETUSERGETINFOPROC *netUserGetInfoProc;
+ GETPROFILESDIRECTORYPROC *getProfilesDirectoryProc;
netApiBufferFreeProc = (NETAPIBUFFERFREEPROC *)
GetProcAddress(netapiInst, "NetApiBufferFree");
@@ -1434,8 +1442,10 @@ TclpGetUserHome(
GetProcAddress(netapiInst, "NetGetDCName");
netUserGetInfoProc = (NETUSERGETINFOPROC *)
GetProcAddress(netapiInst, "NetUserGetInfo");
+ getProfilesDirectoryProc = (GETPROFILESDIRECTORYPROC *)
+ GetProcAddress(userenvInst, "GetProfilesDirectoryW");
if ((netUserGetInfoProc != NULL) && (netGetDCNameProc != NULL)
- && (netApiBufferFreeProc != NULL)) {
+ && (netApiBufferFreeProc != NULL) && (getProfilesDirectoryProc != NULL)) {
USER_INFO_1 *uiPtr, **uiPtrPtr = &uiPtr;
Tcl_DString ds;
int nameLen, badDomain;
@@ -1467,12 +1477,17 @@ TclpGetUserHome(
} else {
/*
* User exists but has no home dir. Return
- * "{Windows Drive}:/users/default".
+ * "{GetProfilesDirectory}/<user>".
*/
-
- GetWindowsDirectoryW(buf, MAX_PATH);
- Tcl_UniCharToUtfDString(buf, 2, bufferPtr);
- Tcl_DStringAppend(bufferPtr, "/users/default", -1);
+ DWORD size = MAX_PATH;
+ int i;
+ getProfilesDirectoryProc(buf, &size);
+ for (i = 0; i < size; ++i){
+ if (buf[i] == '\\') buf[i] = '/';
+ }
+ Tcl_UniCharToUtfDString(buf, size-1, bufferPtr);
+ Tcl_DStringAppend(bufferPtr, "/", -1);
+ Tcl_DStringAppend(bufferPtr, name, -1);
}
result = Tcl_DStringValue(bufferPtr);
(*netApiBufferFreeProc)((void *) uiPtr);
@@ -1483,6 +1498,7 @@ TclpGetUserHome(
(*netApiBufferFreeProc)((void *) wDomain);
}
}
+ FreeLibrary(userenvInst);
FreeLibrary(netapiInst);
}
if (result == NULL) {