# ...more kernel32 to find file attributes

In this lesson, I am going to introduce a number of functions in kernel32.dll which will allow us to change some file attributes. To keep the example simple, it will only be able to change it's own
READONLY
HIDDEN, and
ARCHIVE attributes.
A file with these and other attributes not set is considered NORMAL.
I am going to use check-boxes to both display, and change attributes.
The program will also display the file's size.

The first function used in this program, CreateFile(), is only required because the GetFileSize() function requires a windows file handle, in order to retrieve the file's size. Since I have now opened a file, in effect creating a Windows object, I've also implemented the CloseHandle() function, to destroy this object once I'm done with it.
While Windows would do this for me once I close the program, I thought I'd introduce it here anyways...

Since the GetFileAttributes() and SetFileAttributes() functions only require a pointer to an allocated string which contains the file name, they are a little easier to use.

-- attrib1.exw

    --attrib1.exw--
    --start code--

    include win32lib.ew
    without warning

    atom junk, file_id_ptr, attribs

    --these are the file attribute bits we are concerned with.
    --to keep our program small, we just refer to them by number.
    --to get fancy, declare these as constants,
    --so you can refer to them by name.

    --FILE_ATTRIBUTE_READONLY = 1
    --FILE_ATTRIBUTE_HIDDEN = 2
    --FILE_ATTRIBUTE_ARCHIVE = 32
    --FILE_ATTRIBUTE_NORMAL = 128

    constant
    zzOPEN_EXISTING = 3, -- declared as a constant.

    Win     = create( Window, "File Attributes", 0, 0, 0, 205, 225, 0 ),
    Label0  = create( LText, "filename:", Win, 10, 12, 70, 20, 0 ),
    Entry   = create( EditText, "", Win, 75, 10, 110, 20, 0 ),
    Label1  = create( LText, "", Win, 10, 40, 180, 20, 0 ),
    Label2  = create( LText, "", Win, 10, 65, 180, 20, 0 ),
    Check1  = create( CheckBox, " Read-Only (1)", Win, 10, 90, 170, 20, 0 ),
    Check2  = create( CheckBox, " Hidden    (2)", Win, 10, 115, 170, 20, 0 ),
    Check3  = create( CheckBox, " Archive   (32)", Win, 10, 140, 170, 20, 0 ),
    Button1 = create( PushButton, "Change Attributes", Win, 10, 165, 130, 25, 0 ),
    --**
    --links to kernel32.dll functions not in Win32lib.ew
    zGetFileAttributes = registerw32Function( kernel32, "GetFileAttributesA", {C_POINTER}, C_LONG ),
    zSetFileAttributes = registerw32Function( kernel32, "SetFileAttributesA", {C_POINTER, C_LONG}, C_LONG ),
    zCreateFile = registerw32Function( kernel32, "CreateFileA", {C_POINTER,C_LONG,C_LONG,C_LONG,C_LONG,C_LONG,C_LONG},C_LONG),
    zCloseHandle = registerw32Function( kernel32, "CloseHandle", {C_LONG},C_LONG),
    zGetFileSize = registerw32Function(kernel32,"GetFileSize", {C_LONG,C_LONG},C_LONG )

    --set the font for the check-box labels to 'fixed'
    --so everything stays lined up.
    for i=Check1 to Check3 do
       setFont( i,"Courier New",11,1)
    end for

    --on startup
    procedure onLoad_Win(atom self, atom event, sequence params)
      atom size
      setText(Entry,"attrib1.exw")
      file_id_ptr=allocate_string("attrib1.exw")
      junk=w32Func(zCreateFile,{file_id_ptr,0,0,0,zOPEN_EXISTING,0,0})
      size=w32Func(zGetFileSize,{junk,0})
      setText(Label1,"file size = " & sprintf("%d",size))
      junk=w32Func(zCloseHandle,{junk})
      junk=w32Func(zGetFileAttributes,{file_id_ptr})
      setText(Label2,"current attributes = " & sprintf("%d",junk))
      if junk < 128 then
        if junk >= 32 then setCheck(Check3,1) junk=junk-32 end if
        if junk >= 2 then setCheck(Check2,1) junk=junk-2 end if
        if junk = 1 then setCheck(Check1,1) end if
      end if
      free(file_id_ptr)
    end procedure

    --our 'Button1' procedure to change attributes
    procedure set_attribs(atom self, atom event, sequence params)
    --pre-set the variable
      attribs=0
      --then add up the current check-box settings
      if isChecked(Check1) then attribs=attribs+1 end if
      if isChecked(Check2) then attribs=attribs+2 end if
      if isChecked(Check3) then attribs=attribs+32 end if
      --save our file name in a 'string' structure in memory
      file_id_ptr=allocate_string("attrib1.exw")
      --set the attributes
      junk=w32Func(zSetFileAttributes,{file_id_ptr,attribs})
      --confirm our changes
      junk=w32Func(zGetFileAttributes,{file_id_ptr})
      --and display the numerical value in a text line.
      setText(Label2,"current attributes = " & sprintf("%d",junk))
      free(file_id_ptr)
    end procedure

    setHandler( Win, w32HOpen, routine_id( "onLoad_Win") )
    setHandler( Button1, w32HClick, routine_id( "set_attribs") )

    --end code--

Just in case you don't know yet, where all these Windows function definitions are coming from, they are from Win32.hlp. This file is available through the Euphoria Archives. ( Win32 )

These functions are all described in the 'C' programming language style, which is why they all have to be 'wrapped' to be usable in Euphoria.

Just one caution though, if you are trying to use these in your own programs. The function name in Win32.hlp is NOT necessarily the same as the name in the DLL. For instance, the function CreateFile, described in the help file, is actually called CreateFileA in the DLL. Most common DLL's are in the \Windows\System folder. Right-clicking on a DLL, and using QuickView, if it's installed on your system, will open the file, in which ..somewhere under an EXPORT TABLE heading.. is a list of the proper names for the functions. If you don't see an export table using QuickView, it's likely that the DLL has been compressed, and your only option is to seek information about this DLL elsewhere. The Window's header ( .h ) files included with most Windows compilers are another source for this information.

(4/8/02)
There's a little bug-fix in onLoad_Win(), by Jordah Ferguson. I had previously attempted to close the file by using the file size as the file handle. ( .. not keeping track of my 'junk' ;-) .. )

    junk=w32Func(zGetFileSize,{junk,0})  --junk here takes up the file size
    setText(Label1,"file size = " & sprintf("%d",junk))
    junk=w32Func(zCloseHandle,{junk})  --then you are attempting to close file size

...end...

CONTENTS