Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

499 lines
17 KiB

/*++
Copyright (c) 1987-93 Microsoft Corporation
Module Name:
sfr.c
Abstract:
Contains RplDlcSfr() entry point.
Contains RplFindRcb() function which is also used by server\request.c\RequestThread().
Author:
Vladimir Z. Vulovic (vladimv) 03 - February - 1993
Revision History:
03-Feb-1993 vladimv
Ported to NT
--*/
#include "local.h"
VOID SfrReceiveThread( PADAPTER_INFO pAdapterInfo)
/*++
Routine Description:
Created from RplDlcSfr(). Keeps RECEIVE posted on LOAD_SAP.
Received data is read by RpldSendFileRequest() function using AcsLan
READ command. The RECEIVE call will complete if ...
--*/
{
PLLC_CCB pBadCcb;
DWORD status;
BYTE command; // failed command
RplDump( RG_DebugLevel & RPL_DEBUG_SFR, (
"++SfrReceiveThread: pAdapterInfo=0x%x", pAdapterInfo));
memset( (PVOID)&pAdapterInfo->u2, '\0', sizeof(pAdapterInfo->u2));
pAdapterInfo->u2.r.uchAdapterNumber = pAdapterInfo->adapter_number;
pAdapterInfo->u2.r.uchDlcCommand = LLC_RECEIVE;
pAdapterInfo->u2.r.hCompletionEvent = pAdapterInfo->sfrsem;
pAdapterInfo->u2.r.u.pParameterTable = (PLLC_PARMS)&pAdapterInfo->u2.r1;
pAdapterInfo->u2.r1.ulReceiveFlag = COMPLETE_BY_READ;
pAdapterInfo->u2.r1.usStationId = pAdapterInfo->loadsid;
for ( ; ;) {
status = AcsLan(&pAdapterInfo->u2.r, &pBadCcb);
if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
command = LLC_RECEIVE;
break;
}
//
// Waiting for SEND.FILE.REQUEST
//
status = WaitForSingleObject( pAdapterInfo->sfrsem, INFINITE);
if ( status != WAIT_OBJECT_0) {
if ( status == WAIT_FAILED) {
status = GetLastError();
}
command = SEM_WAIT;
break;
}
if ( pAdapterInfo->u2.r.uchDlcStatus
!= LLC_STATUS_LOST_DATA_NO_BUFFERS
&& pAdapterInfo->u2.r.uchDlcStatus
!= LLC_STATUS_LOST_DATA_INADEQUATE_SPACE) {
status = pAdapterInfo->u2.r.uchDlcStatus;
command = LLC_RECEIVE;
break;
}
}
if ( pAdapterInfo->Closing == TRUE) {
RplDump( RG_DebugLevel & RPL_DEBUG_SFR, (
"--SfrReceiveThread: pAdapterInfo=0x%x", pAdapterInfo));
return;
}
RplDump( ++RG_Assert,( "status=%d, command=0x%x", status, command));
//
// We come here in case of unrecoverable errors. RPL service will
// be terminated. We also set getdata_sem event to unblock
// RpldSendFileRequest() thread.
//
RplDlcReportEvent( status, command);
pAdapterInfo->SfrReturn = TRUE;
(VOID)SetEvent( pAdapterInfo->getdata_sem);
}
VOID set_fdr_fixed(
PLAN_RESOURCE pLanResource,
WORD usStationId
)
/*++
Routine Description:
set_fdr_fixed() initializes the fixed parts of the FILE.DATA.RESPONSE
frame and the TRANSMIT.UI parameter block. It takes a pointer to the
LAN RCB containing the frame and transmit parameters to be initialized
and usStationId for architected FIND SAP.
--*/
{
PFDR pFdr; // point to frame
LLC_TRANSMIT_PARMS *tpp; // point to xmit parms
pFdr = (PFDR)pLanResource->frame; // generate frame here
tpp = &pLanResource->TransmitParms; // locate xmit parms
// setup fixed part of frame
// program length varies
pFdr->program_command = FDR_CMD; // 00 20
pFdr->seq_hdr = SEQ_HDR; // 00 08 40 11
// seq num varies
pFdr->loader_hdr = LDR_HDR; // 00 0d c0 14
pFdr->locate_addr = 0; // 00 00 00 00
pFdr->xfer_addr = 0; // 00 00 00 00
pFdr->flags = 0; // flags zero = no FDR ack
// data_hdr varies
pFdr->data_hdr = DATA_HDR; // 00 ?? 40 18
// setup transmit parm block
tpp->usStationId = usStationId;
tpp->uchTransmitFs = 0; // 00
tpp->uchRemoteSap = FIND_SAP; // FC
// Queue #1 is 1st buffer
tpp->pXmitQueue1 = (PLLC_XMIT_BUFFER)&pLanResource->XmitBuffer;
tpp->pXmitQueue2 = NULL; // 00 00 00 00
tpp->cbBuffer1 = (sizeof *pFdr); // 00 1D
tpp->pBuffer1 = (PCH)pLanResource->frame;
tpp->uchXmitReadOption = DLC_DO_NOT_CHAIN_XMIT; // don't chain on completion
}
VOID ProcessSfr(
PRCB pRcb,
PADAPTER_INFO pAdapterInfo,
PRCVBUF pRcvbuf
)
{
PLAN_RESOURCE pLanResource;
WORD tempword;
pLanResource = (PLAN_RESOURCE)pRcb->lan_rcb_ptr;
pLanResource->retry_count = 0;
tempword = HILO(pRcvbuf->u.SendFileRequest.max_frame);
//
// Both protocol data and boot block data must fit in
// transmit buffer frame (OVRHD == size of protocol data).
//
if (tempword <= pAdapterInfo->max_xmit_buff_size) {
tempword -= OVRHD;
} else {
tempword = (WORD)( pAdapterInfo->max_xmit_buff_size - OVRHD);
}
//
// "max_frame" is used by rpl server to determine the size of boot
// block data frames.
//
pRcb->max_frame = tempword;
memcpy( pLanResource->LanHeader.dest_addr,
&(pRcvbuf->b.auchLanHeader[ 8]), NODE_ADDRESS_LENGTH);
// mask off routing info indication bit
pLanResource->LanHeader.dest_addr[0] &= 0x7F;
// note: byte to word xlate
pLanResource->XmitBuffer.cbBuffer = pRcvbuf->b.cbLanHeader;
if (pAdapterInfo->network_type == RPL_ADAPTER_TOKEN_RING) {
if ( pRcvbuf->b.cbLanHeader > 14) {
//
// There is routing info, we have TokenRing case. Inherit
// the routing from received frame. Note memcpy length! Also,
// we "and" with 0x1f for "non broadcast" and "xor" with 0x80
// for "direction interpreted from right to left".
//
memcpy( pLanResource->LanHeader.routing_info_header,
&pRcvbuf->b.auchLanHeader[14], pRcvbuf->b.cbLanHeader -14);
pLanResource->LanHeader.routing_info_header[0] &= 0x1f;
pLanResource->LanHeader.routing_info_header[1] ^= 0x80;
} else {
//
// There is no routing info, we have Etherner case. We just
// clear the indication bit.
//
pLanResource->LanHeader.source_addr[0] &= 0x7f;
}
}
// set FILE.DATA.RESPONSE
set_fdr_fixed( pLanResource, pAdapterInfo->findsid);
}
PRCB RplFindRcb(
PPRCB HeadRcbList,
PBYTE NodeAddress
)
/*++
Routine Description:
Finds matching rcb from rcbs in use chain.
Arguments:
HeadRcbList pointer to the variable, which contains pointer to the
first RCB in chain
NodeAddress pointer to the hex adapter-id to scan for
Return Value:
Pointer to matching RCB if success, NULL otherwise.
--*/
{
PRCB pRcb;
DebugCheckList( HeadRcbList, NULL, 0);
for ( pRcb = *HeadRcbList; pRcb != NULL; pRcb = pRcb->next_rcb) {
if ( !memcmp( pRcb->NodeAddress, NodeAddress,
sizeof( pRcb->NodeAddress) )) {
break;
}
}
return( pRcb);
}
BOOL RplDlcSfr(
POPEN_INFO pOpenInfo,
PPRCB HeadRcbList,
PCRITICAL_SECTION ProtectRcbList
)
/*++
Routine Description:
Receives SEND.FILE.REQUEST frames. Creates a thread to keep a receive
command outstanding on the opened LOAD_SAP in order to pick up
SEND.FILE.REQUEST frames from workstations. Uses AcsLan READ-function
to get notification for received data.
It validates the frame and places the requested sequence number,
lan header, transmit buffer header and parameters into the RCB
associated with the workstation and clears RAM semaphore (in RCB)
to wake up the service thread for the workstation.
It then frees the buffer containing the frame and waits for the next one.
Arguments:
pOpenInfo pointer to the OPEN_INFO structure
HeadRcbList pointer to the variable, which contains pointer to the
first RCB in chain. The chain contains RCB-s of all clients this
server is interested in getting SEND.FILE.REQUEST frames from.
ProtectRcbList for serialising access to rcb list
Return Value:
ERROR_SUCCESS if success, non-zero otherwise
--*/
{
DWORD status;
PLLC_CCB pBadCcb;
PRCB pRcb;
PRCVBUF pRcvbuf;
DWORD sfr_seq_number; // in the incoming SFR frame
DWORD fdr_seq_number; // of what worker already sent
PADAPTER_INFO pAdapterInfo;
DWORD ThreadId;
pAdapterInfo = (PADAPTER_INFO)pOpenInfo->adapt_info_ptr;
RplDump( RG_DebugLevel & RPL_DEBUG_SFR, (
"++SendFileRequest: pAdapterInfo=0x%x", pAdapterInfo));
//
// Create thread to keep receive posted.
//
pAdapterInfo->SfrReceiveThreadHandle = CreateThread(
NULL, // lpThreadAttribute
0, // dwStackSize - same as first thread
(LPTHREAD_START_ROUTINE)SfrReceiveThread, // lpStartAddress
(LPVOID)pAdapterInfo, // lpParameter
0, // dwCreationFlags
&ThreadId // lpThreadId
);
if ( pAdapterInfo->SfrReceiveThreadHandle == NULL) {
status = GetLastError();
RplDump( ++RG_Assert,( "pAdapterInfo=0x%x, status=%d", pAdapterInfo, status));
RplDlcReportEvent( status, THREAD_CREATE);
return( FALSE);
}
//
// Setup CCB for LLC_READ, then setup LLC_READ_PARMS to wake up
// only when data arrives.
//
memset( (PVOID)&pAdapterInfo->u3, '\0', sizeof(pAdapterInfo->u3));
pAdapterInfo->u3.r.uchAdapterNumber = pAdapterInfo->adapter_number;
pAdapterInfo->u3.r.uchDlcCommand = LLC_READ;
pAdapterInfo->u3.r.hCompletionEvent = pAdapterInfo->getdata_sem;
pAdapterInfo->u3.r.u.pParameterTable = (PLLC_PARMS)&pAdapterInfo->u3.r1;
pAdapterInfo->u3.r1.usStationId = pAdapterInfo->loadsid;
pAdapterInfo->u3.r1.uchOptionIndicator = LLC_OPTION_READ_SAP;
pAdapterInfo->u3.r1.uchEventSet = LLC_EVENT_RECEIVE_DATA;
//
// Loop for ever processing SendFileRequest frames arriving to this
// adapter.
//
for ( ; ;) {
//
// Reset event to be cleared later on by AcsLan.
//
if ( !ResetEvent( pAdapterInfo->getdata_sem)) {
if ( pAdapterInfo->Closing == TRUE) {
return( FALSE);
}
status = GetLastError();
RplDump( ++RG_Assert,( "pAdapterInfo=0x%x, status=%d", pAdapterInfo, status));
RplDlcReportEvent( status, SEM_SET);
return( FALSE);
}
status = AcsLan( &pAdapterInfo->u3.r, &pBadCcb);
if ( pAdapterInfo->Closing == TRUE) {
(VOID)SetEvent( pAdapterInfo->getdata_sem);
return( FALSE);
}
if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
RplDump( ++RG_Assert,( " r=0x%x, status=%d", &pAdapterInfo->u3.r, status));
RplDlcReportEvent( status, LLC_READ); // failed to READ
(VOID)SetEvent( pAdapterInfo->getdata_sem);
return( FALSE);
}
status = WaitForSingleObject( pAdapterInfo->getdata_sem, INFINITE);
if ( pAdapterInfo->Closing == TRUE) {
return( FALSE);
}
if ( ( status != WAIT_OBJECT_0) || (pAdapterInfo->u3.r.uchDlcStatus)) {
if ( status != WAIT_OBJECT_0) {
if ( status == WAIT_FAILED) {
status = GetLastError();
}
RplDlcReportEvent( status, SEM_WAIT);
} else {
RplDlcReportEvent( pAdapterInfo->u3.r.uchDlcStatus, LLC_READ);
}
RplDump( ++RG_Assert,( " pAdapterInfo=0x%x, status=%d, DlcStatus=0x%x",
pAdapterInfo, status, pAdapterInfo->u3.r.uchDlcStatus));
return( FALSE);
}
if ( pAdapterInfo->SfrReturn) { // Check sfr receive
//
// SfrReceiveThreadHandle is being waited in DlcTerm() call.
//
return( TRUE); // event was written by sfr receive
}
//
// Point to receive buffer.
//
pRcvbuf = (PRCVBUF)(pAdapterInfo->u3.r1.Type.Event.pReceivedFrame);
RplDump( TRUE, ("pRcvbuf=0x%x", pRcvbuf));
//
// Whenever we find a matching RCB we set SFR flag so that worker
// thread does not move this RCB while we are working on it. Note
// that this means that SFR must be cleared once we are done with
// this RCB.
//
EnterCriticalSection( ProtectRcbList);
pRcb = RplFindRcb( HeadRcbList, (PBYTE)pRcvbuf->u.SendFileRequest.source_addr);
if ( pRcb != NULL) {
if ( pRcb->Pending == TRUE) {
pRcb = NULL; // pretend we did not see this RCB
} else {
pRcb->SFR = TRUE; // hold this RCB
}
}
LeaveCriticalSection( ProtectRcbList);
if ( pRcb == NULL
|| pRcvbuf->u.SendFileRequest.program_command == ALERT_CMD
|| pRcvbuf->u.SendFileRequest.program_command != SEND_CMD
|| pRcvbuf->u.SendFileRequest.conn_class != CLASS1) {
//
// Calling adapter was not found, or we received an alert frame,
// or we received an unknown frame, or request class was wrong.
//
if ( pRcb != NULL && status == 0
&& pRcvbuf->u.SendFileRequest.program_command == ALERT_CMD) {
//
// Got an alert frame on LOAD_SAP and RCB is found.
//
pRcb->flags.alerted = RCB_ALERTED;// yes: signal
//
// Instead of ACK or rexmit request, we have Alert frame.
// Wake up worker.
//
if ( !SetEvent( pRcb->SF_wakeup)) {
RplDump( ++RG_Assert,("pRcb=0x%x error=%d", pRcb, GetLastError()));
}
}
if ( pRcb != NULL) {
pRcb->SFR = FALSE; // release RCB
}
if ( !RplDlcBufferFree( SFR_FREE, pAdapterInfo)) {
return( FALSE);
}
continue;
}
//
// Get SFR sequence number (in intel format) & validate it.
//
sfr_seq_number = HILO2(pRcvbuf->u.SendFileRequest.seq_num);
fdr_seq_number = pRcb->fdr_seq_number;
if ( sfr_seq_number > fdr_seq_number + 1) {
RplDump( ++RG_Assert, (
"pRcb=0x%x, sfr_seq_number=%d, fdr_seq_number=%d",
pRcb, sfr_seq_number, fdr_seq_number));
pRcb->SFR = FALSE; // release RCB
if ( !RplDlcBufferFree( SFR_FREE, pAdapterInfo)) {
return( FALSE);
}
continue;
}
//
// We received a meaningful SFR frame. Initialize data if this is
// the first SFR frame. Then update clients sequence number & unblock
// worker thread.
//
if ( pRcb->ReceivedSfr == FALSE) {
pRcb->ReceivedSfr = TRUE;
ProcessSfr( pRcb, pAdapterInfo, pRcvbuf);
}
pRcb->sfr_seq_number = sfr_seq_number;
if ( !SetEvent( pRcb->SF_wakeup)) {
RplDump( ++RG_Assert,( "pRcb=0x%x error=%d", pRcb, GetLastError()));
}
pRcb->SFR = FALSE; // release RCB
if ( !RplDlcBufferFree( SFR_FREE, pAdapterInfo)) {
return( FALSE);
}
} // end of big loop
}
#ifdef RPL_DEBUG
VOID DebugCheckList( PPRCB HeadList, PRCB pInputRcb, DWORD Operation)
{
PRCB pRcb;
DWORD count;
DWORD found;
for ( pRcb = *HeadList, count = 0, found = FALSE; pRcb != NULL;
pRcb = pRcb->next_rcb, count++) {
if ( count > 20) {
RplDump( ++RG_Assert,("Circular list"));
}
if ( pRcb == pInputRcb) {
found = TRUE;
}
}
if ( pInputRcb != NULL) {
if ( Operation == RPL_MUST_FIND && found == FALSE) {
RplDump( ++RG_Assert,("Element not present"));
} else if ( Operation == RPL_MUST_NOT_FIND && found == TRUE) {
RplDump( ++RG_Assert,("Element already present"));
}
}
}
#endif