udfDirTimeSetEx
bln udfDirTimeSetEx (str, strDT19, int)
;==========================================================================================================================================
;
; Change the time/date stamps for an existing directory ( folder )
;
; Developers: IFICantBYTE and ferchl
; At the time of writing (05/01/2008), Winbatch only had commands to change the TimeDate stamps for files not folders - hence the
; creation of this script
;
; NOTE: This script has only been tested on Win XP with NTFS - it assumes you have create/modify rights it should be fine on NT4
; Win2K and up, but it MAY NOT WORK ON Win9x/Me NT3 - you have been warned!
;
; Arguments:
; DTSDir         Name of Directory time reset
; DTSDirTime     Datetime in the YYYY:MM:DD:HH:mm:SS format
; DTSTimeField   1 = Directory created, 2 = Directory last modified, 3 = Directory last accessed
;
;==========================================================================================================================================

#DefineFunction udfDirTimeSetEx (DTSDir, DTSDirTime, DTSTimeField) ; (str, strDT19, int)

If WinVersion (1) < 4
   Return @FALSE
EndIf

Switch DTSTimeField
Case 1 ; Created time
   ModifiedYmdHms = FileTimeGetEx (DTSDir, 2)
   AccessedYmdHms = FileTimeGetEx (DTSDir, 3)
   CreatedYmdHms = DTSDirTime
   Break
Case 2 ; Last Modified time
   CreatedYmdHms = FileTimeGetEx (DTSDir, 1)
   AccessedYmdHms = FileTimeGetEx (DTSDir, 3)
   ModifiedYmdHms = DTSDirTime
   Break
Case 3 ; Last accessed time
   CreatedYmdHms = FileTimeGetEx (DTSDir, 1)
   ModifiedYmdHms = FileTimeGetEx (DTSDir, 2)
   AccessedYmdHms = DTSDirTime
   Break
EndSwitch

; FIRST WE CREATE A TEMPORARY FILE THAT WE CAN MANIPULATE USING THE BUILT-IN WINBATCH FILETIME COMMANDS ===================================
; THEN WE CAN COPY IT'S DATES TO OUR DIRECTORY USING A COUPLE OF DLL CALLS ================================================================

TempFile = FileCreateTemp ("AAA")
FileTimeSetEx (TempFile, CreatedYmdHms, 1)  ; Sets the created time to our value.
FileTimeSetEx (TempFile, ModifiedYmdHms, 2) ; Sets the modified time to our value.
FileTimeSetEx (TempFile, AccessedYmdHms, 3) ; Sets the last accessed time to our value.

; HERE COMES THE TRICK... =================================================================================================================
; SOME API CONSTANTS ======================================================================================================================

GENERIC_READ = 2147483648  ; &H80000000
GENERIC_WRITE = 1073741824 ; &H40000000
FILE_SHARE_READ = 1
FILE_SHARE_DELETE = 4
FILE_FLAG_BACKUP_SEMANTICS = 33554432 ; &H2000000 ; This may not be available in older versions of Windows.
OPEN_EXISTING = 3

; MAKE SOME TIME STRUCTURES - OR AT LEAST ALLOCATE THE CORRECT BUFFER SIZES FOR THE STRUCTURES TO FILL LATER ==============================

CTFILETIME = BinaryAlloc (8) ; Will contain the TimeStamp for Created Time.
LAFILETIME = BinaryAlloc (8) ; Will contain Last Accessed Time.
LWFILETIME = BinaryAlloc (8) ; Will contain Last Written (Modified) Time.
Kernel32 = StrCat (DirWindows (1), "kernel32.dll") ; Path to kernel32.dll.

; GET HANDLES TO THE EXISTING DIRECTORY AND THE TEMPFILE THAT ARE SUITABLE TO PASS TO THE OTHER DLL CALLS =================================

hDir = DllCall (Kernel32, long : "CreateFileA", lpstr : DTSDir, long : GENERIC_READ | GENERIC_WRITE, long : FILE_SHARE_READ | FILE_SHARE_DELETE, lpnull, long : OPEN_EXISTING, long : FILE_FLAG_BACKUP_SEMANTICS, lpnull)
hTempFile = DllCall (Kernel32, long : "CreateFileA", lpstr : TempFile, long : GENERIC_READ | GENERIC_WRITE, long : FILE_SHARE_READ | FILE_SHARE_DELETE, lpnull, long : OPEN_EXISTING, long : FILE_FLAG_BACKUP_SEMANTICS, lpnull)

; GET THE 3 TIMESTAMPS FROM THE TEMPFILE WE MODIFIED EARLIER AND SAVE THEM AS FILETIME STRUCTURES IN THE 3 BUFFERS WE MADE ================

DllCall (Kernel32, long : "GetFileTime", long : hTempFile, lpbinary : CTFILETIME, lpbinary : LAFILETIME, lpbinary : LWFILETIME)
DllCall (Kernel32, long : "SetFileTime", long : hDir, lpbinary : CTFILETIME, lpbinary : LAFILETIME, lpbinary : LWFILETIME)

; CLOSE THE DIR AND FILE HANDLES AND DELETE THE TEMP FILE =================================================================================

DllCall (Kernel32, long : "CloseHandle", long : hDir)
DllCall (Kernel32, long : "CloseHandle", long : hTempFile)
FileDelete (TempFile)

; FREE OUR BINARY BUFFERS =================================================================================================================

BinaryFree (CTFILETIME)
BinaryFree (LAFILETIME)
BinaryFree (LWFILETIME)

Return @TRUE
#EndFunction
;==========================================================================================================================================


; Test.

DirChange (DirScript ())

strFolder = ".\TestFolder"
blnResult = DirMake (strFolder)

arrDI = DirInfoToArray (strFolder, 2)
Pause ("Info", arrDI[1, 0] : @LF : @LF : "Created: " : arrDI[1, 4] : @LF : "Last modified: " : arrDI[1, 2] : @LF : "Last accessed: " : arrDI[1, 3])

blnResult1 = udfDirTimeSetEx (strFolder, "2011:01:01:01:01:01", 1)
blnResult2 = udfDirTimeSetEx (strFolder, "2012:02:02:02:02:02", 2)
blnResult3 = udfDirTimeSetEx (strFolder, "2013:03:03:03:03:03", 3)

arrDI = DirInfoToArray (strFolder, 2)
Pause ("Info", arrDI[1, 0] : @LF : @LF : "Created: " : arrDI[1, 4] : @LF : "Last modified: " : arrDI[1, 2] : @LF : "Last accessed: " : arrDI[1, 3])

blnResult = DirRemove (strFolder)

:CANCEL
Exit
; (c)Detlev Dalitz.20120208.