Update to 8.5.19

This commit is contained in:
Zachary Ware
2017-11-24 17:50:39 -06:00
parent 49cac229de
commit 9651fde681
557 changed files with 20338 additions and 26391 deletions

116
win/tclWinFile.c Normal file → Executable file
View 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);