Update to 8.5.19
This commit is contained in:
116
win/tclWinFile.c
Normal file → Executable file
116
win/tclWinFile.c
Normal file → Executable file
@@ -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:
|
||||
*/
|
||||
@@ -704,7 +709,7 @@ NativeReadReparse(
|
||||
HANDLE hFile;
|
||||
DWORD returnedLength;
|
||||
|
||||
hFile = (*tclWinProcs->createFileProc)(linkDirPath, desiredAccess, 0,
|
||||
hFile = (*tclWinProcs->createFileProc)(linkDirPath, desiredAccess, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
|
||||
@@ -1225,9 +1230,9 @@ WinIsReserved(
|
||||
if ((path[0] == 'c' || path[0] == 'C')
|
||||
&& (path[1] == 'o' || path[1] == 'O')) {
|
||||
if ((path[2] == 'm' || path[2] == 'M')
|
||||
&& path[3] >= '1' && path[3] <= '4') {
|
||||
&& path[3] >= '1' && path[3] <= '9') {
|
||||
/*
|
||||
* May have match for 'com[1-4]:?', which is a serial port.
|
||||
* May have match for 'com[1-9]:?', which is a serial port.
|
||||
*/
|
||||
|
||||
if (path[4] == '\0') {
|
||||
@@ -1246,9 +1251,9 @@ WinIsReserved(
|
||||
} else if ((path[0] == 'l' || path[0] == 'L')
|
||||
&& (path[1] == 'p' || path[1] == 'P')
|
||||
&& (path[2] == 't' || path[2] == 'T')) {
|
||||
if (path[3] >= '1' && path[3] <= '3') {
|
||||
if (path[3] >= '1' && path[3] <= '9') {
|
||||
/*
|
||||
* May have match for 'lpt[1-3]:?'
|
||||
* May have match for 'lpt[1-9]:?'
|
||||
*/
|
||||
|
||||
if (path[4] == '\0') {
|
||||
@@ -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,16 @@ 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 i, size = MAX_PATH;
|
||||
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 +1497,7 @@ TclpGetUserHome(
|
||||
(*netApiBufferFreeProc)((void *) wDomain);
|
||||
}
|
||||
}
|
||||
FreeLibrary(userenvInst);
|
||||
FreeLibrary(netapiInst);
|
||||
}
|
||||
if (result == NULL) {
|
||||
@@ -1856,6 +1871,9 @@ TclpObjChdir(
|
||||
|
||||
nativePath = (const TCHAR *) Tcl_FSGetNativePath(pathPtr);
|
||||
|
||||
if (!nativePath) {
|
||||
return -1;
|
||||
}
|
||||
result = (*tclWinProcs->setCurrentDirectoryProc)(nativePath);
|
||||
|
||||
if (result == 0) {
|
||||
@@ -3197,19 +3215,75 @@ TclNativeCreateNativeRep(
|
||||
}
|
||||
|
||||
str = Tcl_GetStringFromObj(validPathPtr, &len);
|
||||
if (str[0] == '/' && str[1] == '/' && str[2] == '?' && str[3] == '/') {
|
||||
char *p;
|
||||
|
||||
for (p = str; p && *p; ++p) {
|
||||
if (*p == '/') {
|
||||
*p = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
Tcl_WinUtfToTChar(str, len, &ds);
|
||||
if (tclWinProcs->useWide) {
|
||||
WCHAR *wp = (WCHAR *) Tcl_DStringValue(&ds);
|
||||
/* For a reserved device, strip a possible postfix ':' */
|
||||
len = WinIsReserved(str);
|
||||
/* For normal devices */
|
||||
if (len == 0) len = Tcl_DStringLength(&ds)>>1;
|
||||
/*
|
||||
** If path starts with "//?/" or "\\?\" (extended path), translate
|
||||
** any slashes to backslashes but accept the '?' as being valid.
|
||||
*/
|
||||
if ((str[0]=='\\' || str[0]=='/') && (str[1]=='\\' || str[1]=='/')
|
||||
&& str[2]=='?' && (str[3]=='\\' || str[3]=='/')) {
|
||||
wp[0] = wp[1] = wp[3] = '\\';
|
||||
str += 4;
|
||||
wp += 4;
|
||||
len -= 4;
|
||||
}
|
||||
/*
|
||||
** If there is a drive prefix, the ':' must be considered valid.
|
||||
**/
|
||||
if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z'))
|
||||
&& str[1]==':') {
|
||||
wp += 2;
|
||||
len -= 2;
|
||||
}
|
||||
while (len-->0) {
|
||||
if ((*wp < ' ') || wcschr(L"\"*:<>?|", *wp)) {
|
||||
Tcl_DecrRefCount(validPathPtr);
|
||||
Tcl_DStringFree(&ds);
|
||||
return NULL;
|
||||
} else if (*wp=='/') {
|
||||
*wp = '\\';
|
||||
}
|
||||
++wp;
|
||||
}
|
||||
len = Tcl_DStringLength(&ds) + sizeof(WCHAR);
|
||||
} else {
|
||||
char *p = Tcl_DStringValue(&ds);
|
||||
len = Tcl_DStringLength(&ds);
|
||||
/*
|
||||
** If path starts with "//?/" or "\\?\" (extended path), translate
|
||||
** any slashes to backslashes but accept the '?' as being valid.
|
||||
*/
|
||||
if ((str[0]=='\\' || str[0]=='/') && (str[1]=='\\' || str[1]=='/')
|
||||
&& str[2]=='?' && (str[3]=='\\' || str[3]=='/')) {
|
||||
p[0] = p[1] = p[3] = '\\';
|
||||
str += 4;
|
||||
p += 4;
|
||||
len -= 4;
|
||||
}
|
||||
/*
|
||||
** If there is a drive prefix, the ':' must be considered valid.
|
||||
**/
|
||||
if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z'))
|
||||
&& str[1]==':') {
|
||||
p += 2;
|
||||
len -= 2;
|
||||
}
|
||||
while (len-->0) {
|
||||
if ((*p < ' ') || strchr("\"*:<>?|", *p)) {
|
||||
Tcl_DecrRefCount(validPathPtr);
|
||||
Tcl_DStringFree(&ds);
|
||||
return NULL;
|
||||
} else if (*p=='/') {
|
||||
*p = '\\';
|
||||
}
|
||||
++p;
|
||||
}
|
||||
len = Tcl_DStringLength(&ds) + sizeof(char);
|
||||
}
|
||||
Tcl_DecrRefCount(validPathPtr);
|
||||
|
||||
Reference in New Issue
Block a user