
Бывалый

Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006
Репутация: 1 Всего: 2
|
вот такой код в принципе работает, но почему то не всегда:( Точнее, не во всех проектах. Когда я пристегиваю юнит к новому проекту все чудесно работает, а вот когда к тому, в котором мне и надо его использовать напарываюсь на RangeCheckError (пометил в коде) Код | unit unit2;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type TID3Tag = record ID: array[0..2] of Char; Titel: array[0..29] of Char; Artist: array[0..29] of Char; Album: array[0..29] of Char; Year: array[0..3] of Char; Comment: array[0..29] of Char; Genre: Byte; end;
NT_STATUS = Cardinal; TFileDirectoryInformation = packed record NextEntryOffset: ULONG; FileIndex: ULONG; CreationTime: LARGE_INTEGER; LastAccessTime: LARGE_INTEGER; LastWriteTime: LARGE_INTEGER; ChangeTime: LARGE_INTEGER; EndOfFile: LARGE_INTEGER; AllocationSize: LARGE_INTEGER; FileAttributes: ULONG; FileNameLength: ULONG; FileName: array[0..0] of WideChar; end;
FILE_DIRECTORY_INFORMATION = TFileDirectoryInformation; PFileDirectoryInformation = ^TFileDirectoryInformation; PFILE_DIRECTORY_INFORMATION = PFileDirectoryInformation; PSYSTEM_THREADS = ^SYSTEM_THREADS; SYSTEM_THREADS = packed record KernelTime: LARGE_INTEGER; UserTime: LARGE_INTEGER; CreateTime: LARGE_INTEGER; WaitTime: ULONG; StartAddress: Pointer; UniqueProcess: DWORD; UniqueThread: DWORD; Priority: Integer; BasePriority: Integer; ContextSwitchCount: ULONG; State: Longint; WaitReason: Longint; end;
PSYSTEM_PROCESS_INFORMATION = ^SYSTEM_PROCESS_INFORMATION;
SYSTEM_PROCESS_INFORMATION = packed record NextOffset: ULONG; ThreadCount: ULONG; Reserved1: array [0..5] of ULONG; CreateTime: FILETIME; UserTime: FILETIME; KernelTime: FILETIME; ModuleNameLength: WORD; ModuleNameMaxLength: WORD; ModuleName: PWideChar; BasePriority: ULONG; ProcessID: ULONG; InheritedFromUniqueProcessID: ULONG; HandleCount: ULONG; Reserved2 : array[0..1] of ULONG; PeakVirtualSize : ULONG; VirtualSize : ULONG; PageFaultCount : ULONG; PeakWorkingSetSize : ULONG; WorkingSetSize : ULONG; QuotaPeakPagedPoolUsage : ULONG; QuotaPagedPoolUsage : ULONG; QuotaPeakNonPagedPoolUsage : ULONG; QuotaNonPagedPoolUsage : ULONG; PageFileUsage : ULONG; PeakPageFileUsage : ULONG; PrivatePageCount : ULONG; ReadOperationCount : LARGE_INTEGER; WriteOperationCount : LARGE_INTEGER; OtherOperationCount : LARGE_INTEGER; ReadTransferCount : LARGE_INTEGER; WriteTransferCount : LARGE_INTEGER; OtherTransferCount : LARGE_INTEGER; ThreadInfo: array [0..0] of SYSTEM_THREADS; end;
PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION; SYSTEM_HANDLE_INFORMATION = packed record ProcessId: DWORD; ObjectTypeNumber: Byte; Flags: Byte; Handle: Word; pObject: Pointer; GrantedAccess: DWORD; end;
PSYSTEM_HANDLE_INFORMATION_EX = ^SYSTEM_HANDLE_INFORMATION_EX; SYSTEM_HANDLE_INFORMATION_EX = packed record NumberOfHandles: dword; Information: array [0..20000] of SYSTEM_HANDLE_INFORMATION; ///<------ошибка была здесь end;
PFILE_NAME_INFORMATION = ^FILE_NAME_INFORMATION; FILE_NAME_INFORMATION = packed record FileNameLength: ULONG; FileName: array [0..MAX_PATH - 1] of WideChar; end;
PUNICODE_STRING = ^TUNICODE_STRING; TUNICODE_STRING = packed record Length : WORD; MaximumLength : WORD; Buffer : array [0..MAX_PATH - 1] of WideChar; end;
POBJECT_NAME_INFORMATION = ^TOBJECT_NAME_INFORMATION; TOBJECT_NAME_INFORMATION = packed record Name : TUNICODE_STRING; end;
PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK; IO_STATUS_BLOCK = packed record Status: NT_STATUS; Information: DWORD; end;
PGetFileNameThreadParam = ^TGetFileNameThreadParam; TGetFileNameThreadParam = packed record hFile: THandle; Data: array [0..MAX_PATH - 1] of Char; Status: NT_STATUS; end;
const STATUS_SUCCESS = NT_STATUS($00000000); STATUS_INVALID_INFO_CLASS = NT_STATUS($C0000003); STATUS_INFO_LENGTH_MISMATCH = NT_STATUS($C0000004); STATUS_INVALID_DEVICE_REQUEST = NT_STATUS($C0000010); ObjectNameInformation = 1; FileDirectoryInformation = 1; FileNameInformation = 9; SystemProcessesAndThreadsInformation = 5; SystemHandleInformation = 16;
Genres : array[0..146] of string = ('Blues','Classic Rock','Country','Dance','Disco','Funk','Grunge', 'Hip- Hop','Jazz','Metal','New Age','Oldies','Other','Pop','R&B', 'Rap','Reggae','Rock','Techno','Industrial','Alternative','Ska', 'Death Metal','Pranks','Soundtrack','Euro-Techno','Ambient', 'Trip-Hop','Vocal','Jazz+Funk','Fusion','Trance','Classical', 'Instrumental','Acid','House','Game','Sound Clip','Gospel','Noise', 'Alternative Rock','Bass','Punk','Space','Meditative','Instrumental Pop', 'Instrumental Rock','Ethnic','Gothic','Darkwave','Techno-Industrial','Electronic', 'Pop-Folk','Eurodance','Dream','Southern Rock','Comedy','Cult','Gangsta', 'Top 40','Christian Rap','Pop/Funk','Jungle','Native US','Cabaret','New Wave', 'Psychadelic','Rave','Showtunes','Trailer','Lo-Fi','Tribal','Acid Punk', 'Acid Jazz','Polka','Retro','Musical','Rock & Roll','Hard Rock','Folk', 'Folk-Rock','National Folk','Swing','Fast Fusion','Bebob','Latin','Revival', 'Celtic','Bluegrass','Avantgarde','Gothic Rock','Progressive Rock', 'Psychedelic Rock','Symphonic Rock','Slow Rock','Big Band','Chorus', 'Easy Listening','Acoustic','Humour','Speech','Chanson','Opera', 'Chamber Music','Sonata','Symphony','Booty Bass','Primus','Porn Groove', 'Satire','Slow Jam','Club','Tango','Samba','Folklore','Ballad', 'Power Ballad','Rhytmic Soul','Freestyle','Duet','Punk Rock','Drum Solo', 'Acapella','Euro-House','Dance Hall','Goa','Drum & Bass','Club-House', 'Hardcore','Terror','Indie','BritPop','Negerpunk','Polsk Punk','Beat', 'Christian Gangsta','Heavy Metal','Black Metal','Crossover','Contemporary C', 'Christian Rock','Merengue','Salsa','Thrash Metal','Anime','JPop','SynthPop');
function ZwQuerySystemInformation(ASystemInformationClass: DWORD; ASystemInformation: Pointer; ASystemInformationLength: DWORD; AReturnLength: PDWORD): NT_STATUS; stdcall; external 'ntdll.dll';
function NtQueryInformationFile(FileHandle: THandle; IoStatusBlock: PIO_STATUS_BLOCK; FileInformation: Pointer; Length: DWORD; FileInformationClass: DWORD): NT_STATUS; stdcall; external 'ntdll.dll';
function NtQueryObject(ObjectHandle: THandle; ObjectInformationClass: DWORD; ObjectInformation: Pointer; ObjectInformationLength: ULONG; ReturnLength: PDWORD): NT_STATUS; stdcall; external 'ntdll.dll';
function GetLongPathNameA(lpszShortPath, lpszLongPath: PChar; cchBuffer: DWORD): DWORD; stdcall; external kernel32;
function ShowLockedProcess(FileName: String):TID3Tag;
implementation
function FillID3TagInformation (mp3File: string):TID3Tag; var ID3 : TID3Tag; fmp3: TFileStream; begin fmp3:=TFileStream.Create(mp3File, fmOpenRead or fmShareDenyWrite); try fmp3.position:=fmp3.size-128; fmp3.Read(ID3,SizeOf(ID3)); finally fmp3.free; end; {if ID3.ID <> 'TAG' then begin ID3.Titel:='No ID3 Tag'; ID3.Artist:='No ID3 Tag'; ID3.Album:='No ID3 Tag'; ID3.Comment:='No ID3 Tag'; ID3.Genre:=0; end else } begin result:=ID3; end; end;
function ShowLockedProcess(FileName: String):TID3Tag;
function GetInfoTable(ATableType: DWORD): Pointer; var dwSize: DWORD; pPtr: Pointer; ntStatus: NT_STATUS; begin Result := nil; dwSize := WORD(-1); GetMem(pPtr, dwSize); ntStatus := ZwQuerySystemInformation(ATableType, pPtr, dwSize, nil); while ntStatus = STATUS_INFO_LENGTH_MISMATCH do begin dwSize := dwSize * 2; ReallocMem(pPtr, dwSize); ntStatus := ZwQuerySystemInformation(ATableType, pPtr, dwSize, nil); end; if ntStatus = STATUS_SUCCESS then Result := pPtr else FreeMem(pPtr); end;
function GetFileNameThread(lpParameters: Pointer): DWORD; stdcall; var FileNameInfo: FILE_NAME_INFORMATION; ObjectNameInfo: TOBJECT_NAME_INFORMATION; IoStatusBlock: IO_STATUS_BLOCK; pThreadParam: TGetFileNameThreadParam; dwReturn: DWORD; begin ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION)); pThreadParam := PGetFileNameThreadParam(lpParameters)^; Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock, @FileNameInfo, MAX_PATH * 2, FileNameInformation); if Result = STATUS_SUCCESS then begin Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn); if Result = STATUS_SUCCESS then begin pThreadParam.Status := Result; WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @pThreadParam.Data[0], MAX_PATH, nil, nil); end else begin pThreadParam.Status := STATUS_SUCCESS; Result := STATUS_SUCCESS; WideCharToMultiByte(CP_ACP, 0, @FileNameInfo.FileName[0], IoStatusBlock.Information, @pThreadParam.Data[0], MAX_PATH, nil, nil); end; end; PGetFileNameThreadParam(lpParameters)^ := pThreadParam; ExitThread(Result); end;
function GetFileNameFromHandle(hFile: THandle): String; var lpExitCode: DWORD; pThreadParam: TGetFileNameThreadParam; hThread: THandle; begin Result := ''; ZeroMemory(@pThreadParam, SizeOf(TGetFileNameThreadParam)); pThreadParam.hFile := hFile; hThread := CreateThread(nil, 0, @GetFileNameThread, @pThreadParam, 0, PDWORD(nil)^); if hThread <> 0 then try case WaitForSingleObject(hThread, 100) of WAIT_OBJECT_0: begin GetExitCodeThread(hThread, lpExitCode); if lpExitCode = STATUS_SUCCESS then Result := pThreadParam.Data; end; WAIT_TIMEOUT: TerminateThread(hThread, 0); end; finally CloseHandle(hThread); end; end;
type DriveQueryData = record DiskLabel: String; DiskDosQuery: String; DosQueryLen: Integer; end;
var hFile, hProcess: THandle; pHandleInfo: PSYSTEM_HANDLE_INFORMATION_EX; I, Drive: Integer; ObjectTypeNumber: Byte; FileDirectory, FilePath, ProcessName: String; SystemInformation, TempSI: PSYSTEM_PROCESS_INFORMATION; DosDevices: array [0..25] of DriveQueryData; LongFileName, TmpFileName: String; s:shortstring; id3:TID3Tag;
begin SetLength(LongFileName, MAX_PATH); GetLongPathNameA(PChar(FileName), @LongFileName[1], MAX_PATH); for Drive := 0 to 25 do begin DosDevices[Drive].DiskLabel := Chr(Drive + Ord('a')) + ':'; SetLength(DosDevices[Drive].DiskDosQuery, MAXCHAR); ZeroMemory(@DosDevices[Drive].DiskDosQuery[1], MAXCHAR); QueryDosDevice(PChar(DosDevices[Drive].DiskLabel), @DosDevices[Drive].DiskDosQuery[1], MAXCHAR); DosDevices[Drive].DosQueryLen := Length(PChar(DosDevices[Drive].DiskDosQuery)); SetLength(DosDevices[Drive].DiskDosQuery, DosDevices[Drive].DosQueryLen); end; ObjectTypeNumber := 0; //SetDebugPriv; hFile := CreateFile('NUL', GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); if hFile = INVALID_HANDLE_VALUE then RaiseLastOSError; try pHandleInfo := GetInfoTable(SystemHandleInformation); if pHandleInfo = nil then RaiseLastOSError; try for I := 0 to pHandleInfo^.NumberOfHandles - 1 do if pHandleInfo^.Information[i].Handle = hFile then //<<<<<------------------ ВАЛИТСЯ ЗДЕСЬ!!!!!!!!! if pHandleInfo^.Information[i].ProcessId = GetCurrentProcessId then begin ObjectTypeNumber := pHandleInfo^.Information[I].ObjectTypeNumber; Break; end; finally FreeMem(pHandleInfo); end; finally CloseHandle(hFile); end;
SystemInformation := GetInfoTable(SystemProcessesAndThreadsInformation); if SystemInformation <> nil then try pHandleInfo := GetInfoTable(SystemHandleInformation); if pHandleInfo <> nil then try //ProgressBar1.Position := 0; // ProgressBar1.Max := pHandleInfo^.NumberOfHandles; for I := 0 to pHandleInfo^.NumberOfHandles - 1 do begin if pHandleInfo^.Information[I].ObjectTypeNumber = ObjectTypeNumber then begin hProcess := OpenProcess(PROCESS_DUP_HANDLE, True, pHandleInfo^.Information[I].ProcessId); if hProcess > 0 then try if DuplicateHandle(hProcess, pHandleInfo^.Information[I].Handle, GetCurrentProcess, @hFile, 0, False, DUPLICATE_SAME_ACCESS) then try if Application.Terminated then Exit; FilePath := GetFileNameFromHandle(hFile); if FilePath <> '' then begin FileDirectory := ''; for Drive := 0 to 25 do if DosDevices[Drive].DosQueryLen > 0 then if Copy(FilePath, 1, DosDevices[Drive].DosQueryLen) = DosDevices[Drive].DiskDosQuery then begin FileDirectory := DosDevices[Drive].DiskLabel; Delete(FilePath, 1, DosDevices[Drive].DosQueryLen); Break; end; if FileDirectory = '' then Continue; TempSI := SystemInformation; repeat if TempSI^.ProcessID = pHandleInfo^.Information[I].ProcessId then begin ProcessName := TempSI^.ModuleName; Break; end; TempSI := Pointer(DWORD(TempSI) + TempSI^.NextOffset); until TempSI^.NextOffset = 0; SetLength(TmpFileName, MAX_PATH); GetLongPathNameA(PChar(FileDirectory + FilePath), @TmpFileName[1], MAX_PATH); s:=copy(TmpFileName,0,pos(#0,TmpFileName)-1); if (s[length(s)]='3') and (s[length(s)-1]='p')and (s[length(s)-2]='m')and (s[length(s)-3]='.') then begin id3:=FillID3TagInformation(s); // edit1.Text:=FillID3TagInformation(s).Titel; { Memo1.Lines.Add(readID3Tag(s).Titel); Memo1.Lines.Add(readID3Tag(s).Album); Memo1.Lines.Add(readID3Tag(s).Artist); Memo1.Lines.Add(readID3Tag(s).Year); } end; end; finally CloseHandle(hFile); end; finally CloseHandle(hProcess); end; end; // ProgressBar1.Position := ProgressBar1.Position + 1; Application.ProcessMessages; end; finally FreeMem(pHandleInfo); end; finally FreeMem(SystemInformation); end; result:=id3; //ShowMessage('All handles found.'); end;
end.
|
пример использования Код | procedure TForm1.Button1Click(Sender: TObject); begin showmessage(ShowLockedProcess('').Titel); end;
|
нашел ошибку Это сообщение отредактировал(а) gonzales - 7.10.2007, 02:07
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
|