options linesize=128; * Various kernel32.dll routines to examine aspects of a specific file; * Richard A. DeVenezia; * http://www.devenezia.com; * 2/6/04; * * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/file_management_reference.asp; * * mod * 7/26/05 rad lengthen sasexe from $40 to $270 (thanks to Scott Bass); filename SASCBTBL 'work.windows.api.source'; data _null_; file SASCBTBL; input; put _infile_; cards4; *-------------------------------------------------------------; routine GetCommandLineA module = kernel32 minarg = 0 maxarg = 0 stackpop = called returns = long ; *-------------------------------------------------------------; routine GetBinaryTypeA module=kernel32 minarg=2 maxarg=2 stackpop=called returns=long ; arg 1 input char format=$cstr200.; * lpApplicationName; arg 2 output num format=pib4. byaddr; * lpBinaryType; *-------------------------------------------------------------; routine GetCompressedFileSizeA module=kernel32 minarg=2 maxarg=2 stackpop=called returns=long ; arg 1 input char format=$cstr200.; * lpApplicationName; arg 2 output num format=pib4. byaddr; * lpBinaryType; *-------------------------------------------------------------; routine GetFileAttributesA module=kernel32 minarg=1 maxarg=1 stackpop=called returns=long ; arg 1 input char format=$cstr200.; * lpFileName; *-------------------------------------------------------------; routine GetFileAttributesExA module=kernel32 minarg=8 maxarg=8 stackpop=called returns=long ; arg 1 input char format=$cstr200. ; * lpFileName; arg 2 input num fdstart format=pib4. byvalue ; * fInfoLevelId (should be 0); * lpFileInformation; arg 3 num output FDSTART format=pib4. ; * dwFileAttributes ; arg 4 num output format=pib8. ; * ftCreationTime; arg 5 num output format=pib8. ; * ftLastAccessTime; arg 6 num output format=pib8. ; * ftLastWriteTime; arg 7 num output format=pib4. ; * nFileSizeHigh; arg 8 num output format=pib4. ; * nFileSizeLow; *-------------------------------------------------------------; routine GetFileTimeA module=kernel32 minarg=8 maxarg=8 stackpop=called returns=long ; arg 1 input format=pib4. byvalue; * HANDLE hFile; arg 2 output format=pib8. ; * LPFILETIME lpCreationTime; arg 3 output format=pib8. ; * LPFILETIME lpLastAccessTime; arg 4 output format=pib8. ; * LPFILETIME lpLastWriteTime; *-------------------------------------------------------------; routine FileTimeToLocalFileTime minarg=2 maxarg=2 stackpop=called module=Kernel32 returns=long ; arg 1 num input format=pib8.; * CONST FILETIME * lpFileTime, // pointer to UTC file time to convert ; arg 2 num output format=pib8.; * LPFILETIME lpLocalFileTime // pointer to converted file time ; *-------------------------------------------------------------; routine FileTimeToSystemTime module=Kernel32 minarg=9 maxarg=9 stackpop=called returns=long ; arg 1 num input format=pib8.; * CONST FILETIME * lpFileTime, // pointer to file time to convert ; * LPSYSTEMTIME lpSystemTime // pointer to structure to receive system time ; arg 2 num output fdstart format=pib2.; * WORD wYear ; arg 3 num output format=pib2.; * WORD wMonth ; arg 4 num output format=pib2.; * WORD wDayOfWeek ; arg 5 num output format=pib2.; * WORD wDay ; arg 6 num output format=pib2.; * WORD wHour ; arg 7 num output format=pib2.; * WORD wMinute ; arg 8 num output format=pib2.; * WORD wSecond ; arg 9 num output format=pib2.; * WORD wMilliseconds ; *-------------------------------------------------------------; routine CreateFileA module=Kernel32 minarg=7 maxarg=7 stackpop=called returns=long ; arg 1 char input format=$cstr256.; * LPCTSTR lpFileName; arg 2 num input format=pib4. byvalue; * DWORD dwDesiredAccess; arg 3 num input format=pib4. byvalue; * DWORD dwShareMode; arg 4 num input format=pib4. byvalue; * LPSECURITY_ATTRIBUTES lpSecurityAttributes (set to null,pass 0 byvalue); arg 5 num input format=pib4. byvalue; * DWORD dwCreationDispostion; arg 6 num input format=pib4. byvalue; * DWORD dwFlagsAndAttributes (set to zero); arg 7 num input format=pib4. byvalue; * HANDLE hTemplateFile (ignored); *-------------------------------------------------------------; routine GetFileSize module=Kernel32 minarg=2 maxarg=2 stackpop=called returns=long ; arg 1 num input format=pib4. byvalue; * HANDLE hFile; arg 2 num output format=pib4. ; * LPDWORD lpFileSizeHigh; *-------------------------------------------------------------; routine CloseHandle module=Kernel32 minarg=1 maxarg=1 stackpop=called returns=long ; arg 1 num input format=pib4. byvalue; * HANDLE hObject; ;;;; data _null_; put / 'GetCommandLineA:'; length cmdline $2000; addr = modulen ('GetCommandLineA'); if addr > 0 then do; cmdline = peekc (addr,2000); z = index (cmdline, '0000'x); if z then do; cmdline = substr (cmdline,1,z-1); end; put +1 cmdline; end; else do; put +1 'GetCommandLineA failed.'; stop; end; * parse sas executable name from command line; * use _infile_ buffer in case sas executable is * enclosed in quotes; infile cards dsd dlm=" "; input @; length sasexe $270; _infile_ = cmdline; input sasexe @; put +1 sasexe=; * run all manner of GetFile api routines against sasexe; rc = modulen ('GetBinaryTypeA', sasexe, binaryType); array binaryTypes [0:5] $16 _temporary_ ( 'SCS_32BIT_BINARY' 'SCS_DOS_BINARY' 'SCS_WOW_BINARY' 'SCS_PIF_BINARY' 'SCS_POSIX_BINARY' 'SCS_OS216_BINARY' ); put / 'GetBinaryType: ' / +1 rc= /+1 binaryTypes[binaryType]=; *----------; rc = modulen ('GetCompressedFileSizeA', sasexe, fileSize); put / 'GetCompressedFileSize: ' /+1 rc= /+1 fileSize=; if fileSize = 0 then put +1 'not compressed, bytes of disk storge=' rc; *----------; rc = modulen ('GetFileAttributesA', sasexe); put / 'GetFileAttributes: ' /+1 rc= hex4.; INVALID_FILE_ATTRIBUTES = -1; if rc ne INVALID_FILE_ATTRIBUTES then do; if band(rc,01x) then put +1 'READONLY'; if band(rc,02x) then put +1 'HIDDEN'; if band(rc,04x) then put +1 'SYSTEM'; if band(rc,10x) then put +1 'DIRECTORY'; if band(rc,20x) then put +1 'ARCHIVE'; if band(rc,80x) then put +1 'NORMAL'; if band(rc,100x) then put +1 'TEMPORARY'; if band(rc,800x) then put +1 'COMPRESSED'; if band(rc,1000x) then put +1 'OFFLINE'; end; *----------; GetFileExInfoStandard = 0; rc = modulen ('GetFileAttributesExA', sasexe, GetFileExInfoStandard , fileAttributes , creationTime , lastAccessTime , lastWriteTime , nFileSizeHigh , nFileSizeLow ); if rc = 1 then do; put / 'GetFileAttributesEx: ' /+1 rc= /+1 fileAttributes= /+1 creationTime= /+1 lastAccessTime= /+1 lastWriteTime= /+1 nFileSizeHigh= /+1 nFileSizeLow= ; filesize = nFileSizeLow + nFileSizeHigh * 2**32; rc = modulen ("FileTimeToLocalFileTime", creationTime, local1); rc = modulen ("FileTimeToLocalFileTime", lastAccessTime, local2); rc = modulen ("FileTimeToLocalFileTime", lastWriteTime, local3); rc = modulen ("FileTimeToSystemTime", local1,year1,month1,dow1,day1,h1,m1,s1,ms1); rc = modulen ("FileTimeToSystemTime", local2,year2,month2,dow2,day2,h2,m2,s2,ms2); rc = modulen ("FileTimeToSystemTime", local3,year3,month3,dow3,day3,h3,m3,s3,ms3); created = dhms (mdy(month1,day1,year1),h1,m1,s1+ms1/1000); accessed = dhms (mdy(month2,day2,year2),h2,m2,s2+ms2/1000); modified = dhms (mdy(month3,day3,year3),h3,m3,s3+ms3/1000); put +1 '-----' / +1 filesize=; if band(fileAttributes,01x) then put +1 'READONLY'; if band(fileAttributes,02x) then put +1 'HIDDEN'; if band(fileAttributes,04x) then put +1 'SYSTEM'; if band(fileAttributes,10x) then put +1 'DIRECTORY'; if band(fileAttributes,20x) then put +1 'ARCHIVE'; if band(fileAttributes,80x) then put +1 'NORMAL'; if band(fileAttributes,100x) then put +1 'TEMPORARY'; if band(fileAttributes,800x) then put +1 'COMPRESSED'; if band(fileAttributes,1000x) then put +1 'OFFLINE'; put +1 created = datetime19.2 /+1 accessed= datetime19.2 /+1 modified= datetime19.2 ; end; else put 'GetFileAttributesEx: ' /+1 'Error occurred'; *----------; put / 'CreateFile:'; GENERIC_READ = 080000000x; FILE_SHARE_READ = 1; OPEN_EXISTING = 3; hFile = modulen ('CreateFileA', sasexe, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0,0); if hFile = 0 then put +1 'Failed to open'; else do; put +1 hFile=hex8.; end; if hFile = 0 then goto AfterHfile; INVALID_FILE_SIZE = 0FFFFFFFFx;; sizeLow = modulen ('GetFileSize', hFile, sizeHigh); put / 'GetFileSize:' /+1 sizeLow= /+1 sizeHigh=; rc = modulen ('CloseHandle', hFile); put / 'CloseHandle:' /+1 rc= @; if rc then put '->success'; else put '->failure!'; AfterHFile: stop; retain _numeric_ .; cards4; necessary when tweaking _infile_ ;;;; run;