diff src/fileio.c @ 3728:6765f2581182

[xemacs-hg @ 2006-12-08 02:21:53 by vins] Added Benson Margulies's patch to avoid the dreaded: "File not found and directory write-protected" message under Windows.
author vins
date Fri, 08 Dec 2006 02:22:02 +0000
parents a0adf5f08c44
children a257e03c580e
line wrap: on
line diff
--- a/src/fileio.c	Fri Dec 08 02:17:16 2006 +0000
+++ b/src/fileio.c	Fri Dec 08 02:22:02 2006 +0000
@@ -2291,6 +2291,75 @@
 static int
 check_writable (const Ibyte *filename)
 {
+#if defined(WIN32_NATIVE) || defined(CYGWIN)
+#ifdef CYGWIN
+    char filename_buffer[PATH_MAX];
+#endif
+	// Since this has to work for a directory, we can't just call 'CreateFile'
+	PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */
+	/* these need not be freed, they point into pDesc */
+	PSID psidOwner;
+	PSID psidGroup;
+	PACL pDacl;
+	PACL pSacl;
+	/* end of insides of descriptor */
+	DWORD error;
+	DWORD attributes;
+	HANDLE tokenHandle;
+	GENERIC_MAPPING genericMapping;
+	DWORD accessMask;
+	PRIVILEGE_SET PrivilegeSet;
+    DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET );
+    BOOL fAccessGranted = FALSE;
+	DWORD dwAccessAllowed;
+  Extbyte *fnameext;
+
+#ifdef CYGWIN
+    cygwin_conv_to_full_win32_path(filename, filename_buffer);
+    filename = (Ibyte*)filename_buffer;
+#endif
+
+    C_STRING_TO_TSTR(filename, fnameext);
+	/* Win32 prototype lacks const. */
+	error = qxeGetNamedSecurityInfo(fnameext, SE_FILE_OBJECT, 
+		DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
+		&psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc);
+	if(error != ERROR_SUCCESS) { // FAT?
+		attributes = qxeGetFileAttributes((Extbyte *)filename);
+		return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY));
+	}
+
+	genericMapping.GenericRead = FILE_GENERIC_READ;
+    genericMapping.GenericWrite = FILE_GENERIC_WRITE;
+    genericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
+    genericMapping.GenericAll = FILE_ALL_ACCESS;
+
+	if(!ImpersonateSelf(SecurityDelegation)) {
+		return 0;
+	}
+	if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) {
+		return 0;
+	}
+
+	accessMask = GENERIC_WRITE;
+	MapGenericMask(&accessMask, &genericMapping);
+
+	if(!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping,
+					&PrivilegeSet,       // receives privileges used in check
+					&dwPrivSetSize,      // size of PrivilegeSet buffer
+					&dwAccessAllowed,    // receives mask of allowed access rights
+					&fAccessGranted)) 
+	{
+		CloseHandle(tokenHandle);
+		RevertToSelf();
+		LocalFree(pDesc);
+		return 0;
+	}
+	CloseHandle(tokenHandle);
+	RevertToSelf();
+	LocalFree(pDesc);
+	return fAccessGranted == TRUE;
+#else
 #ifdef HAVE_EACCESS
   return (qxe_eaccess (filename, W_OK) >= 0);
 #else
@@ -2301,6 +2370,7 @@
      but would lose for directories.  */
   return (qxe_access (filename, W_OK) >= 0);
 #endif
+#endif
 }
 
 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /*