Let's start with a couple of definitions:
&GLOBAL-DEFINE FILE_ATTRIBUTE_READONLY 1 &GLOBAL-DEFINE FILE_ATTRIBUTE_HIDDEN 2 &GLOBAL-DEFINE FILE_ATTRIBUTE_SYSTEM 4 &GLOBAL-DEFINE FILE_ATTRIBUTE_DIRECTORY 16 &GLOBAL-DEFINE FILE_ATTRIBUTE_ARCHIVE 32 &GLOBAL-DEFINE FILE_ATTRIBUTE_NORMAL 128 &GLOBAL-DEFINE FILE_ATTRIBUTE_COMPRESSED 2048 PROCEDURE SetFileAttributesA EXTERNAL "kernel32" : DEFINE INPUT PARAMETER lpFilename AS CHARACTER. DEFINE INPUT PARAMETER dwFileAttributes AS LONG. END. PROCEDURE GetFileAttributesA EXTERNAL "kernel32" : DEFINE INPUT PARAMETER lpFilename AS CHARACTER. DEFINE RETURN PARAMETER dwFileAttributes AS LONG. END.
The first example shows how to make a file read-only. It also clears most of the existing attributes because only one attribute is specified.
RUN SetFileAttributesA ( "c:\autoexec.bat", {&FILE_ATTRIBUTE_READONLY} ).
(Specify FILE_ATTRIBUTE_NORMAL to clear all attributes.)
The next example makes the file read-only and leaves the existing attributes intact.
DEFINE VARIABLE lv_attribs AS INTEGER NO-UNDO. RUN GetFileAttributesA ( "c:\autoexec.bat", OUTPUT lv-attribs ). /* if lv-attribs does not include {&FILE_ATTRIBUTE_READONLY} then */ RUN SetFileAttributesA ( "c:\autoexec.bat", lv-attribs + {&FILE_ATTRIBUTE_READONLY}).
The commented line should be replaced by an actual IF-statement. You can use procedure CheckOneAttribute by Dmitri, or a variant of his procedure, to test if the file already has the attribute set.
/* by Dmitri Levin, dlevin@ryland.com */ DEFINE VARIABLE lv-filename AS CHARACTER INIT "c:\autoexec.bat" NO-UNDO. DEFINE VARIABLE lv-attribs AS INTEGER NO-UNDO. DEFINE VARIABLE lv-attribs-list AS CHARACTER NO-UNDO. RUN GetFileAttributesA ( lv-filename, OUTPUT lv-attribs ). RUN CheckOneAttribute( lv-attribs, {&FILE_ATTRIBUTE_READONLY}, "READONLY", INPUT-OUTPUT lv-attribs-list). RUN CheckOneAttribute( lv-attribs, {&FILE_ATTRIBUTE_HIDDEN}, "HIDDEN", INPUT-OUTPUT lv-attribs-list). RUN CheckOneAttribute( lv-attribs, {&FILE_ATTRIBUTE_SYSTEM}, "SYSTEM", INPUT-OUTPUT lv-attribs-list). RUN CheckOneAttribute( lv-attribs, {&FILE_ATTRIBUTE_DIRECTORY}, "DIRECTORY", INPUT-OUTPUT lv-attribs-list). RUN CheckOneAttribute( lv-attribs, {&FILE_ATTRIBUTE_ARCHIVE}, "ARCHIVE", INPUT-OUTPUT lv-attribs-list). MESSAGE "File Attributes:" lv-attribs-list VIEW-AS ALERT-BOX. PROCEDURE CheckOneAttribute : DEFINE INPUT PARAMETER lp-attribs AS INTEGER NO-UNDO. DEFINE INPUT PARAMETER lp-attrib-num AS INTEGER NO-UNDO. DEFINE INPUT PARAMETER lp-attrib-name AS CHARACTER NO-UNDO. DEFINE INPUT-OUTPUT PARAMETER lp-attrib-list AS CHARACTER NO-UNDO. IF lp-attribs MOD ( lp-attrib-num * 2 ) GE lp-attrib-num THEN lp-attrib-list = lp-attrib-list + MIN(lp-attrib-list,", ") + lp-attrib-name. END.