Ejemplo n.º 1
0
NTSTATUS
FatFsdLockControl (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Lock control operations

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    DebugTrace(+1, Dbg, "FatFsdLockControl\n", 0);

    //
    //  Call the common Lock Control routine, with blocking allowed if
    //  synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        Status = FatCommonLockControl( IrpContext, Irp );

    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFsdLockControl -> %08lx\n", Status);

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Ejemplo n.º 2
0
NTSTATUS
NtfsFsdLockControl (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Lock Control.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;

    NTSTATUS Status = STATUS_SUCCESS;
    PIRP_CONTEXT IrpContext = NULL;

#if __NDAS_NTFS__

	if ((PVOID)NdasNtfsControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    ASSERT_IRP( Irp );

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsFsdLockControl\n") );

    //
    //  Call the common Lock Control routine
    //

    FsRtlEnterFileSystem();

    ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, FALSE, FALSE );

    do {

        try {

            //
            //  We are either initiating this request or retrying it.
            //

            if (IrpContext == NULL) {

                //
                //  Allocate and initialize the Irp.
                //

                NtfsInitializeIrpContext( Irp, CanFsdWait( Irp ), &IrpContext );

                //
                //  Initialize the thread top level structure, if needed.
                //
    
                NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );

            } else if (Status == STATUS_LOG_FILE_FULL) {

                NtfsCheckpointForLogFileFull( IrpContext );
            }

#if __NDAS_NTFS_SECONDARY__

			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( NtfsIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
				SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_FILE );

				Status = STATUS_SUCCESS;

				while (TRUE) {
			
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {
		
						if (!FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT)) {

							Status = NtfsPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
						
						if (!FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT)) {

							Status = NtfsPostRequest( IrpContext, Irp );
							break;
						}
						
						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );
							
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Resource, 
																	 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Resource, 
															  BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );

						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = NtfsCommonLockControl( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
					}
				}

			} else
				Status = NtfsCommonLockControl( IrpContext, Irp );
#else
            Status = NtfsCommonLockControl( IrpContext, Irp );
#endif
            break;

        } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {

            //
            //  We had some trouble trying to perform the requested
            //  operation, so we'll abort the I/O request with
            //  the error status that we get back from the
            //  execption code
            //

            Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
        }

    } while (Status == STATUS_CANT_WAIT ||
Ejemplo n.º 3
0
NTSTATUS
NtCreateSemaphore (
    __out PHANDLE SemaphoreHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in LONG InitialCount,
    __in LONG MaximumCount
    )

/*++

Routine Description:

    This function creates a semaphore object, sets its initial count to the
    specified value, sets its maximum count to the specified value, and opens
    a handle to the object with the specified desired access.

Arguments:

    SemaphoreHandle - Supplies a pointer to a variable that will receive the
        semaphore object handle.

    DesiredAccess - Supplies the desired types of access for the semaphore
        object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    InitialCount - Supplies the initial count of the semaphore object.

    MaximumCount - Supplies the maximum count of the semaphore object.

Return Value:

    NTSTATUS.

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    PVOID Semaphore;
    NTSTATUS Status;

    //
    // Get previous processor mode and probe output handle address if
    // necessary.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {
        try {
            ProbeForWriteHandle(SemaphoreHandle);

        } except(EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }
    }

    //
    // Check argument validity.
    //

    if ((MaximumCount <= 0) || (InitialCount < 0) ||
       (InitialCount > MaximumCount)) {

        return STATUS_INVALID_PARAMETER;
    }

    //
    // Allocate semaphore object.
    //

    Status = ObCreateObject(PreviousMode,
                            ExSemaphoreObjectType,
                            ObjectAttributes,
                            PreviousMode,
                            NULL,
                            sizeof(KSEMAPHORE),
                            0,
                            0,
                            &Semaphore);

    //
    // If the semaphore object was successfully allocated, then initialize
    // the semaphore object and attempt to insert the semaphore object in
    // the current process' handle table.
    //

    if (NT_SUCCESS(Status)) {
        KeInitializeSemaphore((PKSEMAPHORE)Semaphore,
                              InitialCount,
                              MaximumCount);

        Status = ObInsertObject(Semaphore,
                                NULL,
                                DesiredAccess,
                                0,
                                NULL,
                                &Handle);

        //
        // If the semaphore object was successfully inserted in the current
        // process' handle table, then attempt to write the semaphore handle
        // value. If the write attempt fails, then do not report an error.
        // When the caller attempts to access the handle value, an access
        // violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            if (PreviousMode != KernelMode) {
                try {
                    *SemaphoreHandle = Handle;

                } except(EXCEPTION_EXECUTE_HANDLER) {
                    NOTHING;
                }

            } else {
                *SemaphoreHandle = Handle;
            }
        }
    }
Ejemplo n.º 4
0
NTSTATUS PhInitializeMappedImage(
    _Out_ PPH_MAPPED_IMAGE MappedImage,
    _In_ PVOID ViewBase,
    _In_ SIZE_T Size
    )
{
    PIMAGE_DOS_HEADER dosHeader;
    ULONG ntHeadersOffset;

    MappedImage->ViewBase = ViewBase;
    MappedImage->Size = Size;

    dosHeader = (PIMAGE_DOS_HEADER)ViewBase;

    __try
    {
        PhpMappedImageProbe(MappedImage, dosHeader, sizeof(IMAGE_DOS_HEADER));
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        return GetExceptionCode();
    }

    // Check the initial MZ.

    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        return STATUS_INVALID_IMAGE_NOT_MZ;

    // Get a pointer to the NT headers and probe it.

    ntHeadersOffset = (ULONG)dosHeader->e_lfanew;

    if (ntHeadersOffset == 0)
        return STATUS_INVALID_IMAGE_FORMAT;
    if (ntHeadersOffset >= 0x10000000 || ntHeadersOffset >= Size)
        return STATUS_INVALID_IMAGE_FORMAT;

    MappedImage->NtHeaders = (PIMAGE_NT_HEADERS)PTR_ADD_OFFSET(ViewBase, ntHeadersOffset);

    __try
    {
        PhpMappedImageProbe(
            MappedImage,
            MappedImage->NtHeaders,
            FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader)
            );
        PhpMappedImageProbe(
            MappedImage,
            MappedImage->NtHeaders,
            FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) +
            MappedImage->NtHeaders->FileHeader.SizeOfOptionalHeader +
            MappedImage->NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)
            );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        return GetExceptionCode();
    }

    // Check the signature and verify the magic.

    if (MappedImage->NtHeaders->Signature != IMAGE_NT_SIGNATURE)
        return STATUS_INVALID_IMAGE_FORMAT;

    MappedImage->Magic = MappedImage->NtHeaders->OptionalHeader.Magic;

    if (
        MappedImage->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
        MappedImage->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC
        )
        return STATUS_INVALID_IMAGE_FORMAT;

    // Get a pointer to the first section.

    MappedImage->NumberOfSections = MappedImage->NtHeaders->FileHeader.NumberOfSections;
    MappedImage->Sections = IMAGE_FIRST_SECTION(MappedImage->NtHeaders);

    return STATUS_SUCCESS;
}
Ejemplo n.º 5
0
NTSTATUS
FatFsdRead (
    _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    _Inout_ PIRP Irp
    )

/*++

Routine Description:

    This is the driver entry to the common read routine for NtReadFile calls.
    For synchronous requests, the CommonRead is called with Wait == TRUE,
    which means the request will always be completed in the current thread,
    and never passed to the Fsp.  If it is not a synchronous request,
    CommonRead is called with Wait == FALSE, which means the request
    will be passed to the Fsp only if there is a need to block.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Read exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    PFCB Fcb = NULL;
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel = FALSE;

    DebugTrace(+1, Dbg, "FatFsdRead\n", 0);

    //
    //  Call the common Read routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    //
    //  We are first going to do a quick check for paging file IO.  Since this
    //  is a fast path, we must replicate the check for the fsdo.
    //

    if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject))  {

        Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext);

        if ((NodeType(Fcb) == FAT_NTC_FCB) &&
            FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) {

            //
            //  Do the usual STATUS_PENDING things.
            //

            IoMarkIrpPending( Irp );

            //
            //  If there is not enough stack to do this read, then post this
            //  read to the overflow queue.
            //

            if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

                KEVENT Event;
                PAGING_FILE_OVERFLOW_PACKET Packet;

                Packet.Irp = Irp;
                Packet.Fcb = Fcb;

                KeInitializeEvent( &Event, NotificationEvent, FALSE );

                FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead );

                //
                //  And wait for the worker thread to complete the item
                //

                (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

            } else {

                //
                //  Perform the actual IO, it will be completed when the io finishes.
                //

                FatPagingFileIo( Irp, Fcb );
            }

            FsRtlExitFileSystem();

            return STATUS_PENDING;
        }
    }

    try {

        TopLevel = FatIsIrpTopLevel( Irp );

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        //
        //  If this is an Mdl complete request, don't go through
        //  common read.
        //

        if ( FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE) ) {

            DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 );
            try_return( Status = FatCompleteMdl( IrpContext, Irp ));
        }

        //
        //  Check if we have enough stack space to process this request.  If there
        //  isn't enough then we will pass the request off to the stack overflow thread.
        //

        if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

            DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 );
            try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) );
        }

        Status = FatCommonRead( IrpContext, Irp );

    try_exit: NOTHING;
    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFsdRead -> %08lx\n", Status);

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Ejemplo n.º 6
0
BOOLEAN
CmpFileWrite(
    PHHIVE              Hive,
    ULONG               FileType,
    PCMP_OFFSET_ARRAY   offsetArray,
    ULONG               offsetArrayCount,
    PULONG              FileOffset
    )
/*++

Routine Description:

    This routine writes an array of buffers out to a file.

    It is environment specific.

    NOTE:   We assume the handle is opened for asynchronous access,
            and that we, and not the IO system, are keeping the
            offset pointer.

    NOTE:   Only 32bit offsets are supported, even though the underlying
            IO system on NT supports 64 bit offsets.

Arguments:

    Hive - Hive we are doing I/O for

    FileType - which supporting file to use

    offsetArray - array of structures where each structure holds a 32bit offset
                  into the Hive file and pointer the a buffer written to that
                  file offset.

    offsetArrayCount - number of elements in the offsetArray.

    FileOffset - returns the file offset after the last write to the file.

Return Value:

    FALSE if failure
    TRUE if success

--*/
{
    NTSTATUS        status;
    LARGE_INTEGER   Offset;
    PCMHIVE         CmHive;
    HANDLE          FileHandle;
    ULONG           LengthToWrite;
    LONG            WaitBufferCount = 0;
    LONG            idx;
    ULONG           arrayCount = 0;
    PVOID           DataBuffer = NULL;      // W4 only
    ULONG           DataLength;
    BOOLEAN         ret_val = TRUE;
    PCM_WRITE_BLOCK WriteBlock = NULL;

    if (CmpNoWrite) {
        return TRUE;
    }

    ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    CmHive = (PCMHIVE)Hive;
    FileHandle = CmHive->FileHandles[FileType];
    if (FileHandle == NULL) {
        return TRUE;
    }

    CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpFileWrite:\n"));
    CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"\tHandle=%08lx  ", FileHandle));

    //
    // decide whether we wait for IOs to complete or just issue them and
    // rely on the CcFlushCache to do the job
    //
    
    // Bring pages being written into memory first to allow disk to write
    // buffer contiguously.
    try {
        for (idx = 0; (ULONG) idx < offsetArrayCount; idx++) {
            char * start = offsetArray[idx].DataBuffer;
            char * end = (char *) start + offsetArray[idx].DataLength;
            while (start < end) {
                // perftouchbuffer globally declared so that compiler won't try
                // to remove it and this loop (if its smart enough?).
                perftouchbuffer += (ULONG) *start;
                start += PAGE_SIZE;
            }
        }
    } except (EXCEPTION_EXECUTE_HANDLER) {
        //
        // we might get STATUS_IN_PAGE_ERROR 
        //
        CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpFileWrite has raised :%08lx\n",GetExceptionCode()));
        return FALSE;
    }

    WriteBlock = (PCM_WRITE_BLOCK)ExAllocatePool(NonPagedPool,sizeof(CM_WRITE_BLOCK));
    if( WriteBlock == NULL ) {
        return FALSE;
    }

    for (idx = 0; idx < MAXIMUM_WAIT_OBJECTS; idx++) {
        WriteBlock->EventHandles[idx] = NULL;
#if DBG
        WriteBlock->EventObjects[idx] = NULL;
#endif
    }
    //
    // We'd really like to just call the filesystems and have them do
    // the right thing.  But the filesystem will attempt to lock our
    // entire buffer into memory, and that may fail for large requests.
    // So we split our reads into 64k chunks and call the filesystem for
    // each one.
    //
    ASSERT_PASSIVE_LEVEL();
    arrayCount = 0;
    DataLength = 0;
    // This outer loop is hit more than once if the MAXIMUM_WAIT_OBJECTS limit
    // is hit before the offset array is drained.
    while (arrayCount < offsetArrayCount) {
        WaitBufferCount = 0;

        // This loop fills the wait buffer.
        while ((arrayCount < offsetArrayCount) &&
               (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) {

            // If data length isn't zero than the wait buffer filled before the
            // buffer in the last offsetArray element was sent to write file.
            if (DataLength == 0) {
                *FileOffset = offsetArray[arrayCount].FileOffset;
                DataBuffer =  offsetArray[arrayCount].DataBuffer;
                DataLength =  offsetArray[arrayCount].DataLength;
                //
                // Detect attempt to read off end of 2gig file
                // (this should be irrelevant)
                //
                if ((0xffffffff - *FileOffset) < DataLength) {
                    CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpFileWrite: runoff\n"));
                    status = STATUS_INVALID_PARAMETER_5;
                    goto Error_Exit;
                }
            }
            // else still more to write out of last buffer.

            while ((DataLength > 0) && (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) {

                //
                // Convert ULONG to Large
                //
                Offset.LowPart = *FileOffset;
                Offset.HighPart = 0L;

                //
                // trim request down if necessary.
                //
                if (DataLength > MAX_FILE_IO) {
                    LengthToWrite = MAX_FILE_IO;
                } else {
                    LengthToWrite = DataLength;
                }

                // Previously created events are reused.
                if (WriteBlock->EventHandles[WaitBufferCount] == NULL) {
                    status = CmpCreateEvent(SynchronizationEvent,
                                            &(WriteBlock->EventHandles[WaitBufferCount]),
                                            &(WriteBlock->EventObjects[WaitBufferCount]));
                    if (!NT_SUCCESS(status)) {
                        // Make sure we don't try to clean this up.
                        WriteBlock->EventHandles[WaitBufferCount] = NULL;
                        goto Error_Exit;
                    }
                    CmpSetHandleProtection(WriteBlock->EventHandles[WaitBufferCount],TRUE);
                }
                
                status = ZwWriteFile(FileHandle,
                                     WriteBlock->EventHandles[WaitBufferCount],
                                     NULL,               // apcroutine
                                     NULL,               // apccontext
                                     &(WriteBlock->IoStatus[WaitBufferCount]),
                                     DataBuffer,
                                     LengthToWrite,
                                     &Offset,
                                     NULL);
                        
                if (!NT_SUCCESS(status)) {
                    goto Error_Exit;
                } 

                WaitBufferCount++;
                
                //
                // adjust offsets
                //
                *FileOffset = Offset.LowPart + LengthToWrite;
                DataLength -= LengthToWrite;
                DataBuffer = (PVOID)((PCHAR)DataBuffer + LengthToWrite);
            } // while (DataLength > 0 && WaitBufferCount < MAXIMUM_WAIT_OBJECTS)
            
            arrayCount++;
            
        } // while (arrayCount < offsetArrayCount && 
          //        WaitBufferCount < MAXIMUM_WAIT_OBJECTS)

        status = KeWaitForMultipleObjects(WaitBufferCount, 
                                          WriteBlock->EventObjects,
                                          WaitAll,
                                          Executive,
                                          KernelMode, 
                                          FALSE, 
                                          NULL,
                                          WriteBlock->WaitBlockArray);
    
        if (!NT_SUCCESS(status))
            goto Error_Exit;
    
        for (idx = 0; idx < WaitBufferCount; idx++) {
            if (!NT_SUCCESS(WriteBlock->IoStatus[idx].Status)) {
                status = WriteBlock->IoStatus[idx].Status;
                ret_val = FALSE;
                goto Done;
            }
        }
        
        // There may still be more to do if the last element held a big buffer
        // and the wait buffer filled before it was all sent to the file.
        if (DataLength > 0) {
            arrayCount--;
        }

    } // while (arrayCount < offsetArrayCount)

    ret_val = TRUE;

    goto Done;
Error_Exit:
    //
    // set debugging info
    //
    CmRegistryIODebug.Action = CmpIoFileWrite;
    CmRegistryIODebug.Handle = FileHandle;
    CmRegistryIODebug.Status = status;
#if DBG
    DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpFileWrite: error exiting %d\n", status);
#endif
    //
    // if WaitBufferCount > 0 then we have successfully issued
    // some I/Os, but not all of them. This is an error, but we
    // cannot return from this routine until all the successfully
    // issued I/Os have completed.
    //
    if (WaitBufferCount > 0) {
        //
        // only if we decided that we want to wait for the write to complete 
        // (log files and hives not using the mapped views technique)
        //
        status = KeWaitForMultipleObjects(WaitBufferCount, 
                                          WriteBlock->EventObjects,
                                          WaitAll,
                                          Executive,
                                          KernelMode, 
                                          FALSE, 
                                          NULL,
                                          WriteBlock->WaitBlockArray);
    }


    ret_val = FALSE;
Done:
    idx = 0;
    // Clean up open event handles and objects.
    while ((idx < MAXIMUM_WAIT_OBJECTS) && (WriteBlock->EventHandles[idx] != NULL)) {
        ASSERT( WriteBlock->EventObjects[idx] );
        ObDereferenceObject(WriteBlock->EventObjects[idx]);
        CmCloseHandle(WriteBlock->EventHandles[idx]);
        idx++;
    }

    if( WriteBlock != NULL ) {
        ExFreePool(WriteBlock);
    }

    return ret_val;
}
Ejemplo n.º 7
0
static STDCALL NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,ULONG PhysMemSizeInBytes,PVOID *PhysMemLin){
  alloc_priv* alloclisttmp;
  PMDL Mdl=NULL;
  PVOID SystemVirtualAddress=NULL;
  PVOID UserVirtualAddress=NULL;
  PHYSICAL_ADDRESS   pStartPhysAddress;
  OutputDebugString ("dhahelper: entering MapPhysicalMemoryToLinearSpace");

#ifdef _WIN64
  pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress;
#else
  pStartPhysAddress.QuadPart = (ULONGLONG)(ULONG)pPhysAddress;
#endif
#ifndef NO_SEH
  __try {
#endif
    SystemVirtualAddress=MmMapIoSpace(pStartPhysAddress,PhysMemSizeInBytes, /*MmWriteCombined*/MmNonCached);
    if(!SystemVirtualAddress){
      OutputDebugString("dhahelper: MmMapIoSpace failed");
      return STATUS_INVALID_PARAMETER;
    }
    OutputDebugString("dhahelper: SystemVirtualAddress 0x%x",SystemVirtualAddress);
    Mdl=IoAllocateMdl(SystemVirtualAddress, PhysMemSizeInBytes, FALSE, FALSE,NULL);
    if(!Mdl){
      OutputDebugString("dhahelper: IoAllocateMdl failed");
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    OutputDebugString("dhahelper: Mdl 0x%x",Mdl);
    MmBuildMdlForNonPagedPool(Mdl);
#ifdef _WIN64
	UserVirtualAddress = (PVOID)(((ULONGLONG)PAGE_ALIGN(MmMapLockedPages(Mdl,UserMode))) + MmGetMdlByteOffset(Mdl));
#else
    UserVirtualAddress = (PVOID)(((ULONG)PAGE_ALIGN(MmMapLockedPages(Mdl,UserMode))) + MmGetMdlByteOffset(Mdl));
#endif
    if(!UserVirtualAddress){
      OutputDebugString("dhahelper: MmMapLockedPages failed");
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    OutputDebugString("dhahelper: UserVirtualAddress 0x%x",UserVirtualAddress);
#ifndef NO_SEH
  }__except(EXCEPTION_EXECUTE_HANDLER){
       NTSTATUS           ntStatus;
       ntStatus = GetExceptionCode();
       OutputDebugString("dhahelper: MapPhysicalMemoryToLinearSpace failed due to exception 0x%0x\n", ntStatus);
       return ntStatus;
  }
#endif


  OutputDebugString("dhahelper: adding data to internal allocation list");
  alloclisttmp=MmAllocateNonCachedMemory((alloccount+1)*sizeof(alloc_priv));


  if(!alloclisttmp){
    OutputDebugString("dhahelper: not enough memory to create temporary allocation list");
    MmUnmapLockedPages(UserVirtualAddress, Mdl);
    IoFreeMdl(Mdl);
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  if(alloccount){
    memcpy(alloclisttmp,alloclist,alloccount * sizeof(alloc_priv));
    MmFreeNonCachedMemory(alloclist,alloccount*sizeof(alloc_priv));
  }
  alloclist=alloclisttmp;
  alloclist[alloccount].Mdl=Mdl;
  alloclist[alloccount].SystemVirtualAddress=SystemVirtualAddress;
  alloclist[alloccount].UserVirtualAddress=UserVirtualAddress;
  alloclist[alloccount].PhysMemSizeInBytes=PhysMemSizeInBytes;
  ++alloccount;

   *PhysMemLin=UserVirtualAddress;

  OutputDebugString("dhahelper: leaving MapPhysicalMemoryToLinearSpace");
  return STATUS_SUCCESS;
}
/// <summary>
/// Trigger the Null Pointer Dereference Vulnerability
/// </summary>
/// <param name="UserBuffer">The pointer to user mode buffer</param>
/// <returns>NTSTATUS</returns>
NTSTATUS TriggerNullPointerDereference(IN PVOID UserBuffer) {
    ULONG UserValue = 0;
    ULONG MagicValue = 0xBAD0B0B0;
    NTSTATUS Status = STATUS_SUCCESS;
    PNULL_POINTER_DEREFERENCE NullPointerDereference = NULL;

    PAGED_CODE();

    __try {
        // Verify if the buffer resides in user mode
        ProbeForRead(UserBuffer,
                     sizeof(NULL_POINTER_DEREFERENCE),
                     (ULONG)__alignof(NULL_POINTER_DEREFERENCE));

        // Allocate Pool chunk
        NullPointerDereference = (PNULL_POINTER_DEREFERENCE)
                                  ExAllocatePoolWithTag(NonPagedPool,
                                                        sizeof(NULL_POINTER_DEREFERENCE),
                                                        (ULONG)POOL_TAG);

        if (!NullPointerDereference) {
            // Unable to allocate Pool chunk
            DbgPrint("[-] Unable to allocate Pool chunk\n");

            Status = STATUS_NO_MEMORY;
            return Status;
        }
        else {
            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));
            DbgPrint("[+] Pool Type: %s\n", STRINGIFY(NonPagedPool));
            DbgPrint("[+] Pool Size: 0x%X\n", sizeof(NULL_POINTER_DEREFERENCE));
            DbgPrint("[+] Pool Chunk: 0x%p\n", NullPointerDereference);
        }

        // Get the value from user mode
        UserValue = *(PULONG)UserBuffer;

        DbgPrint("[+] UserValue: 0x%p\n", UserValue);
        DbgPrint("[+] NullPointerDereference: 0x%p\n", NullPointerDereference);

        // Validate the magic value
        if (UserValue == MagicValue) {
            NullPointerDereference->Value = UserValue;
            NullPointerDereference->Callback = &NullPointerDereferenceObjectCallback;

            DbgPrint("[+] NullPointerDereference->Value: 0x%p\n", NullPointerDereference->Value);
            DbgPrint("[+] NullPointerDereference->Callback: 0x%p\n", NullPointerDereference->Callback);
        }
        else {
            DbgPrint("[+] Freeing NullPointerDereference Object\n");
            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));
            DbgPrint("[+] Pool Chunk: 0x%p\n", NullPointerDereference);

            // Free the allocated Pool chunk
            ExFreePoolWithTag((PVOID)NullPointerDereference, (ULONG)POOL_TAG);

            // Set to NULL to avoid dangling pointer
            NullPointerDereference = NULL;
        }

#ifdef SECURE
        // Secure Note: This is secure because the developer is checking if
        // 'NullPointerDereference' is not NULL before calling the callback function
        if (NullPointerDereference) {
            NullPointerDereference->Callback();
        }
#else
        DbgPrint("[+] Triggering Null Pointer Dereference\n");

        // Vulnerability Note: This is a vanilla Null Pointer Dereference vulnerability
        // because the developer is not validating if 'NullPointerDereference' is NULL
        // before calling the callback function
        NullPointerDereference->Callback();
#endif
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        Status = GetExceptionCode();
        DbgPrint("[-] Exception Code: 0x%X\n", Status);
    }

    return Status;
}
Ejemplo n.º 9
0
HMODULE                 hD3D9Dll = NULL;

int                     patchType = 0;

extern bool             bDXGIHooked;



bool CompareMemory(const LPVOID lpVal1, const LPVOID lpVal2, UINT nBytes)
{
    __try
    {
        return memcmp(lpVal1, lpVal2, nBytes) == 0;
    }
    __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
    {
        return false;
    }

    return false;
}

struct PatchInfo {
    size_t patchSize;
    const BYTE *patchData;
};

#define NewPatch(x) {sizeof(x), (x)}

#ifdef _WIN64
Ejemplo n.º 10
0
NTSTATUS
AFSQueryFileInfo( IN PDEVICE_OBJECT DeviceObject,
                  IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
    AFSFcb* pFcb = NULL;
    __try
    {

        if( DeviceObject == AFSDeviceObject)
        {

            ntStatus = STATUS_INVALID_DEVICE_REQUEST;

            AFSCompleteRequest( Irp,
                                ntStatus);

            try_return( ntStatus);
        }

        pFcb = (AFSFcb*) pIrpSp->FileObject->FsContext;

        if( pFcb == NULL ||
            pFcb->Header.NodeTypeCode == AFS_REDIRECTOR_FCB)
        {

            //
            // Root open
            //

            ntStatus = STATUS_INVALID_DEVICE_REQUEST;

            AFSCompleteRequest( Irp,
                                ntStatus);

            try_return( ntStatus);
        }

        //
        // Check the state of the library
        //

        ntStatus = AFSCheckLibraryState( Irp);

        if( !NT_SUCCESS( ntStatus) ||
            ntStatus == STATUS_PENDING)
        {

            if( ntStatus != STATUS_PENDING)
            {
                AFSCompleteRequest( Irp, ntStatus);
            }

            try_return( ntStatus);
        }

        IoSkipCurrentIrpStackLocation( Irp);

        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
                                 Irp);

        //
        // Indicate the library is done with the request
        //

        AFSClearLibraryRequest();

try_exit:

        NOTHING;
    }
    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
    {

        AFSDbgLogMsg( 0,
                      0,
                      "EXCEPTION - AFSQueryFileInfo\n");

        ntStatus = STATUS_UNSUCCESSFUL;

        AFSDumpTraceFilesFnc();
    }

    return ntStatus;
}
Ejemplo n.º 11
0
int
main(int argc, char** argv)
{
#ifdef WINDOWS
    HMODULE hmod;

    /* 
     * Cause an exception event
     */
    __try {
        HANDLE heap = GetProcessHeap();
        char *buf = (char *)HeapAlloc(((char *)heap)+1, HEAP_GENERATE_EXCEPTIONS, 10);
    }
    __except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? 
              EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
    }

    /* 
     * Load and unload a module to cause a module unload event
     */
    hmod = LoadLibrary(argv[1]);
    if (hmod == NULL) {
        print("LoadLibrary failed: %x\n", GetLastError());
    }
    FreeLibrary(hmod);
#endif

#ifdef UNIX
    void *hmod;
    char buf[1000];
    size_t len = 0;
    char *end_path = NULL;
    /*
     * Load and unload a module to cause a module unload event
     */

    /* FIXME: We used to test a module with a large .bss here.  Try to do that
     * again.
     */
    hmod = dlopen(argv[1], RTLD_LAZY|RTLD_LOCAL);
    if (hmod != NULL)
        dlclose(hmod);
    else
        print("module load failed: %s\n", dlerror());

    /* test load of non-existent file */
    hmod = dlopen("foo_bar_no_exist.so", RTLD_LAZY|RTLD_LOCAL);
    if (hmod != NULL) {
        print("ERROR - module load of %s succeeded\n", buf);
        dlclose(hmod);
    }

    intercept_signal(SIGUSR1, signal_handler, false);
    intercept_signal(SIGUSR2, signal_handler, false);
    intercept_signal(SIGURG, signal_handler, false);
    print("Sending SIGUSR1\n");
    kill(getpid(), SIGUSR1);
    print("Sending SIGUSR2\n");
    kill(getpid(), SIGUSR2);
    print("Sending SIGURG\n");
    kill(getpid(), SIGURG);
    print("Done\n");
    /*
     * Cause a fork event
     */
    if (fork() == 0) {
        abort();
    }
    else {
        wait(NULL);
    }
#endif /* UNIX */

#ifdef WINDOWS
    /* 
     * Cause an exception event, we test redirecting the application to redirect()
     */
    __try {
        HANDLE heap = GetProcessHeap();
        char *buf = (char *)HeapAlloc(((char *)heap)+1, HEAP_GENERATE_EXCEPTIONS, 10);
    }
    __except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? 
              EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
    }
#else
    *(int *)4 = 0;
#endif
    /* Never Reached */
    print("Shouldn't be reached\n");
}
Ejemplo n.º 12
0
BOOLEAN
KiFloatingException (
    IN OUT PEXCEPTION_RECORD ExceptionRecord,
    IN OUT PKEXCEPTION_FRAME ExceptionFrame,
    IN OUT PKTRAP_FRAME TrapFrame,
    IN BOOLEAN ImpreciseTrap,
    IN OUT PULONG SoftFpcrCopy
    )

/*++

Routine Description:

    This function is called to emulate a floating operation and convert the
    exception status to the proper value. If the exception is a fault, the
    faulting floating point instruction is emulated. If the exception is an
    imprecise trap, an attempt is made to locate and to emulate the original
    trapping floating point instruction.

Arguments:

    ExceptionRecord - Supplies a pointer to an exception record.

    ExceptionFrame - Supplies a pointer to an exception frame.

    TrapFrame - Supplies a pointer to a trap frame.

    ImpreciseTrap - Supplies a boolean value that specifies whether the
        exception is an imprecise trap.

    SoftFpcrCopy - Supplies a pointer to a longword variable that receives
        a copy of the software FPCR.

Return Value:

    A value of TRUE is returned if the floating exception is successfully
    emulated. Otherwise, a value of FALSE is returned.

--*/

{

    BOOLEAN Status;
    PSW_FPCR SoftwareFpcr;
    PTEB Teb;

    try {

        //
        // Obtain a copy of the software FPCR longword from the TEB.
        //

        Teb = NtCurrentTeb();
        *SoftFpcrCopy = Teb->FpSoftwareStatusRegister;
        SoftwareFpcr = (PSW_FPCR)SoftFpcrCopy;
        DBGPRINT("KiFloatingException: SoftFpcr = %.8lx\n", *SoftFpcrCopy);

#if DBG
        //
        // If the floating emulation inhibit flag is set, then bypass all
        // software emulation by the kernel and return FALSE to raise the
        // original PALcode exception.
        //
        // N.B. This is for user-mode development and testing and is not
        //      part of the API.
        //

        if (SoftwareFpcr->NoSoftwareEmulation != 0) {
            DBGPRINT("KiFloatingException: NoSoftwareEmulation\n");
            return FALSE;
        }
#endif

        //
        // If the arithmetic exception is an imprecise trap, the address of
        // the trapping instruction is somewhere before the exception address.
        //
        // Otherwise the exception is a fault and the address of the faulting
        // instruction is the exception address.
        //

        if (ImpreciseTrap != FALSE) {

            //
            // If the arithmetic trap ignore mode is enabled, then do not
            // spend time to locate or to emulate the trapping instruction,
            // leave unpredictable results in the destination register, do
            // not set correct IEEE sticky bits in the software FPCR, leave
            // the hardware FPCR sticky status bits as they are, and return
            // TRUE to continue execution. It is assumed that user code will
            // check the hardware FPCR exception status bits to determine if
            // the instruction succeeded or not (Insignia SoftPc feature).
            //

            if (SoftwareFpcr->ArithmeticTrapIgnore != 0) {
                return TRUE;
            }

            //
            // Attempt to locate the trapping instruction. If the instruction
            // stream is such that this is not possible or was not intended,
            // then set an exception code that best reflects the exception
            // summary register bits and return FALSE to raise the exception.
            //
            // Otherwise emulate the trigger instruction in order to compute
            // the correct destination result value, the correct IEEE status
            // bits, and raise any enabled IEEE exceptions.
            //

            if (KiLocateTriggerPc(ExceptionRecord, TrapFrame) == FALSE) {
                KiSetFloatingStatus(ExceptionRecord);
                return FALSE;
            }
            Status = KiEmulateFloating(ExceptionRecord,
                                       ExceptionFrame,
                                       TrapFrame,
                                       SoftwareFpcr);

        } else {

            //
            // Attempt to emulate the faulting instruction in order to perform
            // floating operations not supported by EV4, to compute the correct
            // destination result value, the correct IEEE status bits, and
            // raise any enabled IEEE exceptions.
            //

            Status = KiEmulateFloating(ExceptionRecord,
                                       ExceptionFrame,
                                       TrapFrame,
                                       SoftwareFpcr);

            //
            // If the emulation resulted in a floating point exception and
            // the arithmetic trap ignore mode is enabled, then set the return
            // value to TRUE to suppress the exception and continue execution.
            //

            if ((Status == FALSE) &&
                (SoftwareFpcr->ArithmeticTrapIgnore != 0) &&
                (ExceptionRecord->ExceptionCode != STATUS_ILLEGAL_INSTRUCTION)) {
                Status = TRUE;
            }
        }

        //
        // Store the updated software FPCR longword in the TEB.
        //

        Teb->FpSoftwareStatusRegister = *SoftFpcrCopy;
        DBGPRINT("KiFloatingException: SoftFpcr = %.8lx\n", *SoftFpcrCopy);

    } except (EXCEPTION_EXECUTE_HANDLER) {

        //
        // An exception occurred accessing the TEB.
        //

        ExceptionRecord->ExceptionCode = GetExceptionCode();
        return FALSE;
    }

    return Status;
}
Ejemplo n.º 13
0
static int
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	proto_item  *volatile ti = NULL, *comment_item;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile tree;
	proto_tree  *comments_tree;
	proto_tree  *volatile fh_tree = NULL;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;
	frame_data_t *fr_data = (frame_data_t*)data;
	const color_filter_t *color_filter;

	tree=parent_tree;

	switch (pinfo->phdr->rec_type) {

	case REC_TYPE_PACKET:
		pinfo->current_proto = "Frame";
		if (pinfo->pseudo_header != NULL) {
			switch (pinfo->pkt_encap) {

			case WTAP_ENCAP_WFLEET_HDLC:
			case WTAP_ENCAP_CHDLC_WITH_PHDR:
			case WTAP_ENCAP_PPP_WITH_PHDR:
			case WTAP_ENCAP_SDLC:
			case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_BLUETOOTH_HCI:
				pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent;
				break;

			case WTAP_ENCAP_LAPB:
			case WTAP_ENCAP_FRELAY_WITH_PHDR:
				pinfo->p2p_dir =
				    (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
				    P2P_DIR_RECV : P2P_DIR_SENT;
				break;

			case WTAP_ENCAP_ISDN:
			case WTAP_ENCAP_V5_EF:
			case WTAP_ENCAP_DPNSS:
			case WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_LINUX_LAPD:
				pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 ||
					pinfo->pseudo_header->lapd.pkttype == 4) ?
					P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_MTP2_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				pinfo->link_number  = pinfo->pseudo_header->mtp2.link_number;
				break;

			case WTAP_ENCAP_GSM_UM:
				pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;
			}
		}
		break;

	case REC_TYPE_FT_SPECIFIC_EVENT:
		pinfo->current_proto = "Event";
		break;

	case REC_TYPE_FT_SPECIFIC_REPORT:
		pinfo->current_proto = "Report";
		break;

	default:
		g_assert_not_reached();
		break;
	}

	if (fr_data && fr_data->pkt_comment) {
		item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, 0, ENC_NA);
		comments_tree = proto_item_add_subtree(item, ett_comments);
		comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, 0,
							                   fr_data->pkt_comment, "%s",
							                   fr_data->pkt_comment);
		expert_add_info_format(pinfo, comment_item, &ei_comments_text,
					                       "%s",  fr_data->pkt_comment);


	}

	/* if FRAME is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if (!proto_field_is_referenced(tree, proto_frame)) {
		tree=NULL;
		if (pinfo->presence_flags & PINFO_HAS_TS) {
			if (pinfo->abs_ts.nsecs < 0 || pinfo->abs_ts.nsecs >= 1000000000)
				expert_add_info(pinfo, NULL, &ei_arrive_time_out_of_range);
		}
	} else {
		gboolean old_visible;

		/* Put in frame header information. */
		cap_len = tvb_captured_length(tvb);
		frame_len = tvb_reported_length(tvb);

		cap_plurality = plurality(cap_len, "", "s");
		frame_plurality = plurality(frame_len, "", "s");

		ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
		    "Frame %u: %u byte%s on wire",
		    pinfo->num, frame_len, frame_plurality);
		if (generate_bits_field)
			proto_item_append_text(ti, " (%u bits)", frame_len * 8);
		proto_item_append_text(ti, ", %u byte%s captured",
		    cap_len, cap_plurality);
		if (generate_bits_field) {
			proto_item_append_text(ti, " (%u bits)",
			    cap_len * 8);
		}
		if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) {
			proto_item_append_text(ti, " on interface %u",
			    pinfo->phdr->interface_id);
		}
		if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
			if (pinfo->phdr->pack_flags & 0x00000001) {
				proto_item_append_text(ti, " (inbound)");
				pinfo->p2p_dir = P2P_DIR_RECV;
			}
			if (pinfo->phdr->pack_flags & 0x00000002) {
				proto_item_append_text(ti, " (outbound)");
				pinfo->p2p_dir = P2P_DIR_SENT;
			}
		}

		fh_tree = proto_item_add_subtree(ti, ett_frame);

		if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID && proto_field_is_referenced(tree, hf_frame_interface_id)) {
			const char *interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id);

			if (interface_name)
				proto_tree_add_uint_format_value(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id, "%u (%s)", pinfo->phdr->interface_id, interface_name);
			else
				proto_tree_add_uint(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id);
		}

		if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
			proto_tree *flags_tree;
			proto_item *flags_item;

			flags_item = proto_tree_add_uint(fh_tree, hf_frame_pack_flags, tvb, 0, 0, pinfo->phdr->pack_flags);
			flags_tree = proto_item_add_subtree(flags_item, ett_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_direction, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_reception_type, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_fcs_length, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_reserved, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_crc_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_long_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_short_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_inter_frame_gap_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_unaligned_frame_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_start_frame_delimiter_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_preamble_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_symbol_error, tvb, 0, 0, pinfo->phdr->pack_flags);
		}

		if (pinfo->phdr->rec_type == REC_TYPE_PACKET)
			proto_tree_add_int(fh_tree, hf_frame_wtap_encap, tvb, 0, 0, pinfo->pkt_encap);

		if (pinfo->presence_flags & PINFO_HAS_TS) {
			proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
					    0, 0, &(pinfo->abs_ts));
			if (pinfo->abs_ts.nsecs < 0 || pinfo->abs_ts.nsecs >= 1000000000) {
				expert_add_info_format(pinfo, ti, &ei_arrive_time_out_of_range,
								  "Arrival Time: Fractional second %09ld is invalid,"
								  " the valid range is 0-1000000000",
								  (long) pinfo->abs_ts.nsecs);
			}
			item = proto_tree_add_time(fh_tree, hf_frame_shift_offset, tvb,
					    0, 0, &(pinfo->fd->shift_offset));
			PROTO_ITEM_SET_GENERATED(item);

			if (generate_epoch_time) {
				proto_tree_add_time(fh_tree, hf_frame_arrival_time_epoch, tvb,
						    0, 0, &(pinfo->abs_ts));
			}

			if (proto_field_is_referenced(tree, hf_frame_time_delta)) {
				nstime_t     del_cap_ts;

				frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->num - 1, &del_cap_ts);

				item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
							   0, 0, &(del_cap_ts));
				PROTO_ITEM_SET_GENERATED(item);
			}

			if (proto_field_is_referenced(tree, hf_frame_time_delta_displayed)) {
				nstime_t del_dis_ts;

				frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->prev_dis_num, &del_dis_ts);

				item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb,
							   0, 0, &(del_dis_ts));
				PROTO_ITEM_SET_GENERATED(item);
			}

			item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
						   0, 0, &(pinfo->rel_ts));
			PROTO_ITEM_SET_GENERATED(item);

			if (pinfo->fd->flags.ref_time) {
				ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, ENC_NA);
				PROTO_ITEM_SET_GENERATED(ti);
			}
		}

		proto_tree_add_uint(fh_tree, hf_frame_number, tvb,
				    0, 0, pinfo->num);

		proto_tree_add_uint_format(fh_tree, hf_frame_len, tvb,
					   0, 0, frame_len, "Frame Length: %u byte%s (%u bits)",
					   frame_len, frame_plurality, frame_len * 8);

		proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
					   0, 0, cap_len, "Capture Length: %u byte%s (%u bits)",
					   cap_len, cap_plurality, cap_len * 8);

		if (generate_md5_hash) {
			const guint8 *cp;
			md5_state_t   md_ctx;
			md5_byte_t    digest[16];
			const gchar  *digest_string;

			cp = tvb_get_ptr(tvb, 0, cap_len);

			md5_init(&md_ctx);
			md5_append(&md_ctx, cp, cap_len);
			md5_finish(&md_ctx, digest);

			digest_string = bytestring_to_str(wmem_packet_scope(), digest, 16, '\0');
			ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string);
			PROTO_ITEM_SET_GENERATED(ti);
		}

		ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
		PROTO_ITEM_SET_GENERATED(ti);

		ti = proto_tree_add_boolean(fh_tree, hf_frame_ignored, tvb, 0, 0,pinfo->fd->flags.ignored);
		PROTO_ITEM_SET_GENERATED(ti);

		if (proto_field_is_referenced(tree, hf_frame_protocols)) {
			/* we are going to be using proto_item_append_string() on
			 * hf_frame_protocols, and we must therefore disable the
			 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
			 * setting it as visible.
			 *
			 * See proto.h for details.
			 */
			old_visible = proto_tree_set_visible(fh_tree, TRUE);
			ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb, 0, 0, "");
			PROTO_ITEM_SET_GENERATED(ti);
			proto_tree_set_visible(fh_tree, old_visible);
		}

		/* Check for existences of P2P pseudo header */
		if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
			proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb,
					   0, 0, pinfo->p2p_dir);
		}

		/* Check for existences of MTP2 link number */
		if ((pinfo->pseudo_header != NULL ) && (pinfo->pkt_encap == WTAP_ENCAP_MTP2_WITH_PHDR)) {
			proto_tree_add_uint(fh_tree, hf_link_number, tvb,
					    0, 0, pinfo->link_number);
		}

		if (show_file_off) {
			proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb,
						    0, 0, pinfo->fd->file_off,
						    "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)",
						    pinfo->fd->file_off, pinfo->fd->file_off);
		}
	}

	if (pinfo->fd->flags.ignored) {
		/* Ignored package, stop handling here */
		col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>");
		proto_tree_add_boolean_format(tree, hf_frame_ignored, tvb, 0, 0, TRUE, "This frame is marked as ignored");
		return tvb_captured_length(tvb);
	}

	/* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
	TRY {
#ifdef _MSC_VER
		/* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions
		   like memory access violations.
		   (a running debugger will be called before the except part below) */
		/* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
		   stack in an inconsistent state thus causing a crash at some point in the
		   handling of the exception.
		   See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
		*/
		__try {
#endif
			switch (pinfo->phdr->rec_type) {

			case REC_TYPE_PACKET:
				if ((force_docsis_encap) && (docsis_handle)) {
					call_dissector_with_data(docsis_handle,
					    tvb, pinfo, parent_tree,
					    (void *)pinfo->pseudo_header);
				} else {
					if (!dissector_try_uint_new(wtap_encap_dissector_table,
					    pinfo->pkt_encap, tvb, pinfo,
					    parent_tree, TRUE,
					    (void *)pinfo->pseudo_header)) {
						col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
						col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d",
							     pinfo->pkt_encap);
						call_dissector_with_data(data_handle,
						    tvb, pinfo, parent_tree,
						    (void *)pinfo->pseudo_header);
					}
				}
				break;

			case REC_TYPE_FT_SPECIFIC_EVENT:
			case REC_TYPE_FT_SPECIFIC_REPORT:
				{
					int file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;

					if (fr_data) {
						file_type_subtype = fr_data->file_type_subtype;
					}

					if (!dissector_try_uint(wtap_fts_rec_dissector_table, file_type_subtype,
					    tvb, pinfo, parent_tree)) {
						col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
						col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d",
							     file_type_subtype);
						call_dissector(data_handle,tvb, pinfo, parent_tree);
					}
				}
				break;
			}
#ifdef _MSC_VER
		} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
			switch (GetExceptionCode()) {
			case(STATUS_ACCESS_VIOLATION):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
				break;
			case(STATUS_INTEGER_DIVIDE_BY_ZERO):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
				break;
			case(STATUS_STACK_OVERFLOW):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
				/* XXX - this will have probably corrupted the stack,
				   which makes problems later in the exception code */
				break;
				/* XXX - add other hardware exception codes as required */
			default:
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
			}
		}
#endif
	}
	CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
		show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
	}
	ENDTRY;

	if (proto_field_is_referenced(tree, hf_frame_protocols)) {
		wmem_strbuf_t *val = wmem_strbuf_sized_new(wmem_packet_scope(), 128, 0);
		wmem_list_frame_t *frame;
		/* skip the first entry, it's always the "frame" protocol */
		frame = wmem_list_frame_next(wmem_list_head(pinfo->layers));
		if (frame) {
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		while (frame) {
			wmem_strbuf_append_c(val, ':');
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		proto_item_append_string(ti, wmem_strbuf_get_str(val));
	}

	/*  Call postdissectors if we have any (while trying to avoid another
	 *  TRY/CATCH)
	 */
	if (have_postdissector()) {
		TRY {
#ifdef _MSC_VER
			/* Win32: Visual-C Structured Exception Handling (SEH)
			   to trap hardware exceptions like memory access violations */
			/* (a running debugger will be called before the except part below) */
			/* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
			   stack in an inconsistent state thus causing a crash at some point in the
			   handling of the exception.
			   See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
			*/
			__try {
#endif
				call_all_postdissectors(tvb, pinfo, parent_tree);
#ifdef _MSC_VER
			} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
				switch (GetExceptionCode()) {
				case(STATUS_ACCESS_VIOLATION):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
					break;
				case(STATUS_INTEGER_DIVIDE_BY_ZERO):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
					break;
				case(STATUS_STACK_OVERFLOW):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
					/* XXX - this will have probably corrupted the stack,
					   which makes problems later in the exception code */
					break;
					/* XXX - add other hardware exception codes as required */
				default:
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
				}
			}
#endif
		}
		CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
			show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
		}
		ENDTRY;
	}

	/* Attempt to (re-)calculate color filters (if any). */
	if (pinfo->fd->flags.need_colorize) {
		color_filter = color_filters_colorize_packet(fr_data->color_edt);
		pinfo->fd->color_filter = color_filter;
		pinfo->fd->flags.need_colorize = 0;
	} else {
		color_filter = pinfo->fd->color_filter;
	}
	if (color_filter) {
		item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb,
					     0, 0, color_filter->filter_name);
		PROTO_ITEM_SET_GENERATED(item);
		item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb,
					     0, 0, color_filter->filter_text);
		PROTO_ITEM_SET_GENERATED(item);
	}

	tap_queue_packet(frame_tap, pinfo, NULL);


	if (pinfo->frame_end_routines) {
		g_slist_foreach(pinfo->frame_end_routines, &call_frame_end_routine, NULL);
		g_slist_free(pinfo->frame_end_routines);
		pinfo->frame_end_routines = NULL;
	}

	if (prefs.enable_incomplete_dissectors_check && tree && tree->tree_data->visible) {
		gchar* decoded;
		guint length;
		guint i;
		guint byte;
		guint bit;

		length = tvb_captured_length(tvb);
		decoded = proto_find_undecoded_data(tree, length);

		for (i = 0; i < length; i++) {
			byte = i / 8;
			bit = i % 8;
			if (!(decoded[byte] & (1 << bit))) {
				field_info* fi = proto_find_field_from_offset(tree, i, tvb);
				if (fi && fi->hfinfo->id != proto_frame) {
					g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING,
						"Dissector %s incomplete in frame %u: undecoded byte number %u "
						"(0x%.4X+%u)",
						(fi ? fi->hfinfo->abbrev : "[unknown]"),
						pinfo->num, i, i - i % 16, i % 16);
					proto_tree_add_expert_format(tree, pinfo, &ei_incomplete, tvb, i, 1, "Undecoded byte number: %u (0x%.4X+%u)", i, i - i % 16, i % 16);
				}
			}
		}
        }

	return tvb_captured_length(tvb);
}
Ejemplo n.º 14
0
static int real_main2 (int argc, TCHAR **argv)
{
#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER)
	extern int EvalException (LPEXCEPTION_POINTERS blah, int n_except);
	__try
#endif
	{

#ifdef USE_SDL
	int result = (SDL_Init (SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == 0);
	if (result)
		atexit (SDL_Quit);
#endif
	config_changed = 1;
	if (restart_config[0]) {
		default_prefs (&currprefs, 0);
		fixup_prefs (&currprefs);
	}

	if (! graphics_setup ()) {
		write_log ("Graphics Setup Failed\n");
		exit (1);
	}

#ifdef NATMEM_OFFSET
	preinit_shm ();
#endif

	if (restart_config[0])
		parse_cmdline_and_init_file (argc, argv);
	else
		currprefs = changed_prefs;

	uae_inithrtimer ();

	if (!machdep_init ()) {
		write_log ("Machine Init Failed.\n");
		restart_program = 0;
		return -1;
	}

	if (console_emulation) {
		consolehook_config (&currprefs);
		fixup_prefs (&currprefs);
	}

	if (! setup_sound ()) {
		write_log ("Sound driver unavailable: Sound output disabled\n");
		currprefs.produce_sound = 0;
	}
	inputdevice_init ();

	changed_prefs = currprefs;
	no_gui = ! currprefs.start_gui;
	if (restart_program == 2)
		no_gui = 1;
	else if (restart_program == 3)
		no_gui = 0;
	restart_program = 0;
	if (! no_gui) {
		int err = gui_init ();
		currprefs = changed_prefs;
		config_changed = 1;
		if (err == -1) {
			write_log ("Failed to initialize the GUI\n");
			return -1;
		} else if (err == -2) {
			return 1;
		}
	}

#ifdef NATMEM_OFFSET
	init_shm ();
#endif

#ifdef JIT
	if (!(currprefs.cpu_model >= 68020 && currprefs.address_space_24 == 0 && currprefs.cachesize))
		canbang = 0;
#endif

	fixup_prefs (&currprefs);
	changed_prefs = currprefs;
	target_run ();
	/* force sound settings change */
	currprefs.produce_sound = 0;

#ifdef AUTOCONFIG
	/* Install resident module to get 8MB chipmem, if requested */
	rtarea_setup ();
#endif
#ifdef FILESYS
	rtarea_init ();
	uaeres_install ();
	hardfile_install ();
#endif
	savestate_init ();
#ifdef SCSIEMU
	scsi_reset ();
	scsidev_install ();
#endif
#ifdef SANA2
	netdev_install ();
#endif
#ifdef UAESERIAL
	uaeserialdev_install ();
#endif
	keybuf_init (); /* Must come after init_joystick */

#ifdef AUTOCONFIG
	expansion_init ();
#endif
#ifdef FILESYS
	filesys_install ();
#endif
	target_startup_sequence (&currprefs);
	memory_init ();
	memory_reset ();

#ifdef AUTOCONFIG
#if defined (BSDSOCKET)
	bsdlib_install ();
#endif
	emulib_install ();
	uaeexe_install ();
	native2amiga_install ();
#endif

	custom_init (); /* Must come after memory_init */
#ifdef SERIAL_PORT
	serial_init ();
#endif
	DISK_init ();

	reset_frame_rate_hack ();
	init_m68k (); /* must come after reset_frame_rate_hack (); */

	gui_update ();

	if (graphics_init ()) {
#ifdef DEBUGGER
		setup_brkhandler ();
		if (currprefs.start_debugger && debuggable ())
			activate_debugger ();
#endif

		if (!init_audio ()) {
			if (sound_available && currprefs.produce_sound > 1) {
				write_log ("Sound driver unavailable: Sound output disabled\n");
			}
			currprefs.produce_sound = 0;
		}
		start_program ();
	}

    }
#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER)
#ifdef JIT
    __except( EvalException( GetExceptionInformation(), GetExceptionCode() ) )
#else
	__except (DummyException (GetExceptionInformation (), GetExceptionCode ()))
#endif
	{
		// EvalException does the good stuff...
	}
#endif
	return 0;
}
Ejemplo n.º 15
0
NTSTATUS
GingkoRead (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
	NTSTATUS status = STATUS_SUCCESS;
	PVOID pBuff = NULL;
	BOOLEAN GingkoFile = FALSE;
	PGINGKO_OBJECT pGingkoObject = NULL;
	PIO_STACK_LOCATION irpsp = NULL;
	PFILE_OBJECT FileObject = NULL;
	SharedNotificationPtr snf = NULL;
	PGINGKO_PROCESS_LIST pProcessList = NULL;
	PGINGKO_DEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension;

	if ( IS_GINGKO_CONTROL_DEVICE_OBJECT(DeviceObject) ) {
		//KdPrint( ("READ: Read Gingko Control Device...") );
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_INVALID_DEVICE_REQUEST;
	}

	REDFISH_NETWORK_DISPATCH( DeviceObject, Irp );

	if( IsGingkoServerProcess()  || PsIsSystemThread(KeGetCurrentThread()) )
	{
		return GingkoPassThrough( DeviceObject, Irp );
	}

	snf = GingkoReferenceSharedNotification();

	if( gGingkoServerStarted == FALSE || snf == NULL )
	{
		return GingkoPassThrough( DeviceObject, Irp );
	}

	GingkoDereferenceSharedNotification( snf );

	irpsp = IoGetCurrentIrpStackLocation(Irp);

	FileObject = irpsp->FileObject;
	
	if( FsRtlIsPagingFile( FileObject ) )
	{
		KdPrint(("This is a Paging file: %wZ.\n", &(FileObject->FileName)));
	}

	//RtlInitUnicodeString( &TempName, L"\\GingkoDebug\\dbgview.chm" );

	//if( RtlCompareUnicodeString( &TempName, &FileObject->FileName, TRUE ) == 0 )
	//{
	//	LARGE_INTEGER OriginalOffset = irpsp->Parameters.Read.ByteOffset;
	//	long		  OriginalLength = irpsp->Parameters.Read.Length;
	//	KdPrint(("Read DbgView: %I64d (L: %08x, H: %08x) Lenght: %08x\n", OriginalOffset.QuadPart, OriginalOffset.LowPart, 
	//		OriginalOffset.HighPart, OriginalLength));
	//}

	if( FindWriteFileObject( FileObject, IoGetRequestorProcessId(Irp), &pGingkoObject, FALSE ) )
	{
	    NTSTATUS status = 0L;
		if( pGingkoObject != NULL ) //&& pGingkoObject->Queue.CryptoInfo != NULL && ( pGingkoObject->Permission & 0x800F0000 | pGingkoObject->Permission & 0x8000F000 ) )
		{
			if( irpsp->Parameters.Read.Length > 0L )
			{
				if( !Irp->MdlAddress )
				{
					__try{
						ProbeForRead( Irp->UserBuffer, irpsp->Parameters.Read.Length, 1);
						IoAllocateMdl( Irp->UserBuffer, irpsp->Parameters.Read.Length, FALSE, FALSE, Irp );
						if( Irp->MdlAddress )
						{
							MmProbeAndLockPages( Irp->MdlAddress, UserMode, IoReadAccess );
						}
					}__except(EXCEPTION_EXECUTE_HANDLER)
					{
						KdPrint(("Exception Code: %08x. PassThrough. The Write Length is %d, Offset: %I64d.\n", GetExceptionCode(), irpsp->Parameters.Read.Length, irpsp->Parameters.Read.ByteOffset ));
						if( Irp->MdlAddress )
						{
							IoFreeMdl( Irp->MdlAddress );
							Irp->MdlAddress = NULL;
						}
					}
				}
			}

			status = EncryptedIoQueueAddIrp (&pGingkoObject->Queue, Irp);
			
			if( status != STATUS_PENDING )
				TCCompleteDiskIrp ( Irp, status, 0 );

			return status;
		}
Ejemplo n.º 16
0
NTSTATUS
NtW32Call (
    IN ULONG ApiNumber,
    IN PVOID InputBuffer,
    IN ULONG InputLength,
    OUT PVOID *OutputBuffer,
    OUT PULONG OutputLength
    )

/*++

Routine Description:

    This function calls a W32 function.

    N.B. ************** This is a temporary service *****************

Arguments:

    ApiNumber - Supplies the API number.

    InputBuffer - Supplies a pointer to a structure that is copied to
        the user stack.

    InputLength - Supplies the length of the input structure.

    Outputbuffer - Supplies a pointer to a variable that recevies the
        output buffer address.

    Outputlength - Supplies a pointer to a variable that recevies the
        output buffer length.

Return Value:

    TBS.

--*/

{

    PVOID ValueBuffer;
    ULONG ValueLength;
    NTSTATUS Status;

    ASSERT(KeGetPreviousMode() == UserMode);

    //
    // If the current thread is not a GUI thread, then fail the service
    // since the thread does not have a large stack.
    //

    if (KeGetCurrentThread()->Win32Thread == (PVOID)&KeServiceDescriptorTable[0]) {
        return STATUS_NOT_IMPLEMENTED;
    }

    //
    // Probe the output buffer address and length for writeability.
    //

    try {
        ProbeForWriteUlong((PULONG)OutputBuffer);
        ProbeForWriteUlong(OutputLength);

    //
    // If an exception occurs during the probe of the output buffer or
    // length, then always handle the exception and return the exception
    // code as the status value.
    //

    } except(EXCEPTION_EXECUTE_HANDLER) {
        return GetExceptionCode();
    }

    //
    // Call out to user mode specifying the input buffer and API number.
    //

    Status = KeUserModeCallback(ApiNumber,
                                InputBuffer,
                                InputLength,
                                &ValueBuffer,
                                &ValueLength);

    //
    // If the callout is successful, then the output buffer address and
    // length.
    //

    if (NT_SUCCESS(Status)) {
        try {
            *OutputBuffer = ValueBuffer;
            *OutputLength = ValueLength;

        } except(EXCEPTION_EXECUTE_HANDLER) {
        }
    }

    return Status;
}
Ejemplo n.º 17
0
BOOLEAN
CmpFileWriteThroughCache(
    PHHIVE              Hive,
    ULONG               FileType,
    PCMP_OFFSET_ARRAY   offsetArray,
    ULONG               offsetArrayCount
    )
/*++

Routine Description:

    This is routine writes dirty ranges of data using Cc mapped views.
    The benefit is that writes don't go through Cc Lazy Writer, so there 
    is no danger to be throttled or deferred.

    It also flushes the cache for the written ranges, guaranteeing that 
    the data was commited to the disk upon return.

Arguments:

    Hive - Hive we are doing I/O for

    FileType - which supporting file to use

    offsetArray - array of structures where each structure holds a 32bit offset
                  into the Hive file and pointer the a buffer written to that
                  file offset.

    offsetArrayCount - number of elements in the offsetArray.

Return Value:

    FALSE if failure
    TRUE if success

Note:

    This routine is intended to deal only with paged bins (i.e. bins crossing the 
    CM_VIEW_SIZE boundary or bins that were added after the last sync)

Assumption:

    We work on the assumption that the data to be written at one iteration never spans 
    over the CM_VIEW_SIZE boundary. HvpFindNextDirtyBlock takes care of that !!! 
--*/
{
    ULONG           i;
    PVOID           DataBuffer;
    ULONG           DataLength;
    ULONG           FileOffset;
    PCMHIVE         CmHive;
    PVOID           Bcb;
    PVOID           FileBuffer;
    LARGE_INTEGER   Offset;
    IO_STATUS_BLOCK IoStatus;

    ASSERT_PASSIVE_LEVEL();

#if !DBG
    UNREFERENCED_PARAMETER (FileType);
#endif

    CmHive = (PCMHIVE)CONTAINING_RECORD(Hive, CMHIVE, Hive);

    ASSERT( ((FileType == HFILE_TYPE_EXTERNAL) && (CmHive->FileObject != NULL)) || HiveWritesThroughCache(Hive,FileType) );

    Offset.HighPart = 0;
    //
    // iterate through the array of data
    //
    for(i=0;i<offsetArrayCount;i++) {
        DataBuffer =  offsetArray[i].DataBuffer;
        DataLength =  offsetArray[i].DataLength;
        FileOffset = offsetArray[i].FileOffset;
        //
        // data should never span over CM_VIEW_SIZE boundary
        //
        ASSERT( (FileOffset & (~(CM_VIEW_SIZE - 1))) == ((FileOffset + DataLength - 1) & (~(CM_VIEW_SIZE - 1))) );

        //
        // unmap any possible mapped view that could overlap with this range ; not needed !!!!
        //

        //
        // map and pin data
        //
        Offset.LowPart = FileOffset;
        try {
            if( !CcPinRead (CmHive->FileObject,&Offset,DataLength,PIN_WAIT,&Bcb,&FileBuffer) ) {
                CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpFileWriteThroughCache - could not pin read view i= %lu\n",i));
#if DBG
                DbgBreakPoint();
#endif //DBG
                return FALSE;        
            }
            //
            // copy data to pinned view; we need to do it inside try except, to protect against devices/volumes
            // dismounting from under us.
            //
            RtlCopyMemory(FileBuffer,DataBuffer, DataLength);

        } except (EXCEPTION_EXECUTE_HANDLER) {
            //
            // in low-memory scenarios, CcPinRead throws a STATUS_INSUFFICIENT_RESOURCES
            // We want to catch this and treat as a  "not enough resources" problem, 
            // rather than letting it to surface the kernel call
            //
            CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpFileWriteThroughCache : CcPinRead has raised :%08lx\n",GetExceptionCode()));
            return FALSE;
        }

        //
        // dirty, unpin and flush
        //
        CcSetDirtyPinnedData (Bcb,NULL);
        CcUnpinData( Bcb );
        CcFlushCache (CmHive->FileObject->SectionObjectPointer,(PLARGE_INTEGER)(((ULONG_PTR)(&Offset)) + 1)/*we are private writers*/,DataLength,&IoStatus);
        if(!NT_SUCCESS(IoStatus.Status) ) {
            return FALSE;
        }
    }

    return TRUE;
}
Ejemplo n.º 18
0
NTSTATUS
KeUserModeCallback (
    IN ULONG ApiNumber,
    IN PVOID InputBuffer,
    IN ULONG InputLength,
    OUT PVOID *OutputBuffer,
    IN PULONG OutputLength
    )

/*++

Routine Description:

    This function call out from kernel mode to a user mode function.

Arguments:

    ApiNumber - Supplies the API number.

    InputBuffer - Supplies a pointer to a structure that is copied
        to the user stack.

    InputLength - Supplies the length of the input structure.

    Outputbuffer - Supplies a pointer to a variable that receives
        the address of the output buffer.

    Outputlength - Supplies a pointer to a variable that receives
        the length of the output buffer.

Return Value:

    If the callout cannot be executed, then an error status is
    returned. Otherwise, the status returned by the callback function
    is returned.

--*/

{
    PUCALLOUT_FRAME CalloutFrame;
    ULONG Length;
    ULONG OldStack;
    NTSTATUS Status;
    PKTRAP_FRAME TrapFrame;
    PULONG UserStack;
    PVOID ValueBuffer;
    ULONG ValueLength;

    ASSERT(KeGetPreviousMode() == UserMode);

    //
    // Get the user mode stack pointer and attempt to copy input buffer
    // to the user stack.
    //

    TrapFrame = KeGetCurrentThread()->TrapFrame;
    OldStack = (ULONG)TrapFrame->Gpr1;
    try {

        //
        // Compute new user mode stack address, probe for writability,
        // and copy the input buffer to the user stack.
        //

        Length =  (InputLength +
                sizeof(QUAD) - 1 + sizeof(UCALLOUT_FRAME)) & ~(sizeof(QUAD) - 1);

        CalloutFrame = (PUCALLOUT_FRAME)(OldStack - Length);
        ProbeForWrite(CalloutFrame, Length, sizeof(QUAD));
        RtlMoveMemory(CalloutFrame + 1, InputBuffer, InputLength);

        //
        // Allocate stack frame fill in callout arguments.
        //

        CalloutFrame->Buffer = (PVOID)(CalloutFrame + 1);
        CalloutFrame->Length = InputLength;
        CalloutFrame->ApiNumber = ApiNumber;
        CalloutFrame->Frame.BackChain = TrapFrame->Gpr1;
        CalloutFrame->Lr = TrapFrame->Lr;

    //
    // If an exception occurs during the probe of the user stack, then
    // always handle the exception and return the exception code as the
    // status value.
    //

    } except (EXCEPTION_EXECUTE_HANDLER) {
        return GetExceptionCode();
    }

    //
    // Call user mode.
    //

    TrapFrame->Gpr1 = (ULONG)CalloutFrame;
    Status = KiCallUserMode(OutputBuffer, OutputLength);
    TrapFrame->Gpr1 = OldStack;

    //
    // When returning from user mode, any drawing done to the GDI TEB
    // batch must be flushed.
    //

    if (((PTEB)KeGetCurrentThread()->Teb)->GdiBatchCount > 0) {

        //
        // call GDI batch flush routine
        //

        KeGdiFlushUserBatch();
    }

    return Status;
}
Ejemplo n.º 19
0
static void
dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
	proto_item  *volatile ti = NULL;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile tree;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;

	tree=parent_tree;

	pinfo->current_proto = "File";

	/* if FILE is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if(!proto_field_is_referenced(tree, proto_file)) {
		tree=NULL;
	} else {
		proto_tree *fh_tree;
		gboolean old_visible;

		/* Put in frame header information. */
		cap_len = tvb_length(tvb);
		frame_len = tvb_reported_length(tvb);

		cap_plurality = plurality(cap_len, "", "s");
		frame_plurality = plurality(frame_len, "", "s");

		ti = proto_tree_add_protocol_format(tree, proto_file, tvb, 0, -1,
		    "File record %u: %u byte%s",
		    pinfo->fd->num, frame_len, frame_plurality);
		proto_item_append_text(ti, ", %u byte%s",
		    cap_len, cap_plurality);

		fh_tree = proto_item_add_subtree(ti, ett_file);

		proto_tree_add_int(fh_tree, hf_file_ftap_encap, tvb, 0, 0, pinfo->fd->lnk_t);

		proto_tree_add_uint(fh_tree, hf_file_record_number, tvb, 0, 0, pinfo->fd->num);

		proto_tree_add_uint_format(fh_tree, hf_file_record_len, tvb,
					   0, 0, frame_len, "Record Length: %u byte%s (%u bits)",
					   frame_len, frame_plurality, frame_len * 8);

		ti = proto_tree_add_boolean(fh_tree, hf_file_marked, tvb, 0, 0,pinfo->fd->flags.marked);
		PROTO_ITEM_SET_GENERATED(ti);

		ti = proto_tree_add_boolean(fh_tree, hf_file_ignored, tvb, 0, 0,pinfo->fd->flags.ignored);
		PROTO_ITEM_SET_GENERATED(ti);

		if(proto_field_is_referenced(tree, hf_file_protocols)) {
			/* we are going to be using proto_item_append_string() on
			 * hf_frame_protocols, and we must therefore disable the
			 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
			 * setting it as visible.
			 *
			 * See proto.h for details.
			 */
			old_visible = proto_tree_set_visible(fh_tree, TRUE);
			ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, "");
			PROTO_ITEM_SET_GENERATED(ti);
			proto_tree_set_visible(fh_tree, old_visible);
		}

		if(pinfo->fd->pfd != 0){
			proto_item *ppd_item;
			guint num_entries = g_slist_length(pinfo->fd->pfd);
			guint i;
			ppd_item = proto_tree_add_uint(fh_tree, hf_file_num_p_prot_data, tvb, 0, 0, num_entries);
			PROTO_ITEM_SET_GENERATED(ppd_item);
			for(i=0; i<num_entries; i++){
				proto_tree_add_text (fh_tree, tvb, 0, 0, "%s",p_get_proto_name_and_key(wmem_file_scope(), pinfo, i));
			}
		}

#if 0
		if (show_file_off) {
			proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb,
						    0, 0, pinfo->fd->file_off,
						    "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)",
						    pinfo->fd->file_off, pinfo->fd->file_off);
		}
#endif

		if(pinfo->fd->color_filter != NULL) {
			const color_filter_t *color_filter = (const color_filter_t *)pinfo->fd->color_filter;
			item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb,
						     0, 0, color_filter->filter_name);
			PROTO_ITEM_SET_GENERATED(item);
			item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb,
						     0, 0, color_filter->filter_text);
			PROTO_ITEM_SET_GENERATED(item);
		}
	}

	if (pinfo->fd->flags.ignored) {
		/* Ignored package, stop handling here */
		col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>");
		proto_tree_add_text (tree, tvb, 0, -1, "This record is marked as ignored");
		return;
	}

	/* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
	TRY {
#ifdef _MSC_VER
		/* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions
		   like memory access violations.
		   (a running debugger will be called before the except part below) */
                /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
                   stack in an inconsistent state thus causing a crash at some point in the
                   handling of the exception.
                   See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
                */
		__try {
#endif
			if (!dissector_try_uint(file_encap_dissector_table, pinfo->fd->lnk_t,
						tvb, pinfo, parent_tree)) {

				col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
				col_add_fstr(pinfo->cinfo, COL_INFO, "FTAP_ENCAP = %d",
					     pinfo->fd->lnk_t);
				call_dissector(data_handle,tvb, pinfo, parent_tree);
			}
#ifdef _MSC_VER
		} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
			switch(GetExceptionCode()) {
			case(STATUS_ACCESS_VIOLATION):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
				break;
			case(STATUS_INTEGER_DIVIDE_BY_ZERO):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
				break;
			case(STATUS_STACK_OVERFLOW):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
				/* XXX - this will have probably corrupted the stack,
				   which makes problems later in the exception code */
				break;
				/* XXX - add other hardware exception codes as required */
			default:
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
			}
		}
#endif
	}
	CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
		show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
	}
	ENDTRY;

    if(proto_field_is_referenced(tree, hf_file_protocols)) {
		wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), "");
		wmem_list_frame_t *frame;
		/* skip the first entry, it's always the "frame" protocol */
		frame = wmem_list_frame_next(wmem_list_head(pinfo->layers));
		if (frame) {
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		while (frame) {
			wmem_strbuf_append_c(val, ':');
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		proto_item_append_string(ti, wmem_strbuf_get_str(val));
	}

	/*  Call postdissectors if we have any (while trying to avoid another
	 *  TRY/CATCH)
	 */
	if (have_postdissector()) {
		TRY {
#ifdef _MSC_VER
			/* Win32: Visual-C Structured Exception Handling (SEH)
			   to trap hardware exceptions like memory access violations */
			/* (a running debugger will be called before the except part below) */
                        /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
                           stack in an inconsistent state thus causing a crash at some point in the
                           handling of the exception.
                           See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
                        */
			__try {
#endif
				call_all_postdissectors(tvb, pinfo, parent_tree);
#ifdef _MSC_VER
			} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
				switch(GetExceptionCode()) {
				case(STATUS_ACCESS_VIOLATION):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
					break;
				case(STATUS_INTEGER_DIVIDE_BY_ZERO):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
					break;
				case(STATUS_STACK_OVERFLOW):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
					/* XXX - this will have probably corrupted the stack,
					   which makes problems later in the exception code */
					break;
					/* XXX - add other hardware exception codes as required */
				default:
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
				}
			}
#endif
		}
		CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
			show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
		}
		ENDTRY;
	}

	tap_queue_packet(file_tap, pinfo, NULL);


	if (pinfo->frame_end_routines) {
		g_slist_foreach(pinfo->frame_end_routines, &call_file_record_end_routine, NULL);
		g_slist_free(pinfo->frame_end_routines);
		pinfo->frame_end_routines = NULL;
	}
}
Ejemplo n.º 20
0
NTSTATUS
AFSSetSecurity( IN PDEVICE_OBJECT DeviceObject,
                IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_NOT_SUPPORTED;
    IO_STACK_LOCATION *pIrpSp;
    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;

    pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    __try
    {

        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSSetSecurity Entry for FO %08lX\n",
                      pIrpSp->FileObject);

        if( DeviceObject == AFSDeviceObject)
        {

            ntStatus = STATUS_INVALID_DEVICE_REQUEST;

            AFSCompleteRequest( Irp,
                                ntStatus);

            try_return( ntStatus);
        }

        if( pIrpSp->FileObject->FsContext == NULL)
        {

            //
            // Root open
            //

            ntStatus = STATUS_INVALID_DEVICE_REQUEST;

            AFSCompleteRequest( Irp,
                                ntStatus);

            try_return( ntStatus);
        }

        //
        // Check the state of the library
        //

        ntStatus = AFSCheckLibraryState( Irp);

        if( !NT_SUCCESS( ntStatus) ||
            ntStatus == STATUS_PENDING)
        {

            if( ntStatus != STATUS_PENDING)
            {
                AFSCompleteRequest( Irp, ntStatus);
            }

            try_return( ntStatus);
        }

        IoSkipCurrentIrpStackLocation( Irp);

        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
                                 Irp);

        //
        // Indicate the library is done with the request
        //

        AFSClearLibraryRequest();

try_exit:

        NOTHING;
    }
    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
    {

        AFSDbgLogMsg( 0,
                      0,
                      "EXCEPTION - AFSSetSecurity\n");
    }

    return ntStatus;
}
Ejemplo n.º 21
0
PPROFBLK SetupProfiling(LPCTSTR ptchFileName)
{
		PVOID	ImageBase;
		PPROFBLK pProfBlk;
		PPROFBLK pPrevProfBlk;
		ULONG	 ulBlkOff;
		LPCSTR  ptchImageName;
	    TCHAR	atchImageName [256];
    	PIMAGE_NT_HEADERS  pImageNtHeader;
		IMAGEHLP_MODULE	 ModuleInfo;

	    // Skip directory name
	    if ( (ptchImageName = strrchr(ptchFileName, '\\')) )
	        ptchImageName++;
	    else
	        ptchImageName = (PTCHAR)ptchFileName;

		// Make uppercase copy
	    _strupr (strcpy (atchImageName, ptchImageName));

		// Don't profile CAP
	    if ( !strcmp (atchImageName, CAPDLL) )
	        return NULL;

		// Search prof blk list for matching image name
		pPrevProfBlk = NULL;
		ulBlkOff = ulLocProfBlkOff;

	    while (ulBlkOff != 0) 
	    {
    		pPrevProfBlk = MKPPROFBLK(ulBlkOff);

			// If found image, no need to set up new block
			if (!strcmp((PCHAR)pPrevProfBlk->atchImageName, atchImageName))
				return FALSE;

			ulBlkOff = pPrevProfBlk->ulNxtBlk;
		}

		try // Accessing new block can cause an access fault
			// which will extend the allocation 
		{
			// Place block at next available offset
			pProfBlk = MKPPROFBLK(*pulProfBlkBase);

			// Fill in initial values
			pProfBlk->ImageBase =0;
		    pProfBlk->CodeStart = 0;
		    pProfBlk->CodeLength = 0;
			pProfBlk->iSymCnt = 0;
			pProfBlk->State = BLKSTATE_ASSIGNED;
			pProfBlk->ulNxtBlk = 0;
		    strcpy ((TCHAR *) pProfBlk->atchImageName, atchImageName);

			// Link to previous block or initial block offset
			if (pPrevProfBlk)
				pPrevProfBlk->ulNxtBlk = *pulProfBlkBase;
			else
				ulLocProfBlkOff = *pulProfBlkBase;

			// Load module symbols
			ImageBase = GetModuleHandle(ptchImageName);
			SymLoadModule(hThisProcess, NULL, (LPSTR)ptchFileName,
												 (LPSTR)ptchImageName, (DWORD)ImageBase, 0);
			if (ImageBase != NULL)
			{
		 		pProfBlk->ImageBase = ImageBase;

				// Get code start address
				if ((pImageNtHeader = ImageNtHeader(ImageBase)) != NULL)
				{
					pProfBlk->CodeStart = (PULONG)((TCHAR *)ImageBase +
													 pImageNtHeader->OptionalHeader.BaseOfCode);
	  			}
				else
				{
					// If can't get code start, use imagebase as next best guess
					pProfBlk->CodeStart = ImageBase;
				}

	#if defined(MIPS) && !defined(MIPS_VC40_INTERFACE)

				// Enumerate symbols to find adress of _penter
		    	fPenterFound = FALSE;
				SymEnumerateSymbols(hThisProcess, (DWORD)ImageBase,
									 FindPenterCallback, (PVOID)pProfBlk);

	#endif // MIPS && !MIPS_VC40_INTERFACE

				// Get module info for symbols count
				SymGetModuleInfo(hThisProcess, (DWORD)ImageBase, &ModuleInfo);
				pProfBlk->iSymCnt = ModuleInfo.NumSyms;

				// Determine location for symbols and symbol names
				pProfSymb = (PSYMINFO)(&pProfBlk->atchImageName[strlen(atchImageName) + 1]);
				pProfBlk->ulSym = (PTCHAR)pProfSymb - (PTCHAR)pulProfBlkBase;
				pcProfSymbName = (PTCHAR)&pProfSymb[ModuleInfo.NumSyms];

				// Now enumerate symbols to build up symbol table
				ulMaxSymbAddr = (ULONG)pProfBlk->CodeStart;
				SymEnumerateSymbols(hThisProcess, (DWORD)ImageBase,
									 SymbolEnumCallback, (PVOID)pProfBlk);

				// Set symbol range based on max symbol address	encountered
				if (ulMaxSymbAddr > (ULONG)pProfBlk->CodeStart)
					pProfBlk->CodeLength = ulMaxSymbAddr - (ULONG)pProfBlk->CodeStart;

				// Update pointer to available space
				*pulProfBlkBase = (ULONG)(pcProfSymbName - (PTCHAR)pulProfBlkBase);

				// Unload the module
				SymUnloadModule(hThisProcess, (DWORD)ImageBase);

				// Do any requested import/export patching
	        	PatchDll (ptchPatchImports, ptchPatchCallers, bCallersToPatch,
	                       atchImageName, ImageBase);
			}
			else
			{	
				// No symbols - Update offset to next free space
				*pulProfBlkBase = (ULONG)&pProfBlk->atchImageName[strlen(atchImageName) + 1]
									-(ULONG)pulProfBlkBase;
			} // ImageBase != NULL

		}
		//
		// + : transfer control to the handler (EXCEPTION_EXECUTE_HANDLER)
		// 0 : continue search                 (EXCEPTION_CONTINUE_SEARCH)
		// - : dismiss exception & continue    (EXCEPTION_CONTINUE_EXECUTION)
		//
		except ( AccessXcptFilter (GetExceptionCode(), GetExceptionInformation(), COMMIT_SIZE))
		{
		    // Should never get here since filter never returns
		    // EXCEPTION_EXECUTE_HANDLER.
		    CapDbgPrint ("CAP:  DoDllInitializations() - *LOGIC ERROR* - "
		              "Inside the EXCEPT: (xcpt=0x%lx)\n", GetExceptionCode());
		} // end of TRY/EXCEPT

		return pProfBlk;
}
Ejemplo n.º 22
0
NTSTATUS
NtLoadDriver(
    IN PUNICODE_STRING DriverServiceName
    )

/*++

Routine Description:

    This service dynamically loads a device or file system driver into
    the currently running system.  It requires that the caller have the
    appropriate privilege to execute this service.

Arguments:

    DriverServiceName - Specifies the name of the node in the registry
        associated with the driver to be loaded.

Return Value:

    The status returned is the final completion status of the load operation.

--*/

{
    KPROCESSOR_MODE requestorMode;
    UNICODE_STRING driverServiceName;
    PWCHAR nameBuffer = (PWCHAR) NULL;
    LOAD_PACKET loadPacket;

    PAGED_CODE();

    //
    // Get the previous mode;  i.e., the mode of the caller.
    //

    requestorMode = KeGetPreviousMode();

    if (requestorMode != KernelMode) {

        //
        // The caller's access mode is not kernel so check to ensure that
        // the caller has the privilege to load a driver and probe and
        // capture the name of the driver service entry.
        //

        if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, requestorMode )) {
            return STATUS_PRIVILEGE_NOT_HELD;
        }

        //
        // The caller has the appropriate privilege to load and unload
        // drivers, so capture the driver service name string so that it
        // can be used to locate the driver from the registry node.
        //

        try {

            driverServiceName = ProbeAndReadUnicodeString( DriverServiceName );

            if (!driverServiceName.Length) {
                return STATUS_INVALID_PARAMETER;
            }

            ProbeForRead( driverServiceName.Buffer,
                          driverServiceName.Length,
                          sizeof( WCHAR ) );

            nameBuffer = ExAllocatePoolWithQuota( PagedPool,
                                                  driverServiceName.Length );

            RtlCopyMemory( nameBuffer,
                           driverServiceName.Buffer,
                           driverServiceName.Length );

            driverServiceName.Buffer = nameBuffer;

        } except(EXCEPTION_EXECUTE_HANDLER) {

            //
            // An exception was incurred while attempting to capture the
            // input name string or while attempting to allocate the name
            // string buffer.  Simply clean everything up and return an
            // appropriate error status code.
            //

            if (nameBuffer) {
                ExFreePool( nameBuffer );
            }
            return GetExceptionCode();
        }
    } else {
Ejemplo n.º 23
0
#include <malloc.h>
#include <excpt.h>

/*
 * Return non-zero when we run out of memory on the stack; zero otherwise.
 */
int
PyOS_CheckStack(void)
{
    __try {
        /* alloca throws a stack overflow exception if there's
           not enough space left on the stack */
        alloca(PYOS_STACK_MARGIN * sizeof(void*));
        return 0;
    } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
                    EXCEPTION_EXECUTE_HANDLER :
            EXCEPTION_CONTINUE_SEARCH) {
        int errcode = _resetstkoflw();
        if (errcode == 0)
        {
            Py_FatalError("Could not reset the stack!");
        }
    }
    return 1;
}

#endif /* WIN32 && _MSC_VER */

/* Alternate implementations can be added here... */
Ejemplo n.º 24
0
NTSTATUS
NtFreeVirtualMemory(
    __in HANDLE ProcessHandle,
    __inout PVOID *BaseAddress,
    __inout PSIZE_T RegionSize,
    __in ULONG FreeType
)

/*++

Routine Description:

    This function deletes a region of pages within the virtual address
    space of a subject process.

Arguments:

    ProcessHandle - An open handle to a process object.

    BaseAddress - The base address of the region of pages
                  to be freed. This value is rounded down to the
                  next host page address boundary.

    RegionSize - A pointer to a variable that will receive
                 the actual size in bytes of the freed region of
                 pages. The initial value of this argument is
                 rounded up to the next host page size boundary.

    FreeType - A set of flags that describe the type of
               free that is to be performed for the specified
               region of pages.

       FreeType Flags

        MEM_DECOMMIT - The specified region of pages is to be decommitted.

        MEM_RELEASE - The specified region of pages is to be released.

Return Value:

    NTSTATUS.

--*/

{
    KAPC_STATE ApcState;
    PMMVAD_SHORT Vad;
    PMMVAD_SHORT NewVad;
    PMMVAD PreviousVad;
    PMMVAD NextVad;
    PMMVAD ChargedVad;
    PEPROCESS Process;
    KPROCESSOR_MODE PreviousMode;
    PVOID StartingAddress;
    PVOID EndingAddress;
    NTSTATUS Status;
    LOGICAL Attached;
    SIZE_T CapturedRegionSize;
    PVOID CapturedBase;
    PMMPTE StartingPte;
    PMMPTE EndingPte;
    SIZE_T OldQuota;
    SIZE_T QuotaCharge;
    SIZE_T CommitReduction;
    LOGICAL UserPhysicalPages;
    PETHREAD CurrentThread;
    PEPROCESS CurrentProcess;

    PAGED_CODE();

    //
    // Check to make sure FreeType is good.
    //

    if ((FreeType & ~(MEM_DECOMMIT | MEM_RELEASE)) != 0) {
        return STATUS_INVALID_PARAMETER_4;
    }

    //
    // One of MEM_DECOMMIT or MEM_RELEASE must be specified, but not both.
    //

    if (((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == 0) ||
            ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) ==
             (MEM_DECOMMIT | MEM_RELEASE))) {
        return STATUS_INVALID_PARAMETER_4;
    }
    CurrentThread = PsGetCurrentThread ();

    CurrentProcess = PsGetCurrentProcessByThread (CurrentThread);

    PreviousMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);

    //
    // Establish an exception handler, probe the specified addresses
    // for write access and capture the initial values.
    //

    try {

        if (PreviousMode != KernelMode) {

            ProbeForWritePointer (BaseAddress);
            ProbeForWriteUlong_ptr (RegionSize);
        }

        //
        // Capture the base address.
        //

        CapturedBase = *BaseAddress;

        //
        // Capture the region size.
        //

        CapturedRegionSize = *RegionSize;

    }
    except (ExSystemExceptionFilter ()) {

        //
        // If an exception occurs during the probe or capture
        // of the initial values, then handle the exception and
        // return the exception code as the status value.
        //

        return GetExceptionCode ();
    }

    //
    // Make sure the specified starting and ending addresses are
    // within the user part of the virtual address space.
    //

    if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {

        //
        // Invalid base address.
        //

        return STATUS_INVALID_PARAMETER_2;
    }

    if ((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)CapturedBase <
            CapturedRegionSize) {

        //
        // Invalid region size;
        //

        return STATUS_INVALID_PARAMETER_3;

    }

    EndingAddress = (PVOID)(((LONG_PTR)CapturedBase + CapturedRegionSize - 1) |
                            (PAGE_SIZE - 1));

    StartingAddress = PAGE_ALIGN(CapturedBase);

    Attached = FALSE;

    if (ProcessHandle == NtCurrentProcess()) {
        Process = CurrentProcess;
    }
    else {

        //
        // Reference the specified process handle for VM_OPERATION access.
        //

        Status = ObReferenceObjectByHandle (ProcessHandle,
                                            PROCESS_VM_OPERATION,
                                            PsProcessType,
                                            PreviousMode,
                                            (PVOID *)&Process,
                                            NULL);

        if (!NT_SUCCESS(Status)) {
            return Status;
        }

        //
        // If the specified process is not the current process, attach
        // to the specified process.
        //

        if (CurrentProcess != Process) {
            KeStackAttachProcess (&Process->Pcb, &ApcState);
            Attached = TRUE;
        }
    }

    CommitReduction = 0;

    //
    // Get the address creation mutex to block multiple threads from
    // creating or deleting address space at the same time and
    // get the working set mutex so virtual address descriptors can
    // be inserted and walked.  Block APCs to prevent page faults while
    // we own the working set mutex.
    //

    LOCK_ADDRESS_SPACE (Process);

    //
    // Make sure the address space was not deleted.
    //

    if (Process->Flags & PS_PROCESS_FLAGS_VM_DELETED) {
        Status = STATUS_PROCESS_IS_TERMINATING;
        goto ErrorReturn;
    }

    Vad = (PMMVAD_SHORT) MiLocateAddress (StartingAddress);

    if (Vad == NULL) {

        //
        // No Virtual Address Descriptor located for Base Address.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Found the associated Virtual Address Descriptor.
    //

    if (Vad->EndingVpn < MI_VA_TO_VPN (EndingAddress)) {

        //
        // The entire range to delete is not contained within a single
        // virtual address descriptor.  Return an error.
        //

        Status = STATUS_UNABLE_TO_FREE_VM;
        goto ErrorReturn;
    }

    //
    // Check to ensure this Vad is deletable.  Delete is required
    // for both decommit and release.
    //

    if (((Vad->u.VadFlags.PrivateMemory == 0) &&
            (Vad->u.VadFlags.VadType != VadRotatePhysical))
            ||
            (Vad->u.VadFlags.VadType == VadDevicePhysicalMemory)) {

        Status = STATUS_UNABLE_TO_DELETE_SECTION;
        goto ErrorReturn;
    }

    if (Vad->u.VadFlags.NoChange == 1) {

        //
        // An attempt is being made to delete a secured VAD, check
        // to see if this deletion is allowed.
        //

        if (FreeType & MEM_RELEASE) {

            //
            // Specify the whole range, this solves the problem with
            // splitting the VAD and trying to decide where the various
            // secure ranges need to go.
            //

            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        MI_VPN_TO_VA (Vad->StartingVpn),
                                        ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT) +
                                        PAGE_SIZE,
                                        MM_SECURE_DELETE_CHECK);

        }
        else {
            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        CapturedBase,
                                        CapturedRegionSize,
                                        MM_SECURE_DELETE_CHECK);
        }
        if (!NT_SUCCESS (Status)) {
            goto ErrorReturn;
        }
    }

    UserPhysicalPages = FALSE;
    ChargedVad = NULL;

    PreviousVad = MiGetPreviousVad (Vad);
    NextVad = MiGetNextVad (Vad);

    if (FreeType & MEM_RELEASE) {

        //
        // *****************************************************************
        // MEM_RELEASE was specified.
        // *****************************************************************
        //

        //
        // The descriptor for the address range is deletable.  Remove or split
        // the descriptor.
        //

        //
        // If the region size is zero, remove the whole VAD.
        //

        if (CapturedRegionSize == 0) {

            //
            // If the region size is specified as 0, the base address
            // must be the starting address for the region.
            //

            if (MI_VA_TO_VPN (CapturedBase) != Vad->StartingVpn) {
                Status = STATUS_FREE_VM_NOT_AT_BASE;
                goto ErrorReturn;
            }

            //
            // This Virtual Address Descriptor has been deleted.
            //

            StartingAddress = MI_VPN_TO_VA (Vad->StartingVpn);
            EndingAddress = MI_VPN_TO_VA_ENDING (Vad->EndingVpn);

            if (Vad->u.VadFlags.VadType == VadRotatePhysical) {
                Status = MiUnmapViewOfSection (Process,
                                               CapturedBase,
                                               UNMAP_ADDRESS_SPACE_HELD | UNMAP_ROTATE_PHYSICAL_OK);
                ASSERT (CommitReduction == 0);
                Vad = NULL;
                CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
                goto AllDone;
            }

            //
            // Free all the physical pages that this VAD might be mapping.
            //

            if (Vad->u.VadFlags.VadType == VadLargePages) {

                MiAweViewRemover (Process, (PMMVAD)Vad);

                MiReleasePhysicalCharges (Vad->EndingVpn - Vad->StartingVpn + 1,
                                          Process);

                LOCK_WS_UNSAFE (CurrentThread, Process);

                MiFreeLargePages (MI_VPN_TO_VA (Vad->StartingVpn),
                                  MI_VPN_TO_VA_ENDING (Vad->EndingVpn),
                                  FALSE);
            }
            else if (Vad->u.VadFlags.VadType == VadAwe) {
                MiAweViewRemover (Process, (PMMVAD)Vad);
                MiRemoveUserPhysicalPagesVad (Vad);
                UserPhysicalPages = TRUE;
                LOCK_WS_UNSAFE (CurrentThread, Process);
            }
            else if (Vad->u.VadFlags.VadType == VadWriteWatch) {
                LOCK_WS_UNSAFE (CurrentThread, Process);
                MiPhysicalViewRemover (Process, (PMMVAD)Vad);
            }
            else {
                LOCK_WS_UNSAFE (CurrentThread, Process);
            }

            ChargedVad = (PMMVAD)Vad;

            MiRemoveVad ((PMMVAD)Vad, Process);

            //
            // Free the VAD pool and release quota after releasing our mutexes
            // to reduce contention.
            //
        }
        else {

            //
            // Region's size was not specified as zero, delete the
            // whole VAD or split the VAD.
            //

            if (MI_VA_TO_VPN (StartingAddress) == Vad->StartingVpn) {
                if (MI_VA_TO_VPN (EndingAddress) == Vad->EndingVpn) {

                    //
                    // This Virtual Address Descriptor has been deleted.
                    //
                    // Free all the physical pages that this VAD might be
                    // mapping.
                    //

                    if (Vad->u.VadFlags.VadType == VadRotatePhysical) {
                        Status = MiUnmapViewOfSection (Process,
                                                       CapturedBase,
                                                       UNMAP_ADDRESS_SPACE_HELD | UNMAP_ROTATE_PHYSICAL_OK);
                        ASSERT (CommitReduction == 0);
                        Vad = NULL;
                        CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
                        goto AllDone;
                    }

                    if (Vad->u.VadFlags.VadType == VadLargePages) {

                        MiAweViewRemover (Process, (PMMVAD)Vad);

                        MiReleasePhysicalCharges (Vad->EndingVpn - Vad->StartingVpn + 1,
                                                  Process);

                        LOCK_WS_UNSAFE (CurrentThread, Process);

                        MiFreeLargePages (MI_VPN_TO_VA (Vad->StartingVpn),
                                          MI_VPN_TO_VA_ENDING (Vad->EndingVpn),
                                          FALSE);
                    }
                    else if (Vad->u.VadFlags.VadType == VadAwe) {
                        MiAweViewRemover (Process, (PMMVAD)Vad);
                        MiRemoveUserPhysicalPagesVad (Vad);
                        UserPhysicalPages = TRUE;
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                    }
                    else if (Vad->u.VadFlags.VadType == VadWriteWatch) {
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                        MiPhysicalViewRemover (Process, (PMMVAD)Vad);
                    }
                    else {
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                    }

                    ChargedVad = (PMMVAD)Vad;

                    MiRemoveVad ((PMMVAD)Vad, Process);

                    //
                    // Free the VAD pool after releasing our mutexes
                    // to reduce contention.
                    //
                }
                else {

                    if ((Vad->u.VadFlags.VadType == VadAwe) ||
                            (Vad->u.VadFlags.VadType == VadLargePages) ||
                            (Vad->u.VadFlags.VadType == VadRotatePhysical) ||
                            (Vad->u.VadFlags.VadType == VadWriteWatch)) {

                        //
                        // Splitting or chopping a physical VAD, large page VAD
                        // or a write-watch VAD is not allowed.
                        //

                        Status = STATUS_FREE_VM_NOT_AT_BASE;
                        goto ErrorReturn;
                    }

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    //
                    // This Virtual Address Descriptor has a new starting
                    // address.
                    //

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    Vad->StartingVpn = MI_VA_TO_VPN ((PCHAR)EndingAddress + 1);
                    Vad->u.VadFlags.CommitCharge -= CommitReduction;
                    ASSERT ((SSIZE_T)Vad->u.VadFlags.CommitCharge >= 0);
                    NextVad = (PMMVAD)Vad;
                    Vad = NULL;
                }
            }
            else {

                if ((Vad->u.VadFlags.VadType == VadAwe) ||
                        (Vad->u.VadFlags.VadType == VadLargePages) ||
                        (Vad->u.VadFlags.VadType == VadRotatePhysical) ||
                        (Vad->u.VadFlags.VadType == VadWriteWatch)) {

                    //
                    // Splitting or chopping a physical VAD, large page VAD
                    // or a write-watch VAD is not allowed.
                    //

                    Status = STATUS_FREE_VM_NOT_AT_BASE;
                    goto ErrorReturn;
                }

                //
                // Starting address is greater than start of VAD.
                //

                if (MI_VA_TO_VPN (EndingAddress) == Vad->EndingVpn) {

                    //
                    // Change the ending address of the VAD.
                    //

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    Vad->u.VadFlags.CommitCharge -= CommitReduction;

                    Vad->EndingVpn = MI_VA_TO_VPN ((PCHAR)StartingAddress - 1);
                    PreviousVad = (PMMVAD)Vad;
                }
                else {

                    //
                    // Split this VAD as the address range is within the VAD.
                    //

                    NewVad = ExAllocatePoolWithTag (NonPagedPool,
                                                    sizeof(MMVAD_SHORT),
                                                    'FdaV');

                    if (NewVad == NULL) {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        goto ErrorReturn;
                    }

                    *NewVad = *Vad;

                    NewVad->StartingVpn = MI_VA_TO_VPN ((PCHAR)EndingAddress + 1);
                    //
                    // Set the commit charge to zero so MiInsertVad will
                    // not charge commitment for splitting the VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = 0;

                    //
                    // Insert the VAD, this could fail due to quota charges.
                    //

                    Status = MiInsertVadCharges ((PMMVAD)NewVad, Process);

                    if (!NT_SUCCESS(Status)) {

                        //
                        // The quota charging failed, free the new VAD
                        // and return an error.
                        //

                        UNLOCK_ADDRESS_SPACE (Process);
                        ExFreePool (NewVad);
                        goto ErrorReturn2;
                    }

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    OldQuota = Vad->u.VadFlags.CommitCharge - CommitReduction;

                    Vad->EndingVpn = MI_VA_TO_VPN ((PCHAR)StartingAddress - 1);

                    MiInsertVad ((PMMVAD)NewVad, Process);

                    //
                    // As we have split the original VAD into 2 separate VADs
                    // there is no way of knowing what the commit charge
                    // is for each VAD.  Calculate the charge and reset
                    // each VAD.  Note that we also use the previous value
                    // to make sure the books stay balanced.
                    //

                    QuotaCharge = MiCalculatePageCommitment (MI_VPN_TO_VA (Vad->StartingVpn),
                                  (PCHAR)StartingAddress - 1,
                                  (PMMVAD)Vad,
                                  Process);

                    Vad->u.VadFlags.CommitCharge = QuotaCharge;

                    //
                    // Give the remaining charge to the new VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = OldQuota - QuotaCharge;
                    PreviousVad = (PMMVAD)Vad;
                    NextVad = (PMMVAD)NewVad;
                }
                Vad = NULL;
            }
        }

        if (UserPhysicalPages == TRUE) {
            MiDeletePageTablesForPhysicalRange (StartingAddress, EndingAddress);
        }
        else {

            MiDeleteVirtualAddresses (StartingAddress,
                                      EndingAddress,
                                      NULL);
        }

        UNLOCK_WS_UNSAFE (CurrentThread, Process);

        //
        // Return commitment for page table pages if possible.
        //

        MiReturnPageTablePageCommitment (StartingAddress,
                                         EndingAddress,
                                         Process,
                                         PreviousVad,
                                         NextVad);

        if (ChargedVad != NULL) {
            MiRemoveVadCharges (ChargedVad, Process);
        }

        CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;

        //
        // Update the virtual size in the process header.
        //

        Process->VirtualSize -= CapturedRegionSize;

        Process->CommitCharge -= CommitReduction;
        Status = STATUS_SUCCESS;

AllDone:
        UNLOCK_ADDRESS_SPACE (Process);

        if (CommitReduction != 0) {

            MI_INCREMENT_TOTAL_PROCESS_COMMIT (0 - CommitReduction);

            ASSERT (Vad == NULL);
            PsReturnProcessPageFileQuota (Process, CommitReduction);
            MiReturnCommitment (CommitReduction);

            if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
                PsChangeJobMemoryUsage (PS_JOB_STATUS_REPORT_COMMIT_CHANGES, -(SSIZE_T)CommitReduction);
            }

            MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_NTFREEVM1, CommitReduction);
        }
        else if (Vad != NULL) {
            ExFreePool (Vad);
        }

        if (Attached == TRUE) {
            KeUnstackDetachProcess (&ApcState);
        }

        if (ProcessHandle != NtCurrentProcess ()) {
            ObDereferenceObject (Process);
        }
        //
        // Establish an exception handler and write the size and base
        // address.
        //

        try {

            *RegionSize = CapturedRegionSize;
            *BaseAddress = StartingAddress;

        }
        except (EXCEPTION_EXECUTE_HANDLER) {

            //
            // An exception occurred, don't take any action (just handle
            // the exception and return success.

        }

        return Status;
    }

    //
    // **************************************************************
    //
    // MEM_DECOMMIT was specified.
    //
    // **************************************************************
    //

    if (Vad->u.VadFlags.VadType == VadAwe) {

        //
        // Pages from a physical VAD must be released via
        // NtFreeUserPhysicalPages, not this routine.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    if ((Vad->u.VadFlags.VadType == VadLargePages) ||
            (Vad->u.VadFlags.VadType == VadRotatePhysical)) {

        //
        // Pages from a large page or rotate physical VAD must be released -
        // they cannot be merely decommitted.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Check to ensure the complete range of pages is already committed.
    //

    if (CapturedRegionSize == 0) {

        if (MI_VA_TO_VPN (CapturedBase) != Vad->StartingVpn) {
            Status = STATUS_FREE_VM_NOT_AT_BASE;
            goto ErrorReturn;
        }
        EndingAddress = MI_VPN_TO_VA_ENDING (Vad->EndingVpn);
    }

    //
    // The address range is entirely committed, decommit it now.
    //

    //
    // Calculate the initial quotas and commit charges for this VAD.
    //

    StartingPte = MiGetPteAddress (StartingAddress);
    EndingPte = MiGetPteAddress (EndingAddress);

    CommitReduction = 1 + EndingPte - StartingPte;

    //
    // Check to see if the entire range can be decommitted by
    // just updating the virtual address descriptor.
    //

    CommitReduction -= MiDecommitPages (StartingAddress,
                                        EndingPte,
                                        Process,
                                        Vad);

    //
    // Adjust the quota charges.
    //

    ASSERT ((LONG)CommitReduction >= 0);

    Vad->u.VadFlags.CommitCharge -= CommitReduction;
    ASSERT ((LONG)Vad->u.VadFlags.CommitCharge >= 0);
    Vad = NULL;

    Process->CommitCharge -= CommitReduction;

    UNLOCK_ADDRESS_SPACE (Process);

    if (CommitReduction != 0) {

        MI_INCREMENT_TOTAL_PROCESS_COMMIT (0 - CommitReduction);

        PsReturnProcessPageFileQuota (Process, CommitReduction);
        MiReturnCommitment (CommitReduction);

        if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
            PsChangeJobMemoryUsage (PS_JOB_STATUS_REPORT_COMMIT_CHANGES, -(SSIZE_T)CommitReduction);
        }

        MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_NTFREEVM2, CommitReduction);
    }
    else if (Vad != NULL) {
        ExFreePool (Vad);
    }

    if (Attached == TRUE) {
        KeUnstackDetachProcess (&ApcState);
    }

    if (ProcessHandle != NtCurrentProcess()) {
        ObDereferenceObject (Process);
    }

    //
    // Establish an exception handler and write the size and base address.
    //

    try {

        *RegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
        *BaseAddress = StartingAddress;

    }
    except (EXCEPTION_EXECUTE_HANDLER) {
        NOTHING;
    }

    return STATUS_SUCCESS;

ErrorReturn:
    UNLOCK_ADDRESS_SPACE (Process);

ErrorReturn2:
    if (Attached == TRUE) {
        KeUnstackDetachProcess (&ApcState);
    }

    if (ProcessHandle != NtCurrentProcess()) {
        ObDereferenceObject (Process);
    }
    return Status;
}
Ejemplo n.º 25
0
VOID
FatStackOverflowRead (
    IN PVOID Context,
    IN PKEVENT Event
    )

/*++

Routine Description:

    This routine processes a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

    Context - Supplies the IrpContext being processed

    Event - Supplies the event to be signaled when we are done processing this
        request.

Return Value:

    None.

--*/

{
    PIRP_CONTEXT IrpContext = Context;
    PKTHREAD SavedVerifyThread = NULL;
    PVCB Vcb = NULL;

    PAGED_CODE();

    //
    //  Make it now look like we can wait for I/O to complete
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

    //
    //  If this read was as the result of a verify we have to fake out the
    //  the Vcb->VerifyThread field.
    //

    if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) {

        PFCB Fcb = (PFCB)IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp)->
                    FileObject->FsContext;

        if (NodeType( Fcb ) == FAT_NTC_VCB) {
    
            Vcb = (PVCB) Fcb;
        
        } else {
    
            Vcb = Fcb->Vcb;
        }

        NT_ASSERT( Vcb->VerifyThread != NULL );
        SavedVerifyThread = Vcb->VerifyThread;
        Vcb->VerifyThread = KeGetCurrentThread();
    }

    //
    //  Do the read operation protected by a try-except clause
    //

    try {

        (VOID) FatCommonRead( IrpContext, IrpContext->OriginatingIrp );

    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        NTSTATUS ExceptionCode;

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        ExceptionCode = GetExceptionCode();

        if (ExceptionCode == STATUS_FILE_DELETED) {

            IrpContext->ExceptionStatus = ExceptionCode = STATUS_END_OF_FILE;
            IrpContext->OriginatingIrp->IoStatus.Information = 0;
        }

        (VOID) FatProcessException( IrpContext, IrpContext->OriginatingIrp, ExceptionCode );
    }

    //
    //  Restore the original VerifyVolumeThread
    //

    if (SavedVerifyThread != NULL) {

        NT_ASSERT( Vcb->VerifyThread == KeGetCurrentThread() );
        Vcb->VerifyThread = SavedVerifyThread;
    }

    //
    //  Set the stack overflow item's event to tell the original
    //  thread that we're done.
    //

    KeSetEvent( Event, 0, FALSE );
}
Ejemplo n.º 26
0
VOID
FatFspDispatch (
    IN PVOID Context
    )

/*++

Routine Description:

    This is the main FSP thread routine that is executed to receive
    and dispatch IRP requests.  Each FSP thread begins its execution here.
    There is one thread created at system initialization time and subsequent
    threads created as needed.

Arguments:


    Context - Supplies the thread id.

Return Value:

    None - This routine never exits

--*/

{
    NTSTATUS Status;

    PIRP Irp;
    PIRP_CONTEXT IrpContext;
    PIO_STACK_LOCATION IrpSp;
    BOOLEAN VcbDeleted;

    PVOLUME_DEVICE_OBJECT VolDo;

    PAGED_CODE();

    IrpContext = (PIRP_CONTEXT)Context;

    Irp = IrpContext->OriginatingIrp;

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Now because we are the Fsp we will force the IrpContext to
    //  indicate true on Wait.
    //

    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);

    //
    //  If this request has an associated volume device object, remember it.
    //

    if ( IrpSp->FileObject != NULL ) {

        VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
                                   VOLUME_DEVICE_OBJECT,
                                   DeviceObject );
    } else {

        VolDo = NULL;
    }

    //
    //  Now case on the function code.  For each major function code,
    //  either call the appropriate FSP routine or case on the minor
    //  function and then call the FSP routine.  The FSP routine that
    //  we call is responsible for completing the IRP, and not us.
    //  That way the routine can complete the IRP and then continue
    //  post processing as required.  For example, a read can be
    //  satisfied right away and then read can be done.
    //
    //  We'll do all of the work within an exception handler that
    //  will be invoked if ever some underlying operation gets into
    //  trouble (e.g., if FatReadSectorsSync has trouble).
    //

    while ( TRUE ) {

        DebugTrace(0, Dbg, "FatFspDispatch: Irp = 0x%08lx\n", Irp);

        //
        //  If this Irp was top level, note it in our thread local storage.
        //

        FsRtlEnterFileSystem();

        if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) {

            IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );

        } else {

            IoSetTopLevelIrp( Irp );
        }

        try {

            switch ( IrpContext->MajorFunction ) {

                //
                //  For Create Operation,
                //

                case IRP_MJ_CREATE:

                    (VOID) FatCommonCreate( IrpContext, Irp );
                    break;

                //
                //  For close operations.  We do a little kludge here in case
                //  this close causes a volume to go away.  It will NULL the
                //  VolDo local variable so that we will not try to look at
                //  the overflow queue.
                //

                case IRP_MJ_CLOSE:

                {
                    PVCB Vcb;
                    PFCB Fcb;
                    PCCB Ccb;
                    TYPE_OF_OPEN TypeOfOpen;

                    //
                    //  Extract and decode the file object
                    //

                    TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );

                    //
                    //  Do the close.  We have a slightly different format
                    //  for this call because of the async closes.
                    //

                    Status = FatCommonClose( Vcb,
                                             Fcb,
                                             Ccb,
                                             TypeOfOpen,
                                             TRUE,
                                             &VcbDeleted );

                    //
                    //  If the VCB was deleted, do not try to access it later.
                    //

                    if (VcbDeleted) {

                        VolDo = NULL;
                    }

                    ASSERT(Status == STATUS_SUCCESS);

                    FatCompleteRequest( IrpContext, Irp, Status );

                    break;
                }

                //
                //  For read operations
                //

                case IRP_MJ_READ:

                    (VOID) FatCommonRead( IrpContext, Irp );
                    break;

                //
                //  For write operations,
                //

                case IRP_MJ_WRITE:

                    (VOID) FatCommonWrite( IrpContext, Irp );
                    break;

                //
                //  For Query Information operations,
                //

                case IRP_MJ_QUERY_INFORMATION:

                    (VOID) FatCommonQueryInformation( IrpContext, Irp );
                    break;

                //
                //  For Set Information operations,
                //

                case IRP_MJ_SET_INFORMATION:

                    (VOID) FatCommonSetInformation( IrpContext, Irp );
                    break;

                //
                //  For Query EA operations,
                //

                case IRP_MJ_QUERY_EA:

                    (VOID) FatCommonQueryEa( IrpContext, Irp );
                    break;

                //
                //  For Set EA operations,
                //

                case IRP_MJ_SET_EA:

                    (VOID) FatCommonSetEa( IrpContext, Irp );
                    break;

                //
                //  For Flush buffers operations,
                //

                case IRP_MJ_FLUSH_BUFFERS:

                    (VOID) FatCommonFlushBuffers( IrpContext, Irp );
                    break;

                //
                //  For Query Volume Information operations,
                //

                case IRP_MJ_QUERY_VOLUME_INFORMATION:

                    (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp );
                    break;

                //
                //  For Set Volume Information operations,
                //

                case IRP_MJ_SET_VOLUME_INFORMATION:

                    (VOID) FatCommonSetVolumeInfo( IrpContext, Irp );
                    break;

                //
                //  For File Cleanup operations,
                //

                case IRP_MJ_CLEANUP:

                    (VOID) FatCommonCleanup( IrpContext, Irp );
                    break;

                //
                //  For Directory Control operations,
                //

                case IRP_MJ_DIRECTORY_CONTROL:

                    (VOID) FatCommonDirectoryControl( IrpContext, Irp );
                    break;

                //
                //  For File System Control operations,
                //

                case IRP_MJ_FILE_SYSTEM_CONTROL:

                    (VOID) FatCommonFileSystemControl( IrpContext, Irp );
                    break;

                //
                //  For Lock Control operations,
                //

                case IRP_MJ_LOCK_CONTROL:

                    (VOID) FatCommonLockControl( IrpContext, Irp );
                    break;

                //
                //  For Device Control operations,
                //

                case IRP_MJ_DEVICE_CONTROL:

                    (VOID) FatCommonDeviceControl( IrpContext, Irp );
                    break;

                //
                //  For the Shutdown operation,
                //

                case IRP_MJ_SHUTDOWN:

                    (VOID) FatCommonShutdown( IrpContext, Irp );
                    break;

                //
                //  For plug and play operations.
                //

                case IRP_MJ_PNP:

                    //
                    //  I don't believe this should ever occur, but allow for the unexpected.
                    //

                    (VOID) FatCommonPnp( IrpContext, Irp );
                    break;

                //
                //  For any other major operations, return an invalid
                //  request.
                //

                default:

                    FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
                    break;

            }

        } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

            //
            //  We had some trouble trying to perform the requested
            //  operation, so we'll abort the I/O request with
            //  the error status that we get back from the
            //  execption code.
            //

            (VOID) FatProcessException( IrpContext, Irp, GetExceptionCode() );
        }

        IoSetTopLevelIrp( NULL );

        FsRtlExitFileSystem();

        //
        //  If there are any entries on this volume's overflow queue, service
        //  them.
        //

        if ( VolDo != NULL ) {

            PVOID Entry;

            //
            //  We have a volume device object so see if there is any work
            //  left to do in its overflow queue.
            //

            Entry = FatRemoveOverflowEntry( VolDo );

            //
            //  There wasn't an entry, break out of the loop and return to
            //  the Ex Worker thread.
            //

            if ( Entry == NULL ) {

                break;
            }

            //
            //  Extract the IrpContext, Irp, and IrpSp, and loop.
            //

            IrpContext = CONTAINING_RECORD( Entry,
                                            IRP_CONTEXT,
                                            WorkQueueItem.List );

            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);

            Irp = IrpContext->OriginatingIrp;

            IrpSp = IoGetCurrentIrpStackLocation( Irp );

            continue;

        } else {

            break;
        }
    }

    //
    //  Decrement the PostedRequestCount.
    //

    if ( VolDo ) {

        ExInterlockedAddUlong( &VolDo->PostedRequestCount,
                               0xffffffff,
                               &VolDo->OverflowQueueSpinLock );
    }

    return;
}
Ejemplo n.º 27
0
NTSTATUS
NtExtendSection(
    IN HANDLE SectionHandle,
    IN OUT PLARGE_INTEGER NewSectionSize
    )

/*++

Routine Description:

    This function extends the size of the specified section.  If
    the current size of the section is greater than or equal to the
    specified section size, the size is not updated.

Arguments:

    SectionHandle - Supplies an open handle to a section object.

    NewSectionSize - Supplies the new size for the section object.

Return Value:

    Returns the status

    TBS


--*/

{
    KPROCESSOR_MODE PreviousMode;
    PVOID Section;
    NTSTATUS Status;
    LARGE_INTEGER CapturedNewSectionSize;

    PAGED_CODE();

    //
    // Check to make sure the new section size is accessible.
    //

    PreviousMode = KeGetPreviousMode();

    if (PreviousMode != KernelMode) {

        try {

            ProbeForWrite (NewSectionSize,
                           sizeof(LARGE_INTEGER),
                           sizeof(ULONG ));

            CapturedNewSectionSize = *NewSectionSize;

        } except (EXCEPTION_EXECUTE_HANDLER) {

            //
            // If an exception occurs during the probe or capture
            // of the initial values, then handle the exception and
            // return the exception code as the status value.
            //

            return GetExceptionCode();
        }

    } else {
Ejemplo n.º 28
0
NTSTATUS
RtlCreateUserThread(
    IN HANDLE Process,
    IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
    IN BOOLEAN CreateSuspended,
    IN ULONG ZeroBits OPTIONAL,
    IN SIZE_T MaximumStackSize OPTIONAL,
    IN SIZE_T CommittedStackSize OPTIONAL,
    IN PUSER_THREAD_START_ROUTINE StartAddress,
    IN PVOID Parameter OPTIONAL,
    OUT PHANDLE Thread OPTIONAL,
    OUT PCLIENT_ID ClientId OPTIONAL
    )

/*++

Routine Description:

    This function creates a user mode thread in a user process.  The caller
    specifies the attributes of the new thread.  A handle to the thread, along
    with its Client Id are returned to the caller.

Arguments:

    Process - Handle to the target process in which to create the new thread.

    ThreadSecurityDescriptor - An optional pointer to the Security Descriptor
        give to the new thread.

    CreateSuspended - A boolean parameter that specifies whether or not the new
        thread is to be created suspended or not.  If TRUE, the new thread
        will be created with an initial suspend count of 1.  If FALSE then
        the new thread will be ready to run when this call returns.

    ZeroBits - This parameter is passed to the virtual memory manager
        when the stack is allocated.  Stacks are always allocated with the
        MEM_TOP_DOWN allocation attribute.

    MaximumStackSize - This is the maximum size of the stack.  This size
        will be rounded up to the next highest page boundary.  If zero is
        specified, then the default size will be 64K bytes.

    CommittedStackSize - This is the initial committed size of the stack.  This
        size is rounded up to the next highest page boundary and then an
        additional page is added for the guard page.  The resulting size
        will then be commited and the guard page protection initialized
        for the last committed page in the stack.

    StartAddress - The initial starting address of the thread.

    Parameter - An optional pointer to a 32-bit pointer parameter that is
        passed as a single argument to the procedure at the start address
        location.

    Thread - An optional pointer that, if specified, points to a variable that
        will receive the handle of the new thread.

    ClientId - An optional pointer that, if specified, points to a variable
        that will receive the Client Id of the new thread.

--*/

{
    NTSTATUS Status;
    CONTEXT ThreadContext={0};
    OBJECT_ATTRIBUTES ObjectAttributes;
    INITIAL_TEB InitialTeb;
    HANDLE ThreadHandle;
    CLIENT_ID ThreadClientId;

    //
    // Allocate a stack for this thread in the address space of the target
    // process.
    //

    Status = RtlpCreateStack( Process,
                              MaximumStackSize,
                              CommittedStackSize,
                              ZeroBits,
                              &InitialTeb
                            );
    if ( !NT_SUCCESS( Status ) ) {
        return( Status );
    }

    //
    // Create an initial context for the new thread.
    //


    try {
        RtlInitializeContext( Process,
                              &ThreadContext,
                              Parameter,
                              (PVOID)StartAddress,
                              InitialTeb.StackBase
                            );
    } except (EXCEPTION_EXECUTE_HANDLER) {
        RtlpFreeStack( Process, &InitialTeb );
        return GetExceptionCode ();
    }

    //
    // Now create a thread in the target process.  The new thread will
    // not have a name and its handle will not be inherited by other
    // processes.
    //

    InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL,
                                ThreadSecurityDescriptor );
    Status = ZwCreateThread( &ThreadHandle,
                             THREAD_ALL_ACCESS,
                             &ObjectAttributes,
                             Process,
                             &ThreadClientId,
                             &ThreadContext,
                             &InitialTeb,
                             CreateSuspended
                           );
    if (!NT_SUCCESS( Status )) {
#if DBG
        DbgPrint( "NTRTL: RtlCreateUserThread Failed. NtCreateThread Status == %X\n",
                  Status );
#endif // DBG
        RtlpFreeStack( Process, &InitialTeb );
    } else {
        if (ARGUMENT_PRESENT( Thread )) {
            *Thread = ThreadHandle;
        } else {
            ZwClose (ThreadHandle);
        }

        if (ARGUMENT_PRESENT( ClientId )) {
            *ClientId = ThreadClientId;
        }

    }

    //
    // Return status
    //

    return( Status );
}
Ejemplo n.º 29
0
	NTSTATUS
Bus_IoCtl (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

    Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

   NT status code

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen, outlen;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;

    PAGED_CODE ();
    
    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    //
    // We only take Device Control requests for the FDO.
    // That is the bus itself.
    //

    if (!fdoData->IsFDO) {
    
        //
        // These commands are only allowed to go to the FDO.
        //   
        status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;

    }

    //
    // Check to see whether the bus is removed
    //
    
    if (fdoData->DevicePnPState == Deleted) {
        Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }
    
    Bus_IncIoCount (fdoData);
    
    irpStack = IoGetCurrentIrpStackLocation (Irp);

    buffer			= Irp->AssociatedIrp.SystemBuffer;  
    inlen			= irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outlen			= irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    status = STATUS_INVALID_PARAMETER;

	Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode));
    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) 
	{

	case IOCTL_LANSCSI_ADD_TARGET:
	{
		PPDO_DEVICE_DATA	pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));

		if ((inlen == outlen) &&
			(sizeof(LANSCSI_ADD_TARGET_DATA) <= inlen)) 
		{
			ULONG						ulSize;
			PLANSCSI_ADD_TARGET_DATA	addTargetData = buffer;
			
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_ADD_TARGET called\n"));
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType));

			// Check Parameter.
			status = STATUS_SUCCESS;
			switch(addTargetData->ucTargetType) 
			{
			case DISK_TYPE_NORMAL: 
			case DISK_TYPE_DVD: 
			case DISK_TYPE_VDVD: 
			case DISK_TYPE_MO:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA);
				if(addTargetData->ulNumberOfUnitDiskList != 1)
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}

				break;

			case DISK_TYPE_MIRROR:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK);
					
				if(2 != addTargetData->ulNumberOfUnitDiskList)
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}

				break;

			case DISK_TYPE_AGGREGATION:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
					sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);

				if (addTargetData->ulNumberOfUnitDiskList < 2 || 
					addTargetData->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) 
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}
				
				break;

			case DISK_TYPE_BIND_RAID0:
				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
					sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);
				switch(addTargetData->ulNumberOfUnitDiskList)
				{
				case 2:
				case 4:
				case 8:
					break;
				default: // do not accept
					ulSize = 0;
					break;
				}
				break;
			case DISK_TYPE_BIND_RAID1:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
						sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);
					if (2 != ulDiskCount) 
					{
						ulSize = 0;	// Exit when Check if(ulSize != inlen)...
					}
				}
				break;
			case DISK_TYPE_BIND_RAID4:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
						sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);
				
					switch(ulDiskCount)
					{
					case 3: // 2 + 1
					case 5: // 4 + 1
					case 9: // 8 + 1
						break;
					default: // do not accept
						ulSize = 0;
						break;
					}
					break;
				}				
			default:
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			// Check Size.
			if(ulSize != inlen) 
			{
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
#if DBG
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_TRY_TO_ADDTARGET,
				IOCTL_LANSCSI_ADD_TARGET,
				addTargetData->ulSlotNo);
#endif
			// Find Pdo Data...
			pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo);
			if(pdoData == NULL) 
			{
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("no pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
									NDASBUS_IO_PDO_NOT_FOUND,
									IOCTL_LANSCSI_ADD_TARGET,
									addTargetData->ulSlotNo);
				break;
			}

			pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, inlen);

			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
			else 
			{
				RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen);
				status = STATUS_SUCCESS;
			}

			pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen;

			//
			//	Notify to LanscsiMiniport
			//
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n"));
			KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE);

			//
			//	Register Target
			//
			if(pdoData->Persistent) {
				status = LSBus_RegisterTarget(fdoData, addTargetData);
				if(!NT_SUCCESS(status)) {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status));
					status = STATUS_INTERNAL_DB_ERROR;
					NDBusIoctlLogError(	fdoData->Self,
										NDASBUS_IO_REGISTER_TARGET_FAIL,
										IOCTL_LANSCSI_ADD_TARGET,
										addTargetData->ulSlotNo);
				} else {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n"));
				}
			}

			ObDereferenceObject(pdoData->Self);

			Irp->IoStatus.Information = outlen;
		}        
		else
		{
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
								("IOCTL_LANSCSI_ADD_TARGET length mismatch!!!"
								" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
								inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}

	}
		break;

	case IOCTL_LANSCSI_REMOVE_TARGET:
	{
	    PPDO_DEVICE_DATA	pdoData;
		PLANSCSI_REMOVE_TARGET_DATA	removeTarget;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REMOVE_TARGET called\n"));

        if (sizeof (LANSCSI_REMOVE_TARGET_DATA) != inlen)
			break;

		removeTarget = (PLANSCSI_REMOVE_TARGET_DATA)buffer;
		pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				removeTarget->ulSlotNo);
			break;
		}

		//
		//	redirect to the NDAS SCSI Device
		//
		status = LSBus_IoctlToLSMPDevice(
				pdoData,
				LANSCSIMINIPORT_IOCTL_REMOVE_TARGET,
				buffer,
				sizeof(LANSCSI_REMOVE_TARGET_DATA),
				NULL,
				0
			);

		if(NT_SUCCESS(status) && pdoData->Persistent) {

			status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId);
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, (	"REMOVE_TARGET: Removed  Target instance,"
															" but LSBus_UnregisterTarget() failed.\n"));
				status = STATUS_INTERNAL_DB_ERROR;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_UNREGISTER_TARGET_FAIL,
					IOCTL_LANSCSI_REMOVE_TARGET,
					removeTarget->ulSlotNo);
			}
#if DBG
			else {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n"));
			}
#endif
		}

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = 0;
		break;
	}

	case IOCTL_LANSCSI_RECOVER_TARGET:
	{
	    PPDO_DEVICE_DATA	pdoData;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_RECOVER_TARGET called\n"));

        if (sizeof (LANSCSI_RECOVER_TARGET_DATA) != inlen)
			break;

		pdoData = LookupPdoData(fdoData, ((PLANSCSI_RECOVER_TARGET_DATA)buffer)->ulSlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				((PLANSCSI_RECOVER_TARGET_DATA)buffer)->ulSlotNo);
			break;
		}

		//
		//	redirect to the LanscsiMiniport Device
		//
		status = LSBus_IoctlToLSMPDevice(
				pdoData,
				LANSCSIMINIPORT_IOCTL_RECOVER_TARGET,
				buffer,
				sizeof(LANSCSI_RECOVER_TARGET_DATA),
				NULL,
				0
			);

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
		break;
	}

	case IOCTL_LANSCSI_STARTSTOP_REGISTRARENUM:{
		PULONG	onOff = (PULONG)buffer;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
			"STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff));

		ExAcquireFastMutex(&fdoData->RegMutex);

		if(*onOff != 0) {

			//
			//	Save old state.
			//	Activate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = TRUE;
		} else {

			//
			//	Save old state.
			//	Deactivate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = FALSE;
		}
		ExReleaseFastMutex(&fdoData->RegMutex);

		Irp->IoStatus.Information = sizeof(ULONG);
		status = STATUS_SUCCESS;

		break;
	}

	case IOCTL_LANSCSI_REGISTER_DEVICE:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
							"REGISTER_DEVICE: inlen %d, outlen %d,"
							" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
							inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PBUSENUM_PLUGIN_HARDWARE_EX2	PlugIn = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n"));

			status = LSBus_RegisterDevice(fdoData, PlugIn);

			Irp->IoStatus.Information = 0;
		}
		else
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
									("REGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));

	}
		break;
	case IOCTL_LANSCSI_REGISTER_TARGET:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_ADD_TARGET_DATA	AddTargetData = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n"));

			status = LSBus_RegisterTarget(fdoData, AddTargetData);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}

	}
		break;
	case IOCTL_LANSCSI_UNREGISTER_DEVICE:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: inlen %d, outlen %d,"
									" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_UNREGISTER_NDASDEV	UnregDev = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n"));

			status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}
	}
	break;
	case IOCTL_LANSCSI_UNREGISTER_TARGET:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_UNREGISTER_TARGET	UnregTarget = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n"));

			status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}
	}
	break;
	case IOCTL_LANSCSI_SETPDOINFO:
		{
	    PPDO_DEVICE_DATA	pdoData;
		PBUSENUM_SETPDOINFO	SetPdoInfo;
		KIRQL				oldIrql;
		PVOID				sectionHandle;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_SETPDOINFO called\n"));

        if (sizeof (BUSENUM_SETPDOINFO) != inlen)
			break;

		SetPdoInfo = (PBUSENUM_SETPDOINFO)buffer;
		pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				SetPdoInfo->SlotNo);
			break;
		}

		//
		//	lock the code section of this function to acquire spinlock in raised IRQL.
		//
	    sectionHandle = MmLockPagableCodeSection(Bus_IoCtl);

		KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql);

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!!  IOCTL_LANSCSI_SETPDOINFO: %08lx %08lx %08lx\n",
										SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess));


		//
		//	Set status values to the corresponding physical device object.
		//

		if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUS_STOPPING) &&
			ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPED)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'Stopping' event occured after 'Stopped' event\n",
					SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess));

		} else {
			pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus;
			pdoData->LanscsiAdapterPDO.DesiredAccess = SetPdoInfo->DesiredAccess;
			pdoData->LanscsiAdapterPDO.GrantedAccess = SetPdoInfo->GrantedAccess;
		}

		//
		//	Queue plugout worker if the NDAS SCSI stop abnormally.
		//
		if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUS_STOPPED) &&
			ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUSFLAG_ABNORMAL_TERMINAT)) {

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n",
					SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess));

			status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo);
		}

		KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql);


		//
		//	Release the code section.
		//

	    MmUnlockPagableImageSection(sectionHandle);

		status = STATUS_SUCCESS;
		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
	}
		break;

	case IOCTL_BUSENUM_QUERY_NODE_ALIVE: 
		{

		PPDO_DEVICE_DATA		pdoData;
		BOOLEAN					bAlive;
		PBUSENUM_NODE_ALIVE_IN	pNodeAliveIn;
		BUSENUM_NODE_ALIVE_OUT	nodeAliveOut;

		// Check Parameter.
		if(inlen != sizeof(BUSENUM_NODE_ALIVE_IN) || 
			outlen != sizeof(BUSENUM_NODE_ALIVE_OUT)) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		
		pNodeAliveIn = (PBUSENUM_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer;  
		
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE,
			("FDO: IOCTL_BUSENUM_QUERY_NODE_ALIVE SlotNumber = %d\n",
			pNodeAliveIn->SlotNo));
		
		pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo);

		if(pdoData == NULL) {
//			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
//				("[LanScsiBus]Bus_IoCtl: IOCTL_BUSENUM_QUERY_NODE_ALIVE No pdo\n"));
			
			bAlive = FALSE;
		} else {
			//
			// Check this PDO would be removed...
			//
			if(pdoData->Present == TRUE) 
				bAlive = TRUE;
			else
				bAlive = FALSE;
		}

		// For Result...
		nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo;
		nodeAliveOut.bAlive = bAlive;
		// Get Adapter Status.
		if(bAlive == TRUE)
		{
			if(	ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_IN_ERROR) ||
				ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPING) /*||
				ADAPTERINFO_ISSTATUSFLAG(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT) */
				) {

				nodeAliveOut.bHasError = TRUE;
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_BUSENUM_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError));
			} else {
				nodeAliveOut.bHasError = FALSE;
			}

		}

		if(pdoData)
			ObDereferenceObject(pdoData->Self);

		RtlCopyMemory(
			Irp->AssociatedIrp.SystemBuffer,
			&nodeAliveOut,
			sizeof(BUSENUM_NODE_ALIVE_OUT)
			);
		
		Irp->IoStatus.Information = sizeof(BUSENUM_NODE_ALIVE_OUT);
		status = STATUS_SUCCESS;
		}
		break;

	//
	//	added by hootch 01172004
	//
	case IOCTL_LANSCSI_UPGRADETOWRITE:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_UPGRADETOWRITE called\n"));
		// Check Parameter.
		if(inlen != sizeof(BUSENUM_UPGRADE_TO_WRITE)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_UPGRADETOWRITE: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		pdoData = LookupPdoData(fdoData, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo);
		} else {
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_LANSCSI_REDIRECT_NDASSCSI:
		{
		PPDO_DEVICE_DATA				pdoData;
		PBUSENUM_REDIRECT_NDASSCSI		redirectIoctl;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI called\n"));
		// Check Parameter.
		if(inlen < sizeof(BUSENUM_REDIRECT_NDASSCSI)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_REDIRECT_NDASSCSI: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		redirectIoctl = (PBUSENUM_REDIRECT_NDASSCSI)buffer;

		pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
		} else {
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					redirectIoctl->IoctlCode,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_LANSCSI_QUERY_LSMPINFORMATION:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION called\n"));
		// Check Parameter.
		if(inlen < FIELD_OFFSET(LSMPIOCTL_QUERYINFO, QueryData) ) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_QUERY_LSMPINFORMATION: Invalid input buffer length too small.\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		pdoData = LookupPdoData(fdoData, ((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo);

		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_QUERY_LSMPINFORMATION No pdo\n"));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo);
		} else {
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					LANSCSIMINIPORT_IOCTL_QUERYINFO_EX,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
        Irp->IoStatus.Information = outlen;
		}
		break;

	case IOCTL_BUSENUM_QUERY_INFORMATION:
		{

//		PPDO_DEVICE_DATA				pdoData;
		BUSENUM_QUERY_INFORMATION		Query;
		PBUSENUM_INFORMATION			Information;
		LONG							BufferLenNeeded;

		// Check Parameter.
		if(	inlen < sizeof(BUSENUM_QUERY_INFORMATION) /*|| 
			outlen < sizeof(BUSENUM_INFORMATION) */) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		RtlCopyMemory(&Query, buffer, sizeof(BUSENUM_QUERY_INFORMATION));
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
			("FDO: IOCTL_BUSENUM_QUERY_INFORMATION QueryType : %d  SlotNumber = %d\n",
			Query.InfoClass, Query.SlotNo));

		Information = (PBUSENUM_INFORMATION)buffer;
		ASSERT(Information);
		Information->InfoClass = Query.InfoClass;
		status = LSBus_QueryInformation(fdoData, &Query, Information, outlen, &BufferLenNeeded);
		if(NT_SUCCESS(status)) {
			Information->Size = BufferLenNeeded;
			Irp->IoStatus.Information = BufferLenNeeded;
		} else {
			Irp->IoStatus.Information = BufferLenNeeded;
		}
		}
		break;

	case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX:
		{
			if ((inlen == outlen) &&
				//
				// Make sure it has at least two nulls and the size 
				// field is set to the declared size of the struct
				//
				((sizeof (BUSENUM_PLUGIN_HARDWARE_EX) + sizeof(UNICODE_NULL) * 2) <=
				inlen) &&

				//
				// The size field should be set to the sizeof the struct as declared
				// and *not* the size of the struct plus the multi_sz
				//
				(sizeof (BUSENUM_PLUGIN_HARDWARE_EX) ==
				((PBUSENUM_PLUGIN_HARDWARE_EX) buffer)->Size)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

				status= Bus_PlugInDeviceEx((PBUSENUM_PLUGIN_HARDWARE_EX)buffer,
											inlen, fdoData, Irp->RequestorMode);
	           
				Irp->IoStatus.Information = outlen;

			}
		}
        break;

	case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX2:
		{
			if ((inlen == outlen) &&
				//
				// Make sure it has at least two nulls and the size 
				// field is set to the declared size of the struct
				//
				((sizeof (BUSENUM_PLUGIN_HARDWARE_EX2) + sizeof(UNICODE_NULL) * 2) <=
				inlen) &&

				//
				// The size field should be set to the sizeof the struct as declared
				// and *not* the size of the struct plus the multi_sz
				//
				(sizeof (BUSENUM_PLUGIN_HARDWARE_EX2) ==
				((PBUSENUM_PLUGIN_HARDWARE_EX2) buffer)->Size)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

				status= Bus_PlugInDeviceEx2((PBUSENUM_PLUGIN_HARDWARE_EX2)buffer,
											inlen, fdoData, Irp->RequestorMode, FALSE);

				Irp->IoStatus.Information = outlen;

			}
		}
        break;

	case IOCTL_LANSCSI_GETVERSION:
		{
			if (outlen >= sizeof(BUSENUM_GET_VERSION)) {
				PBUSENUM_GET_VERSION version = (PBUSENUM_GET_VERSION)buffer;

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_GETVERSION: called\n"));

			try {
				version->VersionMajor = VER_FILEMAJORVERSION;
				version->VersionMinor = VER_FILEMINORVERSION;
				version->VersionBuild = VER_FILEBUILD;
				version->VersionPrivate = VER_FILEBUILD_QFE;

					Irp->IoStatus.Information = sizeof(BUSENUM_GET_VERSION);
					status = STATUS_SUCCESS;

				} except (EXCEPTION_EXECUTE_HANDLER) {

					status = GetExceptionCode();
					Irp->IoStatus.Information = 0;
				}

			}
		}			
		break;

    case IOCTL_BUSENUM_UNPLUG_HARDWARE:
		{
			if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n"));

				status= Bus_UnPlugDevice(
						(PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData);
				Irp->IoStatus.Information = outlen;

			}
		}
        break;

    case IOCTL_BUSENUM_EJECT_HARDWARE:
		{
			if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n"));

				status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData);

				Irp->IoStatus.Information = outlen;
			}
		}
		break;

	case IOCTL_DVD_GET_STATUS:
		{
			PPDO_DEVICE_DATA		pdoData;
			PBUSENUM_DVD_STATUS		pDvdStatusData;


			// Check Parameter.
			if((inlen != outlen)
				|| (sizeof(BUSENUM_DVD_STATUS) >  inlen))
			{
				status = STATUS_UNSUCCESSFUL ;
				break;
			}
			
			pDvdStatusData = (PBUSENUM_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer;  
			
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("FDO: IOCTL_DVD_GET_STATUS SlotNumber = %d\n",
				pDvdStatusData->SlotNo));	

			pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo);
			
			if(pdoData == NULL) {
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_DVD_GET_STATUS No pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_PDO_NOT_FOUND,
					IOCTL_LANSCSI_ADD_TARGET,
					pDvdStatusData->SlotNo);
				break;
			} else {

				if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) {
					//
					//	A LUR descriptor is set.
					//
					if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != DISK_TYPE_DVD)
				{
					Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("IOCTL_DVD_GET_STATUS  No DVD Device\n"));
					status = STATUS_UNSUCCESSFUL;
					break;
				}
				} else {
					//
					//	ADD_TARGET_DATA is set.
					//
					if(((PLANSCSI_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != DISK_TYPE_DVD)
					{
						Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
							("IOCTL_DVD_GET_STATUS  No DVD Device\n"));
						status = STATUS_UNSUCCESSFUL;
						break;
					}
				}
				//
				//	redirect to the LanscsiMiniport Device
				//
				status = LSBus_IoctlToLSMPDevice(
						pdoData,
						LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS,
						buffer,
						inlen,
						buffer,
						outlen
					);

				ObDereferenceObject(pdoData->Self);
				status = STATUS_SUCCESS;
				Irp->IoStatus.Information = outlen;
			}					
		}
		break;
    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }
Ejemplo n.º 30
0
NTSTATUS
FatFsdPnp (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of PnP operations

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;
    BOOLEAN Wait;

    DebugTrace(+1, Dbg, "FatFsdPnp\n", 0);

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

        //
        //  We expect there to never be a fileobject, in which case we will always
        //  wait.  Since at the moment we don't have any concept of pending Pnp
        //  operations, this is a bit nitpicky.
        //
        
        if (IoGetCurrentIrpStackLocation( Irp )->FileObject == NULL) {

            Wait = TRUE;

        } else {

            Wait = CanFsdWait( Irp );
        }

        IrpContext = FatCreateIrpContext( Irp, Wait );

        Status = FatCommonPnp( IrpContext, Irp );

    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFsdPnp -> %08lx\n", Status);

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}