kkuzil.own@gmail.com
언젠가는 쓸데가 있겠지... 훗
interface
...
...
const
STATUS_SUCCESS = $00000000;
{$EXTERNALSYM STATUS_SUCCESS}
type
NT_STATUS = LongInt;
IO_STATUS_BLOCK = record
case integer of
0:
(Status: NT_STATUS);
1:
(Pointer: Pointer;
Information: ULONG); // 'Information' does not belong to the union!
end;
PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK;
_FILE_INTERNAL_INFORMATION = record // Information Class 6
FileId: LARGE_INTEGER;
end;
FILE_INTERNAL_INFORMATION = _FILE_INTERNAL_INFORMATION;
PFILE_INTERNAL_INFORMATION = ^FILE_INTERNAL_INFORMATION;
_FILE_NAME_INFORMATION = record
dwLen: DWORD;
sFileName: array [0..0] of WideChar;
end;
FILE_NAME_INFORMATION = _FILE_NAME_INFORMATION;
PFILE_NAME_INFORMATION = ^FILE_NAME_INFORMATION;
_FILE_INFORMATION_CLASS = (
FileFiller0,
FileDirectoryInformation, // 1
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4 wdm
FileStandardInformation, // 5 wdm
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14 wdm
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20 wdm
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileMaximumInformation);
FILE_INFORMATION_CLASS = _FILE_INFORMATION_CLASS;
PFILE_INFORMATION_CLASS = ^FILE_INFORMATION_CLASS;
..
..
..
implementation
..
..
procedure TDlgScanMain.sButton2Click(Sender: TObject);
var
NtQueryInformationFile: function(FileHandle:DWORD;
IoStatusBlock: PIO_STATUS_BLOCK;
FileInformation: Pointer;//PFILE_INTERNAL_INFORMATION;
Length:DWORD;
FileInformationClass:FILE_INFORMATION_CLASS):DWORD; stdcall;
FileName: string;
hFile: THandle;
io: IO_STATUS_BLOCK;
FileInfo: FILE_INTERNAL_INFORMATION;
Res: NT_STATUS;
FileRecInput: TNtfsFileRecordInputBuffer;
FileRecOutput: PNtfsFileRecordOutputBuffer;
Read: DWORD;
hDevice: THandle;
VolumeDataBuff: NTFS_VOLUME_DATA_BUFFER;
Size: DWORD;
rec: PFileRecordHeader;
pName: PFILE_NAME_INFORMATION;
begin
FileName:='E:\테스트\DOC';
NtQueryInformationFile := GetProcAddress(GetModuleHandle('ntdll.dll'), 'NtQueryInformationFile');
if Assigned(NtQueryInformationFile)=false then
exit;
if FileExists(FileName) then
hFile := CreateFile(PChar(FileName),
GENERIC_READ or
GENERIC_WRITE,
FILE_SHARE_READ or
FILE_SHARE_WRITE or
FILE_SHARE_DELETE,
nil, OPEN_EXISTING, 0, 0)
else if DirectoryExists(FileName) then
hFile := CreateFile(PChar(FileName),
GENERIC_READ or
GENERIC_WRITE,
FILE_SHARE_READ or
FILE_SHARE_WRITE or
FILE_SHARE_DELETE,
nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
else ASSERT(false);
if hFile <> INVALID_HANDLE_VALUE then
begin
ZeroMemory(@FileInfo, sizeof(FileInfo));
Res := NtQueryInformationFile(hFile, @io, @FileInfo, sizeof(FileInfo), FileInternalInformation);
if Res <> STATUS_SUCCESS then Exit;
hDevice := CreateFile(PChar('\\.\'+FileName[1]+':'), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if not(DeviceIoControl(hDevice, FSCTL_GET_NTFS_VOLUME_DATA, nil, 0,
@VolumeDataBuff, sizeof(VolumeDataBuff), Read, nil))
then RaiseLastWin32Error();
Size := sizeof(TNtfsFileRecordOutputBuffer) + VolumeDataBuff.BytesPerFileRecordSegment-1;
GetMem(FileRecOutput, Size);
ZeroMemory(FileRecOutput, Size);
ZeroMemory(@FileRecInput, sizeof(FileRecInput));
FileRecInput.FileReferenceNumber:=FileInfo.FileId;
if not(DeviceIoControl(hFile,
FSCTL_GET_NTFS_FILE_RECORD,
@FileRecInput,
sizeof(FileRecInput),
FileRecOutput,
Size,
Read,
nil)) then
begin
RaiseLastWin32Error();
end;
rec := @FileRecOutput.FileRecordBuffer;
sMemo1.Lines.Add(IntToStr(rec.SequenceNumber));
FreeMem(FileRecOutput);
CloseHandle(hDevice);
end else
RaiseLastWin32Error();
end;
출처 : http://www.delmadang.com/community/bbs_view.asp?bbsNo=3&bbsCat=0&st=&keyword=&indx=422150&keyword1=&keyword2=&page=1
{$IFDEF VER150}
// 델파이 7 버전에서 컴파일 되는 부분..
{$ELIF VER210}
// 델파이2010 버전에서 컴파일 되는 부분..
{$ENDIF}
위의 코드처럼 델파이 버전에 따라서 다르게 컴파일 하고 싶을 때가 있죠..
예를들어 델파이 2009부터는 string 이 UnicodeString 이고 델파이 2007까지는 string 이 ansiString 이기 때문에
다르게 처리하게 되는 경우가 있죠..
그때 델파이 컴파일러 버전을 알아야 하는데 그걸 정리해 봤습니다.
{$IFDEF VER80} - Delphi 1
{$IFDEF VER90} - Delphi 2
{$IFDEF VER100} - Delphi 3
{$IFDEF VER120} - Delphi 4
{$IFDEF VER130} - Delphi 5
{$IFDEF VER140} - Delphi 6
{$IFDEF VER150} - Delphi 7
{$IFDEF VER160} - Delphi 8
{$IFDEF VER170} - Delphi 2005
{$IFDEF VER180} - Delphi 2006
{$IFDEF VER180} - Delphi 2007
{$IFDEF VER185} - Delphi 2007
{$IFDEF VER200} - Delphi 2009
{$IFDEF VER210} - Delphi 2010
그리고 델파이 6 이상에서는 CompilerVersion 을 사용해 버전체크를 할 수 있습니다.
{$IF CompilerVersion >= 18.5}
//델파이 2007 이상에서 컴파일 되는 소스..
{$IFEND}
아래는 델파이 컴파일러 버전입니다.
Delphi 2010 - 21
Delphi 2009 - 20
Delphi 2007 - 18.5
Delphi 2006 - 18
Delphi 2005 - 17
Delphi 8 - 16
Delphi 7 - 15
Delphi 6 - 14
그리고 델파이 8 이상에서는 {$IFDEF_LESS_THAN } 을 사용할 수 있으므로 아래처럼도 됩니다.
{$IFDEF_LESS_THAN VER170}
// 델파이 8 이상에서만 사용가능한 부분.. 델파이 7이하에서는 IFDEF_LESS_THAN 인식이 안됨..
// 델파이 8 이하에서 컴파일되는 Code..
{$END}
델파이7 이하버전은 Delphi7Minus 가 define 되어있으므로
{$IFDEF Delphi7Minus}
// 델파이7 이하에서 컴파일 되는 부분..
{$ENDIF}