Esempio n. 1
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
FsRtlPrivateLock(IN PFILE_LOCK FileLock,
                 IN PFILE_OBJECT FileObject,
                 IN PLARGE_INTEGER FileOffset,
                 IN PLARGE_INTEGER Length,
                 IN PEPROCESS Process,
                 IN ULONG Key,
                 IN BOOLEAN FailImmediately,
                 IN BOOLEAN ExclusiveLock,
                 OUT PIO_STATUS_BLOCK IoStatus,
                 IN PIRP Irp OPTIONAL,
                 IN PVOID Context OPTIONAL,
                 IN BOOLEAN AlreadySynchronized)
{
    NTSTATUS Status;
    COMBINED_LOCK_ELEMENT ToInsert;
    PCOMBINED_LOCK_ELEMENT Conflict;
    PLOCK_INFORMATION LockInfo;
    PLOCK_SHARED_RANGE NewSharedRange;
    BOOLEAN InsertedNew;
    ULARGE_INTEGER UnsignedStart;
    ULARGE_INTEGER UnsignedEnd;
    
    DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %u, Exclusive %u)\n", 
           &FileObject->FileName, 
           FileOffset->HighPart,
           FileOffset->LowPart, 
           (int)FileOffset->QuadPart,
           Length->HighPart,
           Length->LowPart, 
           (int)Length->QuadPart,
           Key,
           FailImmediately, 
           ExclusiveLock);
    
    UnsignedStart.QuadPart = FileOffset->QuadPart;
    UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart;

    if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart)
    {
        DPRINT("File offset out of range\n");
        IoStatus->Status = STATUS_INVALID_PARAMETER;
        if (Irp)
        {
            DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status);
            FsRtlCompleteLockIrpReal
                (FileLock->CompleteLockIrpRoutine,
                 Context,
                 Irp,
                 IoStatus->Status,
                 &Status,
                 FileObject);
        }
        return FALSE;
    }
    
    /* Initialize the lock, if necessary */
    if (!FileLock->LockInformation)
    {
        LockInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOCK_INFORMATION), TAG_FLOCK);
        if (!LockInfo)
        {
            IoStatus->Status = STATUS_NO_MEMORY;
            return FALSE;
        }
        FileLock->LockInformation = LockInfo;

        LockInfo->BelongsTo = FileLock;
        InitializeListHead(&LockInfo->SharedLocks);
        
        RtlInitializeGenericTable
            (&LockInfo->RangeTable,
             LockCompare,
             LockAllocate,
             LockFree,
             NULL);
        
        KeInitializeSpinLock(&LockInfo->CsqLock);
        InitializeListHead(&LockInfo->CsqList);
        
        IoCsqInitializeEx
            (&LockInfo->Csq, 
             LockInsertIrpEx,
             LockRemoveIrp,
             LockPeekNextIrp,
             LockAcquireQueueLock,
             LockReleaseQueueLock,
             LockCompleteCanceledIrp);
    }
    
    LockInfo = FileLock->LockInformation;
    ToInsert.Exclusive.FileLock.FileObject = FileObject;
    ToInsert.Exclusive.FileLock.StartingByte = *FileOffset;
    ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart;
    ToInsert.Exclusive.FileLock.ProcessId = Process->UniqueProcessId;
    ToInsert.Exclusive.FileLock.Key = Key;
    ToInsert.Exclusive.FileLock.ExclusiveLock = ExclusiveLock;

    Conflict = RtlInsertElementGenericTable
        (FileLock->LockInformation,
         &ToInsert,
         sizeof(ToInsert),
         &InsertedNew);

    if (Conflict && !InsertedNew)
    {
        if (Conflict->Exclusive.FileLock.ExclusiveLock || ExclusiveLock)
        {
            DPRINT("Conflict %08x%08x:%08x%08x Exc %u (Want Exc %u)\n",
                   Conflict->Exclusive.FileLock.StartingByte.HighPart,
                   Conflict->Exclusive.FileLock.StartingByte.LowPart,
                   Conflict->Exclusive.FileLock.EndingByte.HighPart,
                   Conflict->Exclusive.FileLock.EndingByte.LowPart,
                   Conflict->Exclusive.FileLock.ExclusiveLock,
                   ExclusiveLock);
            if (FailImmediately)
            {
                DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
                IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
                if (Irp)
                {
                    DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
                    FsRtlCompleteLockIrpReal
                        (FileLock->CompleteLockIrpRoutine,
                         Context,
                         Irp,
                         IoStatus->Status,
                         &Status,
                         FileObject);
                }
                return FALSE;
            }
            else
            {
                IoStatus->Status = STATUS_PENDING;
                if (Irp)
                {
                    Irp->IoStatus.Information = LockInfo->Generation;
                    IoMarkIrpPending(Irp);
                    IoCsqInsertIrpEx
                        (&LockInfo->Csq,
                         Irp,
                         NULL,
                         NULL);
                }
            }
            return FALSE;
        }
        else
        {
            ULONG i;
            /* We know of at least one lock in range that's shared.  We need to
             * find out if any more exist and any are exclusive. */
            for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++)
            {
                Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i);

                /* The first argument will be inserted as a shared range */
                if (Conflict && (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual))
                {
                    if (Conflict->Exclusive.FileLock.ExclusiveLock)
                    {
                        /* Found an exclusive match */
                        if (FailImmediately)
                        {
                            IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
                            DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
                            if (Irp)
                            {
                                DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
                                FsRtlCompleteLockIrpReal
                                    (FileLock->CompleteLockIrpRoutine,
                                     Context,
                                     Irp,
                                     IoStatus->Status,
                                     &Status,
                                     FileObject);
                            }
                        }
                        else
                        {
                            IoStatus->Status = STATUS_PENDING;
                            if (Irp)
                            {
                                IoMarkIrpPending(Irp);
                                IoCsqInsertIrpEx
                                    (&LockInfo->Csq,
                                     Irp,
                                     NULL,
                                     NULL);
                            }
                        }
                        return FALSE;
                    }
                }
            }
            
            DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n",
                   &FileObject->FileName,
                   Conflict->Exclusive.FileLock.StartingByte.HighPart,
                   Conflict->Exclusive.FileLock.StartingByte.LowPart,
                   Conflict->Exclusive.FileLock.EndingByte.HighPart,
                   Conflict->Exclusive.FileLock.EndingByte.LowPart);
            Conflict = FsRtlpRebuildSharedLockRange(FileLock,
                                                    LockInfo,
                                                    &ToInsert);
            if (!Conflict)
            {
                IoStatus->Status = STATUS_NO_MEMORY;
                if (Irp)
                {
                    FsRtlCompleteLockIrpReal
                        (FileLock->CompleteLockIrpRoutine,
                         Context,
                         Irp,
                         IoStatus->Status,
                         &Status,
                         FileObject);
                }
            }

            /* We got here because there were only overlapping shared locks */
            /* A shared lock is both a range *and* a list entry.  Insert the
               entry here. */
            
            DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
            NewSharedRange = 
                ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
            if (!NewSharedRange)
            {
                IoStatus->Status = STATUS_NO_MEMORY;
                if (Irp)
                {
                    FsRtlCompleteLockIrpReal
                        (FileLock->CompleteLockIrpRoutine,
                         Context,
                         Irp,
                         IoStatus->Status,
                         &Status,
                         FileObject);
                }
                return FALSE;
            }
            DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
            NewSharedRange->Start = *FileOffset;
            NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
            NewSharedRange->Key = Key;
            NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId;
            InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);

            DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
                   &FileObject->FileName,
                   Conflict->Exclusive.FileLock.StartingByte.HighPart,
                   Conflict->Exclusive.FileLock.StartingByte.LowPart,
                   Conflict->Exclusive.FileLock.EndingByte.HighPart,
                   Conflict->Exclusive.FileLock.EndingByte.LowPart);
            IoStatus->Status = STATUS_SUCCESS;
            if (Irp)
            {
                FsRtlCompleteLockIrpReal
                    (FileLock->CompleteLockIrpRoutine,
                     Context,
                     Irp,
                     IoStatus->Status,
                     &Status,
                     FileObject);
            }
            return TRUE;
        }
    }
    else if (!Conflict)
    {
        /* Conflict here is (or would be) the newly inserted element, but we ran
         * out of space probably. */
        IoStatus->Status = STATUS_NO_MEMORY;
        if (Irp)
        {
            FsRtlCompleteLockIrpReal
                (FileLock->CompleteLockIrpRoutine,
                 Context,
                 Irp,
                 IoStatus->Status,
                 &Status,
                 FileObject);
        }
        return FALSE;
    }
    else
    {
        DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %u\n",
               &FileObject->FileName,
               Conflict->Exclusive.FileLock.StartingByte.HighPart,
               Conflict->Exclusive.FileLock.StartingByte.LowPart,
               Conflict->Exclusive.FileLock.EndingByte.HighPart,
               Conflict->Exclusive.FileLock.EndingByte.LowPart,
               Conflict->Exclusive.FileLock.ExclusiveLock);
        if (!ExclusiveLock)
        {
            NewSharedRange = 
                ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
            if (!NewSharedRange)
            {
                IoStatus->Status = STATUS_NO_MEMORY;
                if (Irp)
                {
                    FsRtlCompleteLockIrpReal
                        (FileLock->CompleteLockIrpRoutine,
                         Context,
                         Irp,
                         IoStatus->Status,
                         &Status,
                         FileObject);
                }
                return FALSE;
            }
            DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
            NewSharedRange->Start = *FileOffset;
            NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
            NewSharedRange->Key = Key;
            NewSharedRange->ProcessId = Process->UniqueProcessId;
            InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
        }
        
        /* Assume all is cool, and lock is set */
        IoStatus->Status = STATUS_SUCCESS;
        
        if (Irp)
        {
            /* Complete the request */
            FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
                                     Context,
                                     Irp,
                                     IoStatus->Status,
                                     &Status,
                                     FileObject);
            
            /* Update the status */
            IoStatus->Status = Status;
        }
    }
    
    return TRUE;
}
Esempio n. 2
0
static NTSTATUS
V4vAddDevice(PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
    NTSTATUS          status = STATUS_SUCCESS;
    UNICODE_STRING    deviceName;
    PDEVICE_OBJECT    fdo = NULL;
    PXENV4V_EXTENSION pde = NULL;
    LONG              val;
    BOOLEAN           symlink = FALSE;
    LARGE_INTEGER     seed;
    WCHAR            *szSddl = NULL;
    UNICODE_STRING    sddlString;
    CHAR             *szFpath = NULL;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    // We only allow one instance of this device type. If more than on pdo is created we need
    val = InterlockedCompareExchange(&g_deviceCreated, 1, 0);
    if (val != 0) {
        TraceWarning(("cannot instantiate more that one v4v device node.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    do {
        // Create our device
        RtlInitUnicodeString(&deviceName, V4V_DEVICE_NAME);
        szSddl = g_win5Sddl;
        RtlInitUnicodeString(&sddlString, szSddl);

        status = 
            IoCreateDeviceSecure(driverObject,
                                 sizeof(XENV4V_EXTENSION),
                                 &deviceName,
                                 FILE_DEVICE_UNKNOWN,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &sddlString,
                                 (LPCGUID)&GUID_SD_XENV4V_CONTROL_OBJECT,
                                 &fdo);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create device object - error: 0x%x\n", status));
            fdo = NULL;
            break;
        }

        pde = (PXENV4V_EXTENSION)fdo->DeviceExtension;
        RtlZeroMemory(pde, sizeof(XENV4V_EXTENSION));
        RtlStringCchCopyW(pde->symbolicLinkText, XENV4V_SYM_NAME_LEN, V4V_SYMBOLIC_NAME);
        RtlInitUnicodeString(&pde->symbolicLink, pde->symbolicLinkText);

        // Create our symbolic link
        status = IoCreateSymbolicLink(&pde->symbolicLink, &deviceName);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create symbolic - error: 0x%x\n", status));
            break;
        }
        symlink = TRUE;       

        // Get our xenstore path
        szFpath = xenbus_find_frontend(pdo);
        if (szFpath == NULL) {
            status = STATUS_NO_SUCH_DEVICE;
            TraceError(("failed to locate XenStore front end path\n"));
            break;
        }

        // Setup the extension
        pde->magic = XENV4V_MAGIC;
        pde->pdo = pdo;
        pde->fdo = fdo;
        IoInitializeRemoveLock(&pde->removeLock, 'v4vx', 0, 0);
        pde->frontendPath = szFpath;
        szFpath = NULL;
        pde->state = XENV4V_DEV_STOPPED; // wait for start
        pde->lastPoState = PowerSystemWorking;
        pde->virqPort = null_EVTCHN_PORT();
        KeInitializeDpc(&pde->virqDpc, V4vVirqNotifyDpc, fdo);
        KeInitializeSpinLock(&pde->virqLock);
        KeInitializeSpinLock(&pde->dpcLock);
        KeInitializeTimerEx(&pde->timer, NotificationTimer);
        KeInitializeDpc(&pde->timerDpc,
                        V4vConnectTimerDpc,
                        fdo);
        KeInitializeSpinLock(&pde->timerLock);
        pde->timerCounter = 0;
        InitializeListHead(&pde->contextList);
        KeInitializeSpinLock(&pde->contextLock);
        pde->contextCount = 0;
        InitializeListHead(&pde->ringList);
        KeInitializeSpinLock(&pde->ringLock);
        InitializeListHead(&pde->pendingIrpQueue);
        pde->pendingIrpCount = 0;
        KeInitializeSpinLock(&pde->queueLock);
        IoCsqInitializeEx(&pde->csqObject,
                          V4vCsqInsertIrpEx,
                          V4vCsqRemoveIrp,
                          V4vCsqPeekNextIrp,
                          V4vCsqAcquireLock,
                          V4vCsqReleaseLock,
                          V4vCsqCompleteCanceledIrp);
        InitializeListHead(&pde->destList);
        pde->destCount = 0;
        ExInitializeNPagedLookasideList(&pde->destLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        sizeof(XENV4V_DESTINATION),
                                        XENV4V_TAG,
                                        0);
        KeQueryTickCount(&seed);
        pde->seed = seed.u.LowPart;

        // Now attach us to the stack
        pde->ldo = IoAttachDeviceToDeviceStack(fdo, pdo);
        if (pde->ldo == NULL) {
            TraceError(("failed to attach device to stack - error: 0x%x\n", status));
            status = STATUS_NO_SUCH_DEVICE;
            break;
        }

        // Use direct IO and let the IO manager directly map user buffers; clear the init flag
        fdo->Flags |= DO_DIRECT_IO;
        fdo->Flags &= ~DO_DEVICE_INITIALIZING;        

        // Made it here, go to connected state to be consistent
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CONNECTED);
    } while (FALSE);

    if (!NT_SUCCESS(status)) {
        if (fdo != NULL) {         
            if ((pde != NULL)&&(pde->ldo != NULL)) {
                IoDetachDevice(pde->ldo);
            }
            if (szFpath != NULL) {
                XmFreeMemory(szFpath);
            }
            if (symlink) {
                IoDeleteSymbolicLink(&pde->symbolicLink);
            }
            IoDeleteDevice(fdo);
        }
    }

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}