NET_API_STATUS RxpConvertAuditArray( IN LPVOID InputArray, IN DWORD InputByteCount, OUT LPBYTE * OutputArrayPtr, // will be alloc'ed (free w/ NetApiBufferFree). OUT LPDWORD OutputByteCountPtr ) { DWORD EntryType; const LPBYTE InputArrayEndPtr = (LPVOID) ( ((LPBYTE)InputArray) + InputByteCount ); LPBYTE InputBytePtr; DWORD InputDataOffset; DWORD InputTotalEntrySize; LPBYTE InputFixedPtr; LPBYTE InputVariablePtr; DWORD InputVariableSize; LPVOID OutputArray; DWORD OutputArraySize; DWORD OutputBytesUsed = 0; DWORD OutputEntrySizeSoFar; LPAUDIT_ENTRY OutputFixedPtr; DWORD OutputVariableSize; LPBYTE OutputVariablePtr; NET_API_STATUS Status; // // Error check caller's parameters. // Set output parameters to make error handling easier below. // (Also check for memory faults while we're at it.) // if (OutputArrayPtr != NULL) { *OutputArrayPtr = NULL; } if (OutputByteCountPtr != NULL) { *OutputByteCountPtr = 0; } if ( (OutputArrayPtr == NULL) || (OutputByteCountPtr == NULL) ) { return (ERROR_INVALID_PARAMETER); } if ( (InputArray == NULL) || (InputByteCount == 0) ) { return (ERROR_INVALID_PARAMETER); } // // Compute size needed for output buffer, taking into account: // per field expansion, // per entry expansion, // and alignment. // Status = RxpEstimateLogSize( DOWNLEVEL_AUDIT_FIXED_ENTRY_SIZE, InputByteCount, // input (downlevel) array size in bytes. FALSE, // no, we're not doing error log & OutputArraySize); // set estimated array size in bytes. if (Status != NO_ERROR) { return (Status); // (output vars are already set.) } NetpAssert( OutputArraySize > 0 ); NetpAssert( OutputArraySize > InputByteCount ); *OutputByteCountPtr = OutputArraySize; // // Allocate oversize area for output; we'll realloc it to shrink it. // Status = NetApiBufferAllocate( OutputArraySize, (LPVOID *) & OutputArray ); if (Status != NERR_Success) { return (Status); // (output vars are already set.) } NetpAssert( OutputArray != NULL ); NetpAssert( POINTER_IS_ALIGNED( OutputArray, ALIGN_WORST ) ); // // Loop for each entry in the input area. // OutputFixedPtr = OutputArray; for (InputBytePtr = InputArray; InputBytePtr < InputArrayEndPtr; ) { InputFixedPtr = InputBytePtr; NetpAssert( POINTER_IS_ALIGNED( OutputFixedPtr, ALIGN_WORST ) ); IF_DEBUG(AUDIT) { NetpKdPrint(( PREFIX_NETLIB "RxpConvertAuditArray: doing input entry at " FORMAT_LPVOID ", out entry at " FORMAT_LPVOID ".\n", (LPVOID) InputFixedPtr, (LPVOID) OutputFixedPtr )); } // // Process each field in input fixed entry. // InputTotalEntrySize = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr ); if (InputTotalEntrySize < MIN_DOWNLEVEL_ENTRY_SIZE) { goto FileCorrupt; } { LPBYTE EndPos = InputBytePtr + InputTotalEntrySize; if (EndPos > InputArrayEndPtr) { goto FileCorrupt; } EndPos -= sizeof(WORD); // the last ae_len2 if (SmbGetUshort( (LPWORD) EndPos ) != InputTotalEntrySize) { goto FileCorrupt; } } InputBytePtr += sizeof(WORD); // skip ae_len. OutputFixedPtr->ae_reserved = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr ); InputBytePtr += sizeof(WORD); // skip ae_reserved { DWORD LocalTime = (DWORD) SmbGetUlong( (LPDWORD) InputBytePtr ); DWORD GmtTime; NetpLocalTimeToGmtTime( LocalTime, & GmtTime ); OutputFixedPtr->ae_time = GmtTime; InputBytePtr += sizeof(DWORD); } EntryType = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr ); OutputFixedPtr->ae_type = EntryType; InputBytePtr += sizeof(WORD); InputDataOffset = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr ); NetpAssert( InputDataOffset >= DOWNLEVEL_AUDIT_FIXED_ENTRY_SIZE ); InputBytePtr += sizeof(WORD); OutputEntrySizeSoFar = sizeof(AUDIT_ENTRY); // // Process variable portion (if any): // InputVariablePtr = (LPVOID) ( ((LPBYTE) InputFixedPtr) + InputDataOffset ); InputVariableSize = (InputTotalEntrySize - InputDataOffset) - sizeof(WORD); // don't include ae_len2. OutputVariablePtr = (LPVOID) ( ((LPBYTE) OutputFixedPtr) + sizeof(AUDIT_ENTRY) ); // Align variable part. OutputVariablePtr = ROUND_UP_POINTER( OutputVariablePtr, ALIGN_WORST ); OutputEntrySizeSoFar = ROUND_UP_COUNT( OutputEntrySizeSoFar, ALIGN_WORST ); OutputFixedPtr->ae_data_offset = OutputEntrySizeSoFar; // Copy and convert the variable part. RxpConvertAuditEntryVariableData( EntryType, InputVariablePtr, OutputVariablePtr, InputVariableSize, & OutputVariableSize); #ifdef REVISED_AUDIT_ENTRY_STRUCT OutputFixedPtr->ae_data_size = OutputVariableSize; #endif // Account for variable area and ae_len2 in total length. OutputEntrySizeSoFar += (OutputVariableSize + sizeof(DWORD)); // Round size up so next entry (if any) is worst-case aligned. OutputEntrySizeSoFar = ROUND_UP_COUNT( OutputEntrySizeSoFar, ALIGN_WORST ); #define OutputEntrySize OutputEntrySizeSoFar OutputFixedPtr->ae_len = OutputEntrySize; { LPDWORD EndSizePtr = (LPVOID) ( ((LPBYTE)OutputFixedPtr) + OutputEntrySize - sizeof(DWORD) ); *EndSizePtr = OutputEntrySize; // set ae_len2. } // // Update for next loop iteration. // InputBytePtr = (LPVOID) ( ((LPBYTE) InputFixedPtr) + InputTotalEntrySize); OutputFixedPtr = (LPVOID) ( ((LPBYTE) OutputFixedPtr) + OutputEntrySize ); OutputBytesUsed += OutputEntrySize; NetpAssert( OutputBytesUsed <= OutputArraySize ); } NetpAssert(OutputBytesUsed > 0); NetpAssert( OutputBytesUsed <= OutputArraySize ); // BUGBUG: realloc OutputArray to OutputBytesUsed *OutputArrayPtr = OutputArray; *OutputByteCountPtr = OutputBytesUsed; return (NERR_Success); FileCorrupt: NetpKdPrint(( PREFIX_NETAPI "RxpConvertAuditArray: corrupt audit log!\n" )); if (OutputArray != NULL) { (VOID) NetApiBufferFree( OutputArray ); } if (OutputArrayPtr != NULL) { *OutputArrayPtr = NULL; } if (OutputByteCountPtr != NULL) { *OutputByteCountPtr = 0; } return (NERR_LogFileCorrupt); }
NTSTATUS RdrMapSmbError ( IN PSMB_HEADER Smb, IN PSERVERLISTENTRY Sle OPTIONAL ) /*++ Routine Description: This routine takes an SMB, grabs the error from it, and maps it to an NT error. Arguments: IN PSMB_HEADER Smb - Supplies the SMB buffer to check. IN PSERVERLISTENTRY Sle OPTIONAL - Supplies the server name for the Smb. Return Value: NTSTATUS - Status of resulting operation. --*/ { NTSTATUS Status; USHORT Error; USHORT i; UCHAR ErrorClass; DISCARDABLE_CODE(RdrVCDiscardableSection); // // If this SMB contains an NT status for the operation, return // that, otherwise map the resulting error. // if (SmbGetUshort(&Smb->Flags2) & SMB_FLAGS2_NT_STATUS) { PNT_SMB_HEADER NtSmb = (PNT_SMB_HEADER)Smb; return(SmbGetUlong(&NtSmb->Status.NtStatus)); } else { if ((ErrorClass = Smb->ErrorClass) == SMB_ERR_SUCCESS) { return STATUS_SUCCESS; } } Error = SmbGetUshort(&Smb->Error); if (Error == SMB_ERR_SUCCESS) { Status = STATUS_UNEXPECTED_NETWORK_ERROR; goto ReturnStatus; } switch (ErrorClass) { case SMB_ERR_CLASS_DOS: case SMB_ERR_CLASS_HARDWARE: for (i=0; i<RdrOs2ErrorMapLength; i++) { if (RdrOs2ErrorMap[i].ErrorCode==Error) { Status = RdrOs2ErrorMap[i].ResultingStatus; goto ReturnStatus; } } Status = BASE_DOS_ERROR + SmbGetUshort(&Smb->Error); break; case SMB_ERR_CLASS_SERVER: for (i=0; i<RdrSmbErrorMapLength; i++) { if (RdrSmbErrorMap[i].ErrorCode==Error) { Status = RdrSmbErrorMap[i].ResultingStatus; goto ReturnStatus; } } Status = STATUS_UNEXPECTED_NETWORK_ERROR; break; default: dprintf(DPRT_SMB|DPRT_ERROR, ("Unknown error SMB error class %x", ErrorClass)); Status = STATUS_NOT_IMPLEMENTED; break; } ReturnStatus: if ( Status == STATUS_UNEXPECTED_NETWORK_ERROR ) { RdrStatistics.NetworkErrors += 1; RdrWriteErrorLogEntry( Sle, IO_ERR_LAYERED_FAILURE, EVENT_RDR_UNEXPECTED_ERROR, Status, Smb, sizeof(SMB_HEADER) ); } return Status; }
NTSTATUS BowserHandleIpxDomainAnnouncement( IN PTRANSPORT Transport, IN PSMB_IPX_NAME_PACKET NamePacket, IN PBROWSE_ANNOUNCE_PACKET_1 DomainAnnouncement, IN DWORD RequestLength, IN ULONG ReceiveFlags ) /*++ Routine Description: This routine will process receive datagram indication messages, and process them as appropriate. Arguments: IN PTRANSPORT Transport - The transport provider for this request. IN PSMB_IPX_NAME_PACKET NamePacket - The name packet for this request. Return Value: NTSTATUS - Status of operation. --*/ { PVIEW_BUFFER ViewBuffer; DISCARDABLE_CODE(BowserDiscardableCodeSection); ExInterlockedAddLargeStatistic(&BowserStatistics.NumberOfDomainAnnouncements, 1); ViewBuffer = BowserAllocateViewBuffer(); // // If we are unable to allocate a view buffer, ditch this datagram on // the floor. // if (ViewBuffer == NULL) { return STATUS_REQUEST_NOT_ACCEPTED; } BowserCopyOemComputerName(ViewBuffer->ServerName, NamePacket->Name, SMB_IPX_NAME_LENGTH, ReceiveFlags); BowserCopyOemComputerName(ViewBuffer->ServerComment, NamePacket->SourceName, SMB_IPX_NAME_LENGTH, ReceiveFlags); if ( DomainAnnouncement->Type & SV_TYPE_NT ) { ViewBuffer->ServerType = SV_TYPE_DOMAIN_ENUM | SV_TYPE_NT; } else { ViewBuffer->ServerType = SV_TYPE_DOMAIN_ENUM; } ASSERT (Transport->MasterBrowser != NULL); ViewBuffer->TransportName = Transport->MasterBrowser; ViewBuffer->ServerVersionMajor = DomainAnnouncement->VersionMajor; ViewBuffer->ServerVersionMinor = DomainAnnouncement->VersionMinor; ViewBuffer->ServerPeriodicity = (USHORT)((SmbGetUlong(&DomainAnnouncement->Periodicity) + 999) / 1000); BowserReferenceTransportName(Transport->MasterBrowser); BowserReferenceTransport( Transport ); ExInitializeWorkItem(&ViewBuffer->Overlay.WorkHeader, BowserProcessDomainAnnouncement, ViewBuffer); ExQueueWorkItem(&ViewBuffer->Overlay.WorkHeader, DelayedWorkQueue); return STATUS_SUCCESS; }