SetNTFSCompressionFlag Function
From NSIS Wiki
Jump to navigationJump to search
Author: Zinthose (talk, contrib) |
About
Function to enable or disable NTFS encryption flag on a file or folder. Obviously it requires a system with an NTFS formatted drive to be useful but it has built in checks so it should fail gracefully.
Usage
${SetNTFSCompressionFlag} PathToFolderOrFile True|False|Yes|No|1|0 IfErrors ItDidntWork
Example
InitPluginsDir ## Our Control Script SetOutPath "$PLUGINSDIR\Not Compressed" File "${__FILE__}" ## To ensure we reduce any disk space while installing we will enable the NTFS compressed folder flag for the $PLUGINSDIR ${SetNTFSCompressionFlag} "$PLUGINSDIR" True IfErrors 0 +2 Abort "Errors" ## Now any new files extracted to the folder will be compressed. SetOutPath $PLUGINSDIR\Compressed File "${__FILE__}" ## Now Lets Take a Look Exec `explorer "$PLUGINSDIR"`
Function
!define SetNTFSCompressionFlag '!insertmacro _SetNTFSCompressionFlag' !macro _SetNTFSCompressionFlag _PATH _VALUE Push `${_VALUE}` Push `${_PATH}` Call SetNTFSCompressionFlag !macroend Function SetNTFSCompressionFlag ClearErrors ; STACK: _PATH _VALUE Exch $0 ; r0 _VALUE Exch ; _VALUE r0 Exch $1 ; r1 r0 Push $2 ; r2 r1 r0 Push $3 ; r3 r2 r1 r0 ## File/Folder Exists? IfFileExists $0 0 Errors ## Is Compression Supported? System::Call 'Kernel32::GetVolumePathName(t r0,t .r2,i ${NSIS_MAX_STRLEN})i.r3' StrCmp $3 0 Errors ; <-- If Return Code is 0 then ERROR System::Call 'Kernel32::GetVolumeInformation(t r2,t,i ${NSIS_MAX_STRLEN},*i,*i,*i.r3,t,i ${NSIS_MAX_STRLEN})i.r2' StrCmp $2 0 Errors ; <-- If Return Code is 0 then ERROR IntOp $2 $3 & 0x00000010 ; <-- Dose the specified volume support file-based compression. StrCmp $2 0 Errors ;## Tweak Value StrCmp $1 0 ValueSet StrCmp $1 True ValueTrue StrCmp $1 Yes ValueTrue StrCmp $1 T ValueTrue StrCmp $1 Y ValueTrue StrCpy $1 0x0000 Goto ValueSet ValueTrue: StrCpy $1 0x0001 ValueSet: ;## Get status of compression System::Call 'kernel32::GetFileAttributes(t r0)i .r2' StrCmp $2 -1 Errors ; <-- If Return Code is -1 then ERROR IntOp $2 $2 & 0x0800 ; <-- Determine if the Compressed flag is set StrCmp $1 $2 ExitFunction ; <-- No Change Needed as new setting and current = NoCompression StrCmp $2 0 DoChange StrCmp $1 1 ExitFunction ; <-- No Change Needed as new setting and current - Compressed StrCmp $1 0 DoChange ## Change Compression DoChange: ## Open FileHandle to Directory System::Call "kernel32::CreateFile(t r0, i 0x40000000|0x80000000, i 0x00000003, i 0, i 3, i 0x02000000, i 0) i.r2" StrCmp $2 -1 Errors ; <-- InvalidFileHandle! ## Apply Change System::Call "kernel32::DeviceIoControl(i r2,i 0x9C040,*i r1,i 16,i 0,i 0,*i r3r3,i,0)i.r3" System::Call "kernel32::CloseHandle(i r2)i.r2" StrCmp $2 0 Errors ## Validate System::Call 'kernel32::GetFileAttributes(t r0)i .r2' StrCmp $2 -1 Errors ; <-- If Return Code is -1 then ERROR IntOp $2 $2 & 0x0800 ; <-- Determine if the Compressed flag is set StrCmp $1 $2 Errors ; <-- Change Failed! StrCmp $2 0 ExitFunction StrCmp $1 1 Errors ; <-- Change Failed! StrCmp $1 0 ExitFunction Goto ExitFunction Errors: SetErrors Goto ExitFunction ExitFunction: Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd