Esempio n. 1
0
File: wmi.c Progetto: kcrazy/winekit
NTSTATUS
PciDrvQueryWmiRegInfo(
    PDEVICE_OBJECT DeviceObject,
    ULONG *RegFlags,
    PUNICODE_STRING InstanceName,
    PUNICODE_STRING *RegistryPath,
    PUNICODE_STRING MofResourceName,
    PDEVICE_OBJECT *Pdo
    )
/*++

Routine Description:

    This routine is a callback into the driver to retrieve the list of
    guids or data blocks that the driver wants to register with WMI. This
    routine may not pend or block. Driver should NOT call
    WmiCompleteRequest.

Arguments:

    DeviceObject is the device whose data block is being queried

    *RegFlags returns with a set of flags that describe the guids being
        registered for this device. If the device wants enable and disable
        collection callbacks before receiving queries for the registered
        guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
        returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
        the instance name is determined from the PDO associated with the
        device object. Note that the PDO must have an associated devnode. If
        WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
        name for the device.

    InstanceName returns with the instance name for the guids if
        WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
        caller will call ExFreePool with the buffer returned.

    *RegistryPath returns with the registry path of the driver

    *MofResourceName returns with the name of the MOF resource attached to
        the binary file. If the driver does not have a mof resource attached
        then this can be returned as NULL.

    *Pdo returns with the device object for the PDO associated with this
        device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
        *RegFlags.

Return Value:

    status

--*/
{
    PFDO_DATA fdoData;

    PAGED_CODE();

    DebugPrint(TRACE, DBG_WMI, "Entered PciDrvQueryWmiRegInfo\n");

    fdoData = DeviceObject->DeviceExtension;

    *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
    *RegistryPath = &Globals.RegistryPath;
    *Pdo = fdoData->UnderlyingPDO;
    RtlInitUnicodeString(MofResourceName, MOFRESOURCENAME);

    return STATUS_SUCCESS;
}
Esempio n. 2
0
NTSTATUS
NTAPI
PspCreateThread(OUT PHANDLE ThreadHandle,
                IN ACCESS_MASK DesiredAccess,
                IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
                IN HANDLE ProcessHandle,
                IN PEPROCESS TargetProcess,
                OUT PCLIENT_ID ClientId,
                IN PCONTEXT ThreadContext,
                IN PINITIAL_TEB InitialTeb,
                IN BOOLEAN CreateSuspended,
                IN PKSTART_ROUTINE StartRoutine OPTIONAL,
                IN PVOID StartContext OPTIONAL)
{
    HANDLE hThread;
    PEPROCESS Process;
    PETHREAD Thread;
    PTEB TebBase = NULL;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status, AccessStatus;
    HANDLE_TABLE_ENTRY CidEntry;
    ACCESS_STATE LocalAccessState;
    PACCESS_STATE AccessState = &LocalAccessState;
    AUX_ACCESS_DATA AuxData;
    BOOLEAN Result, SdAllocated;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    SECURITY_SUBJECT_CONTEXT SubjectContext;
    PAGED_CODE();
    PSTRACE(PS_THREAD_DEBUG,
            "ThreadContext: %p TargetProcess: %p ProcessHandle: %p\n",
            ThreadContext, TargetProcess, ProcessHandle);

    /* If we were called from PsCreateSystemThread, then we're kernel mode */
    if (StartRoutine) PreviousMode = KernelMode;

    /* Reference the Process by handle or pointer, depending on what we got */
    if (ProcessHandle)
    {
        /* Normal thread or System Thread */
        Status = ObReferenceObjectByHandle(ProcessHandle,
                                           PROCESS_CREATE_THREAD,
                                           PsProcessType,
                                           PreviousMode,
                                           (PVOID*)&Process,
                                           NULL);
        PSREFTRACE(Process);
    }
    else
    {
        /* System thread inside System Process, or Normal Thread with a bug */
        if (StartRoutine)
        {
            /* Reference the Process by Pointer */
            ObReferenceObject(TargetProcess);
            Process = TargetProcess;
            Status = STATUS_SUCCESS;
        }
        else
        {
            /* Fake ObReference returning this */
            Status = STATUS_INVALID_HANDLE;
        }
    }

    /* Check for success */
    if (!NT_SUCCESS(Status)) return Status;

    /* Also make sure that User-Mode isn't trying to create a system thread */
    if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess))
    {
        /* Fail */
        ObDereferenceObject(Process);
        return STATUS_INVALID_HANDLE;
    }

    /* Create Thread Object */
    Status = ObCreateObject(PreviousMode,
                            PsThreadType,
                            ObjectAttributes,
                            PreviousMode,
                            NULL,
                            sizeof(ETHREAD),
                            0,
                            0,
                            (PVOID*)&Thread);
    if (!NT_SUCCESS(Status))
    {
        /* We failed; dereference the process and exit */
        ObDereferenceObject(Process);
        return Status;
    }

    /* Zero the Object entirely */
    RtlZeroMemory(Thread, sizeof(ETHREAD));

    /* Initialize rundown protection */
    ExInitializeRundownProtection(&Thread->RundownProtect);

    /* Initialize exit code */
    Thread->ExitStatus = STATUS_PENDING;

    /* Set the Process CID */
    Thread->ThreadsProcess = Process;
    Thread->Cid.UniqueProcess = Process->UniqueProcessId;

    /* Create Cid Handle */
    CidEntry.Object = Thread;
    CidEntry.GrantedAccess = 0;
    Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry);
    if (!Thread->Cid.UniqueThread)
    {
        /* We couldn't create the CID, dereference the thread and fail */
        ObDereferenceObject(Thread);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Save the read cluster size */
    Thread->ReadClusterSize = MmReadClusterSize;

    /* Initialize the LPC Reply Semaphore */
    KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1);

    /* Initialize the list heads and locks */
    InitializeListHead(&Thread->LpcReplyChain);
    InitializeListHead(&Thread->IrpList);
    InitializeListHead(&Thread->PostBlockList);
    InitializeListHead(&Thread->ActiveTimerListHead);
    KeInitializeSpinLock(&Thread->ActiveTimerListLock);

    /* Acquire rundown protection */
    if (!ExAcquireRundownProtection (&Process->RundownProtect))
    {
        /* Fail */
        ObDereferenceObject(Thread);
        return STATUS_PROCESS_IS_TERMINATING;
    }

    /* Now let the kernel initialize the context */
    if (ThreadContext)
    {
        /* User-mode Thread, create Teb */
        Status = MmCreateTeb(Process, &Thread->Cid, InitialTeb, &TebBase);
        if (!NT_SUCCESS(Status))
        {
            /* Failed to create the TEB. Release rundown and dereference */
            ExReleaseRundownProtection(&Process->RundownProtect);
            ObDereferenceObject(Thread);
            return Status;
        }

        /* Set the Start Addresses */
        Thread->StartAddress = (PVOID)KeGetContextPc(ThreadContext);
        Thread->Win32StartAddress = (PVOID)KeGetContextReturnRegister(ThreadContext);

        /* Let the kernel intialize the Thread */
        Status = KeInitThread(&Thread->Tcb,
                              NULL,
                              PspUserThreadStartup,
                              NULL,
                              Thread->StartAddress,
                              ThreadContext,
                              TebBase,
                              &Process->Pcb);
    }
    else
    {
        /* System Thread */
        Thread->StartAddress = StartRoutine;
        PspSetCrossThreadFlag(Thread, CT_SYSTEM_THREAD_BIT);

        /* Let the kernel intialize the Thread */
        Status = KeInitThread(&Thread->Tcb,
                              NULL,
                              PspSystemThreadStartup,
                              StartRoutine,
                              StartContext,
                              NULL,
                              NULL,
                              &Process->Pcb);
    }

    /* Check if we failed */
    if (!NT_SUCCESS(Status))
    {
        /* Delete the TEB if we had done */
        if (TebBase) MmDeleteTeb(Process, TebBase);

        /* Release rundown and dereference */
        ExReleaseRundownProtection(&Process->RundownProtect);
        ObDereferenceObject(Thread);
        return Status;
    }

    /* Lock the process */
    KeEnterCriticalRegion();
    ExAcquirePushLockExclusive(&Process->ProcessLock);

    /* Make sure the proces didn't just die on us */
    if (Process->ProcessDelete) goto Quickie;

    /* Check if the thread was ours, terminated and it was user mode */
    if ((Thread->Terminated) &&
        (ThreadContext) &&
        (Thread->ThreadsProcess == Process))
    {
        /* Cleanup, we don't want to start it up and context switch */
        goto Quickie;
    }

    /*
     * Insert the Thread into the Process's Thread List
     * Note, this is the ETHREAD Thread List. It is removed in
     * ps/kill.c!PspExitThread.
     */
    InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
    Process->ActiveThreads++;

    /* Start the thread */
    KeStartThread(&Thread->Tcb);

    /* Release the process lock */
    ExReleasePushLockExclusive(&Process->ProcessLock);
    KeLeaveCriticalRegion();

    /* Release rundown */
    ExReleaseRundownProtection(&Process->RundownProtect);

    /* Notify WMI */
    //WmiTraceProcess(Process, TRUE);
    //WmiTraceThread(Thread, InitialTeb, TRUE);

    /* Notify Thread Creation */
    PspRunCreateThreadNotifyRoutines(Thread, TRUE);

    /* Reference ourselves as a keep-alive */
    ObReferenceObjectEx(Thread, 2);

    /* Suspend the Thread if we have to */
    if (CreateSuspended) KeSuspendThread(&Thread->Tcb);

    /* Check if we were already terminated */
    if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);

    /* Create an access state */
    Status = SeCreateAccessStateEx(NULL,
                                   ThreadContext ?
                                   PsGetCurrentProcess() : Process,
                                   &LocalAccessState,
                                   &AuxData,
                                   DesiredAccess,
                                   &PsThreadType->TypeInfo.GenericMapping);
    if (!NT_SUCCESS(Status))
    {
        /* Access state failed, thread is dead */
        PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);

        /* If we were suspended, wake it up */
        if (CreateSuspended) KeResumeThread(&Thread->Tcb);

        /* Dispatch thread */
        KeReadyThread(&Thread->Tcb);

        /* Dereference completely to kill it */
        ObDereferenceObjectEx(Thread, 2);
        return Status;
    }

    /* Insert the Thread into the Object Manager */
    Status = ObInsertObject(Thread,
                            AccessState,
                            DesiredAccess,
                            0,
                            NULL,
                            &hThread);

    /* Delete the access state if we had one */
    if (AccessState) SeDeleteAccessState(AccessState);

    /* Check for success */
    if (NT_SUCCESS(Status))
    {
        /* Wrap in SEH to protect against bad user-mode pointers */
        _SEH2_TRY
        {
            /* Return Cid and Handle */
            if (ClientId) *ClientId = Thread->Cid;
            *ThreadHandle = hThread;
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Thread insertion failed, thread is dead */
            PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);

            /* If we were suspended, wake it up */
            if (CreateSuspended) KeResumeThread(&Thread->Tcb);

            /* Dispatch thread */
            KeReadyThread(&Thread->Tcb);

            /* Dereference it, leaving only the keep-alive */
            ObDereferenceObject(Thread);

            /* Close its handle, killing it */
            ObCloseHandle(ThreadHandle, PreviousMode);

            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
    else
    {
Esempio n. 3
0
NTSTATUS
NTAPI
NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp)
{
    PIO_STACK_LOCATION IoStackLocation;
    NODE_TYPE_CODE NodeTypeCode;
    PNP_CCB Ccb;
    ULONG Length;
    PNP_CLIENT_PROCESS InputBuffer, ClientSession, OldClientSession;
    PAGED_CODE();

    /* Get the current stack location */
    IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

    /* Only kernel calls are allowed! */
    if (IoStackLocation->MinorFunction != IRP_MN_KERNEL_CALL)
    {
        return STATUS_ACCESS_DENIED;
    }

    /* Decode the file object and check the node type */
    NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0);
    if (NodeTypeCode != NPFS_NTC_CCB)
    {
        return STATUS_PIPE_DISCONNECTED;
    }

    /* Get the length of the query buffer and check if it's valid */
    Length = IoStackLocation->Parameters.QueryFile.Length;
    if (Length != sizeof(NP_CLIENT_PROCESS))
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Get the buffer and check if the data Length is valid */
    InputBuffer = Irp->AssociatedIrp.SystemBuffer;
    if (InputBuffer->DataLength > 30)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Allocate a new structure */
    ClientSession = ExAllocatePoolWithQuotaTag(PagedPool,
                                               sizeof(NP_CLIENT_PROCESS),
                                               'iFpN');

    /* Copy the full input buffer */
    RtlCopyMemory(ClientSession, InputBuffer, sizeof(NP_CLIENT_PROCESS));

    /* Lock the Ccb */
    ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);

    /* Get the old ClientSession and set the new */
    OldClientSession = Ccb->ClientSession;
    Ccb->ClientSession = ClientSession;

    /* Copy the process to the CCB */
    Ccb->Process = ClientSession->Process;

    /* Unlock the Ccb */
    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);

    /* Check if there was already a ClientSession */
    if (OldClientSession != NULL)
    {
        /* Free it */
        ExFreePoolWithTag(OldClientSession, 'iFpN');
    }

    return STATUS_SUCCESS;
}
Esempio n. 4
0
NTSTATUS
CdQueryDirectory (
    __inout PIRP_CONTEXT IrpContext,
    __inout PIRP Irp,
    __in PIO_STACK_LOCATION IrpSp,
    __in PFCB Fcb,
    __in PCCB Ccb
    )

/*++

Routine Description:

    This routine performs the query directory operation.  It is responsible
    for either completing of enqueuing the input Irp.  We store the state of the
    search in the Ccb.

Arguments:

    Irp - Supplies the Irp to process

    IrpSp - Stack location for this Irp.

    Fcb - Fcb for this directory.

    Ccb - Ccb for this directory open.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG Information = 0;

    ULONG LastEntry = 0;
    ULONG NextEntry = 0;

    ULONG FileNameBytes;
    ULONG SeparatorBytes;
    ULONG VersionStringBytes;

    FILE_ENUM_CONTEXT FileContext;
    PDIRENT ThisDirent;
    BOOLEAN InitialQuery;
    BOOLEAN ReturnNextEntry;
    BOOLEAN ReturnSingleEntry;
    BOOLEAN Found;
    BOOLEAN DoCcbUpdate = FALSE;

    PCHAR UserBuffer;
    ULONG BytesRemainingInBuffer;

    ULONG BaseLength;

    PFILE_BOTH_DIR_INFORMATION DirInfo;
    PFILE_NAMES_INFORMATION NamesInfo;
    PFILE_ID_FULL_DIR_INFORMATION IdFullDirInfo;
    PFILE_ID_BOTH_DIR_INFORMATION IdBothDirInfo;

    PAGED_CODE();

    //
    //  Check if we support this search mode.  Also remember the size of the base part of
    //  each of these structures.
    //

    switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {

    case FileDirectoryInformation:

        BaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
                                   FileName[0] );
        break;

    case FileFullDirectoryInformation:

        BaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
                                   FileName[0] );
        break;

    case FileIdFullDirectoryInformation:

        BaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
                                   FileName[0] );
        break;

    case FileNamesInformation:

        BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
                                   FileName[0] );
        break;

    case FileBothDirectoryInformation:

        BaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
                                   FileName[0] );
        break;

    case FileIdBothDirectoryInformation:

        BaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
                                   FileName[0] );
        break;

    default:

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_INFO_CLASS );
        return STATUS_INVALID_INFO_CLASS;
    }

    //
    //  Get the user buffer.
    //

    CdMapUserBuffer( IrpContext, &UserBuffer);

    //
    //  Initialize our search context.
    //

    CdInitializeFileContext( IrpContext, &FileContext );

    //
    //  Acquire the directory.
    //

    CdAcquireFileShared( IrpContext, Fcb );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Verify the Fcb is still good.
        //

        CdVerifyFcbOperation( IrpContext, Fcb );

        //
        //  Start by getting the initial state for the enumeration.  This will set up the Ccb with
        //  the initial search parameters and let us know the starting offset in the directory
        //  to search.
        //

        CdInitializeEnumeration( IrpContext,
                                 IrpSp,
                                 Fcb,
                                 Ccb,
                                 &FileContext,
                                 &ReturnNextEntry,
                                 &ReturnSingleEntry,
                                 &InitialQuery );

        //
        //  The current dirent is stored in the InitialDirent field.  We capture
        //  this here so that we have a valid restart point even if we don't
        //  find a single entry.
        //

        ThisDirent = &FileContext.InitialDirent->Dirent;

        //
        //  At this point we are about to enter our query loop.  We have
        //  determined the index into the directory file to begin the
        //  search.  LastEntry and NextEntry are used to index into the user
        //  buffer.  LastEntry is the last entry we've added, NextEntry is
        //  current one we're working on.  If NextEntry is non-zero, then
        //  at least one entry was added.
        //

        while (TRUE) {

            //
            //  If the user had requested only a single match and we have
            //  returned that, then we stop at this point.  We update the Ccb with
            //  the status based on the last entry returned.
            //

            if ((NextEntry != 0) && ReturnSingleEntry) {

                DoCcbUpdate = TRUE;
                try_leave( Status );
            }

            //
            //  We try to locate the next matching dirent.  Our search if based on a starting
            //  dirent offset, whether we should return the current or next entry, whether
            //  we should be doing a short name search and finally whether we should be
            //  checking for a version match.
            //

            Found = CdEnumerateIndex( IrpContext, Ccb, &FileContext, ReturnNextEntry );

            //
            //  Initialize the value for the next search.
            //

            ReturnNextEntry = TRUE;

            //
            //  If we didn't receive a dirent, then we are at the end of the
            //  directory.  If we have returned any files, we exit with
            //  success, otherwise we return STATUS_NO_MORE_FILES.
            //

            if (!Found) {

                if (NextEntry == 0) {

                    Status = STATUS_NO_MORE_FILES;

                    if (InitialQuery) {

                        Status = STATUS_NO_SUCH_FILE;
                    }
                }

                DoCcbUpdate = TRUE;
                try_leave( Status );
            }

            //
            //  Remember the dirent for the file we just found.
            //

            ThisDirent = &FileContext.InitialDirent->Dirent;

            //
            //  Here are the rules concerning filling up the buffer:
            //
            //  1.  The Io system garentees that there will always be
            //      enough room for at least one base record.
            //
            //  2.  If the full first record (including file name) cannot
            //      fit, as much of the name as possible is copied and
            //      STATUS_BUFFER_OVERFLOW is returned.
            //
            //  3.  If a subsequent record cannot completely fit into the
            //      buffer, none of it (as in 0 bytes) is copied, and
            //      STATUS_SUCCESS is returned.  A subsequent query will
            //      pick up with this record.
            //

            //
            //  Let's compute the number of bytes we need to transfer the current entry.
            //

            SeparatorBytes =
            VersionStringBytes = 0;

            //
            //  We can look directly at the dirent that we found.
            //

            FileNameBytes = ThisDirent->CdFileName.FileName.Length;

            //
            //  Compute the number of bytes for the version string if
            //  we will return this. Allow directories with illegal ";".
            //

            if (((Ccb->SearchExpression.VersionString.Length != 0) ||
                 (FlagOn(ThisDirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY))) &&
                (ThisDirent->CdFileName.VersionString.Length != 0)) {

                SeparatorBytes = 2;

                VersionStringBytes = ThisDirent->CdFileName.VersionString.Length;
            }

            //
            //  If the slot for the next entry would be beyond the length of the
            //  user's buffer just exit (we know we've returned at least one entry
            //  already). This will happen when we align the pointer past the end.
            //

            if (NextEntry > IrpSp->Parameters.QueryDirectory.Length) {

                ReturnNextEntry = FALSE;
                DoCcbUpdate = TRUE;
                try_leave( Status = STATUS_SUCCESS );
            }

            //
            //  Compute the number of bytes remaining in the buffer.  Round this
            //  down to a WCHAR boundary so we can copy full characters.
            //

            BytesRemainingInBuffer = IrpSp->Parameters.QueryDirectory.Length - NextEntry;
            ClearFlag( BytesRemainingInBuffer, 1 );

            //
            //  If this won't fit and we have returned a previous entry then just
            //  return STATUS_SUCCESS.
            //

            if ((BaseLength + FileNameBytes + SeparatorBytes + VersionStringBytes) > BytesRemainingInBuffer) {

                //
                //  If we already found an entry then just exit.
                //

                if (NextEntry != 0) {

                    ReturnNextEntry = FALSE;
                    DoCcbUpdate = TRUE;
                    try_leave( Status = STATUS_SUCCESS );
                }

                //
                //  Don't even try to return the version string if it doesn't all fit.
                //  Reduce the FileNameBytes to just fit in the buffer.
                //

                if ((BaseLength + FileNameBytes) > BytesRemainingInBuffer) {

                    FileNameBytes = BytesRemainingInBuffer - BaseLength;
                }

                //
                //  Don't return any version string bytes.
                //

                VersionStringBytes =
                SeparatorBytes = 0;

                //
                //  Use a status code of STATUS_BUFFER_OVERFLOW.  Also set
                //  ReturnSingleEntry so that we will exit the loop at the top.
                //

                Status = STATUS_BUFFER_OVERFLOW;
                ReturnSingleEntry = TRUE;
            }

            //
            //  Protect access to the user buffer with an exception handler.
            //  Since (at our request) IO doesn't buffer these requests, we have
            //  to guard against a user messing with the page protection and other
            //  such trickery.
            //
            
            try {
            
                //
                //  Zero and initialize the base part of the current entry.
                //

                RtlZeroMemory( Add2Ptr( UserBuffer, NextEntry, PVOID ),
                               BaseLength );
    
                //
                //  Now we have an entry to return to our caller.
                //  We'll case on the type of information requested and fill up
                //  the user buffer if everything fits.
                //

                switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
    
                case FileBothDirectoryInformation:
                case FileFullDirectoryInformation:
                case FileIdBothDirectoryInformation:
                case FileIdFullDirectoryInformation:
                case FileDirectoryInformation:
    
                    DirInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_BOTH_DIR_INFORMATION );
    
                    //
                    //  Use the create time for all the time stamps.
                    //
    
                    CdConvertCdTimeToNtTime( IrpContext,
                                             FileContext.InitialDirent->Dirent.CdTime,
                                             &DirInfo->CreationTime );
    
                    DirInfo->LastWriteTime = DirInfo->ChangeTime = DirInfo->CreationTime;
    
                    //
                    //  Set the attributes and sizes separately for directories and
                    //  files.
                    //
    
                    if (FlagOn( ThisDirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY )) {
    
                        DirInfo->EndOfFile.QuadPart = DirInfo->AllocationSize.QuadPart = 0;
    
                        SetFlag( DirInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
                        
                    } else {
    
                        DirInfo->EndOfFile.QuadPart = FileContext.FileSize;
                        DirInfo->AllocationSize.QuadPart = LlSectorAlign( FileContext.FileSize );
                        
                        SetFlag( DirInfo->FileAttributes, FILE_ATTRIBUTE_READONLY);
                    }

                    if (FlagOn( ThisDirent->DirentFlags,
                                CD_ATTRIBUTE_HIDDEN )) {
    
                        SetFlag( DirInfo->FileAttributes, FILE_ATTRIBUTE_HIDDEN );
                    }
    
                    DirInfo->FileIndex = ThisDirent->DirentOffset;
    
                    DirInfo->FileNameLength = FileNameBytes + SeparatorBytes + VersionStringBytes;
    
                    break;
    
                case FileNamesInformation:
    
                    NamesInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_NAMES_INFORMATION );
    
                    NamesInfo->FileIndex = ThisDirent->DirentOffset;
    
                    NamesInfo->FileNameLength = FileNameBytes + SeparatorBytes + VersionStringBytes;
    
                    break;
                }

                //
                //  Fill in the FileId
                //

                switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {

                case FileIdBothDirectoryInformation:

                    IdBothDirInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_ID_BOTH_DIR_INFORMATION );
                    CdSetFidFromParentAndDirent( IdBothDirInfo->FileId, Fcb, ThisDirent );
                    break;

                case FileIdFullDirectoryInformation:

                    IdFullDirInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_ID_FULL_DIR_INFORMATION );
                    CdSetFidFromParentAndDirent( IdFullDirInfo->FileId, Fcb, ThisDirent );
                    break;

                default:
                    break;
                }
    
                //
                //  Now copy as much of the name as possible.  We also may have a version
                //  string to copy.
                //
    
                if (FileNameBytes != 0) {
    
                    //
                    //  This is a Unicode name, we can copy the bytes directly.
                    //
    
                    RtlCopyMemory( Add2Ptr( UserBuffer, NextEntry + BaseLength, PVOID ),
                                   ThisDirent->CdFileName.FileName.Buffer,
                                   FileNameBytes );
    
                    if (SeparatorBytes != 0) {
    
                        *(Add2Ptr( UserBuffer,
                                   NextEntry + BaseLength + FileNameBytes,
                                   PWCHAR )) = L';';
    
                        if (VersionStringBytes != 0) {
    
                            RtlCopyMemory( Add2Ptr( UserBuffer,
                                                    NextEntry + BaseLength + FileNameBytes + sizeof( WCHAR ),
                                                    PVOID ),
                                           ThisDirent->CdFileName.VersionString.Buffer,
                                           VersionStringBytes );
                        }
                    }
                }

                //
                //  Fill in the short name if we got STATUS_SUCCESS.  The short name
                //  may already be in the file context.  Otherwise we will check
                //  whether the long name is 8.3.  Special case the self and parent
                //  directory names.
                //

                if ((Status == STATUS_SUCCESS) &&
                    (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
                     IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation) &&
                    (Ccb->SearchExpression.VersionString.Length == 0) &&
                    !FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY )) {
    
                    //
                    //  If we already have the short name then copy into the user's buffer.
                    //
    
                    if (FileContext.ShortName.FileName.Length != 0) {
    
                        RtlCopyMemory( DirInfo->ShortName,
                                       FileContext.ShortName.FileName.Buffer,
                                       FileContext.ShortName.FileName.Length );
    
                        DirInfo->ShortNameLength = (CCHAR) FileContext.ShortName.FileName.Length;
    
                    //
                    //  If the short name length is currently zero then check if
                    //  the long name is not 8.3.  We can copy the short name in
                    //  unicode form directly into the caller's buffer.
                    //
    
                    } else {
    
                        if (!CdIs8dot3Name( IrpContext,
                                            ThisDirent->CdFileName.FileName )) {
    
                            CdGenerate8dot3Name( IrpContext,
                                                 &ThisDirent->CdCaseFileName.FileName,
                                                 ThisDirent->DirentOffset,
                                                 DirInfo->ShortName,
                                                 &FileContext.ShortName.FileName.Length );
    
                            DirInfo->ShortNameLength = (CCHAR) FileContext.ShortName.FileName.Length;
                        }
                    }
    
                }

                //
                //  Sum the total number of bytes for the information field.
                //

                FileNameBytes += SeparatorBytes + VersionStringBytes;

                //
                //  Update the information with the number of bytes stored in the
                //  buffer.  We quad-align the existing buffer to add any necessary
                //  pad bytes.
                //

                Information = NextEntry + BaseLength + FileNameBytes;

                //
                //  Go back to the previous entry and fill in the update to this entry.
                //

                *(Add2Ptr( UserBuffer, LastEntry, PULONG )) = NextEntry - LastEntry;

                //
                //  Set up our variables for the next dirent.
                //

                InitialQuery = FALSE;

                LastEntry = NextEntry;
                NextEntry = QuadAlign( Information );
            
            } except (EXCEPTION_EXECUTE_HANDLER) {

                  //
                  //  We had a problem filling in the user's buffer, so stop and
                  //  fail this request.  This is the only reason any exception
                  //  would have occured at this level.
                  //
                  
                  Information = 0;
                  try_leave( Status = GetExceptionCode());
            }
        }
        
        DoCcbUpdate = TRUE;

    } finally {

        //
        //  Cleanup our search context - *before* aquiring the FCB mutex exclusive,
        //  else can block on threads in cdcreateinternalstream/purge which 
        //  hold the FCB but are waiting for all maps in this stream to be released.
        //

        CdCleanupFileContext( IrpContext, &FileContext );

        //
        //  Now we can safely aqure the FCB mutex if we need to.
        //

        if (DoCcbUpdate && !NT_ERROR( Status )) {
        
            //
            //  Update the Ccb to show the current state of the enumeration.
            //

            CdLockFcb( IrpContext, Fcb );
            
            Ccb->CurrentDirentOffset = ThisDirent->DirentOffset;

            ClearFlag( Ccb->Flags, CCB_FLAG_ENUM_RETURN_NEXT );

            if (ReturnNextEntry) {

                SetFlag( Ccb->Flags, CCB_FLAG_ENUM_RETURN_NEXT );
            }

            CdUnlockFcb( IrpContext, Fcb );
        }

        //
        //  Release the Fcb.
        //

        CdReleaseFile( IrpContext, Fcb );
    }

    //
    //  Complete the request here.
    //

    Irp->IoStatus.Information = Information;

    CdCompleteRequest( IrpContext, Irp, Status );
    return Status;
}
Esempio n. 5
0
NTSTATUS
CdNotifyChangeDirectory (
    __inout PIRP_CONTEXT IrpContext,
    __inout PIRP Irp,
    __in PIO_STACK_LOCATION IrpSp,
    __in PCCB Ccb
    )

/*++

Routine Description:

    This routine performs the notify change directory operation.  It is
    responsible for either completing of enqueuing the input Irp.  Although there
    will never be a notify signalled on a CDROM disk we still support this call.

    We have already checked that this is not an OpenById handle.

Arguments:

    Irp - Supplies the Irp to process

    IrpSp - Io stack location for this request.

    Ccb - Handle to the directory being watched.

Return Value:

    NTSTATUS - STATUS_PENDING, any other error will raise.

--*/

{
    PAGED_CODE();

    //
    //  Always set the wait bit in the IrpContext so the initial wait can't fail.
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

    //
    //  Acquire the Vcb shared.
    //

    CdAcquireVcbShared( IrpContext, IrpContext->Vcb, FALSE );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Verify the Vcb.
        //

        CdVerifyVcb( IrpContext, IrpContext->Vcb );

        //
        //  Call the Fsrtl package to process the request.  We cast the
        //  unicode strings to ansi strings as the dir notify package
        //  only deals with memory matching.
        //

        FsRtlNotifyFullChangeDirectory( IrpContext->Vcb->NotifySync,
                                        &IrpContext->Vcb->DirNotifyList,
                                        Ccb,
                                        (PSTRING) &IrpSp->FileObject->FileName,
                                        BooleanFlagOn( IrpSp->Flags, SL_WATCH_TREE ),
                                        FALSE,
                                        IrpSp->Parameters.NotifyDirectory.CompletionFilter,
                                        Irp,
                                        NULL,
                                        NULL );

    } finally {

        //
        //  Release the Vcb.
        //

        CdReleaseVcb( IrpContext, IrpContext->Vcb );
    }

    //
    //  Cleanup the IrpContext.
    //

    CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );

    return STATUS_PENDING;
}
Esempio n. 6
0
// Driver entry routine
NTSTATUS
DriverEntry(
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS 		status = STATUS_SUCCESS;
	SOCKADDR_IN 	LocalAddress = {0,};
	SOCKADDR_IN 	RemoteAddress = {0,};
	
    LONG    		BufferSize = 0;
    CHAR    		GreetMessage[] = "Hello there\r\n";
	
    //PWSK_SOCKET 	Socket = NULL;
    	
    UNREFERENCED_PARAMETER(RegistryPath);

    PAGED_CODE();

	

    DriverObject->DriverUnload = WskudpUnload;

	status = WSKStartup();

    g_UdpSocket = CreateSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, WSK_FLAG_DATAGRAM_SOCKET);
    if (g_UdpSocket == NULL) {
        DbgPrint("DriverEntry(): CreateSocket() returned NULL\n");
		return (status = STATUS_UNSUCCESSFUL);
    }

    LocalAddress.sin_family = AF_INET;
    LocalAddress.sin_addr.s_addr = INADDR_ANY;
    //LocalAddress.sin_port = INADDR_PORT;
	
	// Bind Required
	status = Bind(g_UdpSocket, (PSOCKADDR)&LocalAddress);
	if (!NT_SUCCESS(status)) {
		DbgPrint("Bind() failed with status 0x%08X\n", status);
		CloseSocket(g_UdpSocket);
		return status;
	}
	
	RemoteAddress.sin_family = AF_INET;
    RemoteAddress.sin_addr.s_addr = HTON_LONG(INADDR_LOOPBACK);//HTON_LONG(0xc0a802a2);//HTON_LONG(INADDR_LOOPBACK);
    RemoteAddress.sin_port = HTON_SHORT(LOG_PORT);
	

    if (SendTo(g_UdpSocket, GreetMessage, sizeof(GreetMessage)-1, (PSOCKADDR)&RemoteAddress) == sizeof(GreetMessage)-1) {
	} else {
		
	}

	CloseSocket(g_UdpSocket);
		
    // Initialize software tracing
    WPP_INIT_TRACING(DriverObject, RegistryPath);
    
    DoTraceMessage(TRCINFO, "LOADED");
    
    return status;
}
Esempio n. 7
0
NTSTATUS DokanOplockRequest(__in PIRP *pIrp) {
  NTSTATUS Status = STATUS_SUCCESS;
  ULONG FsControlCode;
  PDokanDCB Dcb;
  PDokanVCB Vcb;
  PDokanFCB Fcb = NULL;
  PDokanCCB Ccb;
  PFILE_OBJECT fileObject;
  PIRP Irp = *pIrp;

  ULONG OplockCount = 0;

  PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);

  BOOLEAN AcquiredVcb = FALSE;

#if (NTDDI_VERSION >= NTDDI_WIN7)
  PREQUEST_OPLOCK_INPUT_BUFFER InputBuffer = NULL;
  ULONG InputBufferLength;
  ULONG OutputBufferLength;
#endif

  PAGED_CODE();

  //
  //  Save some references to make our life a little easier
  //
  FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;

  fileObject = IrpSp->FileObject;
  DokanPrintFileName(fileObject);

  Ccb = fileObject->FsContext2;
  if (Ccb == NULL || Ccb->Identifier.Type != CCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

  Fcb = Ccb->Fcb;
  if (Fcb == NULL || Fcb->Identifier.Type != FCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

  Vcb = Fcb->Vcb;
  if (Vcb == NULL || Vcb->Identifier.Type != VCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }
  Dcb = Vcb->Dcb;

#if (NTDDI_VERSION >= NTDDI_WIN7)

  //
  //  Get the input & output buffer lengths and pointers.
  //
  if (FsControlCode == FSCTL_REQUEST_OPLOCK) {

    InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
    InputBuffer = (PREQUEST_OPLOCK_INPUT_BUFFER)Irp->AssociatedIrp.SystemBuffer;

    OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;

    //
    //  Check for a minimum length on the input and ouput buffers.
    //
    if ((InputBufferLength < sizeof(REQUEST_OPLOCK_INPUT_BUFFER)) ||
        (OutputBufferLength < sizeof(REQUEST_OPLOCK_OUTPUT_BUFFER))) {
      DDbgPrint("    DokanOplockRequest STATUS_BUFFER_TOO_SMALL\n");
      return STATUS_BUFFER_TOO_SMALL;
    }
  }

  //
  //  If the oplock request is on a directory it must be for a Read or
  //  Read-Handle
  //  oplock only.
  //
  if ((DokanFCBFlagsIsSet(Fcb, DOKAN_FILE_DIRECTORY)) &&
      ((FsControlCode != FSCTL_REQUEST_OPLOCK) ||
       !FsRtlOplockIsSharedRequest(Irp))) {

    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

#endif

  //
  //  Use a try finally to free the Fcb/Vcb
  //
  try {

    //
    //  We grab the Fcb exclusively for oplock requests, shared for oplock
    //  break acknowledgement.
    //
    if ((FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1) ||
        (FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK) ||
        (FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) ||
        (FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2)
#if (NTDDI_VERSION >= NTDDI_WIN7)
        || ((FsControlCode == FSCTL_REQUEST_OPLOCK) &&
            FlagOn(InputBuffer->Flags, REQUEST_OPLOCK_INPUT_FLAG_REQUEST))
#endif
            ) {

      AcquiredVcb = ExAcquireResourceSharedLite(&(Fcb->Vcb->Resource), TRUE);

#if (NTDDI_VERSION >= NTDDI_WIN7)
      if (!Dcb->FileLockInUserMode && FsRtlOplockIsSharedRequest(Irp)) {
#else
      if (!Dcb->FileLockInUserMode &&
          FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) {
#endif
        //
        //  Byte-range locks are only valid on files.
        //
        if (!DokanFCBFlagsIsSet(Fcb, DOKAN_FILE_DIRECTORY)) {

//
//  Set OplockCount to nonzero if FsRtl denies access
//  based on current byte-range lock state.
//
#if (NTDDI_VERSION >= NTDDI_WIN8)
          OplockCount = (ULONG)!FsRtlCheckLockForOplockRequest(
              &Fcb->FileLock, &Fcb->AdvancedFCBHeader.AllocationSize);
#elif (NTDDI_VERSION >= NTDDI_WIN7)
          OplockCount =
              (ULONG)FsRtlAreThereCurrentOrInProgressFileLocks(&Fcb->FileLock);
#else
        OplockCount = (ULONG)FsRtlAreThereCurrentFileLocks(&Fcb->FileLock);
#endif
        }
      } else {
        // Shouldn't be something like UncleanCount counter and not FileCount
        // here?
        OplockCount = 0;//Fcb->FileCount;
      }
    } else if ((FsControlCode == FSCTL_OPLOCK_BREAK_ACKNOWLEDGE) ||
               (FsControlCode == FSCTL_OPBATCH_ACK_CLOSE_PENDING) ||
               (FsControlCode == FSCTL_OPLOCK_BREAK_NOTIFY) ||
               (FsControlCode == FSCTL_OPLOCK_BREAK_ACK_NO_2)
#if (NTDDI_VERSION >= NTDDI_WIN7)
               || ((FsControlCode == FSCTL_REQUEST_OPLOCK) &&
                   FlagOn(InputBuffer->Flags, REQUEST_OPLOCK_INPUT_FLAG_ACK))
#endif
                   ) {

#if (NTDDI_VERSION >= NTDDI_WIN7)
    } else if (FsControlCode == FSCTL_REQUEST_OPLOCK) {
      //
      //  The caller didn't provide either REQUEST_OPLOCK_INPUT_FLAG_REQUEST or
      //  REQUEST_OPLOCK_INPUT_FLAG_ACK on the input buffer.
      //
      DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
      Status = STATUS_INVALID_PARAMETER;
      __leave;
    } else {
#else
    } else {
#endif
      DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
      Status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    //
    //  Fail batch, filter, and handle oplock requests if the file is marked
    //  for delete.
    //
    if (((FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) ||
         (FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK)
#if (NTDDI_VERSION >= NTDDI_WIN7)
         ||
         ((FsControlCode == FSCTL_REQUEST_OPLOCK) &&
          FlagOn(InputBuffer->RequestedOplockLevel, OPLOCK_LEVEL_CACHE_HANDLE))
#endif
             ) &&
        DokanFCBFlagsIsSet(Fcb, DOKAN_DELETE_ON_CLOSE)) {

      DDbgPrint("    DokanOplockRequest STATUS_DELETE_PENDING\n");
      Status = STATUS_DELETE_PENDING;
      __leave;
    }

    //
    //  Call the FsRtl routine to grant/acknowledge oplock.
    //
    Status = FsRtlOplockFsctrl(DokanGetFcbOplock(Fcb), Irp, OplockCount);

    //
    //  Once we call FsRtlOplockFsctrl, we no longer own the IRP and we should
    //  not complete it.
    //
    *pIrp = NULL;

  } finally {
Esempio n. 8
0
NTSTATUS
DCamHwInitialize(
    IN PHW_STREAM_REQUEST_BLOCK Srb
    )

/*++

Routine Description:

    This where we perform the necessary initialization tasks.

Arguments:

    Srb - Pointer to stream request block

Return Value:

    Nothing

--*/

{

    PIRB pIrb;
    PIRP pIrp;
    CCHAR StackSize;
    ULONG i;
    ULONG DirectoryLength;
    NTSTATUS status = STATUS_SUCCESS;
    PDCAM_EXTENSION pDevExt;
    PPORT_CONFIGURATION_INFORMATION ConfigInfo; 

         

    PAGED_CODE();

    ConfigInfo = Srb->CommandData.ConfigInfo;
    pIrb = (PIRB) Srb->SRBExtension;
    pDevExt = (PDCAM_EXTENSION) ConfigInfo->HwDeviceExtension;

    //
    // Initialize DeviceExtension
    //
    InitializeDeviceExtension(ConfigInfo); 


    StackSize = pDevExt->BusDeviceObject->StackSize;
    pIrp = IoAllocateIrp(StackSize, FALSE);
    if (!pIrp) {

        ASSERT(FALSE);
        return (STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // find what the host adaptor below us supports...
    //
    pIrb->FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
    pIrb->Flags = 0;
    pIrb->u.GetLocalHostInformation.nLevel = GET_HOST_CAPABILITIES;
    pIrb->u.GetLocalHostInformation.Information = &pDevExt->HostControllerInfomation;
    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
    if (status) {

        ERROR_LOG(("DCamHwInitialize: Error (Status=%x) while trying to get local hsot info.\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }        


    //
    // find what the max buffer size is supported by the host.
    //
    pIrb->FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
    pIrb->Flags = 0;
    pIrb->u.GetLocalHostInformation.nLevel = GET_HOST_DMA_CAPABILITIES;
    pIrb->u.GetLocalHostInformation.Information = &pDevExt->HostDMAInformation;
    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
    if (status) {
        ERROR_LOG(("DCamHwInitialize: Error (Status=%x) while trying to get GET_HOST_DMA_CAPABILITIES.\n", status));
        // May not supported in the ealier version of 1394
        // Set default.
    } else {
        ERROR_LOG(("\'GET_HOST_DMA_CAPABILITIES: HostDmaCapabilities;:%x; MaxDmaBufferSize:(Quad:%x; High:%x;Low:%x)\n",
            pDevExt->HostDMAInformation.HostDmaCapabilities, 
            (DWORD) pDevExt->HostDMAInformation.MaxDmaBufferSize.QuadPart,
            pDevExt->HostDMAInformation.MaxDmaBufferSize.u.HighPart,
            pDevExt->HostDMAInformation.MaxDmaBufferSize.u.LowPart
            ));
    }
    

    //
    // Make a call to determine what the generation # is on the bus,
    // followed by a call to find out about ourself (config rom info)
    //
    //
    // Get the current generation count first
    //

    pIrb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
    pIrb->Flags = 0;

    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);

    if (status) {

        ERROR_LOG(("\'DCamHwInitialize: Error %x while trying to get generation number\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }

    InterlockedExchange((PLONG)&pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount);

    //
    // Now that we have the current generation count, find out how much
    // configuration space we need by setting lengths to zero.
    //

    pIrb->FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
    pIrb->Flags = 0;
    pIrb->u.GetConfigurationInformation.UnitDirectoryBufferSize = 0;
    pIrb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize = 0;
    pIrb->u.GetConfigurationInformation.VendorLeafBufferSize = 0;
    pIrb->u.GetConfigurationInformation.ModelLeafBufferSize = 0;

    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);

    if (status) {

        ERROR_LOG(("\'DCamHwInitialize: Error %x while trying to get configuration info (1)\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }

    //
    // Now go thru and allocate what we need to so we can get our info.
    //

    pDevExt->ConfigRom = ExAllocatePoolWithTag(PagedPool, sizeof(CONFIG_ROM), 'macd');
    if (!pDevExt->ConfigRom) {

        ERROR_LOG(("\'DCamHwInitialize: Couldn't allocate memory for the Config Rom\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto AbortLoading;
    }


    pDevExt->UnitDirectory = ExAllocatePoolWithTag(PagedPool, pIrb->u.GetConfigurationInformation.UnitDirectoryBufferSize, 'macd');
    if (!pDevExt->UnitDirectory) {

        ERROR_LOG(("\'DCamHwInitialize: Couldn't allocate memory for the UnitDirectory\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto AbortLoading;
    }


    if (pIrb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize) {

        pDevExt->UnitDependentDirectory = ExAllocatePoolWithTag(PagedPool, pIrb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize, 'macd');
        if (!pDevExt->UnitDependentDirectory) {

            ERROR_LOG(("\'DCamHwInitialize: Couldn't allocate memory for the UnitDependentDirectory\n"));
            status = STATUS_INSUFFICIENT_RESOURCES;
            goto AbortLoading;
        }
    }


    if (pIrb->u.GetConfigurationInformation.VendorLeafBufferSize) {

        // From NonPaged pool since vendor name can be used in a func with DISPATCH level
        pDevExt->VendorLeaf = ExAllocatePoolWithTag(NonPagedPool, pIrb->u.GetConfigurationInformation.VendorLeafBufferSize, 'macd');
        if (!pDevExt->VendorLeaf) {

            ERROR_LOG(("\'DCamHwInitialize: Couldn't allocate memory for the VendorLeaf\n"));
            status = STATUS_INSUFFICIENT_RESOURCES;
            goto AbortLoading;
        }
    } 

    if (pIrb->u.GetConfigurationInformation.ModelLeafBufferSize) {

        pDevExt->ModelLeaf = ExAllocatePoolWithTag(NonPagedPool, pIrb->u.GetConfigurationInformation.ModelLeafBufferSize, 'macd');
        if (!pDevExt->ModelLeaf) {

            ERROR_LOG(("\'DCamHwInitialize: Couldn't allocate memory for the ModelLeaf\n"));
            status = STATUS_INSUFFICIENT_RESOURCES;
            goto AbortLoading;
        }
    }

    //
    // Now resubmit the pIrb with the appropriate pointers inside
    //

    pIrb->FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
    pIrb->Flags = 0;
    pIrb->u.GetConfigurationInformation.ConfigRom = pDevExt->ConfigRom;
    pIrb->u.GetConfigurationInformation.UnitDirectory = pDevExt->UnitDirectory;
    pIrb->u.GetConfigurationInformation.UnitDependentDirectory = pDevExt->UnitDependentDirectory;
    pIrb->u.GetConfigurationInformation.VendorLeaf = pDevExt->VendorLeaf;
    pIrb->u.GetConfigurationInformation.ModelLeaf = pDevExt->ModelLeaf;

    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);

    if (status) {

        ERROR_LOG(("DCamHwInitialize: Error %x while trying to get configuration info (2)\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }

    //
    // We might be able to return strings about a Device
    //

    if (pDevExt->VendorLeaf) {

        //
        // bswap to get the actual leaf length (in quadlets)
        //

        *((PULONG) pDevExt->VendorLeaf) = bswap(*((PULONG) pDevExt->VendorLeaf));

        DbgMsg1(("\'DCamHwInitialize: BufSize %d (byte); VendorLeaf %p; Len %d (Quad)\n", 
            pIrb->u.GetConfigurationInformation.VendorLeafBufferSize, 
            pDevExt->VendorLeaf, 
            pDevExt->VendorLeaf->TL_Length));

        if(pDevExt->VendorLeaf->TL_Length >= 1) {
            pDevExt->pchVendorName = (PCHAR)&pDevExt->VendorLeaf->TL_Data;

        } else {
            pDevExt->pchVendorName = szUnknownVendorName;
        }

        DbgMsg1(("\'DCamHwInitialize: VendorName %s, strLen %d\n", pDevExt->pchVendorName, strlen(pDevExt->pchVendorName)));
    }

    //
    // Now we chew thru the Unit Dependent Directory looking for our command
    // base register key.
    //

    DirectoryLength = pIrb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize >> 2;
    for (i=1; i < DirectoryLength; i++) {

        if ((*(((PULONG) pDevExt->UnitDependentDirectory)+i) & CONFIG_ROM_KEY_MASK) == COMMAND_BASE_KEY_SIGNATURE) {

            //
            // Found the command base offset.  This is a quadlet offset from
            // the initial register space.  (Should come out to 0xf0f00000)
            //

            pDevExt->BaseRegister = bswap(*(((PULONG) pDevExt->UnitDependentDirectory)+i) & CONFIG_ROM_OFFSET_MASK);
            pDevExt->BaseRegister <<= 2;
            pDevExt->BaseRegister |= INITIAL_REGISTER_SPACE_LO;
            break;

        }
        
    }

    ASSERT( pDevExt->BaseRegister );

    if(!DCamDeviceInUse(pIrb, pDevExt)) {
        //
        // Now let's actually do a write request to initialize the device
        //
        pDevExt->RegisterWorkArea.AsULONG = 0;
        pDevExt->RegisterWorkArea.Initialize.Initialize = TRUE;
        pDevExt->RegisterWorkArea.AsULONG = bswap(pDevExt->RegisterWorkArea.AsULONG);

        status = DCamWriteRegister ((PIRB) Srb->SRBExtension, pDevExt, 
                  FIELDOFFSET(CAMERA_REGISTER_MAP, Initialize), pDevExt->RegisterWorkArea.AsULONG);

        if(status) {

            ERROR_LOG(("DCamHwInitialize: Error %x while trying to write to Initialize register\n", status));
            status = STATUS_UNSUCCESSFUL;
            goto AbortLoading;   
        }
    }

    //
    // Now we initialize the size of stream descriptor information.
    // We have one stream descriptor, and we attempt to dword align the
    // structure.
    //

    ConfigInfo->StreamDescriptorSize = 
        1 * (sizeof (HW_STREAM_INFORMATION)) +      // 1 stream descriptor
        sizeof(HW_STREAM_HEADER);                   // and 1 stream header


    //
    // Construct the device property table from querying the device and registry
    //
    if(!NT_SUCCESS(status = DCamPrepareDevProperties(pDevExt))) {
        goto AbortLoading;
    }

    // Get the features of the properties as well as its persisted value.
    // It will also updated the table.
    // The return is ignored since the default values are set when there is a failure.
    DCamGetPropertyValuesFromRegistry(
        pDevExt
        );

    //
    // Query video mode supported, and then contruct the stream format table.
    //
    if(!DCamBuildFormatTable(pDevExt, pIrb)) {
        ERROR_LOG(("\'Failed to get Video Format and Mode information; return STATUS_NOT_SUPPORTED\n"));
        status = STATUS_NOT_SUPPORTED;    
        goto AbortLoading;
    }

    //
    // register a bus reset callback notification (as the last action in this function)
    //
    // The controller driver will call (at DPC level)
    // if and only if the device is STILL attached.
    //
    // The device that has been removed, its
    // driver will get SRB_SURPRISE_REMOVAL instead.
    //
    
    pIrb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
    pIrb->Flags = 0;
    pIrb->u.BusResetNotification.fulFlags = REGISTER_NOTIFICATION_ROUTINE;
    pIrb->u.BusResetNotification.ResetRoutine = (PBUS_BUS_RESET_NOTIFICATION) DCamBusResetNotification;
    pIrb->u.BusResetNotification.ResetContext = pDevExt;
    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
    if (status) {

        ERROR_LOG(("DCamHwInitialize: Error (Status=%x) while trying to get local host info.\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }

    // This Irp is used locally only.
    IoFreeIrp(pIrp);  pIrp = NULL;


    DbgMsg1(("#### %s DCam loaded. ClassDO %p, PhyDO %p, BusDO %p, pDevExt %p, Gen# %d\n", 
        pDevExt->pchVendorName, pDevExt->SharedDeviceObject, pDevExt->PhysicalDeviceObject, pDevExt->BusDeviceObject, pDevExt, pDevExt->CurrentGeneration));

    return (STATUS_SUCCESS);

AbortLoading:


    if(pIrp) {
        IoFreeIrp(pIrp); pIrp = NULL;
    }

    if(pDevExt->ConfigRom) {
        ExFreePool(pDevExt->ConfigRom); pDevExt->ConfigRom = NULL;
    }

    if(pDevExt->UnitDirectory) {
        ExFreePool(pDevExt->UnitDirectory); pDevExt->UnitDirectory = NULL;
    }

    if(pDevExt->UnitDependentDirectory) {
        ExFreePool(pDevExt->UnitDependentDirectory); pDevExt->UnitDependentDirectory = NULL;
    }

    if(pDevExt->VendorLeaf) {
        ExFreePool(pDevExt->VendorLeaf); pDevExt->VendorLeaf = NULL;
    }

    if(pDevExt->ModelLeaf) {
        ExFreePool(pDevExt->ModelLeaf); pDevExt->ModelLeaf = NULL;
    }

    return status;

}
Esempio n. 9
0
VOID
Bus_EvtIoDeviceControl(
    IN WDFQUEUE     Queue,
    IN WDFREQUEST   Request,
    IN size_t       OutputBufferLength,
    IN size_t       InputBufferLength,
    IN ULONG        IoControlCode
    )

/*++
Routine Description:

  Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the IRP_MJ_DEVICE_CONTROL IRP received by the framework.

    OutputBufferLength - Length, in bytes, of the request's output buffer,
                        if an output buffer is available.

    InputBufferLength - Length, in bytes, of the request's input buffer,
                        if an input buffer is available.
    IoControlCode - Driver-defined or system-defined I/O control code (IOCTL)
                    that is associated with the request.

Return Value:

   VOID

--*/
{
    NTSTATUS                 status = STATUS_INVALID_PARAMETER;
    WDFDEVICE                hDevice;
    size_t                   length = 0;
    PBUSENUM_PLUGIN_HARDWARE plugIn = NULL;
    PBUSENUM_UNPLUG_HARDWARE unPlug = NULL;
    PBUSENUM_EJECT_HARDWARE  eject  = NULL;


    UNREFERENCED_PARAMETER(OutputBufferLength);

    PAGED_CODE ();

    hDevice = WdfIoQueueGetDevice(Queue);

    KdPrint(("Bus_EvtIoDeviceControl: 0x%p\n", hDevice));

    switch (IoControlCode) {
    case IOCTL_BUSENUM_PLUGIN_HARDWARE:

        status = WdfRequestRetrieveInputBuffer (Request,
                                    sizeof (BUSENUM_PLUGIN_HARDWARE) +
                                    (sizeof(UNICODE_NULL) * 2), // 2 for double NULL termination (MULTI_SZ)
                                    &plugIn, &length);
        if( !NT_SUCCESS(status) ) {
            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
            break;
        }

        ASSERT(length == InputBufferLength);

        if (sizeof (BUSENUM_PLUGIN_HARDWARE) == plugIn->Size)
        {

            length = (InputBufferLength - sizeof (BUSENUM_PLUGIN_HARDWARE))/sizeof(WCHAR);
            //
            // Make sure the IDs is two NULL terminated.
            //
            if ((UNICODE_NULL != plugIn->HardwareIDs[length - 1]) ||
                (UNICODE_NULL != plugIn->HardwareIDs[length - 2])) {

                status = STATUS_INVALID_PARAMETER;
                break;
            }

            status = Bus_PlugInDevice( hDevice,
                                       plugIn->HardwareIDs,
                                       length,
                                       plugIn->SerialNo );
        }

        break;

    case IOCTL_BUSENUM_UNPLUG_HARDWARE:

        status = WdfRequestRetrieveInputBuffer( Request,
                                                sizeof(BUSENUM_UNPLUG_HARDWARE),
                                                &unPlug,
                                                &length );
        if( !NT_SUCCESS(status) ) {
            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
            break;
        }

        if (unPlug->Size == InputBufferLength)
        {

            status= Bus_UnPlugDevice(hDevice, unPlug->SerialNo );

        }

        break;

    case IOCTL_BUSENUM_EJECT_HARDWARE:

        status = WdfRequestRetrieveInputBuffer (Request,
                                                sizeof (BUSENUM_EJECT_HARDWARE),
                                                &eject, &length);
        if( !NT_SUCCESS(status) ) {
            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
            break;
        }

        if (eject->Size == InputBufferLength)
        {
            status= Bus_EjectDevice(hDevice, eject->SerialNo);

        }

        break;

    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }

    WdfRequestCompleteWithInformation(Request, status, length);
}
Esempio n. 10
0
NTSTATUS
CdCommonQueryVolInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for querying volume information called by both
    the fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status = STATUS_INVALID_PARAMETER;
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

    ULONG Length;

    TYPE_OF_OPEN TypeOfOpen;
    PFCB Fcb;
    PCCB Ccb;

    PAGED_CODE();

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.QueryVolume.Length;

    //
    //  Decode the file object and fail if this an unopened file object.
    //

    TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );

    if (TypeOfOpen == UnopenedFileObject) {

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        return STATUS_INVALID_PARAMETER;
    }

    //
    //  Acquire the Vcb for this volume.
    //

    CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Verify the Vcb.
        //

        CdVerifyVcb( IrpContext, Fcb->Vcb );

        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling fills up the output buffer
        //  if possible and returns true if it successfully filled the buffer
        //  and false if it couldn't wait for any I/O to complete.
        //

        switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {

        case FileFsSizeInformation:

            Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
            break;

        case FileFsVolumeInformation:

            Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
            break;

        case FileFsDeviceInformation:

            Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
            break;

        case FileFsAttributeInformation:

            Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
            break;
        }

        //
        //  Set the information field to the number of bytes actually filled in
        //

        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;

    } finally {

        //
        //  Release the Vcb.
        //

        CdReleaseVcb( IrpContext, Fcb->Vcb );
    }

    //
    //  Complete the request if we didn't raise.
    //

    CdCompleteRequest( IrpContext, Irp, Status );

    return Status;
}
Esempio n. 11
0
NTSTATUS
DCamHwUnInitialize(
    IN PHW_STREAM_REQUEST_BLOCK Srb
    )
/*++

Routine Description:

    Device is asked to be unloaded.
       
    Note: this can be called BEFORE CloseStream in the situation when a DCam 
    is unplugged while streaming in any state (RUN,PAUSE or STOP).  So if we 
    are here and the stream is not yet close, we will stop, close stream and then
    free resource.

Arguments:

    Srb - Pointer to stream request block

Return Value:

    Nothing

--*/
{
    NTSTATUS Status;
    PIRP pIrp;
    PIRB pIrb;    
    PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;

    PAGED_CODE();


    //
    // Wait until all pending work items are completed!
    //

    KeWaitForSingleObject( &pDevExt->PendingWorkItemEvent, Executive, KernelMode, FALSE, NULL );


    ASSERT(pDevExt->PendingReadCount == 0);

    //
    // Host controller could be disabled which will cause us to be uninitialized.
    //
    if(DCamAllocateIrbAndIrp(&pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {

        //
        // un-register a bus reset callback notification
        //
        pIrb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
        pIrb->Flags = 0;
        pIrb->u.BusResetNotification.fulFlags = DEREGISTER_NOTIFICATION_ROUTINE;
        pIrb->u.BusResetNotification.ResetRoutine = (PBUS_BUS_RESET_NOTIFICATION) DCamBusResetNotification;
        pIrb->u.BusResetNotification.ResetContext = 0; 
        Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
        if(Status) {
            ERROR_LOG(("DCamHwUnInitialize: Error (Status %x) while trying to deregister reset callback routine.\n", Status));
        } 

        DbgMsg1(("DCamHwUnInitialize: DeRegister bus reset notification done; status %x.\n", Status));

        DCamFreeIrbIrpAndContext(0, pIrb, pIrp);
    } else {
        ERROR_LOG(("DCamBusResetNotification: DcamAllocateIrbAndIrp has failed!!\n\n\n"));
        ASSERT(FALSE);   
    }

    // Free resource (from below)
    if(pDevExt->UnitDirectory) {
        ExFreePool(pDevExt->UnitDirectory);
        pDevExt->UnitDirectory = 0;
    }

    if(pDevExt->UnitDependentDirectory) {
        ExFreePool(pDevExt->UnitDependentDirectory);
        pDevExt->UnitDependentDirectory = 0;
    }

    if(pDevExt->ModelLeaf) {
        ExFreePool(pDevExt->ModelLeaf);
        pDevExt->ModelLeaf = 0;
    }

    if (pDevExt->ConfigRom) {
        ExFreePool(pDevExt->ConfigRom);
        pDevExt->ConfigRom = 0;
    }

    if (pDevExt->VendorLeaf) {
        ExFreePool(pDevExt->VendorLeaf);
        pDevExt->VendorLeaf = 0;
    }
      
    return STATUS_SUCCESS;
}
Esempio n. 12
0
NTSTATUS
CdQueryFsAttributeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine implements the query volume attribute call.

Arguments:

    Vcb - Vcb for this volume.

    Buffer - Supplies a pointer to the output buffer where the information
        is to be returned

    Length - Supplies the length of the buffer in byte.  This variable
        upon return recieves the remaining bytes free in the buffer

Return Value:

    NTSTATUS - Returns the status for the query

--*/

{
    ULONG BytesToCopy;

    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    //
    //  Fill out the fixed portion of the buffer.
    //

    Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH;

    if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {

        SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );

        Buffer->MaximumComponentNameLength = 110;

    } else {

        Buffer->MaximumComponentNameLength = 221;
    }

    *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );

    //
    //  Make sure we can copy full unicode characters.
    //

    ClearFlag( *Length, 1 );

    //
    //  Determine how much of the file system name will fit.
    //

    if (*Length >= 8) {

        BytesToCopy = 8;

    } else {

        BytesToCopy = *Length;
        Status = STATUS_BUFFER_OVERFLOW;
    }

    *Length -= BytesToCopy;

    //
    //  Do the file system name.
    //

    Buffer->FileSystemNameLength = BytesToCopy;

    RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );

    //
    //  And return to our caller
    //

    return Status;
}
Esempio n. 13
0
NTSTATUS
CdQueryFsVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_VOLUME_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine implements the query volume info call

Arguments:

    Vcb - Vcb for this volume.

    Buffer - Supplies a pointer to the output buffer where the information
        is to be returned

    Length - Supplies the length of the buffer in byte.  This variable
        upon return recieves the remaining bytes free in the buffer

Return Value:

    NTSTATUS - Returns the status for the query

--*/

{
    ULONG BytesToCopy;

    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    //
    //  Fill in the data from the Vcb.
    //

    Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
    Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;

    Buffer->SupportsObjects = FALSE;

    *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );

    //
    //  Check if the buffer we're given is long enough
    //

    if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {

        BytesToCopy = Vcb->Vpb->VolumeLabelLength;

    } else {

        BytesToCopy = *Length;

        Status = STATUS_BUFFER_OVERFLOW;
    }

    //
    //  Copy over what we can of the volume label, and adjust *Length
    //

    Buffer->VolumeLabelLength = BytesToCopy;

    if (BytesToCopy) {

        RtlCopyMemory( &Buffer->VolumeLabel[0],
                       &Vcb->Vpb->VolumeLabel[0],
                       BytesToCopy );
    }

    *Length -= BytesToCopy;

    //
    //  Set our status and return to our caller
    //

    return Status;
}
Esempio n. 14
0
NTSTATUS
ToasterWmiRegistration(
    _In_ WDFDEVICE Device
    )

/*++

Routine Description

    Registers with WMI as a data provider for this instance of the device.

Arguments:

    Device - The Framework device object for which the WMI provider instances
        are to be created and registered. This device object will be the parent
        object of the new WMI instance objects.

Return Value:

    NT Status code.

--*/

{
    NTSTATUS status;
    PFDO_DATA fdoData;
    PToasterDeviceInformation pData;
    PToasterControl controlData;

    WDFWMIINSTANCE instance;
    WDF_OBJECT_ATTRIBUTES woa;
    WDF_WMI_PROVIDER_CONFIG providerConfig;
    WDF_WMI_INSTANCE_CONFIG instanceConfig;
    DECLARE_CONST_UNICODE_STRING(mofResourceName, MOFRESOURCENAME);

    PAGED_CODE();

    fdoData = ToasterFdoGetData(Device);

    //
    // Register the MOF resource names of any customized WMI data providers
    // that are not defined in wmicore.mof.
    //
    status = WdfDeviceAssignMofResourceName(Device, &mofResourceName);
    if (!NT_SUCCESS(status)) {

        WppPrintDeviceError(fdoData->WppRecorderLog,
                            "[Toaster] Status = 0x%08x, WdfDeviceAssignMofResourceName failed\n",
                            status);
        return status;
    }

    //
    // Initialize the config structures for the Provider and the Instance and
    // define event callback functions that support a WMI client's request to
    // access the driver's WMI data blocks.
    //

    WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &ToasterDeviceInformation_GUID);

    //
    // Specify minimum expected buffer size for query and set instance requests.
    // Since the query block size is different than the set block size, set it
    // to zero and manually check for the buffer size for each operation.
    //
    providerConfig.MinInstanceBufferSize = 0;

    //
    // The WDFWMIPROVIDER handle is needed if multiple instances for the provider
    // has to be created or if the instances have to be created sometime after
    // the provider is created. In case below, the provider handle is not needed
    // because only one instance is needed and can be created when the provider
    // is created.
    //
    WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig);

    //
    // Create the Provider object as part of the Instance creation call by setting
    // the Register value in the Instance Config to TRUE. This eliminates the
    // need to call WdfWmiProviderRegister.
    //
    instanceConfig.Register = TRUE;

    instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceStdDeviceDataQueryInstance;
    instanceConfig.EvtWmiInstanceSetInstance   = EvtWmiInstanceStdDeviceDataSetInstance;
    instanceConfig.EvtWmiInstanceSetItem       = EvtWmiInstanceStdDeviceDataSetItem;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, ToasterDeviceInformation);

    //
    // Create the WMI instance object for this data block.
    //
    status = WdfWmiInstanceCreate(Device,
                                  &instanceConfig,
                                  &woa,
                                  &instance);
    if (!NT_SUCCESS(status)) {

        WppPrintDeviceError(fdoData->WppRecorderLog,
                            "[Toaster] Status = 0x%08x, WdfWmiInstanceCreate failed\n",
                            status);
        return status;
    }

    pData = ToasterWmiGetData(instance);

    pData->ConnectorType = TOASTER_WMI_STD_USB;
    pData->Capacity = 2000;
    pData->ErrorCount = 0;
    pData->Controls = 5;
    pData->DebugPrintLevel = DebugLevel;

    WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &TOASTER_NOTIFY_DEVICE_ARRIVAL_EVENT);
    providerConfig.Flags = WdfWmiProviderEventOnly;

    //
    // Specify minimum expected buffer size for query and set instance requests.
    // Since the query block size is different than the set block size, set it
    // to zero and manually check for the buffer size for each operation.
    //
    providerConfig.MinInstanceBufferSize = 0;

    WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig);
    instanceConfig.Register = TRUE;

    //
    // Create the WMI instance object for this data block.
    //
    status = WdfWmiInstanceCreate(Device,
                                  &instanceConfig,
                                  WDF_NO_OBJECT_ATTRIBUTES,
                                  &fdoData->WmiDeviceArrivalEvent);

    if (!NT_SUCCESS(status)) {

        WppPrintDeviceError(fdoData->WppRecorderLog,
                            "[Toaster] Status = 0x%08x, WdfWmiInstanceCreate failed\n",
                            status);
        return status;
    }


    //
    // Register the Toaster Control class.
    //

    //
    // Initialize the config structures for the Provider and the Instance and
    // define event callback functions that support a WMI client's request to
    // access the driver's WMI data blocks.
    //

    WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &ToasterControl_GUID);

    //
    // Specify minimum expected buffer size for query and set instance requests.
    //
    providerConfig.MinInstanceBufferSize = ToasterControl_SIZE;

    //
    // The WDFWMIPROVIDER handle is needed if multiple instances for the provider
    // has to be created or if the instances have to be created sometime after
    // the provider is created. In case below, the provider handle is not needed
    // because only one instance is needed and can be created when the provider
    // is created.
    //
    WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig);

    //
    // Create the Provider object as part of the Instance creation call by setting
    // the Register value in the Instance Config to TRUE. This eliminates the
    // need to call WdfWmiProviderRegister.
    //
    instanceConfig.Register = TRUE;

    instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceToasterControlQueryInstance;
    instanceConfig.EvtWmiInstanceSetInstance   = EvtWmiInstanceToasterControlSetInstance;
    instanceConfig.EvtWmiInstanceSetItem       = EvtWmiInstanceToasterControlSetItem;
    instanceConfig.EvtWmiInstanceExecuteMethod = EvtWmiInstanceToasterControlExecuteMethod;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, ToasterControl);

    //
    // Create the WMI instance object for this data block.
    //
    status = WdfWmiInstanceCreate(Device,
                                  &instanceConfig,
                                  &woa,
                                  &instance);
    if (!NT_SUCCESS(status)) {

        WppPrintDeviceError(fdoData->WppRecorderLog,
                            "[Toaster] Status = 0x%08x, WdfWmiInstanceCreate failed\n",
                            status);
        return status;
    }

    controlData = ToasterWmiGetControlData(instance);
    controlData->ControlValue = 25;

    return status;
}
Esempio n. 15
0
void changeTrapFlagForThread( ADDRESS ethread, int setTheFlag )
{
    PAGED_CODE();

    /* Is this a system thread, because if so, I have no interest in it. */
    /* System thread has teb == NULL */
    if (
        (NULL != *(ADDRESS *)(ethread + offsets->ethread.Teb)) &&
        (0 == ((*(UINT32 *)(ethread + offsets->ethread.CrossThreadFlags)) & 0x00000010UL /* PS_CROSS_THREAD_FLAGS_SYSTEM */ )) ) {

        /* This is not a system thread */

        HANDLE threadId = (HANDLE)(*(UINT32 *)(ethread + offsets->ethread.Cid + sizeof(UINT32)));

        /* Is that the target thread, or are we set to trace all threads */
        if (    (0 == targetThreadId) ||
                (targetThreadId == threadId) ) {

            DbgPrint("Oregano: This thread is in target %p\r\n", targetThreadId);
            UINT32 hashIndex = 0;
            KEVENT operationComplete = {0};
            KeInitializeEvent(&operationComplete, NotificationEvent, FALSE);

            if (FALSE != setTheFlag)
            {
                ThreadContext * threadCtx = NULL;
#pragma warning( disable : 4305 )
                /* Find a free entry in the Hash table */
                hashIndex = (((UINT32)ethread) & THREAD_ID_MASK) >> THREAD_ID_IGNORED_BITS;
                DbgPrint("Oregano: setTrapFlagAPC: EThread %p hash id %x\r\n", ethread, hashIndex);
                while (0 != threads[hashIndex].ID) {
                    hashIndex = (hashIndex + 1) % THREAD_CONTEXT_MAX_THREADS;
                }
                threadCtx = &threads[hashIndex];
#pragma warning( default : 4305 )
#ifdef AMD64
                threadCtx->ID  = (UINT64)ethread;
                threadCtx->RDI = UNKNOWN_QWORD_VALUE;
                threadCtx->RSI = UNKNOWN_QWORD_VALUE;
                threadCtx->RBP = UNKNOWN_QWORD_VALUE;
                threadCtx->RBX = UNKNOWN_QWORD_VALUE;
                threadCtx->RDX = UNKNOWN_QWORD_VALUE;
                threadCtx->RCX = UNKNOWN_QWORD_VALUE;
                threadCtx->RAX = UNKNOWN_QWORD_VALUE;
                threadCtx->R8  = UNKNOWN_QWORD_VALUE;
                threadCtx->R9  = UNKNOWN_QWORD_VALUE;
                threadCtx->R10 = UNKNOWN_QWORD_VALUE;
                threadCtx->R11 = UNKNOWN_QWORD_VALUE;
                threadCtx->R12 = UNKNOWN_QWORD_VALUE;
                threadCtx->R13 = UNKNOWN_QWORD_VALUE;
                threadCtx->R14 = UNKNOWN_QWORD_VALUE;
                threadCtx->R15 = UNKNOWN_QWORD_VALUE;
                threadCtx->RIP = (ADDRESS)0;
                threadCtx->RCS = UNKNOWN_QWORD_VALUE;
                threadCtx->RFLAGS = UNKNOWN_QWORD_VALUE;
                threadCtx->RSP = UNKNOWN_QWORD_VALUE;
#else
                /* Set the flag */
                threadCtx->ID  = (UINT32)ethread;
                threadCtx->EDI = UNKNOWN_DWORD_VALUE;
                threadCtx->ESI = UNKNOWN_DWORD_VALUE;
                threadCtx->EBP = UNKNOWN_DWORD_VALUE;
                threadCtx->EBX = UNKNOWN_DWORD_VALUE;
                threadCtx->EDX = UNKNOWN_DWORD_VALUE;
                threadCtx->ECX = UNKNOWN_DWORD_VALUE;
                threadCtx->EAX = UNKNOWN_DWORD_VALUE;
                threadCtx->EIP = (ADDRESS)0;
                threadCtx->ECS = UNKNOWN_DWORD_VALUE;
                threadCtx->EFLAGS = UNKNOWN_DWORD_VALUE;
                threadCtx->ESP = UNKNOWN_DWORD_VALUE;
#endif
            }
Esempio n. 16
0
NTSTATUS
Bus_PlugInDevice(
    __in WDFDEVICE       Device,
    __in PWCHAR          HardwareIds,
    __in size_t          CchHardwareIds,
    __in ULONG           SerialNo
    )

/*++

Routine Description:

    The user application has told us that a new device on the bus has arrived.

    We therefore create a description structure in stack, fill in information about
    the child device and call WdfChildListAddOrUpdateChildDescriptionAsPresent
    to add the device.

--*/

{
    PDO_IDENTIFICATION_DESCRIPTION description;
    NTSTATUS         status;

    PAGED_CODE ();

    //
    // Initialize the description with the information about the newly
    // plugged in device.
    //
    WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(
        &description.Header,
        sizeof(description)
        );

    description.SerialNo = SerialNo;
    description.CchHardwareIds = CchHardwareIds;
    description.HardwareIds = HardwareIds;

    //
    // Call the framework to add this child to the childlist. This call
    // will internaly call our DescriptionCompare callback to check
    // whether this device is a new device or existing device. If
    // it's a new device, the framework will call DescriptionDuplicate to create
    // a copy of this description in nonpaged pool.
    // The actual creation of the child device will happen when the framework
    // receives QUERY_DEVICE_RELATION request from the PNP manager in
    // response to InvalidateDeviceRelations call made as part of adding
    // a new child.
    //
    status = WdfChildListAddOrUpdateChildDescriptionAsPresent(
                    WdfFdoGetDefaultChildList(Device), &description.Header,
                    NULL); // AddressDescription

    if (status == STATUS_OBJECT_NAME_EXISTS) {
        //
        // The description is already present in the list, the serial number is
        // not unique, return error.
        //
        status = STATUS_INVALID_PARAMETER;
    }

    return status;
}
Esempio n. 17
0
void changeTrapFlag(ADDRESS ethread, int setTheFlag)
{
    KIRQL   oldIrql;
    ADDRESS eflags = NULL;
    ADDRESS threadKStack = NULL;
    MODE    previousMode = 0;

    PAGED_CODE();

    oldIrql = KeGetCurrentIrql();
    if (oldIrql < APC_LEVEL) {
        KeRaiseIrql(APC_LEVEL, &oldIrql);
    }

    previousMode = *(char *)(ethread + offsets->ethread.PreviousMode);
    DbgPrint("Oregano: changeTrapFlag: previous mode is: %x\r\n", (UINT32)(previousMode));
    if (KernelMode == previousMode)
    {
        DbgPrint("Oregano: changeTrapFlag: Taking KStack from Tcp.TrapFrame");
        threadKStack = *(ADDRESS *)(ethread + offsets->ethread.TrapFrame);
    }
    else if (UserMode == previousMode)
    {
        threadKStack = *(ADDRESS *)(ethread + offsets->ethread.InitialStack);
        DbgPrint("Oregano: changeTrapFlag: KStack is %p\r\n", threadKStack);
        threadKStack -= offsets->threadContext.ktrapFrameSize;
    }
    else
    {
        DbgPrint("Oregano: changeTrapFlag: Unknown mode %x!\r\n", (int)previousMode);
        goto changeTrapFlag_cleanup;
    }
    DbgPrint("Oregano: changeTrapFlag: Trap frame is %p\r\n", threadKStack);

    /* The kernel stack can't be paged out! */

    if (NULL == threadKStack)
    {
        DbgPrint("Oregano: Wrong value for threadKStack\r\n");
        goto changeTrapFlag_cleanup;
    }
    eflags = threadKStack + offsets->threadContext.eflags;
    DbgPrint("Oregano: changeTrapFlag: EFlags = %x\r\n", *((UINT32 *)eflags));
    if (setTheFlag)
    {
        /* Set the flag */
        *((UINT32 *)eflags) |= TRAP_FLAG;
    }
    else
    {
        /* Clear the flag */
        *((UINT32 *)eflags) &= ~TRAP_FLAG;
    }
    DbgPrint("Oregano: changeTrapFlag: EFlags new value = %x\r\n", *((UINT32 *)eflags));

changeTrapFlag_cleanup:
    if (oldIrql < APC_LEVEL) {
        KeLowerIrql(oldIrql);
    }

    return;
}
Esempio n. 18
0
NTSTATUS
Bus_UnPlugDevice(
    WDFDEVICE   Device,
    ULONG       SerialNo
    )
/*++

Routine Description:

    The application has told us a device has departed from the bus.

    We therefore need to flag the PDO as no longer present.

Arguments:


Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/

{
    NTSTATUS       status;
    WDFCHILDLIST   list;

    PAGED_CODE ();

    list = WdfFdoGetDefaultChildList(Device);

    if (0 == SerialNo) {
        //
        // Unplug everybody.  We do this by starting a scan and then not reporting
        // any children upon its completion
        //
        status = STATUS_SUCCESS;

        WdfChildListBeginScan(list);
        //
        // A call to WdfChildListBeginScan indicates to the framework that the
        // driver is about to scan for dynamic children. After this call has
        // returned, all previously reported children associated with this will be
        // marked as potentially missing.  A call to either
        // WdfChildListUpdateChildDescriptionAsPresent  or
        // WdfChildListMarkAllChildDescriptionsPresent will mark all previuosly
        // reported missing children as present.  If any children currently
        // present are not reported present by calling
        // WdfChildListUpdateChildDescriptionAsPresent at the time of
        // WdfChildListEndScan, they will be reported as missing to the PnP subsystem
        // After WdfChildListEndScan call has returned, the framework will
        // invalidate the device relations for the FDO associated with the list
        // and report the changes
        //
        WdfChildListEndScan(list);

    }
    else {
        PDO_IDENTIFICATION_DESCRIPTION description;

        WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(
            &description.Header,
            sizeof(description)
            );

        description.SerialNo = SerialNo;
        //
        // WdfFdoUpdateChildDescriptionAsMissing indicates to the framework that a
        // child device that was previuosly detected is no longe present on the bus.
        // This API can be called by itself or after a call to WdfChildListBeginScan.
        // After this call has returned, the framework will invalidate the device
        // relations for the FDO associated with the list and report the changes.
        //
        status = WdfChildListUpdateChildDescriptionAsMissing(list,
                                                              &description.Header);
        if (status == STATUS_NO_SUCH_DEVICE) {
            //
            // serial number didn't exist. Remap it to a status that user
            // application can understand when it gets translated to win32
            // error code.
            //
            status = STATUS_INVALID_PARAMETER;
        }
    }

    return status;
}
Esempio n. 19
0
BOOLEAN
LfsInitializeLogFileService (
    )

/*++

Routine Description:

    This routine must be called during system initialization before the
    first call to logging service, to allow the Log File Service to initialize
    its global data structures.  This routine has no dependencies on other
    system components being initialized.

    This routine will initialize the global structures used by the logging
    service and start the Lfs worker thread.

Arguments:

    None

Return Value:

    TRUE if initialization was successful

--*/

{
    LARGE_INTEGER CurrentTime;

    PAGED_CODE();

    DebugTrace( +1, Dbg, "LfsInitializeLogFileService:  Enter\n", 0 );

    //
    //  If the structure has already been initialized then we can return
    //  immediately.
    //

    if (LfsData.NodeTypeCode == LFS_NTC_DATA
        && LfsData.NodeByteSize == sizeof( LFS_DATA )
        && FlagOn( LfsData.Flags, LFS_DATA_INITIALIZED )) {

        DebugTrace( -1, Dbg, "LfsInitializeLogFileService:  Exit  ->  %01x\n", TRUE );

        return TRUE;
    }

    //
    //  Zero out the structure initially.
    //

    RtlZeroMemory( &LfsData, sizeof( LFS_DATA ));

    //
    //  Assume the operation will fail.
    //

    LfsData.Flags = LFS_DATA_INIT_FAILED;

    //
    //  Initialize the global structure for Lfs.
    //

    LfsData.NodeTypeCode = LFS_NTC_DATA;
    LfsData.NodeByteSize = sizeof( LFS_DATA );

    InitializeListHead( &LfsData.LfcbLinks );

    //
    //  Initialize the synchronization objects.
    //

    ExInitializeFastMutex( &LfsData.LfsDataLock );

    //
    //  Initialize the buffer allocation.  System will be robust enough to tolerate
    //  allocation failures.
    //

    ExInitializeFastMutex( &LfsData.BufferLock );
    KeInitializeEvent( &LfsData.BufferNotification, NotificationEvent, TRUE );
    LfsData.Buffer1 = LfsAllocatePoolNoRaise( PagedPool, LFS_BUFFER_SIZE );

    if (LfsData.Buffer1 == NULL) {

        return FALSE;
    }

    LfsData.Buffer2 = LfsAllocatePoolNoRaise( PagedPool, LFS_BUFFER_SIZE );

    //
    //  Make sure we got both.
    //

    if (LfsData.Buffer2 == NULL) {

        LfsFreePool( LfsData.Buffer1 );
        LfsData.Buffer1 = NULL;
        return FALSE;
    }

    //
    //  Initialization has been successful.
    //

    ClearFlag( LfsData.Flags, LFS_DATA_INIT_FAILED );
    SetFlag( LfsData.Flags, LFS_DATA_INITIALIZED );

    //
    //  Get a random number as a seed for the Usa sequence numbers.  Use the lower
    //  bits of the current time.
    //

    KeQuerySystemTime( &CurrentTime );
    LfsUsaSeqNumber = (USHORT) CurrentTime.LowPart;

    DebugTrace( -1, Dbg, "LfsInitializeLogFileService:  Exit  ->  %01x\n", TRUE );

    return TRUE;
}
Esempio n. 20
0
NTSTATUS
Bus_EjectDevice(
    WDFDEVICE   Device,
    ULONG       SerialNo
    )

/*++

Routine Description:

    The user application has told us to eject the device from the bus.
    In a real situation the driver gets notified by an interrupt when the
    user presses the Eject button on the device.

Arguments:


Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the ejection was unsuccessful

--*/

{
    WDFDEVICE        hChild;
    NTSTATUS         status = STATUS_INVALID_PARAMETER;
    WDFCHILDLIST     list;

    PAGED_CODE ();

    list = WdfFdoGetDefaultChildList(Device);

    //
    // A zero serial number means eject all children
    //
    if (0 == SerialNo) {
        WDF_CHILD_LIST_ITERATOR     iterator;

        WDF_CHILD_LIST_ITERATOR_INIT( &iterator,
                                      WdfRetrievePresentChildren );

        WdfChildListBeginIteration(list, &iterator);

        for ( ; ; ) {
            WDF_CHILD_RETRIEVE_INFO         childInfo;
            PDO_IDENTIFICATION_DESCRIPTION  description;
            BOOLEAN                         ret;

            //
            // Init the structures.
            //
            WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);

            WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(
                                    &description.Header,
                                    sizeof(description)
                                    );
            //
            // Get the device identification description
            //
            status = WdfChildListRetrieveNextDevice(list,
                                                &iterator,
                                                &hChild,
                                                &childInfo);

            if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) {
                break;
            }

            ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess);

            //
            // Use that description to request an eject.
            //
            ret = WdfChildListRequestChildEject(list, &description.Header);
            if(!ret) {
                WDFVERIFY(ret);
            }

        }

        WdfChildListEndIteration(list, &iterator);

        if (status == STATUS_NO_MORE_ENTRIES) {
            status = STATUS_SUCCESS;
        }

    }
    else {

        PDO_IDENTIFICATION_DESCRIPTION description;

        WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(
            &description.Header,
            sizeof(description)
            );

        description.SerialNo = SerialNo;

        if (WdfChildListRequestChildEject(list, &description.Header)) {
            status = STATUS_SUCCESS;
        }
    }

    return status;
}
Esempio n. 21
0
BOOLEAN
CdEnumerateIndex (
    __in PIRP_CONTEXT IrpContext,
    __in PCCB Ccb,
    __inout PFILE_ENUM_CONTEXT FileContext,
    __in BOOLEAN ReturnNextEntry
    )

/*++

Routine Description:

    This routine is the worker routine for index enumeration.  We are positioned
    at some dirent in the directory and will either return the first match
    at that point or look to the next entry.  The Ccb contains details about
    the type of matching to do.  If the user didn't specify a version in
    his search string then we only return the first version of a sequence
    of files with versions.  We also don't return any associated files.

Arguments:

    Ccb - Ccb for this directory handle.

    FileContext - File context already positioned at some entry in the directory.

    ReturnNextEntry - Indicates if we are returning this entry or should start
        with the next entry.

Return Value:

    BOOLEAN - TRUE if next entry is found, FALSE otherwise.

--*/

{
    PDIRENT PreviousDirent = NULL;
    PDIRENT ThisDirent = &FileContext->InitialDirent->Dirent;

    BOOLEAN Found = FALSE;

    PAGED_CODE();

    //
    //  Loop until we find a match or exaust the directory.
    //

    while (TRUE) {

        //
        //  Move to the next entry unless we want to consider the current
        //  entry.
        //

        if (ReturnNextEntry) {

            if (!CdLookupNextInitialFileDirent( IrpContext, Ccb->Fcb, FileContext )) {

                break;
            }

            PreviousDirent = ThisDirent;
            ThisDirent = &FileContext->InitialDirent->Dirent;

            CdUpdateDirentName( IrpContext, ThisDirent, FlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE ));
        
        } else {

            ReturnNextEntry = TRUE;
        }

        //
        //  Don't bother if we have a constant entry and are ignoring them.
        //
        
        if (FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY ) &&
            FlagOn( Ccb->Flags, CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY )) {

            continue;
        }

        //
        //  Look at the current entry if it is not an associated file
        //  and the name doesn't match the previous file if the version
        //  name is not part of the search.
        //

        if (!FlagOn( ThisDirent->DirentFlags, CD_ATTRIBUTE_ASSOC )) {

            //
            //  Check if this entry matches the previous entry except
            //  for version number and whether we should return the
            //  entry in that case.  Go directly to the name comparison
            //  if:
            //
            //      There is no previous entry.
            //      The search expression has a version component.
            //      The name length doesn't match the length of the previous entry.
            //      The base name strings don't match.
            //

            if ((PreviousDirent == NULL) ||
                (Ccb->SearchExpression.VersionString.Length != 0) ||
                (PreviousDirent->CdCaseFileName.FileName.Length != ThisDirent->CdCaseFileName.FileName.Length) ||
                FlagOn( PreviousDirent->DirentFlags, CD_ATTRIBUTE_ASSOC ) ||
                !RtlEqualMemory( PreviousDirent->CdCaseFileName.FileName.Buffer,
                                 ThisDirent->CdCaseFileName.FileName.Buffer,
                                 ThisDirent->CdCaseFileName.FileName.Length )) {

                //
                //  If we match all names then return to our caller.
                //

                if (FlagOn( Ccb->Flags, CCB_FLAG_ENUM_MATCH_ALL )) {

                    FileContext->ShortName.FileName.Length = 0;
                    Found = TRUE;
                    break;
                }

                //
                //  Check if the long name matches the search expression.
                //

                if (CdIsNameInExpression( IrpContext,
                                          &ThisDirent->CdCaseFileName,
                                          &Ccb->SearchExpression,
                                          Ccb->Flags,
                                          TRUE )) {

                    //
                    //  Let our caller know we found an entry.
                    //

                    Found = TRUE;
                    FileContext->ShortName.FileName.Length = 0;
                    break;
                }

                //
                //  The long name didn't match so we need to check for a
                //  possible short name match.  There is no match if the
                //  long name is 8dot3 or the search expression has a
                //  version component.  Special case the self and parent
                //  entries.
                //

                if ((Ccb->SearchExpression.VersionString.Length == 0) &&
                    !FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY ) &&
                    !CdIs8dot3Name( IrpContext,
                                    ThisDirent->CdFileName.FileName )) {

                    CdGenerate8dot3Name( IrpContext,
                                         &ThisDirent->CdCaseFileName.FileName,
                                         ThisDirent->DirentOffset,
                                         FileContext->ShortName.FileName.Buffer,
                                         &FileContext->ShortName.FileName.Length );

                    //
                    //  Check if this name matches.
                    //

                    if (CdIsNameInExpression( IrpContext,
                                              &FileContext->ShortName,
                                              &Ccb->SearchExpression,
                                              Ccb->Flags,
                                              FALSE )) {

                        //
                        //  Let our caller know we found an entry.
                        //

                        Found = TRUE;
                        break;
                    }
                }
            }
        }
    }

    //
    //  If we found the entry then make sure we walk through all of the
    //  file dirents.
    //

    if (Found) {

        CdLookupLastFileDirent( IrpContext, Ccb->Fcb, FileContext );
    }

    return Found;
}
Esempio n. 22
0
NTSTATUS
Bus_EvtDeviceAdd(
    IN WDFDRIVER        Driver,
    IN PWDFDEVICE_INIT  DeviceInit
    )
/*++
Routine Description:

    Bus_EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of toaster bus.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_CHILD_LIST_CONFIG      config;
    WDF_OBJECT_ATTRIBUTES      fdoAttributes;
    NTSTATUS                   status;
    WDFDEVICE                  device;
    WDF_IO_QUEUE_CONFIG        queueConfig;
    PNP_BUS_INFORMATION        busInfo;
    PFDO_DEVICE_DATA           deviceData;
    WDFQUEUE                   queue;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE ();

    KdPrint(("Bus_EvtDeviceAdd: 0x%p\n", Driver));

    //
    // Initialize all the properties specific to the device.
    // Framework has default values for the one that are not
    // set explicitly here. So please read the doc and make sure
    // you are okay with the defaults.
    //
    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
    WdfDeviceInitSetExclusive(DeviceInit, TRUE);

    //
    // Since this is pure software bus enumerator, we don't have to register for
    // any PNP/Power callbacks. Framework will take the default action for
    // all the PNP and Power IRPs.
    //


    //
    // WDF_ DEVICE_LIST_CONFIG describes how the framework should handle
    // dynamic child enumeration on behalf of the driver writer.
    // Since we are a bus driver, we need to specify identification description
    // for our child devices. This description will serve as the identity of our
    // child device. Since the description is opaque to the framework, we
    // have to provide bunch of callbacks to compare, copy, or free
    // any other resources associated with the description.
    //
    WDF_CHILD_LIST_CONFIG_INIT(&config,
                                sizeof(PDO_IDENTIFICATION_DESCRIPTION),
                                Bus_EvtDeviceListCreatePdo // callback to create a child device.
                                );
    //
    // This function pointer will be called when the framework needs to copy a
    // identification description from one location to another.  An implementation
    // of this function is only necessary if the description contains description
    // relative pointer values (like  LIST_ENTRY for instance) .
    // If set to NULL, the framework will use RtlCopyMemory to copy an identification .
    // description. In this sample, it's not required to provide these callbacks.
    // they are added just for illustration.
    //
    config.EvtChildListIdentificationDescriptionDuplicate =
                                Bus_EvtChildListIdentificationDescriptionDuplicate;

    //
    // This function pointer will be called when the framework needs to compare
    // two identificaiton descriptions.  If left NULL a call to RtlCompareMemory
    // will be used to compare two identificaiton descriptions.
    //
    config.EvtChildListIdentificationDescriptionCompare =
                                Bus_EvtChildListIdentificationDescriptionCompare;
    //
    // This function pointer will be called when the framework needs to free a
    // identification description.  An implementation of this function is only
    // necessary if the description contains dynamically allocated memory
    // (by the driver writer) that needs to be freed. The actual identification
    // description pointer itself will be freed by the framework.
    //
    config.EvtChildListIdentificationDescriptionCleanup =
                                Bus_EvtChildListIdentificationDescriptionCleanup;

    //
    // Tell the framework to use the built-in childlist to track the state
    // of the device based on the configuration we just created.
    //
    WdfFdoInitSetDefaultChildListConfig(DeviceInit,
                                         &config,
                                         WDF_NO_OBJECT_ATTRIBUTES);

    //
    // Initialize attributes structure to specify size and accessor function
    // for storing device context.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA);

    //
    // Create a framework device object. In response to this call, framework
    // creates a WDM deviceobject and attach to the PDO.
    //
    status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);

    if (!NT_SUCCESS(status)) {
        KdPrint(("Error creating device 0x%x\n", status));
        return status;
    }

    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
        &queueConfig,
        WdfIoQueueDispatchParallel
    );

    queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;

    status = WdfIoQueueCreate( device,
                               &queueConfig,
                               WDF_NO_OBJECT_ATTRIBUTES,
                               &queue );

    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfIoQueueCreate failed status 0x%x\n", status));
        return status;
    }

    //
    // Get the device context.
    //
    deviceData = FdoGetData(device);

    //
    // Create device interface for this device. The interface will be
    // enabled by the framework when we return from StartDevice successfully.
    // Clients of this driver will open this interface and send ioctls.
    //
    status = WdfDeviceCreateDeviceInterface(
        device,
        &GUID_DEVINTERFACE_BUSENUM_TOASTER,
        NULL // No Reference String. If you provide one it will appended to the
        );   // symbolic link. Some drivers register multiple interfaces for the same device
             // and use the reference string to distinguish between them
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION
    // for the child devices. This is an optional information provided to
    // uniquely idenitfy the bus the device is connected.
    //
    busInfo.BusTypeGuid = GUID_DEVCLASS_TOASTER;
    busInfo.LegacyBusType = PNPBus;
    busInfo.BusNumber = 0;

    WdfDeviceSetBusInformationForChildren(device, &busInfo);

    status = Bus_WmiRegistration(device);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Check the registry to see if we need to enumerate child devices during
    // start.
    //
    status = Bus_DoStaticEnumeration(device);

    return status;
}
Esempio n. 23
0
NTSTATUS
CdCommonDirControl (
    __inout PIRP_CONTEXT IrpContext,
    __inout PIRP Irp
    )

/*++

Routine Description:

    This routine is the entry point for the directory control operations.  These
    are directory enumerations and directory notify calls.  We verify the
    user's handle is for a directory and then call the appropriate routine.

Arguments:

    Irp - Irp for this request.

Return Value:

    NTSTATUS - Status returned from the lower level routines.

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

    PFCB Fcb;
    PCCB Ccb;

    PAGED_CODE();

    //
    //  Decode the user file object and fail this request if it is not
    //  a user directory.
    //

    if (CdDecodeFileObject( IrpContext,
                            IrpSp->FileObject,
                            &Fcb,
                            &Ccb ) != UserDirectoryOpen) {

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        return STATUS_INVALID_PARAMETER;
    }

    //
    //  We know this is a directory control so we'll case on the
    //  minor function, and call a internal worker routine to complete
    //  the irp.
    //

    switch (IrpSp->MinorFunction) {

    case IRP_MN_QUERY_DIRECTORY:

        Status = CdQueryDirectory( IrpContext, Irp, IrpSp, Fcb, Ccb );
        break;

    case IRP_MN_NOTIFY_CHANGE_DIRECTORY:

        Status = CdNotifyChangeDirectory( IrpContext, Irp, IrpSp, Ccb );
        break;

    default:

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return Status;
}
Esempio n. 24
0
NTSTATUS
RamDiskEvtDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    NTSTATUS                status;
    WDFDEVICE               device;
    WDF_OBJECT_ATTRIBUTES   queueAttributes;
    WDF_IO_QUEUE_CONFIG     ioQueueConfig;
    PDEVICE_EXTENSION       pDeviceExtension;
    PQUEUE_EXTENSION        pQueueContext = NULL;
    WDFQUEUE                queue;
    DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME);

    PAGED_CODE();

    UNREFERENCED_PARAMETER(Driver);

    //
    // Storage drivers have to name their FDOs. Since we are not unique'fying
    // the device name, we wouldn't be able to install more than one instance
    // of this ramdisk driver.
    //
    status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK);
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
    WdfDeviceInitSetExclusive(DeviceInit, FALSE);

    //
    // Since this is a pure software only driver, there is no need to register
    // any PNP/Power event callbacks. Framework will respond to these
    // events appropriately.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION);
    deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup;

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Now that the WDF device object has been created, set up any context
    // that it requires.
    //

    pDeviceExtension = DeviceGetExtension(device);

    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (
        &ioQueueConfig,
        WdfIoQueueDispatchSequential
        );

    ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl;
    ioQueueConfig.EvtIoRead          = RamDiskEvtIoRead;
    ioQueueConfig.EvtIoWrite         = RamDiskEvtIoWrite;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION);

    status = WdfIoQueueCreate( device,
                               &ioQueueConfig,
                               &queueAttributes,
                               &queue );
    if (!NT_SUCCESS(status)) {
        return status;
    }

     // Context is the Queue handle
    pQueueContext = QueueGetExtension(queue);

    //
    // Set the context for our default queue as our device extension.
    //
    pQueueContext->DeviceExtension = pDeviceExtension;

    //
    // Enable forward progress on the queue we just created.
    // NOTE: If you are planning to use this code without forward progress,
    // comment out the call to SetForwardProgressOnQueue below. 
    //
    status = SetForwardProgressOnQueue(queue);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Now do any RAM-Disk specific initialization
    //
    pDeviceExtension->DiskRegInfo.DriveLetter.Buffer =
        (PWSTR) &pDeviceExtension->DriveLetterBuffer;
    pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength =
        sizeof(pDeviceExtension->DriveLetterBuffer);

    //
    // Get the disk parameters from the registry
    //
    RamDiskQueryDiskRegParameters(
        WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)),
        &pDeviceExtension->DiskRegInfo
        );

    //
    // Allocate memory for the disk image.
    //
    pDeviceExtension->DiskImage = ExAllocatePoolWithTag(
        NonPagedPool,
        pDeviceExtension->DiskRegInfo.DiskSize,
        RAMDISK_TAG
        );

    if (pDeviceExtension->DiskImage) {

        UNICODE_STRING deviceName;
        UNICODE_STRING win32Name;

        RamDiskFormatDisk(pDeviceExtension);

        status = STATUS_SUCCESS;

        //
        // Now try to create a symbolic link for the drive letter.
        //
        RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME);
        RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME);

        pDeviceExtension->SymbolicLink.Buffer = (PWSTR)
            &pDeviceExtension->DosDeviceNameBuffer;
        pDeviceExtension->SymbolicLink.MaximumLength =
            sizeof(pDeviceExtension->DosDeviceNameBuffer);
        pDeviceExtension->SymbolicLink.Length = win32Name.Length;

        RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name);
        RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink,
                                       &pDeviceExtension->DiskRegInfo.DriveLetter);

        status = WdfDeviceCreateSymbolicLink(device,
                                             &pDeviceExtension->SymbolicLink);
    }

    return status;
}
Esempio n. 25
0
VOID
CdInitializeEnumeration (
    __in PIRP_CONTEXT IrpContext,
    __in PIO_STACK_LOCATION IrpSp,
    __in PFCB Fcb,
    __inout PCCB Ccb,
    __inout PFILE_ENUM_CONTEXT FileContext,
    __out PBOOLEAN ReturnNextEntry,
    __out PBOOLEAN ReturnSingleEntry,
    __out PBOOLEAN InitialQuery
    )

/*++

Routine Description:

    This routine is called to initialize the enumeration variables and structures.
    We look at the state of a previous enumeration from the Ccb as well as any
    input values from the user.  On exit we will position the FileContext at
    a file in the directory and let the caller know whether this entry or the
    next entry should be returned.

Arguments:

    IrpSp - Irp stack location for this request.

    Fcb - Fcb for this directory.

    Ccb - Ccb for the directory handle.

    FileContext - FileContext to use for this enumeration.

    ReturnNextEntry - Address to store whether we should return the entry at
        the FileContext position or the next entry.

    ReturnSingleEntry - Address to store whether we should only return
        a single entry.

    InitialQuery - Address to store whether this is the first enumeration
        query on this handle.

Return Value:

    None.

--*/

{
    NTSTATUS Status;

    PUNICODE_STRING FileName;
    CD_NAME WildCardName;
    CD_NAME SearchExpression;

    ULONG CcbFlags;

    ULONG DirentOffset;
    ULONG LastDirentOffset;
    BOOLEAN KnownOffset;

    BOOLEAN Found;

    PAGED_CODE();

    //
    //  If this is the initial query then build a search expression from the input
    //  file name.
    //

    if (!FlagOn( Ccb->Flags, CCB_FLAG_ENUM_INITIALIZED )) {

        FileName = IrpSp->Parameters.QueryDirectory.FileName;

        CcbFlags = 0;

        //
        //  If the filename is not specified or is a single '*' then we will
        //  match all names.
        //

        if ((FileName == NULL) ||
            (FileName->Buffer == NULL) ||
            (FileName->Length == 0) ||
            ((FileName->Length == sizeof( WCHAR )) &&
             (FileName->Buffer[0] == L'*'))) {

            SetFlag( CcbFlags, CCB_FLAG_ENUM_MATCH_ALL );
            RtlZeroMemory( &SearchExpression, sizeof( SearchExpression ));

        //
        //  Otherwise build the CdName from the name in the stack location.
        //  This involves building both the name and version portions and
        //  checking for wild card characters.  We also upcase the string if
        //  this is a case-insensitive search.
        //

        } else {

            //
            //  Create a CdName to check for wild cards.
            //

            WildCardName.FileName = *FileName;

            CdConvertNameToCdName( IrpContext, &WildCardName );

            //
            //  The name better have at least one character.
            //

            if (WildCardName.FileName.Length == 0) {

                CdRaiseStatus( IrpContext, STATUS_INVALID_PARAMETER );
            }

            //
            //  Check for wildcards in the separate components.
            //

            if (FsRtlDoesNameContainWildCards( &WildCardName.FileName)) {

                SetFlag( CcbFlags, CCB_FLAG_ENUM_NAME_EXP_HAS_WILD );
            }

            if ((WildCardName.VersionString.Length != 0) &&
                (FsRtlDoesNameContainWildCards( &WildCardName.VersionString ))) {

                SetFlag( CcbFlags, CCB_FLAG_ENUM_VERSION_EXP_HAS_WILD );

                //
                //  Check if this is a wild card only and match all version
                //  strings.
                //

                if ((WildCardName.VersionString.Length == sizeof( WCHAR )) &&
                    (WildCardName.VersionString.Buffer[0] == L'*')) {

                    SetFlag( CcbFlags, CCB_FLAG_ENUM_VERSION_MATCH_ALL );
                }
            }

            //
            //  Now create the search expression to store in the Ccb.
            //

            SearchExpression.FileName.Buffer = FsRtlAllocatePoolWithTag( CdPagedPool,
                                                                         FileName->Length,
                                                                         TAG_ENUM_EXPRESSION );

            SearchExpression.FileName.MaximumLength = FileName->Length;

            //
            //  Either copy the name directly or perform the upcase.
            //

            if (FlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE )) {

                Status = RtlUpcaseUnicodeString( (PUNICODE_STRING) &SearchExpression.FileName,
                                                 FileName,
                                                 FALSE );

                //
                //  This should never fail.
                //

                ASSERT( Status == STATUS_SUCCESS );

            } else {

                RtlCopyMemory( SearchExpression.FileName.Buffer,
                               FileName->Buffer,
                               FileName->Length );
            }

            //
            //  Now split into the separate name and version components.
            //

            SearchExpression.FileName.Length = WildCardName.FileName.Length;
            SearchExpression.VersionString.Length = WildCardName.VersionString.Length;
            SearchExpression.VersionString.MaximumLength = WildCardName.VersionString.MaximumLength;

            SearchExpression.VersionString.Buffer = Add2Ptr( SearchExpression.FileName.Buffer,
                                                             SearchExpression.FileName.Length + sizeof( WCHAR ),
                                                             PWCHAR );
        }

        //
        //  But we do not want to return the constant "." and ".." entries for
        //  the root directory, for consistency with the rest of Microsoft's
        //  filesystems.
        //

        if (Fcb == Fcb->Vcb->RootIndexFcb) {

            SetFlag( CcbFlags, CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY );
        }

        //
        //  Now lock the Fcb in order to update the Ccb with the inital
        //  enumeration values.
        //

        CdLockFcb( IrpContext, Fcb );

        //
        //  Check again that this is the initial search.
        //

        if (!FlagOn( Ccb->Flags, CCB_FLAG_ENUM_INITIALIZED )) {

            //
            //  Update the values in the Ccb.
            //

            Ccb->CurrentDirentOffset = Fcb->StreamOffset;
            Ccb->SearchExpression = SearchExpression;

            //
            //  Set the appropriate flags in the Ccb.
            //

            SetFlag( Ccb->Flags, CcbFlags | CCB_FLAG_ENUM_INITIALIZED );

        //
        //  Otherwise cleanup any buffer allocated here.
        //

        } else {

            if (!FlagOn( CcbFlags, CCB_FLAG_ENUM_MATCH_ALL )) {

                CdFreePool( &SearchExpression.FileName.Buffer );
            }
        }

    //
    //  Otherwise lock the Fcb so we can read the current enumeration values.
    //

    } else {

        CdLockFcb( IrpContext, Fcb );
    }

    //
    //  Capture the current state of the enumeration.
    //
    //  If the user specified an index then use his offset.  We always
    //  return the next entry in this case.
    //

    if (FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED )) {

        KnownOffset = FALSE;
        DirentOffset = IrpSp->Parameters.QueryDirectory.FileIndex;
        *ReturnNextEntry = TRUE;

    //
    //  If we are restarting the scan then go from the self entry.
    //

    } else if (FlagOn( IrpSp->Flags, SL_RESTART_SCAN )) {

        KnownOffset = TRUE;
        DirentOffset = Fcb->StreamOffset;
        *ReturnNextEntry = FALSE;

    //
    //  Otherwise use the values from the Ccb.
    //

    } else {

        KnownOffset = TRUE;
        DirentOffset = Ccb->CurrentDirentOffset;
        *ReturnNextEntry = BooleanFlagOn( Ccb->Flags, CCB_FLAG_ENUM_RETURN_NEXT );
    }

    //
    //  Unlock the Fcb.
    //

    CdUnlockFcb( IrpContext, Fcb );

    //
    //  We have the starting offset in the directory and whether to return
    //  that entry or the next.  If we are at the beginning of the directory
    //  and are returning that entry, then tell our caller this is the
    //  initial query.
    //

    *InitialQuery = FALSE;

    if ((DirentOffset == Fcb->StreamOffset) &&
        !(*ReturnNextEntry)) {

        *InitialQuery = TRUE;
    }

    //
    //  If there is no file object then create it now.
    //

    CdVerifyOrCreateDirStreamFile( IrpContext, Fcb);

    //
    //  Determine the offset in the stream to position the FileContext and
    //  whether this offset is known to be a file offset.
    //
    //  If this offset is known to be safe then go ahead and position the
    //  file context.  This handles the cases where the offset is the beginning
    //  of the stream, the offset is from a previous search or this is the
    //  initial query.
    //

    if (KnownOffset) {

        CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, DirentOffset );

    //
    //  Otherwise we walk through the directory from the beginning until
    //  we reach the entry which contains this offset.
    //

    } else {

        LastDirentOffset = Fcb->StreamOffset;
        Found = TRUE;

        CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, LastDirentOffset );

        //
        //  If the requested offset is prior to the beginning offset in the stream
        //  then don't return the next entry.
        //

        if (DirentOffset < LastDirentOffset) {

            *ReturnNextEntry = FALSE;

        //
        //  Else look for the last entry which ends past the desired index.
        //

        } else {

            //
            //  Keep walking through the directory until we run out of
            //  entries or we find an entry which ends beyond the input
            //  index value.
            //

            do {

                //
                //  If we have passed the index value then exit.
                //

                if (FileContext->InitialDirent->Dirent.DirentOffset > DirentOffset) {

                    Found = FALSE;
                    break;
                }

                //
                //  Remember the current position in case we need to go back.
                //

                LastDirentOffset = FileContext->InitialDirent->Dirent.DirentOffset;

                //
                //  Exit if the next entry is beyond the desired index value.
                //

                if (LastDirentOffset + FileContext->InitialDirent->Dirent.DirentLength > DirentOffset) {

                    break;
                }

                Found = CdLookupNextInitialFileDirent( IrpContext, Fcb, FileContext );

            } while (Found);

            //
            //  If we didn't find the entry then go back to the last known entry.
            //  This can happen if the index lies in the unused range at the
            //  end of a sector.
            //

            if (!Found) {

                CdCleanupFileContext( IrpContext, FileContext );
                CdInitializeFileContext( IrpContext, FileContext );

                CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, LastDirentOffset );
            }
        }
    }

    //
    //  Only update the dirent name if we will need it for some reason.
    //  Don't update this name if we are returning the next entry and
    //  the search string has a version component.
    //

    FileContext->ShortName.FileName.Length = 0;

    if (!(*ReturnNextEntry) ||
        (Ccb->SearchExpression.VersionString.Length == 0)) {

        //
        //  Update the name in the dirent into filename and version components.
        //

        CdUpdateDirentName( IrpContext,
                            &FileContext->InitialDirent->Dirent,
                            FlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE ));
    }

    //
    //  Look at the flag in the IrpSp indicating whether to return just
    //  one entry.
    //

    *ReturnSingleEntry = FALSE;

    if (FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY )) {

        *ReturnSingleEntry = TRUE;
    }

    return;
}
Esempio n. 26
0
VOID
RamDiskQueryDiskRegParameters(
    __in PWSTR RegistryPath,
    __in PDISK_INFO DiskRegInfo
    )

/*++

Routine Description:

    This routine is called from the DriverEntry to get the debug
    parameters from the registry. If the registry query fails, then
    default values are used.

Arguments:

    RegistryPath    - Points the service path to get the registry parameters

Return Value:

    None

--*/

{

    RTL_QUERY_REGISTRY_TABLE rtlQueryRegTbl[5 + 1];  // Need 1 for NULL
    NTSTATUS                 Status;
    DISK_INFO                defDiskRegInfo;

    PAGED_CODE();

    ASSERT(RegistryPath != NULL);

    // Set the default values

    defDiskRegInfo.DiskSize          = DEFAULT_DISK_SIZE;
    defDiskRegInfo.RootDirEntries    = DEFAULT_ROOT_DIR_ENTRIES;
    defDiskRegInfo.SectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER;

    RtlInitUnicodeString(&defDiskRegInfo.DriveLetter, DEFAULT_DRIVE_LETTER);

    RtlZeroMemory(rtlQueryRegTbl, sizeof(rtlQueryRegTbl));

    //
    // Setup the query table
    //

    rtlQueryRegTbl[0].Flags         = RTL_QUERY_REGISTRY_SUBKEY;
    rtlQueryRegTbl[0].Name          = L"Parameters";
    rtlQueryRegTbl[0].EntryContext  = NULL;
    rtlQueryRegTbl[0].DefaultType   = (ULONG_PTR)NULL;
    rtlQueryRegTbl[0].DefaultData   = NULL;
    rtlQueryRegTbl[0].DefaultLength = (ULONG_PTR)NULL;

    //
    // Disk paramters
    //

    rtlQueryRegTbl[1].Flags         = RTL_QUERY_REGISTRY_DIRECT;
    rtlQueryRegTbl[1].Name          = L"DiskSize";
    rtlQueryRegTbl[1].EntryContext  = &DiskRegInfo->DiskSize;
    rtlQueryRegTbl[1].DefaultType   = REG_DWORD;
    rtlQueryRegTbl[1].DefaultData   = &defDiskRegInfo.DiskSize;
    rtlQueryRegTbl[1].DefaultLength = sizeof(ULONG);

    rtlQueryRegTbl[2].Flags         = RTL_QUERY_REGISTRY_DIRECT;
    rtlQueryRegTbl[2].Name          = L"RootDirEntries";
    rtlQueryRegTbl[2].EntryContext  = &DiskRegInfo->RootDirEntries;
    rtlQueryRegTbl[2].DefaultType   = REG_DWORD;
    rtlQueryRegTbl[2].DefaultData   = &defDiskRegInfo.RootDirEntries;
    rtlQueryRegTbl[2].DefaultLength = sizeof(ULONG);

    rtlQueryRegTbl[3].Flags         = RTL_QUERY_REGISTRY_DIRECT;
    rtlQueryRegTbl[3].Name          = L"SectorsPerCluster";
    rtlQueryRegTbl[3].EntryContext  = &DiskRegInfo->SectorsPerCluster;
    rtlQueryRegTbl[3].DefaultType   = REG_DWORD;
    rtlQueryRegTbl[3].DefaultData   = &defDiskRegInfo.SectorsPerCluster;
    rtlQueryRegTbl[3].DefaultLength = sizeof(ULONG);

    rtlQueryRegTbl[4].Flags         = RTL_QUERY_REGISTRY_DIRECT;
    rtlQueryRegTbl[4].Name          = L"DriveLetter";
    rtlQueryRegTbl[4].EntryContext  = &DiskRegInfo->DriveLetter;
    rtlQueryRegTbl[4].DefaultType   = REG_SZ;
    rtlQueryRegTbl[4].DefaultData   = defDiskRegInfo.DriveLetter.Buffer;
    rtlQueryRegTbl[4].DefaultLength = 0;


    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
                 RegistryPath,
                 rtlQueryRegTbl,
                 NULL,
                 NULL
             );

    if (NT_SUCCESS(Status) == FALSE) {

        DiskRegInfo->DiskSize          = defDiskRegInfo.DiskSize;
        DiskRegInfo->RootDirEntries    = defDiskRegInfo.RootDirEntries;
        DiskRegInfo->SectorsPerCluster = defDiskRegInfo.SectorsPerCluster;
        RtlCopyUnicodeString(&DiskRegInfo->DriveLetter, &defDiskRegInfo.DriveLetter);
    }

    KdPrint(("DiskSize          = 0x%lx\n", DiskRegInfo->DiskSize));
    KdPrint(("RootDirEntries    = 0x%lx\n", DiskRegInfo->RootDirEntries));
    KdPrint(("SectorsPerCluster = 0x%lx\n", DiskRegInfo->SectorsPerCluster));
    KdPrint(("DriveLetter       = %wZ\n",   &(DiskRegInfo->DriveLetter)));

    return;
}
Esempio n. 27
0
VOID
NTAPI
PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine,
                     IN PVOID StartContext)
{
    PETHREAD Thread;
    PTEB Teb;
    BOOLEAN DeadThread = FALSE;
    KIRQL OldIrql;
    PAGED_CODE();
    PSTRACE(PS_THREAD_DEBUG,
            "StartRoutine: %p StartContext: %p\n", StartRoutine, StartContext);

    /* Go to Passive Level */
    KeLowerIrql(PASSIVE_LEVEL);
    Thread = PsGetCurrentThread();

    /* Check if the thread is dead */
    if (Thread->DeadThread)
    {
        /* Remember that we're dead */
        DeadThread = TRUE;
    }
    else
    {
        /* Get the Locale ID and save Preferred Proc */
        Teb =  NtCurrentTeb();
        Teb->CurrentLocale = MmGetSessionLocaleId();
        Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
    }

    /* Check if this is a dead thread, or if we're hiding */
    if (!(Thread->DeadThread) && !(Thread->HideFromDebugger))
    {
        /* We're not, so notify the debugger */
        DbgkCreateThread(Thread, StartContext);
    }

    /* Make sure we're not already dead */
    if (!DeadThread)
    {
        /* Check if the Prefetcher is enabled */
        if (CcPfEnablePrefetcher)
        {
            /* FIXME: Prepare to prefetch this process */
        }

        /* Raise to APC */
        KeRaiseIrql(APC_LEVEL, &OldIrql);

        /* Queue the User APC */
        KiInitializeUserApc(KeGetExceptionFrame(&Thread->Tcb),
                            KeGetTrapFrame(&Thread->Tcb),
                            PspSystemDllEntryPoint,
                            NULL,
                            PspSystemDllBase,
                            NULL);

        /* Lower it back to passive */
        KeLowerIrql(PASSIVE_LEVEL);
    }
    else
    {
        /* We're dead, kill us now */
        PspTerminateThreadByPointer(Thread,
                                    STATUS_THREAD_IS_TERMINATING,
                                    TRUE);
    }

    /* Do we have a cookie set yet? */
    while (!SharedUserData->Cookie)
    {
        LARGE_INTEGER SystemTime;
        ULONG NewCookie;
        PKPRCB Prcb;

        /* Generate a new cookie */
        KeQuerySystemTime(&SystemTime);
        Prcb = KeGetCurrentPrcb();
        NewCookie = Prcb->MmPageFaultCount ^ Prcb->InterruptTime ^
                    SystemTime.u.LowPart ^ SystemTime.u.HighPart ^
                    (ULONG_PTR)&SystemTime;

        /* Set the new cookie*/
        InterlockedCompareExchange((LONG*)&SharedUserData->Cookie,
                                   NewCookie,
                                   0);
    }
}
Esempio n. 28
0
NTSTATUS
RamDiskFormatDisk(
    IN PDEVICE_EXTENSION devExt
    )

/*++

Routine Description:

    This routine formats the new disk.


Arguments:

    DeviceObject - Supplies a pointer to the device object that represents
                   the device whose capacity is to be read.

Return Value:

    status is returned.

--*/
{

    PBOOT_SECTOR bootSector = (PBOOT_SECTOR) devExt->DiskImage;
    PUCHAR       firstFatSector;
    ULONG        rootDirEntries;
    ULONG        sectorsPerCluster;
    USHORT       fatType;        // Type FAT 12 or 16
    USHORT       fatEntries;     // Number of cluster entries in FAT
    USHORT       fatSectorCnt;   // Number of sectors for FAT
    PDIR_ENTRY   rootDir;        // Pointer to first entry in root dir

    PAGED_CODE();
    ASSERT(sizeof(BOOT_SECTOR) == 512);
    ASSERT(devExt->DiskImage != NULL);

    RtlZeroMemory(devExt->DiskImage, devExt->DiskRegInfo.DiskSize);

    devExt->DiskGeometry.BytesPerSector = 512;
    devExt->DiskGeometry.SectorsPerTrack = 32;     // Using Ramdisk value
    devExt->DiskGeometry.TracksPerCylinder = 2;    // Using Ramdisk value

    //
    // Calculate number of cylinders.
    //

    devExt->DiskGeometry.Cylinders.QuadPart = devExt->DiskRegInfo.DiskSize / 512 / 32 / 2;

    //
    // Our media type is RAMDISK_MEDIA_TYPE
    //

    devExt->DiskGeometry.MediaType = RAMDISK_MEDIA_TYPE;

    KdPrint((
        "Cylinders: %ld\n TracksPerCylinder: %ld\n SectorsPerTrack: %ld\n BytesPerSector: %ld\n",
        devExt->DiskGeometry.Cylinders.QuadPart, devExt->DiskGeometry.TracksPerCylinder,
        devExt->DiskGeometry.SectorsPerTrack, devExt->DiskGeometry.BytesPerSector
        ));

    rootDirEntries = devExt->DiskRegInfo.RootDirEntries;
    sectorsPerCluster = devExt->DiskRegInfo.SectorsPerCluster;

    //
    // Round Root Directory entries up if necessary
    //

    if (rootDirEntries & (DIR_ENTRIES_PER_SECTOR - 1)) {

        rootDirEntries =
            (rootDirEntries + (DIR_ENTRIES_PER_SECTOR - 1)) &
                ~ (DIR_ENTRIES_PER_SECTOR - 1);
    }

    KdPrint((
        "Root dir entries: %ld\n Sectors/cluster: %ld\n",
        rootDirEntries, sectorsPerCluster
        ));

    //
    // We need to have the 0xeb and 0x90 since this is one of the
    // checks the file system recognizer uses
    //

    bootSector->bsJump[0] = 0xeb;
    bootSector->bsJump[1] = 0x3c;
    bootSector->bsJump[2] = 0x90;

    //
    // Set OemName to "RajuRam "
    // NOTE: Fill all 8 characters, eg. sizeof(bootSector->bsOemName);
    //
    bootSector->bsOemName[0] = 'R';
    bootSector->bsOemName[1] = 'a';
    bootSector->bsOemName[2] = 'j';
    bootSector->bsOemName[3] = 'u';
    bootSector->bsOemName[4] = 'R';
    bootSector->bsOemName[5] = 'a';
    bootSector->bsOemName[6] = 'm';
    bootSector->bsOemName[7] = ' ';

    bootSector->bsBytesPerSec = (SHORT)devExt->DiskGeometry.BytesPerSector;
    bootSector->bsResSectors  = 1;
    bootSector->bsFATs        = 1;
    bootSector->bsRootDirEnts = (USHORT)rootDirEntries;

    // See http://www.winvistatips.com/ramdisk-larger-than-16-m-partition-t195928.html
    //bootSector->bsSectors     = (USHORT)(devExt->DiskRegInfo.DiskSize / 
    //devExt->DiskGeometry.BytesPerSector);
    if( devExt->DiskRegInfo.DiskSize/devExt->DiskGeometry.BytesPerSector < 65536 ) {
            bootSector->bsSectors = (USHORT)(devExt->DiskRegInfo.DiskSize / devExt->DiskGeometry.BytesPerSector);
    } else {
        bootSector->bsSectors = 0;
        bootSector->bsHugeSectors = devExt->DiskRegInfo.DiskSize / devExt->DiskGeometry.BytesPerSector;
    }
    
    bootSector->bsMedia       = (UCHAR)devExt->DiskGeometry.MediaType;
    bootSector->bsSecPerClus  = (UCHAR)sectorsPerCluster;

    //
    // Calculate number of sectors required for FAT
    //

    //fatEntries =
    //    (bootSector->bsSectors - bootSector->bsResSectors -
    //        bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
    //            bootSector->bsSecPerClus + 2;

    if(bootSector->bsSectors) {
        fatEntries =
            (bootSector->bsSectors - bootSector->bsResSectors -
            bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
            bootSector->bsSecPerClus + 2;
    } else {
        fatEntries =
            (USHORT)((bootSector->bsHugeSectors - bootSector->bsResSectors -
            bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
            bootSector->bsSecPerClus + 2);
    }
    
    //
    // Choose between 12 and 16 bit FAT based on number of clusters we
    // need to map
    //

    if (fatEntries > 4087) {
        fatType =  16;
        fatSectorCnt = (fatEntries * 2 + 511) / 512;
        fatEntries   = fatEntries + fatSectorCnt;
        fatSectorCnt = (fatEntries * 2 + 511) / 512;
    }
    else {
        fatType =  12;
        fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
        fatEntries   = fatEntries + fatSectorCnt;
        fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
    }

    bootSector->bsFATsecs       = fatSectorCnt;
    bootSector->bsSecPerTrack   = (USHORT)devExt->DiskGeometry.SectorsPerTrack;
    bootSector->bsHeads         = (USHORT)devExt->DiskGeometry.TracksPerCylinder;
    bootSector->bsBootSignature = 0x29;
    bootSector->bsVolumeID      = 0x12345678;

    //
    // Set Label to "RamDisk    "
    // NOTE: Fill all 11 characters, eg. sizeof(bootSector->bsLabel);
    //
    bootSector->bsLabel[0]  = 'R';
    bootSector->bsLabel[1]  = 'a';
    bootSector->bsLabel[2]  = 'm';
    bootSector->bsLabel[3]  = 'D';
    bootSector->bsLabel[4]  = 'i';
    bootSector->bsLabel[5]  = 's';
    bootSector->bsLabel[6]  = 'k';
    bootSector->bsLabel[7]  = ' ';
    bootSector->bsLabel[8]  = ' ';
    bootSector->bsLabel[9]  = ' ';
    bootSector->bsLabel[10] = ' ';

    //
    // Set FileSystemType to "FAT1?   "
    // NOTE: Fill all 8 characters, eg. sizeof(bootSector->bsFileSystemType);
    //
    bootSector->bsFileSystemType[0] = 'F';
    bootSector->bsFileSystemType[1] = 'A';
    bootSector->bsFileSystemType[2] = 'T';
    bootSector->bsFileSystemType[3] = '1';
    bootSector->bsFileSystemType[4] = '?';
    bootSector->bsFileSystemType[5] = ' ';
    bootSector->bsFileSystemType[6] = ' ';
    bootSector->bsFileSystemType[7] = ' ';

    bootSector->bsFileSystemType[4] = ( fatType == 16 ) ? '6' : '2';

    bootSector->bsSig2[0] = 0x55;
    bootSector->bsSig2[1] = 0xAA;

    //
    // The FAT is located immediately following the boot sector.
    //

    firstFatSector    = (PUCHAR)(bootSector + 1);
    firstFatSector[0] = (UCHAR)devExt->DiskGeometry.MediaType;
    firstFatSector[1] = 0xFF;
    firstFatSector[2] = 0xFF;

    if (fatType == 16) {
        firstFatSector[3] = 0xFF;
    }

    //
    // The Root Directory follows the FAT
    //
    rootDir = (PDIR_ENTRY)(bootSector + 1 + fatSectorCnt);

    //
    // Set device name to "MS-RAMDR"
    // NOTE: Fill all 8 characters, eg. sizeof(rootDir->deName);
    //
    rootDir->deName[0] = 'S';
    rootDir->deName[1] = 'A';
    rootDir->deName[2] = 'M';
    rootDir->deName[3] = 'S';
    rootDir->deName[4] = '-';
    rootDir->deName[5] = 'D';
    rootDir->deName[6] = 'R';
    rootDir->deName[7] = 'I';

    //
    // Set device extension name to "IVE"
    // NOTE: Fill all 3 characters, eg. sizeof(rootDir->deExtension);
    //
    rootDir->deExtension[0] = 'V';
    rootDir->deExtension[1] = 'E';
    rootDir->deExtension[2] = 'R';

    rootDir->deAttributes = DIR_ATTR_VOLUME;

    return STATUS_SUCCESS;
}
Esempio n. 29
0
NTSTATUS
NTAPI
NpPeek(IN PDEVICE_OBJECT DeviceObject,
       IN PIRP Irp,
       IN PLIST_ENTRY List)
{
    PIO_STACK_LOCATION IoStack;
    NODE_TYPE_CODE Type;
    ULONG OutputLength;
    ULONG NamedPipeEnd;
    PNP_CCB Ccb;
    PFILE_PIPE_PEEK_BUFFER PeekBuffer;
    PNP_DATA_QUEUE DataQueue;
    ULONG_PTR BytesPeeked;
    IO_STATUS_BLOCK IoStatus;
    NTSTATUS Status;
    PNP_DATA_QUEUE_ENTRY DataEntry;
    PAGED_CODE();

    IoStack = IoGetCurrentIrpStackLocation(Irp);
    OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
    Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);

    if (!Type)
    {
        return STATUS_PIPE_DISCONNECTED;
    }

    if ((Type != NPFS_NTC_CCB) &&
        (OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)))
    {
        return STATUS_INVALID_PARAMETER;
    }

    PeekBuffer = Irp->AssociatedIrp.SystemBuffer;
    if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
    {
        if (NamedPipeEnd != FILE_PIPE_SERVER_END)
        {
            NpBugCheck(NamedPipeEnd, 0, 0);
        }

        DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
    }
    else
    {
        DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
    }

    if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
    {
        if (Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE)
        {
            return STATUS_INVALID_PIPE_STATE;
        }

        if (DataQueue->QueueState != WriteEntries)
        {
            return STATUS_PIPE_BROKEN;
        }
    }

    PeekBuffer->NamedPipeState = 0;
    PeekBuffer->ReadDataAvailable = 0;
    PeekBuffer->NumberOfMessages = 0;
    PeekBuffer->MessageLength = 0;
    PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
    BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data);

    if (DataQueue->QueueState == WriteEntries)
    {
        DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
                                      NP_DATA_QUEUE_ENTRY,
                                      QueueEntry);
        ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered));

        PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset;
        if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE)
        {
            PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
            PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
        }

        if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))
        {
            Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
        }
        else
        {
            IoStatus = NpReadDataQueue(DataQueue,
                                       TRUE,
                                       FALSE,
                                       PeekBuffer->Data,
                                       OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data),
                                       Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
                                       Ccb,
                                       List);
            Status = IoStatus.Status;
            BytesPeeked += IoStatus.Information;
        }
    }
    else
    {
        Status = STATUS_SUCCESS;
    }

    Irp->IoStatus.Information = BytesPeeked;
    return Status;
}
Esempio n. 30
0
File: wmi.c Progetto: kcrazy/winekit
NTSTATUS
PciDrvWmiRegistration(
    __in PFDO_DATA               FdoData
)
/*++
Routine Description

    Registers with WMI as a data provider for this
    instance of the device

--*/
{
    NTSTATUS status;
    ULONG    guidCount = 0;


    PAGED_CODE();

    //
    // Register a guid to get standard device information.
    //
    PciDrvWmiGuidList[guidCount].Flags = 0;
    PciDrvWmiGuidList[guidCount].InstanceCount = 1;
    PciDrvWmiGuidList[guidCount].Guid = &PCIDRV_WMI_STD_DATA_GUID;
    guidCount++;

    //
    // If upper edge is not NDIS, we will be the power policy
    // owner for this device.
    //
    if(!FdoData->IsUpperEdgeNdis) {

        //
        // If you handle the following two GUIDs, the device manager will
        // show the power-management tab in the device properites dialog.
        //
        PciDrvWmiGuidList[guidCount].Flags = 0;
        PciDrvWmiGuidList[guidCount].InstanceCount = 1;
        PciDrvWmiGuidList[guidCount].Guid = &GUID_POWER_DEVICE_WAKE_ENABLE;
        guidCount++;

        PciDrvWmiGuidList[guidCount].Flags = 0;
        PciDrvWmiGuidList[guidCount].InstanceCount = 1;
        PciDrvWmiGuidList[guidCount].Guid = &GUID_POWER_DEVICE_ENABLE;
        guidCount++;
        //
        // Following two guids are used to get/set the conservation and
        // performance time during idle detection.
        //
        PciDrvWmiGuidList[guidCount].Flags = 0;
        PciDrvWmiGuidList[guidCount].InstanceCount = 1;
        PciDrvWmiGuidList[guidCount].Guid = &GUID_POWER_CONSERVATION_IDLE_TIME;
        guidCount++;

        PciDrvWmiGuidList[guidCount].Flags = 0;
        PciDrvWmiGuidList[guidCount].InstanceCount = 1;
        PciDrvWmiGuidList[guidCount].Guid = &GUID_POWER_PERFORMANCE_IDLE_TIME;
        guidCount++;

    }

#if defined(WIN2K) && defined(EVENT_TRACING)
    //
    // The GUID acts as the control GUID for enabling and disabling
    // the tracing.
    //
    PciDrvWmiGuidList[guidCount].Flags = 0;
    PciDrvWmiGuidList[guidCount].InstanceCount = 1;
    PciDrvWmiGuidList[guidCount].Guid = &WPP_TRACE_CONTROL_NULL_GUID;
    guidCount++;

#endif

    ASSERT(guidCount <= NUMBER_OF_WMI_GUIDS);

    FdoData->WmiLibInfo.GuidCount = guidCount;
    FdoData->WmiLibInfo.GuidList = PciDrvWmiGuidList;
    FdoData->WmiLibInfo.QueryWmiRegInfo = PciDrvQueryWmiRegInfo;
    FdoData->WmiLibInfo.QueryWmiDataBlock = PciDrvQueryWmiDataBlock;
    FdoData->WmiLibInfo.SetWmiDataBlock = PciDrvSetWmiDataBlock;
    FdoData->WmiLibInfo.SetWmiDataItem = NULL;
    FdoData->WmiLibInfo.ExecuteWmiMethod = NULL;
    FdoData->WmiLibInfo.WmiFunctionControl = NULL;

    //
    // Register with WMI
    //

    status = IoWMIRegistrationControl(FdoData->Self,
                             WMIREG_ACTION_REGISTER
                             );

    //
    // Initialize the Std device data structure
    //

    FdoData->StdDeviceData.DebugPrintLevel = DebugLevel;

    return status;

}