Note that there are some explanatory texts on larger screens.

plurals
  1. POReading Invalid FileNames from a folder
    text
    copied!<p>I have an interesting problem. A client of ours recorded voice conversations from phone calls, but the filename that was given to the recording was invalid. Here is an example of the filename <code>123:123.wmv</code></p> <p>Believe it, Windows Media encoder created the file, and all the information is in the file, however Windows obviously don't recognise the filename, and only display it in the folder as <code>123</code> and the file is 0KB</p> <p>Well from here it is edited: Thanks to Keith Miller that pointed me in the right direction I could write a function that will extract the stream names from the file and use it.</p> <p>I've included a working copy of how to create two streams of data into a file, read the stream names and read the data from each stream. This is totally awesome, so I hope other people can use this as well. My code ignores the main stream. If you write data into the main stream, it is best if you do not ignore it.</p> <pre><code>unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, uGeneralStuff; type _FILE_STREAM_INFORMATION = record NextEntryOffset: cardinal; StreamNameLength: cardinal; StreamSize: int64; StreamAllocationSize: int64; StreamName: array[0..MAX_PATH] of WideChar; end; PFILE_STREAM_INFORMATION = ^_FILE_STREAM_INFORMATION; TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private InfoBlock: _FILE_STREAM_INFORMATION; StatusBlock : record Status: Cardinal; Information: PDWORD; end; procedure CreateFile(FileName, Info: String); function ReadFile(FileName: String): String; function ReadStreams(filename: String): TStringList; { Private declarations } public { Public declarations } end; var Form1: TForm1; function NtQueryInformationFile(FileHandle : Cardinal; IoStatusBlock : Pointer; FileInformation : Pointer; FileInformationLength : Cardinal; FileInformationClass : Cardinal ): Cardinal; stdcall; external 'ntdll.dll'; implementation uses Math, StrUtils; {$R *.dfm} function TForm1.ReadStreams(filename: String): TStringList; var iFH1: Integer; aFileName: array[0..MAX_PATH] of WideChar; aStreamName: String; begin Result := TStringList.Create; iFH1 := FileOpen(filename, GENERIC_READ); NtQueryInformationFile(iFH1, @StatusBlock, @InfoBlock, SizeOf(InfoBlock), 22); // 22 Means FileStreamInformation FileClose(iFH1); while (1=1) do begin if InfoBlock.StreamNameLength = 0 then break; CopyMemory(@aFileName, @InfoBlock.StreamName, InfoBlock.StreamNameLength); aStreamName := Copy(aFileName, 1, PosEx(':', aFileName, 2) - 1); if aStreamName &lt;&gt; ':' then //Ignore main stream, because I know I didn't write data in there Result.Add(aStreamName); if (InfoBlock.NextEntryOffset = 0) then break; InfoBlock := PFILE_STREAM_INFORMATION(PByte(@InfoBlock) + InfoBlock.NextEntryOffset)^; end; end; procedure TForm1.Button2Click(Sender: TObject); var aStreams: TStringList; I: Integer; begin aStreams := ReadStreams('C:\Temp\123'); for I := 0 to aStreams.Count - 1 do begin ShowMessage(ReadFile('C:\Temp\123' + aStreams[I])); end; end; procedure TForm1.CreateFile(FileName, Info: String); var iFH1: Integer; Buffer: PAnsiString; begin iFH1 := FileCreate(FileName); Buffer := PAnsiString(AnsiString(Info) + #0); FileWrite(iFH1, Buffer^, Length(Info)); FileClose(iFH1); end; function TForm1.ReadFile(FileName: String): String; var iFH1: Integer; Buffer: PAnsiChar; iFL: Integer; iBR, iCurPos, iReadSize: Integer; begin iFH1 := FileOpen(FileName, GENERIC_READ); iFL := FileSeek(iFH1, 0, 2); FileSeek(iFH1, 0, 0); iReadSize := Min(iFL, 1024); Buffer := AllocMem(iReadSize + 1); iCurPos := 0; Result := ''; while iCurPos &lt; iFL do begin iBR := FileRead(iFH1, Buffer^, iReadSize); if iBR = -1 then break; Result := Result + Buffer; Inc(iCurPos, iBR); end; FileClose(iFH1); end; procedure TForm1.Button1Click(Sender: TObject); begin CreateFile('C:\Temp\123:123.txt', 'This is TestFile 1'); CreateFile('C:\Temp\123:345.txt', 'This is TestFile 2'); ShowMessage(ReadFile('C:\Temp\123:123.txt')); ShowMessage(ReadFile('C:\Temp\123:345.txt')); end; end. </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload