#define WIN32_FILENAMES
#ifdef WIN32_NATIVE
#include "nt.h"
+#include <aclapi.h>
#endif /* WIN32_NATIVE */
+#ifdef CYGWIN
+#include <w32api/aclapi.h>
+#endif
+
+
#define IS_DRIVE(x) isalpha (x)
/* Need to lower-case the drive letter, or else expanded
filenames will sometimes compare inequal, because
#endif /* not WIN32_NATIVE */
}
+
+
/* Return nonzero if file FILENAME exists and can be written. */
static int
check_writable (const char *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;
+
+#ifdef CYGWIN
+ cygwin_conv_to_full_win32_path(filename, filename_buffer);
+ filename = filename_buffer;
+#endif
+
+ /* Win32 prototype lacks const. */
+ error = GetNamedSecurityInfo((LPTSTR)filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
+ &psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc);
+ if (error != ERROR_SUCCESS) { // FAT?
+ attributes = GetFileAttributes(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))
+ {
+ DWORD oops = GetLastError();
+ CloseHandle(tokenHandle);
+ RevertToSelf();
+ LocalFree(pDesc);
+ return 0;
+ }
+ CloseHandle(tokenHandle);
+ RevertToSelf();
+ LocalFree(pDesc);
+ return fAccessGranted == TRUE;
+#else
#ifdef HAVE_EACCESS
return (eaccess (filename, W_OK) >= 0);
#else
but would lose for directories. */
return (access (filename, W_OK) >= 0);
#endif
+#endif
}
DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /*