May 08, 2024, 06:16:19 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Folder Attrributes

Started by LarryMc, July 28, 2009, 12:34:22 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

What's the best way (if there is one) to determine if a user can create a read/write file in a particular folder?

i.e. a folder protected by Vista

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

ZeroDog

The OPENFILE function will return a value of 0 if it was successful, and 1 if it fails.  You could use it to determine if a file can be opened for writing:

DEF myfile as BFILE
IF OPENFILE(myfile, "C:\\temp.txt", "W") = 0
    MESSAGEBOX 0, "File successfully opened for writing.","Woot!"
    CLOSEFILE myfile
ELSE
    MESSAGEBOX 0, "Could not open file for writing.","Error!"
ENDIF

LarryMc

I just didn't know if it was going to be that simple and straight-forward on Vista.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

ZeroDog

You can also use the GetFileAttributes to get info on files and folders:

DECLARE "kernel32.dll", GetFileAttributesA(lpFileName:STRING),INT
CONST FILE_ATTRIBUTE_ARCHIVE = 0x20 :'32
CONST FILE_ATTRIBUTE_COMPRESSED = 0x800 :'2048
CONST FILE_ATTRIBUTE_DEVICE = 0x40 :'64
CONST FILE_ATTRIBUTE_DIRECTORY = 0x10 :'16
CONST FILE_ATTRIBUTE_ENCRYPTED = 0x4000 :'16384
CONST FILE_ATTRIBUTE_HIDDEN = 0x2 :'2
CONST FILE_ATTRIBUTE_NORMAL = 0x80 :'128
CONST FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000 :'8192
CONST FILE_ATTRIBUTE_OFFLINE = 0x1000 :'4096
CONST FILE_ATTRIBUTE_READONLY = 0x1 :'1
CONST FILE_ATTRIBUTE_REPARSE_POINT = 0x400 :'1024
CONST FILE_ATTRIBUTE_SPARSE_FILE = 0x200 :'512
CONST FILE_ATTRIBUTE_SYSTEM = 0x4 :'4
CONST FILE_ATTRIBUTE_TEMPORARY = 0x100 :'256
FileAttributes=GetFileAttributesA("C:\\Program Files")
MESSAGEBOX 0,STR$(fileattributes),""
END


I dont use Vista, so I cant exactly do any testing for it.  Just throwing out ideas here.

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

GetFileAttributes can't be used to determine whether a folder is read-only.  At least according to the Microsoft docs.

Ionic Wind Support Team

ZeroDog

Msdn GetFileAttributes function page:
http://msdn.microsoft.com/en-us/library/aa364944(VS.85).aspx

leads to the File attributes page listing the different types and values:
http://msdn.microsoft.com/en-us/library/ee332330(VS.85).aspx

and under the FILE_ATTRIBUTE_READONLY section it lists:
QuoteA file that is read-only. Applications can read the file, but cannot write to it or delete it. This attribute is not honored on directories. For more information, see "You cannot view or change the Read-only or the System attributes of folders in Windows Server 2003, in Windows XP, or in Windows Vista".

and when you click the "for more information, see" link, it brings you to this page:
http://support.microsoft.com/kb/326549

Which has absolutely nothing to do with the function at all...it was about using the Attrib command in dos (or whatever the current equivilent is) to change the read only flags of the folders...  lol. Leave it to microsoft to give thier website attention defeciet dis-hey wanna go ride bikes? 

I didnt really find anything that said that te function would not return the appropriate values for readonly folders... its kind of late, so maybe Im missing something here...

Ionic Wind Support Team

"You cannot view or change the Read-only or the System attributes of folders in Windows Server 2003, in Windows XP, or in Windows Vista"

Which is saying the FILE_ATTRIBUTE_READONLY bit isn't returned (viewable) when the function is used on a folder (directory).

Never tried it though.

Ionic Wind Support Team

ZeroDog

July 29, 2009, 09:59:55 AM #8 Last Edit: July 29, 2009, 10:05:45 AM by ZeroDog
Okay, so I'm getting confused by Microsoft's logic here.  lol.

It says:
For more information, see "You cannot view or change the Read-only or the System attributes of folders in Windows Server 2003, in Windows XP, or in Windows Vista".

This is where it gets confusing.  The "You cannot view .... " line isnt actually a statement, but in fact is the title of the page that it is linked to.  Its a knowledge base article about people having problems viewing or changing the attributes of folders, not with the GetFileAttributes or SetFileAttributes, but in general.

When you click the link, it brings you to a page that has nothing to do with the GetFileAttributes function.  This is what confused me.  It should have been linked to a page that describes why you cannot get the read only flag from winxp and higher, instead of a page that tells you how to change the attributes of files and folders using the ATTRIB.EXE program.

Now, I've just been trying to get the read only attributes of a folder in WinXP using GetFileAttributes.   It works, and it doesnt work at the same time... lol.   If you change the ReadOnly flag within the folder properties page, then it will not return the read only flag, it returns 16 (FILE_ATTRIBUTE_DIRECTORY).   However, if you change the read only flag using ATTRIB.EXE +R then GetFileAttributes will return 17 for the directory (FILE_ATTRIBUTE_DIRECTORY and FILE_ATTRIBUTE_READONLY).

So, it DOES work, but only if the read only flag is set by the ATTRIB.EXE  program.  Apparently setting the read-only flag in the folder properties window does nothing, since it always reverts back to a grayed out checkbox that is checked.
   ???

Leave it to Microsoft to take something simple like file attributes and make it complex and  awkward..... 


sapero

July 29, 2009, 01:27:56 PM #9 Last Edit: July 29, 2009, 01:56:36 PM by sapero
Larry, maybe this little subroutine will show what you need:$include "windowssdk.inc"
$include "aclapi.inc"

if (!CheckDirectoryAccess2("c:\\")) then CheckDirectoryAccess("c:\\")

' method 1: uses security api
sub CheckDirectoryAccess(string path)

HANDLE hFile = CreateFile(path, MAXIMUM_ALLOWED, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
if (hFile = INVALID_HANDLE_VALUE)
_MessageBox(0, "CreateFile error")

else

pointer dacl
pointer pSecurityDesc

if (GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, NULL, &pSecurityDesc))
_MessageBox(0, "GetSecurityInfo error")
else

ACCESS_MASK access
TRUSTEE tr
tr.pMultipleTrustee = 0
tr.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE
tr.TrusteeForm = TRUSTEE_IS_NAME
tr.TrusteeType = TRUSTEE_IS_USER
tr.ptstrName   = "CURRENT_USER"

if (GetEffectiveRightsFromAcl(dacl, &tr, &access))
_MessageBox(0, "GetEffectiveRightsFromAcl error", "")
else

ShowAccess(access)
endif
LocalFree(pSecurityDesc)
endif
CloseHandle(hFile)
endif
endsub


sub ShowAccess(ACCESS_MASK access)
string txt = ""
' selected set of flags from "File Security and Access Rights"
if (access & DELETE_CONTROL) then txt += "DELETE\n"
if (access & FILE_ADD_FILE) then txt += "FILE_ADD_FILE\n"
if (access & FILE_ADD_SUBDIRECTORY) then txt += "FILE_ADD_SUBDIRECTORY\n"
if (access & FILE_ALL_ACCESS) then txt += "FILE_ALL_ACCESS\n"
if (access & FILE_DELETE_CHILD) then txt += "FILE_DELETE_CHILD\n"
if (access & FILE_LIST_DIRECTORY) then txt += "FILE_LIST_DIRECTORY\n"
if (access & FILE_READ_ATTRIBUTES) then txt += "FILE_READ_ATTRIBUTES\n"
if (access & FILE_READ_EA) then txt += "FILE_READ_EA\n"
if (access & FILE_TRAVERSE) then txt += "FILE_TRAVERSE\n"
if (access & FILE_WRITE_ATTRIBUTES) then txt += "FILE_WRITE_ATTRIBUTES\n"
if (access & FILE_WRITE_EA) then txt += "FILE_WRITE_EA\n"
if (access & STANDARD_RIGHTS_READ) then txt += "STANDARD_RIGHTS_READ\n"
if (access & STANDARD_RIGHTS_WRITE) then txt += "STANDARD_RIGHTS_WRITE\n"
_MessageBox(0, txt, "Effective Rights")
endsub


type OBJECT_BASIC_INFORMATION ' un
ULONG Unknown1
ACCESS_MASK DesiredAccess
ULONG HandleCount
ULONG ReferenceCount
ULONG PagedPoolQuota
ULONG NonPagedPoolQuota
BYTE  Unknown2[32]
endtype

enum OBJECT_INFORMATION_CLASS
ObjectBasicInformation = 0
endenum


' method 2: uses native api
sub CheckDirectoryAccess2(string path),BOOL
BOOL success = FALSE
declare NTQO(HANDLE ObjectHandle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG Length, pointer ResultLength),int
UINT NtQueryObject = GetProcAddress(GetModuleHandle("ntdll"), "NtQueryObject")
if (NtQueryObject)

HANDLE hFile = CreateFile(path, MAXIMUM_ALLOWED, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,_
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)

if (hFile = INVALID_HANDLE_VALUE)
_MessageBox(0, "CreateFile error")
else

OBJECT_BASIC_INFORMATION obi
ULONG cch
if (!<NTQO>NtQueryObject(hFile, ObjectBasicInformation, &obi, len(obi), &cch))
_MessageBox(0, "NtQueryObject error")
else
success = TRUE
ShowAccess(obi.DesiredAccess)
endif
CloseHandle(hFile)
endif
endif
return success
endsub


The second option is much (faster?) better, because NtQueryObject is accepting any (real) handle: file, directory, registry, pipe, mutex... without additional flag changes like SE_FILE_OBJECT in GetSecurityInfo.

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

ZeroDog

Nice snippet.  I saw a few people using the CreateFile function in a similar manner in other languages when I was trying to figure this out, but didnt have time to dig too deep into it.  I was also looking at the SHGetFileInfo function in the shell32.dll but I didnt have any luck with that.  Thanks  :)