diff options
| author | sebres <sebres@users.sourceforge.net> | 2018-05-28 12:05:15 (GMT) |
|---|---|---|
| committer | sebres <sebres@users.sourceforge.net> | 2018-05-28 12:05:15 (GMT) |
| commit | 89a84af271178d64a75a68b44f8434452fcba03e (patch) | |
| tree | 67e81891ed43cbfe3ccc68548890666ec0d0fd1e /win/tclWinFile.c | |
| parent | a410c0d8d504868b1dbdcaf70a521859e32327fd (diff) | |
| parent | 5e7a1545a61ab4e66c1796ad19343e15cd2cc2ba (diff) | |
| download | tcl-89a84af271178d64a75a68b44f8434452fcba03e.zip tcl-89a84af271178d64a75a68b44f8434452fcba03e.tar.gz tcl-89a84af271178d64a75a68b44f8434452fcba03e.tar.bz2 | |
merge-integrate sebres-bug-9e6b569963-8-5-branch to 8.5
Diffstat (limited to 'win/tclWinFile.c')
| -rwxr-xr-x | win/tclWinFile.c | 179 |
1 files changed, 111 insertions, 68 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 1acc225..0bed39e 100755 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -1422,84 +1422,127 @@ TclpGetUserHome( * name of user's home directory. */ { char *result; - HINSTANCE netapiInst; - HINSTANCE userenvInst; + + static NETAPIBUFFERFREEPROC *netApiBufferFreeProc; + static NETGETDCNAMEPROC *netGetDCNameProc; + static NETUSERGETINFOPROC *netUserGetInfoProc; + static GETPROFILESDIRECTORYPROC *getProfilesDirectoryProc; + static int apistubs = 0; result = NULL; Tcl_DStringInit(bufferPtr); - netapiInst = LoadLibraryA("netapi32.dll"); - userenvInst = LoadLibraryA("userenv.dll"); - if (netapiInst != NULL && userenvInst != NULL) { - NETAPIBUFFERFREEPROC *netApiBufferFreeProc; - NETGETDCNAMEPROC *netGetDCNameProc; - NETUSERGETINFOPROC *netUserGetInfoProc; - GETPROFILESDIRECTORYPROC *getProfilesDirectoryProc; - - netApiBufferFreeProc = (NETAPIBUFFERFREEPROC *) - GetProcAddress(netapiInst, "NetApiBufferFree"); - netGetDCNameProc = (NETGETDCNAMEPROC *) - GetProcAddress(netapiInst, "NetGetDCName"); - netUserGetInfoProc = (NETUSERGETINFOPROC *) - GetProcAddress(netapiInst, "NetUserGetInfo"); - getProfilesDirectoryProc = (GETPROFILESDIRECTORYPROC *) - GetProcAddress(userenvInst, "GetProfilesDirectoryW"); - if ((netUserGetInfoProc != NULL) && (netGetDCNameProc != NULL) - && (netApiBufferFreeProc != NULL) && (getProfilesDirectoryProc != NULL)) { - USER_INFO_1 *uiPtr, **uiPtrPtr = &uiPtr; - Tcl_DString ds; - int nameLen, badDomain; - char *domain; - WCHAR *wName, *wHomeDir, *wDomain; - WCHAR buf[MAX_PATH]; - - badDomain = 0; - nameLen = -1; - wDomain = NULL; - domain = strchr(name, '@'); - if (domain != NULL) { - Tcl_DStringInit(&ds); - wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds); - badDomain = (netGetDCNameProc)(NULL, wName, - (LPBYTE *) &wDomain); - Tcl_DStringFree(&ds); - nameLen = domain - name; + if (!apistubs) { + HINSTANCE handle; + TCL_DECLARE_MUTEX(initializeMutex) + Tcl_MutexLock(&initializeMutex); + if (!apistubs) { + handle = LoadLibraryA("netapi32.dll"); + if (handle) { + netApiBufferFreeProc = (NETAPIBUFFERFREEPROC *) + GetProcAddress(handle, "NetApiBufferFree"); + netGetDCNameProc = (NETGETDCNAMEPROC *) + GetProcAddress(handle, "NetGetDCName"); + netUserGetInfoProc = (NETUSERGETINFOPROC *) + GetProcAddress(handle, "NetUserGetInfo"); + Tcl_CreateExitHandler(TclpUnloadFile, handle); } - if (badDomain == 0) { - Tcl_DStringInit(&ds); - wName = Tcl_UtfToUniCharDString(name, nameLen, &ds); - if ((netUserGetInfoProc)(wDomain, wName, 1, - (LPBYTE *) uiPtrPtr) == 0) { - DWORD i, size = MAX_PATH; - wHomeDir = uiPtr->usri1_home_dir; - if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) { - size = lstrlenW(wHomeDir); - Tcl_UniCharToUtfDString(wHomeDir, size, bufferPtr); - } else { - /* - * User exists but has no home dir. Return - * "{GetProfilesDirectory}/<user>". - */ - getProfilesDirectoryProc(buf, &size); - Tcl_UniCharToUtfDString(buf, size-1, bufferPtr); - Tcl_DStringAppend(bufferPtr, "/", 1); - Tcl_DStringAppend(bufferPtr, name, nameLen); - } + handle = LoadLibraryA("userenv.dll"); + if (handle) { + getProfilesDirectoryProc = (GETPROFILESDIRECTORYPROC *) + GetProcAddress(handle, "GetProfilesDirectoryW"); + Tcl_CreateExitHandler(TclpUnloadFile, handle); + } + + apistubs = -1; + if ( (netUserGetInfoProc != NULL) && (netGetDCNameProc != NULL) + && (netApiBufferFreeProc != NULL) && (getProfilesDirectoryProc != NULL) + ) { + apistubs = 1; + } + } + Tcl_MutexUnlock(&initializeMutex); + } + + if (apistubs == 1) { + USER_INFO_1 *uiPtr; + Tcl_DString ds; + int nameLen, rc; + char *domain; + WCHAR *wName, *wHomeDir, *wDomain; + WCHAR buf[MAX_PATH]; + + rc = 0; + nameLen = -1; + wDomain = NULL; + domain = strchr(name, '@'); + if (domain == NULL) { + const char *ptr; + + /* no domain - firstly check it's the current user */ + if ( (ptr = TclpGetUserName(&ds)) != 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); - /* be sure we returns normalized path */ - for (i = 0; i < size; ++i){ - if (result[i] == '\\') result[i] = '/'; - } - (*netApiBufferFreeProc)((void *) uiPtr); } - Tcl_DStringFree(&ds); } - if (wDomain != NULL) { - (*netApiBufferFreeProc)((void *) wDomain); + Tcl_DStringFree(&ds); + } else { + Tcl_DStringInit(&ds); + wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds); + rc = (netGetDCNameProc)(NULL, wName, (LPBYTE *) &wDomain); + Tcl_DStringFree(&ds); + nameLen = domain - name; + } + if (rc == 0) { + Tcl_DStringInit(&ds); + wName = Tcl_UtfToUniCharDString(name, nameLen, &ds); + while ((netUserGetInfoProc)(wDomain, wName, 1, + (LPBYTE *) &uiPtr) != 0) { + /* + * user does not exists - if domain was not specified, + * try again using current domain. + */ + rc = 1; + if (domain != NULL) break; + /* get current domain */ + rc = (netGetDCNameProc)(NULL, NULL, (LPBYTE *) &wDomain); + if (rc != 0) break; + domain = INT2PTR(-1); /* repeat once */ } + if (rc == 0) { + DWORD i, size = MAX_PATH; + wHomeDir = uiPtr->usri1_home_dir; + if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) { + size = lstrlenW(wHomeDir); + Tcl_UniCharToUtfDString(wHomeDir, size, bufferPtr); + } else { + /* + * User exists but has no home dir. Return + * "{GetProfilesDirectory}/<user>". + */ + getProfilesDirectoryProc(buf, &size); + Tcl_UniCharToUtfDString(buf, size-1, bufferPtr); + Tcl_DStringAppend(bufferPtr, "/", 1); + Tcl_DStringAppend(bufferPtr, name, nameLen); + } + result = Tcl_DStringValue(bufferPtr); + /* be sure we returns normalized path */ + for (i = 0; i < size; ++i){ + if (result[i] == '\\') result[i] = '/'; + } + (*netApiBufferFreeProc)((void *) uiPtr); + } + Tcl_DStringFree(&ds); + } + if (wDomain != NULL) { + (*netApiBufferFreeProc)((void *) wDomain); } - FreeLibrary(userenvInst); - FreeLibrary(netapiInst); } if (result == NULL) { /* |
