mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
409 lines
14 KiB
409 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1987-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
_read.c
|
|
|
|
Abstract:
|
|
|
|
Module reads next send packet from a VIRTUAL boot block.
|
|
THIS IS VERY COMPLICATED ALGORITHM, YOU MUST UNDERSTAND THE ALGORITHM
|
|
AND KNOW THE SIDE EFFECTS IF YOU DO ANY CHANGES.
|
|
|
|
Provides similar functionality to rmapread.c in LANMAN 2.1 code.
|
|
|
|
Author:
|
|
|
|
Vladimir Z. Vulovic 27 - July - 1993
|
|
|
|
Environment:
|
|
|
|
User mode
|
|
|
|
Revision History :
|
|
|
|
--*/
|
|
|
|
#include "local.h"
|
|
#include "read.h"
|
|
|
|
|
|
VOID RplMakePatch(
|
|
IN PRPL_WORKER_DATA pWorkerData,
|
|
OUT PBYTE send_buffer,
|
|
IN DWORD read_len,
|
|
IN DWORD read_offset
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Makes NLS patch to send buffer.
|
|
|
|
Arguments:
|
|
send_buffer - send buffer to be sent to DLL
|
|
read_len - length of buffer
|
|
read_offset - offset of buffer in bblock image
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD Length;
|
|
DWORD PatchOffset;
|
|
PBYTE Source;
|
|
PBYTE Target;
|
|
DWORD base_offset;
|
|
|
|
PatchOffset = pWorkerData->PatchOffset + pWorkerData->fblock_base_offset;
|
|
|
|
// if top 1 less that bottom 2 or bottom 1 greater that top 2
|
|
// => blocks do not overlap and there is nothing to patch here
|
|
|
|
if ( !(PatchOffset + DBCS_MESSAGE_BUFFER_SIZE < read_offset ||
|
|
PatchOffset > read_offset + read_len)) {
|
|
|
|
// blocks overlap, get copy address and length,
|
|
// read offset is MAX( bottom1, bottom2 )
|
|
|
|
if (read_offset < PatchOffset) {
|
|
Source = RG_DbcsMessageBuffer;
|
|
Target = send_buffer + (WORD)(PatchOffset - read_offset);
|
|
base_offset = PatchOffset;
|
|
} else {
|
|
Source = RG_DbcsMessageBuffer + (WORD)(read_offset - PatchOffset);
|
|
Target = send_buffer;
|
|
base_offset = read_offset;
|
|
}
|
|
|
|
// end offset is MIN( top1, top2 )
|
|
if (read_offset + read_len < PatchOffset + DBCS_MESSAGE_BUFFER_SIZE) {
|
|
Length = read_offset + read_len - base_offset;
|
|
} else {
|
|
Length = PatchOffset + DBCS_MESSAGE_BUFFER_SIZE - base_offset;
|
|
}
|
|
|
|
// copy data from source to destination
|
|
memcpy( Target, Source, (WORD)Length );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL RplReadData(
|
|
IN PRPL_WORKER_DATA pWorkerData,
|
|
IN DWORD read_offset,
|
|
OUT PDWORD pBytesRead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns pointer to send buffer and its length. The data is read from
|
|
the offset (input param) of virtual boot block. The boot block consists
|
|
of small wksta specific data buffer, virtual file block and unused
|
|
memory between them (if any). Virtual file block is a file table.
|
|
The names are in memory, but the data is in hard disk (or in disk cache).
|
|
|
|
Arguments:
|
|
|
|
read_offset - offset of data that we need to read
|
|
pBuffer - address of location where pointer to send buffer is returned
|
|
pBytesRead - pointer to number of bytes read
|
|
|
|
Return Value:
|
|
TRUE if success, else FALSE.
|
|
|
|
--*/
|
|
{
|
|
DWORD bytes_read = 0; // the length of send buffer
|
|
LONG sint; // signed integer for length comp
|
|
DWORD temp;
|
|
DWORD read_len;
|
|
DWORD file_len;
|
|
PBYTE wksta_buf;
|
|
DWORD wksta_buf_len;
|
|
DWORD LengthDataBuffer;
|
|
PBYTE pDataBuffer;
|
|
PFLIST_TBL flist_tbl;
|
|
DWORD flist_tbl_len;
|
|
DWORD cur_flist_i;
|
|
DWORD cur_offset;
|
|
DWORD cur_file_base_offset;
|
|
DWORD fblock_base_offset;
|
|
BOOL is_end_of_bblock;
|
|
BOOL LAN_err;
|
|
|
|
// RplDump( RG_DebugLevel & RPL_DEBUG_FLOW,( "++RplReadData"));
|
|
|
|
//
|
|
// The following is set in RplWorkerThread2
|
|
//
|
|
LengthDataBuffer = pWorkerData->send_buf_len;
|
|
|
|
//
|
|
// The following are set in RplMakeWkstaBuf
|
|
//
|
|
wksta_buf = pWorkerData->wksta_buf;
|
|
wksta_buf_len = pWorkerData->wksta_buf_len;
|
|
fblock_base_offset = pWorkerData->fblock_base_offset;
|
|
|
|
//
|
|
// The following are set in RplOpenData
|
|
//
|
|
pDataBuffer = pWorkerData->pDataBuffer;
|
|
|
|
flist_tbl = pWorkerData->flist_tbl;
|
|
flist_tbl_len = pWorkerData->flist_tbl_len;
|
|
|
|
cur_flist_i = pWorkerData->cur_flist_i;
|
|
cur_offset = pWorkerData->cur_offset;
|
|
cur_file_base_offset = pWorkerData->cur_file_base_offset;
|
|
is_end_of_bblock = pWorkerData->is_end_of_bblock;
|
|
|
|
|
|
if ( fblock_base_offset > read_offset) {
|
|
|
|
// We have to copy at least some data from wksta buffer or/and from
|
|
// the empty space between "wksta_buf_len" (end of wksta buffer
|
|
// data) and "fblock_base_offset" (beginning of file list data).
|
|
// First copy the data from wksta buffer then from empty space.
|
|
|
|
if ( wksta_buf_len > read_offset) { // wksta buffer data
|
|
|
|
if ( wksta_buf_len >= read_offset + LengthDataBuffer) {
|
|
bytes_read = LengthDataBuffer; // all is here
|
|
} else {
|
|
// Some but not all of the leftover data is here.
|
|
bytes_read = wksta_buf_len - read_offset;
|
|
}
|
|
|
|
memcpy( pDataBuffer, &wksta_buf[read_offset], bytes_read);
|
|
}
|
|
|
|
if ( bytes_read < LengthDataBuffer) { // empty space data
|
|
|
|
if ( read_offset + LengthDataBuffer <= fblock_base_offset) {
|
|
temp = LengthDataBuffer - bytes_read; // rest is here
|
|
} else {
|
|
// Some but not all of the leftover data is here.
|
|
temp = fblock_base_offset - wksta_buf_len;
|
|
}
|
|
|
|
memset( &pDataBuffer[ bytes_read], 0, temp);
|
|
bytes_read += temp;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if the right file is opened and the seek is OK. There may
|
|
// have been a LAN I/O error in which case we must read the data from
|
|
// a new position.
|
|
//
|
|
if ( read_offset == cur_offset || cur_offset == -1L) {
|
|
LAN_err = FALSE; // everything OK
|
|
|
|
} else {
|
|
LAN_err = TRUE; // error in LAN I/O, this is not a sequential read
|
|
//
|
|
// this flag is set if we were reading the last buffer,
|
|
// reset flag, otherwise the rest is not read with ReadFile()
|
|
//
|
|
is_end_of_bblock = FALSE;
|
|
}
|
|
|
|
|
|
if ( bytes_read < LengthDataBuffer && !is_end_of_bblock) {
|
|
//
|
|
// All the data has not been read yet. Read the rest from
|
|
// files mentioned in the file list table.
|
|
//
|
|
if ( LAN_err && pWorkerData->hFile != INVALID_HANDLE_VALUE) {
|
|
if ( !CloseHandle( pWorkerData->hFile)) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
}
|
|
pWorkerData->hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
// Check if this read is from a wrong position or there was
|
|
// fatal error in the first file read => start from the beginning.
|
|
|
|
if ( LAN_err && read_offset > fblock_base_offset) {
|
|
//
|
|
// error => reset bytes_read counter, reject the possible data
|
|
// resend an old packet, search the new file of read_offset
|
|
//
|
|
bytes_read = 0;
|
|
cur_file_base_offset = fblock_base_offset;
|
|
|
|
for ( cur_flist_i = 0; cur_flist_i < flist_tbl_len; cur_flist_i++) {
|
|
if (read_offset <
|
|
cur_file_base_offset + flist_tbl[cur_flist_i].FileData.file_len) {
|
|
|
|
break; // found, exit the search loop
|
|
}
|
|
cur_file_base_offset += flist_tbl[cur_flist_i].FileData.file_len;
|
|
}
|
|
|
|
//
|
|
// If wksta has sent a wrong read offset, terminate read ahead.
|
|
//
|
|
if ( cur_flist_i >= flist_tbl_len) {
|
|
is_end_of_bblock = TRUE;
|
|
goto end_of_block_exit;
|
|
}
|
|
|
|
//
|
|
// Open file for reading
|
|
//
|
|
pWorkerData->hFile = CreateFile( flist_tbl[cur_flist_i].path_name,
|
|
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, 0L);
|
|
if ( pWorkerData->hFile == INVALID_HANDLE_VALUE) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
|
|
pWorkerData->EventStrings[ 1] = flist_tbl[cur_flist_i].path_name;
|
|
pWorkerData->EventId = NELOG_RplWkstaFileOpen;
|
|
return( FALSE);
|
|
}
|
|
|
|
//
|
|
// seek the current position, we are probably not reading from
|
|
// the start of file
|
|
//
|
|
file_len = SetFilePointer( pWorkerData->hFile,
|
|
read_offset - cur_file_base_offset, NULL, FILE_BEGIN);
|
|
if ( file_len == INVALID_FILE_OFFSET) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
|
|
pWorkerData->EventStrings[ 1] = flist_tbl[cur_flist_i].path_name;
|
|
pWorkerData->EventId = NELOG_RplWkstaFileRead;
|
|
return( FALSE);
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Open the primary file, if it's not opened yet
|
|
//
|
|
if ( pWorkerData->hFile == INVALID_HANDLE_VALUE) {
|
|
if (read_offset <= fblock_base_offset) {
|
|
// open the first file
|
|
cur_flist_i = 0;
|
|
cur_file_base_offset = fblock_base_offset;
|
|
}
|
|
//
|
|
// Open file for reading
|
|
//
|
|
pWorkerData->hFile = CreateFile( flist_tbl[cur_flist_i].path_name,
|
|
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, 0L);
|
|
if ( pWorkerData->hFile == INVALID_HANDLE_VALUE) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
|
|
pWorkerData->EventStrings[ 1] = flist_tbl[cur_flist_i].path_name;
|
|
pWorkerData->EventId = NELOG_RplWkstaFileOpen;
|
|
return( FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// read files until send buffer is full
|
|
//
|
|
while( bytes_read < LengthDataBuffer) {
|
|
if ( !ReadFile( pWorkerData->hFile, &pDataBuffer[bytes_read],
|
|
LengthDataBuffer - bytes_read, &read_len, NULL)) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
|
|
pWorkerData->EventStrings[ 1] = flist_tbl[cur_flist_i].path_name;
|
|
pWorkerData->EventId = NELOG_RplWkstaFileRead;
|
|
return( FALSE);
|
|
}
|
|
|
|
bytes_read += read_len;
|
|
|
|
if (bytes_read == LengthDataBuffer) {
|
|
break; // we read all the data for now, exit the loop
|
|
}
|
|
//
|
|
// We have not read all the data we asked for. Therefore, we
|
|
// must have reached end of file. Therefore, close the current
|
|
// file handle and prepare to read the next file.
|
|
//
|
|
if ( !CloseHandle( pWorkerData->hFile)) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
}
|
|
|
|
pWorkerData->hFile = INVALID_HANDLE_VALUE;
|
|
cur_file_base_offset += flist_tbl[cur_flist_i].FileData.file_len;
|
|
cur_flist_i++;
|
|
|
|
// reset the last bytes in the file
|
|
|
|
temp = cur_file_base_offset - read_offset;
|
|
|
|
if ( (sint = (LONG)(temp - bytes_read)) > 0) {
|
|
memset( pDataBuffer + bytes_read, 0, sint );
|
|
}
|
|
bytes_read = temp;
|
|
|
|
if ( cur_flist_i >= flist_tbl_len) {
|
|
is_end_of_bblock = TRUE;
|
|
break; // end of file list
|
|
}
|
|
|
|
//
|
|
// Open file for reading
|
|
//
|
|
pWorkerData->hFile = CreateFile( flist_tbl[cur_flist_i].path_name,
|
|
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, 0L);
|
|
if ( pWorkerData->hFile == INVALID_HANDLE_VALUE) {
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
RplDump( ++RG_Assert, ("Error=%d", GetLastError()));
|
|
pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
|
|
pWorkerData->EventStrings[ 1] = flist_tbl[cur_flist_i].path_name;
|
|
pWorkerData->EventId = NELOG_RplWkstaFileOpen;
|
|
return( FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
cur_offset = read_offset + LengthDataBuffer;
|
|
|
|
//
|
|
// only for end of boot block
|
|
//
|
|
|
|
end_of_block_exit:
|
|
|
|
//
|
|
// update the changed values
|
|
//
|
|
|
|
pWorkerData->cur_offset = cur_offset;
|
|
pWorkerData->cur_file_base_offset = cur_file_base_offset;
|
|
pWorkerData->cur_flist_i = cur_flist_i;
|
|
pWorkerData->is_end_of_bblock = is_end_of_bblock;
|
|
|
|
//
|
|
// Make NLS (DBCS ?) patch to RPLBOOT.SYS.
|
|
//
|
|
|
|
if ( pWorkerData->MakePatch == TRUE) {
|
|
RplMakePatch( pWorkerData, pDataBuffer, bytes_read, read_offset);
|
|
}
|
|
|
|
//
|
|
// return the buffer address and the length
|
|
//
|
|
|
|
*pBytesRead = bytes_read;
|
|
// RplDump( RG_DebugLevel & RPL_DEBUG_FLOW,( "--RplReadData"));
|
|
return( TRUE);
|
|
|
|
}
|
|
|
|
|