I need read each line of a txt file and pass this line as parameter to a method.
I have found this example:
LARGE_INTEGER byteOffset;
ntstatus = ZwCreateFile(&handle,
GENERIC_READ,
&objAttr, &ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
if(NT_SUCCESS(ntstatus)) {
byteOffset.LowPart = byteOffset.HighPart = 0;
ntstatus = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, BUFFER_SIZE, &byteOffset, NULL);
if(NT_SUCCESS(ntstatus)) {
buffer[BUFFER_SIZE-1] = '\0';
DbgPrint("%s\n", buffer);
}
ZwClose(handle);
}
but this read all content of file and not line by line.
Some idea about how do this?
read all file to buffer or map it as section. than execute next code:
extern "C" PCSTR __fastcall findRN(SIZE_T cb, PCSTR sz);
void processLine(SIZE_T len, PCSTR line)
{
DbgPrint("%.*s\n", len, line);
}
NTSTATUS process(PCSTR buf, SIZE_T cb)
{
PCSTR end = buf + cb, line = buf;
while (buf = findRN(end - line, line))
{
processLine(buf - line, line);
line = buf + 2;
}
if (line != end)
{
processLine(end - line, line);
}
return 0;
}
implementation of findRN
on c/c++
PCSTR __fastcall findRN(SIZE_T cb, PCSTR sz)
{
if (cb < 2)
{
return 0;
}
cb--;
do
{
if (*sz++ == '\r')
{
if (*sz == '\n')
{
return sz - 1;
}
}
} while (--cb);
return 0;
}
if you need/want ultra fast most effective implementation, do this in asm. for example x64:
findRN proc
cmp rcx,1
ja @@0
xor rax,rax
ret
@@0:
mov ax,0a0dh
xchg rdi,rdx
dec rcx
@@1:
repne scasb
jne @@2
cmp [rdi],ah
jne @@1
@@2:
sete al
dec rdi
movzx rax,al
neg rax
and rax,rdi
xchg rdi,rdx
ret
findRN endp
on x86 code the same, only change r to e in register names
map file:
NTSTATUS process(POBJECT_ATTRIBUTES poa)
{
HANDLE hFile, hSection = 0;
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtOpenFile(&hFile, FILE_GENERIC_READ, poa, &iosb,
FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
if (0 <= status)
{
FILE_STANDARD_INFORMATION fsi;
if (0 <= (status = NtQueryInformationFile(hFile, &iosb, &fsi, sizeof(fsi), FileStandardInformation)))
{
if (fsi.EndOfFile.HighPart)
{
status = STATUS_FILE_TOO_LARGE;
}
else if (!fsi.EndOfFile.LowPart)
{
status = STATUS_MAPPED_FILE_SIZE_ZERO;
}
else
{
status = NtCreateSection(&hSection, SECTION_MAP_READ, 0, 0, PAGE_READONLY, SEC_COMMIT, hFile);
}
}
NtClose(hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0,
0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= status)
{
status = process((PCSTR)BaseAddress, fsi.EndOfFile.LowPart);
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
}
return status;
}