From 5023da78932b97809749a5c1b485ae80080bc3a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Sat, 19 Jan 2013 14:35:11 +0000 Subject: [PATCH] Windows SWI upgrades --- os/windows/dirent.h | 8 +-- os/windows/popen.c | 4 +- os/windows/utf8.c | 8 +-- os/windows/utf8.h | 6 +- os/windows/uxnt.c | 157 ++++++++++++++++++++++++++++++++++++++------ 5 files changed, 149 insertions(+), 34 deletions(-) diff --git a/os/windows/dirent.h b/os/windows/dirent.h index 5d9cfd694..92e0b6943 100644 --- a/os/windows/dirent.h +++ b/os/windows/dirent.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _DIRENT_H_INCLUDED @@ -28,8 +28,8 @@ #include #undef _export -#if defined(_UXNT_KERNEL) && !defined(__LCC__) -#define _export __declspec(dllexport) +#if defined(_UXNT_KERNEL) && !defined(__MINGW32__) +#define _export _declspec(dllexport) #else #define _export extern #endif @@ -37,7 +37,7 @@ #define DIRENT_MAX 512 typedef struct dirent -{ void * data; /* actually WIN32_FIND_DATA * */ +{ void * data; /* actually WIN32_FIND_DATA * */ int first; void * handle; /* actually HANDLE */ /* dirent */ diff --git a/os/windows/popen.c b/os/windows/popen.c index d1a253e86..e4a19ed6c 100644 --- a/os/windows/popen.c +++ b/os/windows/popen.c @@ -297,9 +297,9 @@ pt_popen(const char *cmd, const char *mode) } if ( pc->mode == 'r' ) - fptr = _fdopen(_open_osfhandle((long)pc->out[0],_O_BINARY),"r"); + fptr = _fdopen(_open_osfhandle((intptr_t)pc->out[0],_O_BINARY),"r"); else - fptr = _fdopen(_open_osfhandle((long)pc->in[1],_O_BINARY),"w"); + fptr = _fdopen(_open_osfhandle((intptr_t)pc->in[1],_O_BINARY),"w"); finito: if ( fptr ) diff --git a/os/windows/utf8.c b/os/windows/utf8.c index 46d1dba45..54e8a7428 100644 --- a/os/windows/utf8.c +++ b/os/windows/utf8.c @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "utf8.h" @@ -31,7 +31,7 @@ UTF-8 Decoding, based on http://www.cl.cam.ac.uk/~mgk25/unicode.html #define CONT(i) ISUTF8_CB(in[1]) #define VAL(i, s) ((in[i]&0x3f) << s) -char * +static char * _xos_utf8_get_char(const char *in, int *chr) { /* 2-byte, 0x80-0x7ff */ if ( (in[0]&0xe0) == 0xc0 && CONT(1) ) @@ -60,12 +60,12 @@ _xos_utf8_get_char(const char *in, int *chr) } *chr = *in; - + return (char *)in+1; } -char * +static char * _xos_utf8_put_char(char *out, int chr) { if ( chr < 0x80 ) { *out++ = chr; diff --git a/os/windows/utf8.h b/os/windows/utf8.h index 410557d18..85ff86120 100644 --- a/os/windows/utf8.h +++ b/os/windows/utf8.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -52,7 +52,7 @@ ((chr) < 0x80 ? out[0]=(char)(chr), out+1 \ : _xos_utf8_put_char(out, (chr))) -extern char *_xos_utf8_get_char(const char *in, int *chr); -extern char *_xos_utf8_put_char(char *out, int chr); +static char *_xos_utf8_get_char(const char *in, int *chr); +static char *_xos_utf8_put_char(char *out, int chr); #endif /*UTF8_H_INCLUDED*/ diff --git a/os/windows/uxnt.c b/os/windows/uxnt.c index 752fb124d..9df64ac64 100644 --- a/os/windows/uxnt.c +++ b/os/windows/uxnt.c @@ -1,11 +1,10 @@ -/* $Id$ - - Part of SWI-Prolog +/* Part of SWI-Prolog Author: Jan Wielemaker - E-mail: jan@swi.psy.uva.nl + E-mail: J.Wielemaker@vu.nl WWW: http://www.swi-prolog.org - Copyright (C): 1985-2002, University of Amsterdam + Copyright (C): 1985-2012, University of Amsterdam + Vu University Amsterdam This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,7 +18,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define UNICODE 1 @@ -52,11 +51,6 @@ #define FALSE 0 #endif -#ifndef MAXPATHLEN -#define MAXPATHLEN 256 -#endif - - #ifdef __LCC__ #define _close close #define _read read @@ -72,6 +66,10 @@ #define XENOMAP 1 #define XENOMEM 2 +#ifndef PATH_MAX +#define PATH_MAX 260 +#endif + /******************************* * ERRNO * @@ -146,6 +144,21 @@ utf8towcs(wchar_t *dest, const char *src, size_t len) } +static size_t +utf8_strlen(const char *s, size_t len) +{ const char *e = &s[len]; + unsigned int l = 0; + + while(s= e ) { errno = ENAMETOOLONG; return NULL; @@ -600,7 +614,6 @@ _xos_fopen(const char *path, const char *mode) } - /******************************* * FILE MANIPULATIONS * *******************************/ @@ -608,11 +621,101 @@ _xos_fopen(const char *path, const char *mode) int _xos_access(const char *path, int mode) { TCHAR buf[PATH_MAX]; + char sd_buf[512]; + SECURITY_DESCRIPTOR *sd; + BOOL access_status; + DWORD desired_access = 0; + DWORD sd_size, granted_access; + HANDLE token = 0, imp_token = 0; + GENERIC_MAPPING generic_mapping; + PRIVILEGE_SET privelege_set; + DWORD priv_set_len = sizeof(PRIVILEGE_SET); + int retval = -1; + SECURITY_INFORMATION sec_info = + DACL_SECURITY_INFORMATION | + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION; if ( !_xos_os_filenameW(path, buf, PATH_MAX) ) return -1; - return _waccess(buf, mode); + if ( mode == F_OK ) + return _waccess(buf, F_OK); + + sd = (SECURITY_DESCRIPTOR*)&sd_buf; + if ( !GetFileSecurity(buf, sec_info, sd, sizeof(sd_buf), &sd_size) ) + { if ( GetLastError() == ERROR_INVALID_FUNCTION ) + { goto simple; + } else if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) + { errno = ENOENT; + return -1; + } + + if ( !(sd = malloc(sd_size)) ) + { errno = ENOMEM; + return -1; + } + + if ( !GetFileSecurity(buf, sec_info, sd, sd_size, &sd_size) ) + goto simple; + } + + if ( mode & W_OK ) + { if ( _waccess(buf, W_OK ) < 0 ) /* read-only bit set */ + goto out; + } + + if ( !OpenThreadToken(GetCurrentThread(), + TOKEN_DUPLICATE | TOKEN_READ, + TRUE, + &token) ) + { if ( GetLastError() != ERROR_NO_TOKEN ) + goto simple; + + if ( !OpenProcessToken(GetCurrentProcess(), + TOKEN_DUPLICATE | TOKEN_READ, + &token) ) + goto simple; + } + + if ( !DuplicateToken(token, + SecurityImpersonation, + &imp_token) ) + goto simple; + + if (mode & R_OK) desired_access |= GENERIC_READ; + if (mode & W_OK) desired_access |= GENERIC_WRITE; + if (mode & X_OK) desired_access |= GENERIC_EXECUTE; + + generic_mapping.GenericRead = FILE_GENERIC_READ; + generic_mapping.GenericWrite = FILE_GENERIC_WRITE; + generic_mapping.GenericExecute = FILE_GENERIC_EXECUTE; + generic_mapping.GenericAll = FILE_ALL_ACCESS; + MapGenericMask(&desired_access, &generic_mapping); + + if ( !AccessCheck(sd, + imp_token, + desired_access, + &generic_mapping, + &privelege_set, + &priv_set_len, + &granted_access, + &access_status) ) + goto simple; + + if ( access_status ) + retval = 0; + +out: + if ( sd && (char*)sd != sd_buf ) free(sd); + if (imp_token) CloseHandle(imp_token); + if (token) CloseHandle(token); + + return retval; + +simple: + retval = _waccess(buf, mode); + goto out; } @@ -858,6 +961,7 @@ _xos_getenv(const char *name, char *buf, size_t buflen) size = GetEnvironmentVariable(nm, valp, size+1); } + size = wcslen(valp); /* return sometimes holds 0-bytes */ if ( wcstoutf8(buf, valp, buflen) ) rc = strlen(buf); else @@ -876,16 +980,27 @@ _xos_getenv(const char *name, char *buf, size_t buflen) int _xos_setenv(const char *name, char *value, int overwrite) { TCHAR nm[PATH_MAX]; - TCHAR val[PATH_MAX]; + TCHAR buf[PATH_MAX]; + TCHAR *val = buf; + int rc; if ( !utf8towcs(nm, name, PATH_MAX) ) return -1; if ( !overwrite && GetEnvironmentVariable(nm, NULL, 0) > 0 ) return 0; if ( !utf8towcs(val, value, PATH_MAX) ) - return -1; + { size_t wlen = utf8_strlen(value, strlen(value)) + 1; - if ( SetEnvironmentVariable(nm, val) ) + if ( (val = malloc(wlen*sizeof(TCHAR))) == NULL ) + return -1; + utf8towcs(val, value, wlen); + } + + rc = SetEnvironmentVariable(nm, val); + if ( val != buf ) + free(val); + + if ( rc ) return 0; return -1; /* TBD: convert error */